Rollup merge of #95634 - dtolnay:mailmap, r=Mark-Simulacrum Mailmap update I noticed there are a lot of contributors who appear multiple times in https://thanks.rust-lang.org/rust/all-time/, which makes their "rank" on that page inaccurate. For example Nick Cameron currently appears at rank 21 with 2010 contributions and at rank 27 with 1287 contributions, because some of those are from nrc⁠```@ncameron.org``` and some from ncameron⁠```@mozilla.com.``` In reality Nick's rank would be 11 if counted correctly, which is a large difference. Solving this in a totally automated way is tricky because it involves figuring out whether Nick is 1 person with multiple emails, or is 2 people sharing the same name. This PR addresses a subset of the cases: only where a person has committed under multiple names using the same email. This is still not something that can be totally automated (e.g. by modifying https://github.com/rust-lang/thanks to dedup by email instead of name+email) because: - Some emails are not necessarily unique to one contributor, such as `ubuntu@localhost`. - It involves some judgement and mindfulness in picking the "canonical name" among the names used with a particular email. This is the name that will appear on thanks.rust-lang.org. Humans change their names sometimes and can be sensitive or picky about the use of names that are no longer preferred. For the purpose of this PR, I've tried to stick to the following heuristics which should be unobjectionable: - If one of the names is currently set as the display name on the contributor's GitHub profile, prefer that name. - If one of the names is used exclusively over the others in chronologically newer pull requests, prefer the newest name. - If one of the names has whitespace and the other doesn't (i.e. is username-like), such as `Foo Bar` vs `FooBar` or `foobar` or `foo-bar123`, but otherwise closely resemble one another, then prefer the human-like name. - If none of the above suffice in determining a canonical name and the contributor has some other name set on their GitHub profile, use the name from the GitHub profile. - If no name on their GitHub profile but the profile links to their personal website which unambiguously identifies their preferred name, then use that name. I'm also thinking about how to handle cases like Nick's, but that will be a project for a different PR. Basically I'd like to be able to find cases of the same person making commits that differ in name *and* email by looking at all the commits present in pull requests opened by the same GitHub user. <details> <summary>script</summary> ```toml [dependencies] anyhow = "1.0" git2 = "0.14" mailmap = "0.1" ``` ```rust use anyhow::{bail, Context, Result}; use git2::{Commit, Oid, Repository}; use mailmap::{Author, Mailmap}; use std::collections::{BTreeMap as Map, BTreeSet as Set}; use std::fmt::{self, Debug}; use std::fs; use std::path::Path; const REPO: &str = "/git/rust"; fn main() -> Result<()> { let repo = Repository::open(REPO)?; let head_oid = repo .head()? .target() .context("expected head to be a direct reference")?; let head = repo.find_commit(head_oid)?; let mailmap_path = Path::new(REPO).join(".mailmap"); let mailmap_contents = fs::read_to_string(mailmap_path)?; let mailmap = match Mailmap::from_string(mailmap_contents) { Ok(mailmap) => mailmap, Err(box_error) => bail!("{}", box_error), }; let mut history = Set::new(); let mut merges = Vec::new(); let mut authors = Set::new(); let mut emails = Map::new(); let mut all_authors = Set::new(); traverse_left(head, &mut history, &mut merges, &mut authors, &mailmap)?; while let Some((commit, i)) = merges.pop() { let right = commit.parents().nth(i).unwrap(); authors.clear(); traverse_left(right, &mut history, &mut merges, &mut authors, &mailmap)?; for author in &authors { all_authors.insert(author.clone()); if !author.email.is_empty() { emails .entry(author.email.clone()) .or_insert_with(Map::new) .entry(author.name.clone()) .or_insert_with(Set::new); } } if let Some(summary) = commit.summary() { if let Some(pr) = parse_summary(summary)? { for author in &authors { if !author.email.is_empty() { emails .get_mut(&author.email) .unwrap() .get_mut(&author.name) .unwrap() .insert(pr); } } } } } for (email, names) in emails { if names.len() > 1 { println!("<{}>", email); for (name, prs) in names { let prs = DebugSet(prs.iter().rev()); println!(" {} {:?}", name, prs); } } } eprintln!("{} commits", history.len()); eprintln!("{} authors", all_authors.len()); Ok(()) } fn traverse_left<'repo>( mut commit: Commit<'repo>, history: &mut Set<Oid>, merges: &mut Vec<(Commit<'repo>, usize)>, authors: &mut Set<Author>, mailmap: &Mailmap, ) -> Result<()> { loop { let oid = commit.id(); if !history.insert(oid) { return Ok(()); } let author = author(mailmap, &commit); let is_bors = author.name == "bors" && author.email == "bors@rust-lang.org"; if !is_bors { authors.insert(author); } let mut parents = commit.parents(); let parent = match parents.next() { Some(parent) => parent, None => return Ok(()), }; for i in 1..1 + parents.len() { merges.push((commit.clone(), i)); } commit = parent; } } fn parse_summary(summary: &str) -> Result<Option<PullRequest>> { let mut rest = None; for prefix in [ "Auto merge of #", "Merge pull request #", " Manual merge of #", "auto merge of #", "auto merge of pull req #", "rollup merge of #", "Rollup merge of #", "Rollup merge of #", "Rollup merge of ", "Merge PR #", "Merge #", "Merged #", ] { if summary.starts_with(prefix) { rest = Some(&summary[prefix.len()..]); break; } } let rest = match rest { Some(rest) => rest, None => return Ok(None), }; let end = rest.find([' ', ':']).unwrap_or(rest.len()); let number = match rest[..end].parse::<u32>() { Ok(number) => number, Err(err) => { eprintln!("{}", summary); bail!(err); } }; Ok(Some(PullRequest(number))) } fn author(mailmap: &Mailmap, commit: &Commit) -> Author { let signature = commit.author(); let name = String::from_utf8_lossy(signature.name_bytes()).into_owned(); let email = String::from_utf8_lossy(signature.email_bytes()).into_owned(); mailmap.canonicalize(&Author { name, email }) } #[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq)] struct PullRequest(u32); impl Debug for PullRequest { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { write!(formatter, "#{}", self.0) } } struct DebugSet<T>(T); impl<T> Debug for DebugSet<T> where T: Iterator + Clone, T::Item: Debug, { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.debug_set().entries(self.0.clone()).finish() } } ``` </details>
diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 0000000..307e22b --- /dev/null +++ b/.git-blame-ignore-revs
@@ -0,0 +1,6 @@ +# format the world +a06baa56b95674fc626b3c3fd680d6a65357fe60 +# format libcore +95e00bfed801e264e9c4ac817004153ca0f19eb6 +# reformat with new rustfmt +971c549ca334b7b7406e61e958efcca9c4152822
diff --git a/Cargo.lock b/Cargo.lock index 80f0a0b..bdfb517 100644 --- a/Cargo.lock +++ b/Cargo.lock
@@ -1239,6 +1239,40 @@ ] [[package]] +name = "fluent-bundle" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e242c601dec9711505f6d5bbff5bedd4b61b2469f2e8bb8e57ee7c9747a87ffd" +dependencies = [ + "fluent-langneg", + "fluent-syntax", + "intl-memoizer", + "intl_pluralrules", + "rustc-hash", + "self_cell", + "smallvec", + "unic-langid", +] + +[[package]] +name = "fluent-langneg" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c4ad0989667548f06ccd0e306ed56b61bd4d35458d54df5ec7587c0e8ed5e94" +dependencies = [ + "unic-langid", +] + +[[package]] +name = "fluent-syntax" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0abed97648395c902868fee9026de96483933faa54ea3b40d652f7dfe61ca78" +dependencies = [ + "thiserror", +] + +[[package]] name = "fnv" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1783,6 +1817,26 @@ ] [[package]] +name = "intl-memoizer" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c310433e4a310918d6ed9243542a6b83ec1183df95dff8f23f87bb88a264a66f" +dependencies = [ + "type-map", + "unic-langid", +] + +[[package]] +name = "intl_pluralrules" +version = "7.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b18f988384267d7066cc2be425e6faf352900652c046b6971d2e228d3b1c5ecf" +dependencies = [ + "tinystr", + "unic-langid", +] + +[[package]] name = "itertools" version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1965,9 +2019,9 @@ [[package]] name = "libc" -version = "0.2.116" +version = "0.2.121" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "565dbd88872dbe4cc8a46e527f26483c1d1f7afa6b884a3bd6cd893d4f98da74" +checksum = "efaa7b300f3b5fe8eb6bf21ce3895e1751d9665086af2d64b42f19701015ff4f" dependencies = [ "rustc-std-workspace-core", ] @@ -2813,6 +2867,12 @@ ] [[package]] +name = "proc-macro-hack" +version = "0.5.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" + +[[package]] name = "proc-macro2" version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -3646,12 +3706,28 @@ version = "0.0.0" [[package]] +name = "rustc_error_messages" +version = "0.0.0" +dependencies = [ + "fluent-bundle", + "fluent-syntax", + "intl-memoizer", + "rustc_data_structures", + "rustc_macros", + "rustc_serialize", + "rustc_span", + "tracing", + "unic-langid", +] + +[[package]] name = "rustc_errors" version = "0.0.0" dependencies = [ "annotate-snippets", "atty", "rustc_data_structures", + "rustc_error_messages", "rustc_lint_defs", "rustc_macros", "rustc_serialize", @@ -3708,6 +3784,7 @@ "odht", "rustc_ast", "rustc_data_structures", + "rustc_error_messages", "rustc_feature", "rustc_index", "rustc_macros", @@ -3864,6 +3941,7 @@ dependencies = [ "rustc_ast", "rustc_data_structures", + "rustc_error_messages", "rustc_hir", "rustc_macros", "rustc_serialize", @@ -4574,6 +4652,12 @@ ] [[package]] +name = "self_cell" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ef965a420fe14fdac7dd018862966a4c14094f900e1650bbc71ddd7d580c8af" + +[[package]] name = "semver" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -5105,6 +5189,12 @@ ] [[package]] +name = "tinystr" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29738eedb4388d9ea620eeab9384884fc3f06f586a2eddb56bedc5885126c7c1" + +[[package]] name = "tinyvec" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -5263,6 +5353,15 @@ ] [[package]] +name = "type-map" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d3364c5e96cb2ad1603037ab253ddd34d7fb72a58bdddf4b7350760fc69a46" +dependencies = [ + "rustc-hash", +] + +[[package]] name = "typenum" version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -5317,6 +5416,49 @@ ] [[package]] +name = "unic-langid" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73328fcd730a030bdb19ddf23e192187a6b01cd98be6d3140622a89129459ce5" +dependencies = [ + "unic-langid-impl", + "unic-langid-macros", +] + +[[package]] +name = "unic-langid-impl" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a4a8eeaf0494862c1404c95ec2f4c33a2acff5076f64314b465e3ddae1b934d" +dependencies = [ + "tinystr", +] + +[[package]] +name = "unic-langid-macros" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18f980d6d87e8805f2836d64b4138cc95aa7986fa63b1f51f67d5fbff64dd6e5" +dependencies = [ + "proc-macro-hack", + "tinystr", + "unic-langid-impl", + "unic-langid-macros-impl", +] + +[[package]] +name = "unic-langid-macros-impl" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29396ffd97e27574c3e01368b1a64267d3064969e4848e2e130ff668be9daa9f" +dependencies = [ + "proc-macro-hack", + "quote", + "syn", + "unic-langid-impl", +] + +[[package]] name = "unic-ucd-version" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/RELEASES.md b/RELEASES.md index 08040f4..0965e37 100644 --- a/RELEASES.md +++ b/RELEASES.md
@@ -1,3 +1,158 @@ +Version 1.60.0 (2022-04-07) +========================== + +Language +-------- +- [Stabilize `#[cfg(panic = "...")]` for either `"unwind"` or `"abort"`.][93658] +- [Stabilize `#[cfg(target_has_atomic = "...")]` for each integer size and `"ptr"`.][93824] + +Compiler +-------- +- [Enable combining `+crt-static` and `relocation-model=pic` on `x86_64-unknown-linux-gnu`][86374] +- [Fixes wrong `unreachable_pub` lints on nested and glob public reexport][87487] +- [Stabilize `-Z instrument-coverage` as `-C instrument-coverage`][90132] +- [Stabilize `-Z print-link-args` as `--print link-args`][91606] +- [Add new Tier 3 target `mips64-openwrt-linux-musl`\*][92300] +- [Add new Tier 3 target `armv7-unknown-linux-uclibceabi` (softfloat)\*][92383] +- [Fix invalid removal of newlines from doc comments][92357] +- [Add kernel target for RustyHermit][92670] +- [Deny mixing bin crate type with lib crate types][92933] +- [Make rustc use `RUST_BACKTRACE=full` by default][93566] +- [Upgrade to LLVM 14][93577] + +\* Refer to Rust's [platform support page][platform-support-doc] for more + information on Rust's tiered platform support. + +Libraries +--------- +- [Guarantee call order for `sort_by_cached_key`][89621] +- [Improve `Duration::try_from_secs_f32`/`f64` accuracy by directly processing exponent and mantissa][90247] +- [Make `Instant::{duration_since, elapsed, sub}` saturating][89926] +- [Remove non-monotonic clocks workarounds in `Instant::now`][89926] +- [Make `BuildHasherDefault`, `iter::Empty` and `future::Pending` covariant][92630] + +Stabilized APIs +--------------- +- [`Arc::new_cyclic`][arc_new_cyclic] +- [`Rc::new_cyclic`][rc_new_cyclic] +- [`slice::EscapeAscii`][slice_escape_ascii] +- [`<[u8]>::escape_ascii`][slice_u8_escape_ascii] +- [`u8::escape_ascii`][u8_escape_ascii] +- [`Vec::spare_capacity_mut`][vec_spare_capacity_mut] +- [`MaybeUninit::assume_init_drop`][assume_init_drop] +- [`MaybeUninit::assume_init_read`][assume_init_read] +- [`i8::abs_diff`][i8_abs_diff] +- [`i16::abs_diff`][i16_abs_diff] +- [`i32::abs_diff`][i32_abs_diff] +- [`i64::abs_diff`][i64_abs_diff] +- [`i128::abs_diff`][i128_abs_diff] +- [`isize::abs_diff`][isize_abs_diff] +- [`u8::abs_diff`][u8_abs_diff] +- [`u16::abs_diff`][u16_abs_diff] +- [`u32::abs_diff`][u32_abs_diff] +- [`u64::abs_diff`][u64_abs_diff] +- [`u128::abs_diff`][u128_abs_diff] +- [`usize::abs_diff`][usize_abs_diff] +- [`Display for io::ErrorKind`][display_error_kind] +- [`From<u8> for ExitCode`][from_u8_exit_code] +- [`Not for !` (the "never" type)][not_never] +- [_Op_`Assign<$t> for Wrapping<$t>`][wrapping_assign_ops] +- [`arch::is_aarch64_feature_detected!`][is_aarch64_feature_detected] + +Cargo +----- +- [Port cargo from `toml-rs` to `toml_edit`][cargo/10086] +- [Stabilize `-Ztimings` as `--timings`][cargo/10245] +- [Stabilize namespaced and weak dependency features.][cargo/10269] +- [Accept more `cargo:rustc-link-arg-*` types from build script output.][cargo/10274] +- [cargo-new should not add ignore rule on Cargo.lock inside subdirs][cargo/10379] + +Misc +---- +- [Ship docs on Tier 2 platforms by reusing the closest Tier 1 platform docs][92800] +- [Drop rustc-docs from complete profile][93742] +- [bootstrap: tidy up flag handling for llvm build][93918] + +Compatibility Notes +------------------- +- [Remove compiler-rt linking hack on Android][83822] +- [Mitigations for platforms with non-monotonic clocks have been removed from + `Instant::now`][89926]. On platforms that don't provide monotonic clocks, an + instant is not guaranteed to be greater than an earlier instant anymore. +- [`Instant::{duration_since, elapsed, sub}` do not panic anymore on underflow, + saturating to `0` instead][89926]. In the real world the panic happened mostly + on platforms with buggy monotonic clock implementations rather than catching + programming errors like reversing the start and end times. Such programming + errors will now results in `0` rather than a panic. +- In a future release we're planning to increase the baseline requirements for + the Linux kernel to version 3.2, and for glibc to version 2.17. We'd love + your feedback in [PR #95026][95026]. + +Internal Changes +---------------- + +These changes provide no direct user facing benefits, but represent significant +improvements to the internals and overall performance of rustc +and related tools. + +- [Switch all libraries to the 2021 edition][92068] + +[83822]: https://github.com/rust-lang/rust/pull/83822 +[86374]: https://github.com/rust-lang/rust/pull/86374 +[87487]: https://github.com/rust-lang/rust/pull/87487 +[89621]: https://github.com/rust-lang/rust/pull/89621 +[89926]: https://github.com/rust-lang/rust/pull/89926 +[90132]: https://github.com/rust-lang/rust/pull/90132 +[90247]: https://github.com/rust-lang/rust/pull/90247 +[91606]: https://github.com/rust-lang/rust/pull/91606 +[92068]: https://github.com/rust-lang/rust/pull/92068 +[92300]: https://github.com/rust-lang/rust/pull/92300 +[92357]: https://github.com/rust-lang/rust/pull/92357 +[92383]: https://github.com/rust-lang/rust/pull/92383 +[92630]: https://github.com/rust-lang/rust/pull/92630 +[92670]: https://github.com/rust-lang/rust/pull/92670 +[92800]: https://github.com/rust-lang/rust/pull/92800 +[92933]: https://github.com/rust-lang/rust/pull/92933 +[93566]: https://github.com/rust-lang/rust/pull/93566 +[93577]: https://github.com/rust-lang/rust/pull/93577 +[93658]: https://github.com/rust-lang/rust/pull/93658 +[93742]: https://github.com/rust-lang/rust/pull/93742 +[93824]: https://github.com/rust-lang/rust/pull/93824 +[93918]: https://github.com/rust-lang/rust/pull/93918 +[95026]: https://github.com/rust-lang/rust/pull/95026 + +[cargo/10086]: https://github.com/rust-lang/cargo/pull/10086 +[cargo/10245]: https://github.com/rust-lang/cargo/pull/10245 +[cargo/10269]: https://github.com/rust-lang/cargo/pull/10269 +[cargo/10274]: https://github.com/rust-lang/cargo/pull/10274 +[cargo/10379]: https://github.com/rust-lang/cargo/pull/10379 + +[arc_new_cyclic]: https://doc.rust-lang.org/stable/std/sync/struct.Arc.html#method.new_cyclic +[rc_new_cyclic]: https://doc.rust-lang.org/stable/std/rc/struct.Rc.html#method.new_cyclic +[slice_escape_ascii]: https://doc.rust-lang.org/stable/std/slice/struct.EscapeAscii.html +[slice_u8_escape_ascii]: https://doc.rust-lang.org/stable/std/primitive.slice.html#method.escape_ascii +[u8_escape_ascii]: https://doc.rust-lang.org/stable/std/primitive.u8.html#method.escape_ascii +[vec_spare_capacity_mut]: https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#method.spare_capacity_mut +[assume_init_drop]: https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#method.assume_init_drop +[assume_init_read]: https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#method.assume_init_read +[i8_abs_diff]: https://doc.rust-lang.org/stable/std/primitive.i8.html#method.abs_diff +[i16_abs_diff]: https://doc.rust-lang.org/stable/std/primitive.i16.html#method.abs_diff +[i32_abs_diff]: https://doc.rust-lang.org/stable/std/primitive.i32.html#method.abs_diff +[i64_abs_diff]: https://doc.rust-lang.org/stable/std/primitive.i64.html#method.abs_diff +[i128_abs_diff]: https://doc.rust-lang.org/stable/std/primitive.i128.html#method.abs_diff +[isize_abs_diff]: https://doc.rust-lang.org/stable/std/primitive.isize.html#method.abs_diff +[u8_abs_diff]: https://doc.rust-lang.org/stable/std/primitive.u8.html#method.abs_diff +[u16_abs_diff]: https://doc.rust-lang.org/stable/std/primitive.u16.html#method.abs_diff +[u32_abs_diff]: https://doc.rust-lang.org/stable/std/primitive.u32.html#method.abs_diff +[u64_abs_diff]: https://doc.rust-lang.org/stable/std/primitive.u64.html#method.abs_diff +[u128_abs_diff]: https://doc.rust-lang.org/stable/std/primitive.u128.html#method.abs_diff +[usize_abs_diff]: https://doc.rust-lang.org/stable/std/primitive.usize.html#method.abs_diff +[display_error_kind]: https://doc.rust-lang.org/stable/std/io/enum.ErrorKind.html#impl-Display +[from_u8_exit_code]: https://doc.rust-lang.org/stable/std/process/struct.ExitCode.html#impl-From%3Cu8%3E +[not_never]: https://doc.rust-lang.org/stable/std/primitive.never.html#impl-Not +[wrapping_assign_ops]: https://doc.rust-lang.org/stable/std/num/struct.Wrapping.html#trait-implementations +[is_aarch64_feature_detected]: https://doc.rust-lang.org/stable/std/arch/macro.is_aarch64_feature_detected.html + Version 1.59.0 (2022-02-24) ==========================
diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs index 550c66e..80caf37 100644 --- a/compiler/rustc_ast/src/attr/mod.rs +++ b/compiler/rustc_ast/src/attr/mod.rs
@@ -439,7 +439,7 @@ fn from_tokens<I>(tokens: &mut iter::Peekable<I>) -> Option<MetaItem> } Some(TokenTree::Token(Token { kind: token::Interpolated(nt), .. })) => match *nt { token::Nonterminal::NtMeta(ref item) => return item.meta(item.path.span), - token::Nonterminal::NtPath(ref path) => path.clone(), + token::Nonterminal::NtPath(ref path) => (**path).clone(), _ => return None, }, _ => return None,
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 32621eb..15f7ace 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -772,7 +772,9 @@ pub fn visit_interpolated<T: MutVisitor>(nt: &mut token::Nonterminal, vis: &mut token::NtBlock(block) => vis.visit_block(block), token::NtStmt(stmt) => visit_clobber(stmt, |stmt| { // See reasoning above. - vis.flat_map_stmt(stmt).expect_one("expected visitor to produce exactly one item") + stmt.map(|stmt| { + vis.flat_map_stmt(stmt).expect_one("expected visitor to produce exactly one item") + }) }), token::NtPat(pat) => vis.visit_pat(pat), token::NtExpr(expr) => vis.visit_expr(expr),
diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 2132cdf..031c6ca 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs
@@ -668,7 +668,7 @@ fn eq(&self, rhs: &TokenKind) -> bool { pub enum Nonterminal { NtItem(P<ast::Item>), NtBlock(P<ast::Block>), - NtStmt(ast::Stmt), + NtStmt(P<ast::Stmt>), NtPat(P<ast::Pat>), NtExpr(P<ast::Expr>), NtTy(P<ast::Ty>), @@ -677,13 +677,13 @@ pub enum Nonterminal { NtLiteral(P<ast::Expr>), /// Stuff inside brackets for attributes NtMeta(P<ast::AttrItem>), - NtPath(ast::Path), - NtVis(ast::Visibility), + NtPath(P<ast::Path>), + NtVis(P<ast::Visibility>), } // `Nonterminal` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(Nonterminal, 48); +rustc_data_structures::static_assert_size!(Nonterminal, 16); #[derive(Debug, Copy, Clone, PartialEq, Encodable, Decodable)] pub enum NonterminalKind {
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index e4ed48d..e7e82e6 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -2068,7 +2068,7 @@ fn lower_generic_param( hir::GenericParam { hir_id, name, - span: self.lower_span(param.ident.span), + span: self.lower_span(param.span()), pure_wrt_drop: self.sess.contains_name(¶m.attrs, sym::may_dangle), bounds: self.arena.alloc_from_iter(bounds), kind,
diff --git a/compiler/rustc_borrowck/src/borrowck_errors.rs b/compiler/rustc_borrowck/src/borrowck_errors.rs index 21b582e..70f7f1e 100644 --- a/compiler/rustc_borrowck/src/borrowck_errors.rs +++ b/compiler/rustc_borrowck/src/borrowck_errors.rs
@@ -1,6 +1,6 @@ -use rustc_errors::{struct_span_err, DiagnosticBuilder, DiagnosticId, ErrorGuaranteed}; +use rustc_errors::{struct_span_err, DiagnosticBuilder, DiagnosticId, ErrorGuaranteed, MultiSpan}; use rustc_middle::ty::{self, Ty, TyCtxt}; -use rustc_span::{MultiSpan, Span}; +use rustc_span::Span; impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { crate fn cannot_move_when_borrowed(
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 883f711..b945d68 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -1,7 +1,7 @@ use either::Either; use rustc_const_eval::util::CallKind; use rustc_data_structures::fx::FxHashSet; -use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed}; +use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::{AsyncGeneratorKind, GeneratorKind}; @@ -15,7 +15,7 @@ use rustc_middle::ty::{self, subst::Subst, suggest_constraining_type_params, PredicateKind, Ty}; use rustc_mir_dataflow::move_paths::{InitKind, MoveOutIndex, MovePathIndex}; use rustc_span::symbol::sym; -use rustc_span::{BytePos, MultiSpan, Span}; +use rustc_span::{BytePos, Span}; use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::TraitEngineExt as _; @@ -772,14 +772,7 @@ pub(crate) fn report_conflicting_borrow( Some((issued_span, span)), ); - self.suggest_using_local_if_applicable( - &mut err, - location, - (place, span), - gen_borrow_kind, - issued_borrow, - explanation, - ); + self.suggest_using_local_if_applicable(&mut err, location, issued_borrow, explanation); err } @@ -789,8 +782,6 @@ fn suggest_using_local_if_applicable( &self, err: &mut Diagnostic, location: Location, - (place, span): (Place<'tcx>, Span), - gen_borrow_kind: BorrowKind, issued_borrow: &BorrowData<'tcx>, explanation: BorrowExplanation, ) { @@ -822,7 +813,7 @@ fn suggest_using_local_if_applicable( return; }; let inner_param_uses = find_all_local_uses::find(self.body, inner_param.local); - let Some((inner_call_loc,inner_call_term)) = inner_param_uses.into_iter().find_map(|loc| { + let Some((inner_call_loc, inner_call_term)) = inner_param_uses.into_iter().find_map(|loc| { let Either::Right(term) = self.body.stmt_at(loc) else { debug!("{:?} is a statement, so it can't be a call", loc); return None; @@ -833,7 +824,7 @@ fn suggest_using_local_if_applicable( }; debug!("checking call args for uses of inner_param: {:?}", args); if args.contains(&Operand::Move(inner_param)) { - Some((loc,term)) + Some((loc, term)) } else { None }
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index e63450a..1798c52 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
@@ -330,14 +330,14 @@ pub(crate) fn report_region_error( ty::RawPtr(ty_mut) => { assert_eq!(ty_mut.mutbl, rustc_hir::Mutability::Mut); ( - format!("a mutable pointer to {}", ty_mut.ty), + format!("a mutable pointer to `{}`", ty_mut.ty), "mutable pointers are invariant over their type parameter".to_string(), ) } ty::Ref(_, inner_ty, mutbl) => { assert_eq!(*mutbl, rustc_hir::Mutability::Mut); ( - format!("a mutable reference to {}", inner_ty), + format!("a mutable reference to `{}`", inner_ty), "mutable references are invariant over their type parameter" .to_string(), ) @@ -351,10 +351,21 @@ pub(crate) fn report_region_error( let adt_desc = adt.descr(); let desc = format!( - "the type {ty}, which makes the generic argument {generic_arg} invariant" + "the type `{ty}`, which makes the generic argument `{generic_arg}` invariant" ); let note = format!( - "the {adt_desc} {base_ty} is invariant over the parameter {base_generic_arg}" + "the {adt_desc} `{base_ty}` is invariant over the parameter `{base_generic_arg}`" + ); + (desc, note) + } + ty::FnDef(def_id, _) => { + let name = self.infcx.tcx.item_name(*def_id); + let identity_substs = + InternalSubsts::identity_for_item(self.infcx.tcx, *def_id); + let desc = format!("a function pointer to `{name}`"); + let note = format!( + "the function `{name}` is invariant over the parameter `{}`", + identity_substs[param_index as usize] ); (desc, note) }
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index c939549..723adb8 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
@@ -109,7 +109,7 @@ impl RegionName { *span, format!("lifetime `{}` represents this closure's body", self), ); - diag.note(¬e); + diag.note(note); } RegionNameSource::AnonRegionFromArgument(RegionNameHighlight::CannotMatchHirTy( span,
diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index 9242c6a..927eb08 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs
@@ -1,6 +1,7 @@ //! The entry point of the NLL borrow checker. use rustc_data_structures::vec_map::VecMap; +use rustc_hir::def_id::DefId; use rustc_index::vec::IndexVec; use rustc_infer::infer::InferCtxt; use rustc_middle::mir::{create_dump_file, dump_enabled, dump_mir, PassWhere}; @@ -8,7 +9,7 @@ BasicBlock, Body, ClosureOutlivesSubject, ClosureRegionRequirements, LocalKind, Location, Promoted, }; -use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, Region, RegionVid}; +use rustc_middle::ty::{self, OpaqueHiddenType, Region, RegionVid}; use rustc_span::symbol::sym; use std::env; use std::fmt::Debug; @@ -43,7 +44,7 @@ /// closure requirements to propagate, and any generated errors. crate struct NllOutput<'tcx> { pub regioncx: RegionInferenceContext<'tcx>, - pub opaque_type_values: VecMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>, + pub opaque_type_values: VecMap<DefId, OpaqueHiddenType<'tcx>>, pub polonius_input: Option<Box<AllFacts>>, pub polonius_output: Option<Rc<PoloniusOutput>>, pub opt_closure_req: Option<ClosureRegionRequirements<'tcx>>, @@ -372,7 +373,7 @@ pub(super) fn dump_annotation<'a, 'tcx>( body: &Body<'tcx>, regioncx: &RegionInferenceContext<'tcx>, closure_region_requirements: &Option<ClosureRegionRequirements<'_>>, - opaque_type_values: &VecMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>, + opaque_type_values: &VecMap<DefId, OpaqueHiddenType<'tcx>>, errors: &mut crate::error::BorrowckErrors<'tcx>, ) { let tcx = infcx.tcx;
diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index f454141..fa07c4f 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
@@ -1,5 +1,6 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::vec_map::VecMap; +use rustc_hir::def_id::DefId; use rustc_hir::OpaqueTyOrigin; use rustc_infer::infer::InferCtxt; use rustc_middle::ty::subst::GenericArgKind; @@ -54,76 +55,97 @@ pub(crate) fn infer_opaque_types( &self, infcx: &InferCtxt<'_, 'tcx>, opaque_ty_decls: VecMap<OpaqueTypeKey<'tcx>, (OpaqueHiddenType<'tcx>, OpaqueTyOrigin)>, - ) -> VecMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>> { - opaque_ty_decls - .into_iter() - .map(|(opaque_type_key, (concrete_type, origin))| { - let substs = opaque_type_key.substs; - debug!(?concrete_type, ?substs); + ) -> VecMap<DefId, OpaqueHiddenType<'tcx>> { + let mut result: VecMap<DefId, OpaqueHiddenType<'tcx>> = VecMap::new(); + for (opaque_type_key, (concrete_type, origin)) in opaque_ty_decls { + let substs = opaque_type_key.substs; + debug!(?concrete_type, ?substs); - let mut subst_regions = vec![self.universal_regions.fr_static]; - let universal_substs = infcx.tcx.fold_regions(substs, &mut false, |region, _| { - if let ty::RePlaceholder(..) = region.kind() { - // Higher kinded regions don't need remapping, they don't refer to anything outside of this the substs. - return region; + let mut subst_regions = vec![self.universal_regions.fr_static]; + let universal_substs = infcx.tcx.fold_regions(substs, &mut false, |region, _| { + if let ty::RePlaceholder(..) = region.kind() { + // Higher kinded regions don't need remapping, they don't refer to anything outside of this the substs. + return region; + } + let vid = self.to_region_vid(region); + trace!(?vid); + let scc = self.constraint_sccs.scc(vid); + trace!(?scc); + match self.scc_values.universal_regions_outlived_by(scc).find_map(|lb| { + self.eval_equal(vid, lb).then_some(self.definitions[lb].external_name?) + }) { + Some(region) => { + let vid = self.universal_regions.to_region_vid(region); + subst_regions.push(vid); + region } - let vid = self.to_region_vid(region); - trace!(?vid); - let scc = self.constraint_sccs.scc(vid); - trace!(?scc); - match self.scc_values.universal_regions_outlived_by(scc).find_map(|lb| { - self.eval_equal(vid, lb).then_some(self.definitions[lb].external_name?) - }) { - Some(region) => { - let vid = self.universal_regions.to_region_vid(region); - subst_regions.push(vid); - region - } - None => { - subst_regions.push(vid); - infcx.tcx.sess.delay_span_bug( - concrete_type.span, - "opaque type with non-universal region substs", - ); - infcx.tcx.lifetimes.re_static - } + None => { + subst_regions.push(vid); + infcx.tcx.sess.delay_span_bug( + concrete_type.span, + "opaque type with non-universal region substs", + ); + infcx.tcx.lifetimes.re_static } + } + }); + + subst_regions.sort(); + subst_regions.dedup(); + + let universal_concrete_type = + infcx.tcx.fold_regions(concrete_type, &mut false, |region, _| match *region { + ty::ReVar(vid) => subst_regions + .iter() + .find(|ur_vid| self.eval_equal(vid, **ur_vid)) + .and_then(|ur_vid| self.definitions[*ur_vid].external_name) + .unwrap_or(infcx.tcx.lifetimes.re_root_empty), + _ => region, }); - subst_regions.sort(); - subst_regions.dedup(); + debug!(?universal_concrete_type, ?universal_substs); - let universal_concrete_type = - infcx.tcx.fold_regions(concrete_type, &mut false, |region, _| match *region { - ty::ReVar(vid) => subst_regions - .iter() - .find(|ur_vid| self.eval_equal(vid, **ur_vid)) - .and_then(|ur_vid| self.definitions[*ur_vid].external_name) - .unwrap_or(infcx.tcx.lifetimes.re_root_empty), - _ => region, - }); - - debug!(?universal_concrete_type, ?universal_substs); - - let opaque_type_key = - OpaqueTypeKey { def_id: opaque_type_key.def_id, substs: universal_substs }; - let remapped_type = infcx.infer_opaque_definition_from_instantiation( - opaque_type_key, - universal_concrete_type, + let opaque_type_key = + OpaqueTypeKey { def_id: opaque_type_key.def_id, substs: universal_substs }; + let remapped_type = infcx.infer_opaque_definition_from_instantiation( + opaque_type_key, + universal_concrete_type, + ); + let ty = if check_opaque_type_parameter_valid( + infcx.tcx, + opaque_type_key, + origin, + concrete_type.span, + ) { + remapped_type + } else { + infcx.tcx.ty_error() + }; + // Sometimes two opaque types are the same only after we remap the generic parameters + // back to the opaque type definition. E.g. we may have `OpaqueType<X, Y>` mapped to `(X, Y)` + // and `OpaqueType<Y, X>` mapped to `(Y, X)`, and those are the same, but we only know that + // once we convert the generic parameters to those of the opaque type. + if let Some(prev) = result.get_mut(&opaque_type_key.def_id) { + if prev.ty != ty { + if !ty.references_error() { + prev.report_mismatch( + &OpaqueHiddenType { ty, span: concrete_type.span }, + infcx.tcx, + ); + } + prev.ty = infcx.tcx.ty_error(); + } + // Pick a better span if there is one. + // FIXME(oli-obk): collect multiple spans for better diagnostics down the road. + prev.span = prev.span.substitute_dummy(concrete_type.span); + } else { + result.insert( + opaque_type_key.def_id, + OpaqueHiddenType { ty, span: concrete_type.span }, ); - let ty = if check_opaque_type_parameter_valid( - infcx.tcx, - opaque_type_key, - origin, - concrete_type.span, - ) { - remapped_type - } else { - infcx.tcx.ty_error() - }; - (opaque_type_key, OpaqueHiddenType { ty, span: concrete_type.span }) - }) - .collect() + } + } + result } /// Map the regions in the type to named regions. This is similar to what
diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs index 3121341..138e1fa 100644 --- a/compiler/rustc_builtin_macros/src/format.rs +++ b/compiler/rustc_builtin_macros/src/format.rs
@@ -7,11 +7,11 @@ use rustc_ast::visit::{self, Visitor}; use rustc_ast::{token, BlockCheckMode, UnsafeSource}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_errors::{pluralize, Applicability, PResult}; +use rustc_errors::{pluralize, Applicability, MultiSpan, PResult}; use rustc_expand::base::{self, *}; use rustc_parse_format as parse; use rustc_span::symbol::{sym, Ident, Symbol}; -use rustc_span::{InnerSpan, MultiSpan, Span}; +use rustc_span::{InnerSpan, Span}; use smallvec::SmallVec; use std::borrow::Cow; @@ -446,7 +446,9 @@ fn report_invalid_references(&self, numbered_position_args: bool) { .iter() .filter(|fmt| fmt.precision_span.is_some()) .count(); - e.span_label(span, &format!( + e.span_label( + span, + &format!( "this precision flag adds an extra required argument at position {}, \ which is why there {} expected", pos, @@ -455,7 +457,8 @@ fn report_invalid_references(&self, numbered_position_args: bool) { } else { format!("are {} arguments", count) }, - )); + ), + ); if let Some(arg) = self.args.get(pos) { e.span_label( arg.span,
diff --git a/compiler/rustc_builtin_macros/src/source_util.rs b/compiler/rustc_builtin_macros/src/source_util.rs index be628c9..ece250f 100644 --- a/compiler/rustc_builtin_macros/src/source_util.rs +++ b/compiler/rustc_builtin_macros/src/source_util.rs
@@ -141,7 +141,7 @@ fn make_expr(mut self: Box<ExpandResult<'a>>) -> Option<P<ast::Expr>> { fn make_items(mut self: Box<ExpandResult<'a>>) -> Option<SmallVec<[P<ast::Item>; 1]>> { let mut ret = SmallVec::new(); - while self.p.token != token::Eof { + loop { match self.p.parse_item(ForceCollect::No) { Err(mut err) => { err.emit(); @@ -149,9 +149,12 @@ fn make_expr(mut self: Box<ExpandResult<'a>>) -> Option<P<ast::Expr>> { } Ok(Some(item)) => ret.push(item), Ok(None) => { - let token = pprust::token_to_string(&self.p.token); - let msg = format!("expected item, found `{}`", token); - self.p.struct_span_err(self.p.token.span, &msg).emit(); + if self.p.token != token::Eof { + let token = pprust::token_to_string(&self.p.token); + let msg = format!("expected item, found `{}`", token); + self.p.struct_span_err(self.p.token.span, &msg).emit(); + } + break; } }
diff --git a/compiler/rustc_codegen_cranelift/src/common.rs b/compiler/rustc_codegen_cranelift/src/common.rs index 89fd0bf..ffa629c 100644 --- a/compiler/rustc_codegen_cranelift/src/common.rs +++ b/compiler/rustc_codegen_cranelift/src/common.rs
@@ -21,7 +21,7 @@ pub(crate) fn pointer_ty(tcx: TyCtxt<'_>) -> types::Type { } pub(crate) fn scalar_to_clif_type(tcx: TyCtxt<'_>, scalar: Scalar) -> Type { - match scalar.value { + match scalar.primitive() { Primitive::Int(int, _sign) => match int { Integer::I8 => types::I8, Integer::I16 => types::I16,
diff --git a/compiler/rustc_codegen_cranelift/src/discriminant.rs b/compiler/rustc_codegen_cranelift/src/discriminant.rs index 6b2893f..357cb4a 100644 --- a/compiler/rustc_codegen_cranelift/src/discriminant.rs +++ b/compiler/rustc_codegen_cranelift/src/discriminant.rs
@@ -105,7 +105,7 @@ pub(crate) fn codegen_get_discriminant<'tcx>( // Decode the discriminant (specifically if it's niche-encoded). match *tag_encoding { TagEncoding::Direct => { - let signed = match tag_scalar.value { + let signed = match tag_scalar.primitive() { Int(_, signed) => signed, _ => false, };
diff --git a/compiler/rustc_codegen_cranelift/src/value_and_place.rs b/compiler/rustc_codegen_cranelift/src/value_and_place.rs index afe8797..8f80b02 100644 --- a/compiler/rustc_codegen_cranelift/src/value_and_place.rs +++ b/compiler/rustc_codegen_cranelift/src/value_and_place.rs
@@ -50,7 +50,7 @@ fn codegen_field<'tcx>( } fn scalar_pair_calculate_b_offset(tcx: TyCtxt<'_>, a_scalar: Scalar, b_scalar: Scalar) -> Offset32 { - let b_offset = a_scalar.value.size(&tcx).align_to(b_scalar.value.align(&tcx).abi); + let b_offset = a_scalar.size(&tcx).align_to(b_scalar.align(&tcx).abi); Offset32::new(b_offset.bytes().try_into().unwrap()) }
diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs index 21c7d42..41f88f1 100644 --- a/compiler/rustc_codegen_gcc/src/builder.rs +++ b/compiler/rustc_codegen_gcc/src/builder.rs
@@ -694,11 +694,11 @@ fn load_operand(&mut self, place: PlaceRef<'tcx, RValue<'gcc>>) -> OperandRef<'t } fn scalar_load_metadata<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>, load: RValue<'gcc>, scalar: &abi::Scalar) { - let vr = scalar.valid_range.clone(); - match scalar.value { + let vr = scalar.valid_range(bx); + match scalar.primitive() { abi::Int(..) => { if !scalar.is_always_valid(bx) { - bx.range_metadata(load, scalar.valid_range); + bx.range_metadata(load, vr); } } abi::Pointer if vr.start < vr.end && !vr.contains(0) => { @@ -720,7 +720,7 @@ fn scalar_load_metadata<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>, load: OperandValue::Immediate(self.to_immediate(load, place.layout)) } else if let abi::Abi::ScalarPair(ref a, ref b) = place.layout.abi { - let b_offset = a.value.size(self).align_to(b.value.align(self).abi); + let b_offset = a.size(self).align_to(b.align(self).abi); let pair_type = place.layout.gcc_type(self, false); let mut load = |i, scalar: &abi::Scalar, align| {
diff --git a/compiler/rustc_codegen_gcc/src/common.rs b/compiler/rustc_codegen_gcc/src/common.rs index 19127c7..b056b6d 100644 --- a/compiler/rustc_codegen_gcc/src/common.rs +++ b/compiler/rustc_codegen_gcc/src/common.rs
@@ -158,14 +158,14 @@ fn const_to_opt_u128(&self, _v: RValue<'gcc>, _sign_ext: bool) -> Option<u128> { } fn scalar_to_backend(&self, cv: Scalar, layout: abi::Scalar, ty: Type<'gcc>) -> RValue<'gcc> { - let bitsize = if layout.is_bool() { 1 } else { layout.value.size(self).bits() }; + let bitsize = if layout.is_bool() { 1 } else { layout.size(self).bits() }; match cv { Scalar::Int(ScalarInt::ZST) => { - assert_eq!(0, layout.value.size(self).bytes()); + assert_eq!(0, layout.size(self).bytes()); self.const_undef(self.type_ix(0)) } Scalar::Int(int) => { - let data = int.assert_bits(layout.value.size(self)); + let data = int.assert_bits(layout.size(self)); // FIXME(antoyo): there's some issues with using the u128 code that follows, so hard-code // the paths for floating-point values. @@ -209,7 +209,7 @@ fn scalar_to_backend(&self, cv: Scalar, layout: abi::Scalar, ty: Type<'gcc>) -> let base_addr = self.const_bitcast(base_addr, self.usize_type); let offset = self.context.new_rvalue_from_long(self.usize_type, offset.bytes() as i64); let ptr = self.const_bitcast(base_addr + offset, ptr_type); - if layout.value != Pointer { + if layout.primitive() != Pointer { self.const_bitcast(ptr.dereference(None).to_rvalue(), ty) } else {
diff --git a/compiler/rustc_codegen_gcc/src/consts.rs b/compiler/rustc_codegen_gcc/src/consts.rs index de52f3e..3dc456f 100644 --- a/compiler/rustc_codegen_gcc/src/consts.rs +++ b/compiler/rustc_codegen_gcc/src/consts.rs
@@ -328,7 +328,7 @@ pub fn const_alloc_to_gcc<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, alloc: ConstAl interpret::Pointer::new(alloc_id, Size::from_bytes(ptr_offset)), &cx.tcx, ), - abi::Scalar { value: Primitive::Pointer, valid_range: WrappingRange { start: 0, end: !0 } }, + abi::Scalar::Initialized { value: Primitive::Pointer, valid_range: WrappingRange::full(dl.pointer_size) }, cx.type_i8p(), )); next_offset = offset + pointer_size;
diff --git a/compiler/rustc_codegen_gcc/src/type_of.rs b/compiler/rustc_codegen_gcc/src/type_of.rs index ed8f044..2c042ba 100644 --- a/compiler/rustc_codegen_gcc/src/type_of.rs +++ b/compiler/rustc_codegen_gcc/src/type_of.rs
@@ -224,7 +224,7 @@ fn immediate_gcc_type<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc> { } fn scalar_gcc_type_at<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>, scalar: &abi::Scalar, offset: Size) -> Type<'gcc> { - match scalar.value { + match scalar.primitive() { Int(i, true) => cx.type_from_integer(i), Int(i, false) => cx.type_from_unsigned_integer(i), F32 => cx.type_f32(), @@ -282,7 +282,7 @@ fn scalar_pair_element_gcc_type<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>, index: Size::ZERO } else { - a.value.size(cx).align_to(b.value.align(cx).abi) + a.size(cx).align_to(b.align(cx).abi) }; self.scalar_gcc_type_at(cx, scalar, offset) }
diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs index b14a4f2..b9baa87 100644 --- a/compiler/rustc_codegen_llvm/src/abi.rs +++ b/compiler/rustc_codegen_llvm/src/abi.rs
@@ -510,9 +510,9 @@ fn apply_attrs_callsite(&self, bx: &mut Builder<'_, 'll, 'tcx>, callsite: &'ll V // If the value is a boolean, the range is 0..2 and that ultimately // become 0..0 when the type becomes i1, which would be rejected // by the LLVM verifier. - if let Int(..) = scalar.value { + if let Int(..) = scalar.primitive() { if !scalar.is_bool() && !scalar.is_always_valid(bx) { - bx.range_metadata(callsite, scalar.valid_range); + bx.range_metadata(callsite, scalar.valid_range(bx)); } } }
diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index 96c7d88..03c390b 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs
@@ -753,7 +753,7 @@ fn dummy_output_type<'ll>(cx: &CodegenCx<'ll, '_>, reg: InlineAsmRegClass) -> &' /// Helper function to get the LLVM type for a Scalar. Pointers are returned as /// the equivalent integer type. fn llvm_asm_scalar_type<'ll>(cx: &CodegenCx<'ll, '_>, scalar: Scalar) -> &'ll Type { - match scalar.value { + match scalar.primitive() { Primitive::Int(Integer::I8, _) => cx.type_i8(), Primitive::Int(Integer::I16, _) => cx.type_i16(), Primitive::Int(Integer::I32, _) => cx.type_i32(), @@ -774,7 +774,7 @@ fn llvm_fixup_input<'ll, 'tcx>( ) -> &'ll Value { match (reg, layout.abi) { (InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg), Abi::Scalar(s)) => { - if let Primitive::Int(Integer::I8, _) = s.value { + if let Primitive::Int(Integer::I8, _) = s.primitive() { let vec_ty = bx.cx.type_vector(bx.cx.type_i8(), 8); bx.insert_element(bx.const_undef(vec_ty), value, bx.const_i32(0)) } else { @@ -785,7 +785,7 @@ fn llvm_fixup_input<'ll, 'tcx>( let elem_ty = llvm_asm_scalar_type(bx.cx, s); let count = 16 / layout.size.bytes(); let vec_ty = bx.cx.type_vector(elem_ty, count); - if let Primitive::Pointer = s.value { + if let Primitive::Pointer = s.primitive() { value = bx.ptrtoint(value, bx.cx.type_isize()); } bx.insert_element(bx.const_undef(vec_ty), value, bx.const_i32(0)) @@ -800,7 +800,7 @@ fn llvm_fixup_input<'ll, 'tcx>( bx.shuffle_vector(value, bx.const_undef(vec_ty), bx.const_vector(&indices)) } (InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd), Abi::Scalar(s)) - if s.value == Primitive::F64 => + if s.primitive() == Primitive::F64 => { bx.bitcast(value, bx.cx.type_i64()) } @@ -812,7 +812,7 @@ fn llvm_fixup_input<'ll, 'tcx>( InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg | ArmInlineAsmRegClass::sreg_low16), Abi::Scalar(s), ) => { - if let Primitive::Int(Integer::I32, _) = s.value { + if let Primitive::Int(Integer::I32, _) = s.primitive() { bx.bitcast(value, bx.cx.type_f32()) } else { value @@ -826,19 +826,21 @@ fn llvm_fixup_input<'ll, 'tcx>( ), Abi::Scalar(s), ) => { - if let Primitive::Int(Integer::I64, _) = s.value { + if let Primitive::Int(Integer::I64, _) = s.primitive() { bx.bitcast(value, bx.cx.type_f64()) } else { value } } - (InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg), Abi::Scalar(s)) => match s.value { - // MIPS only supports register-length arithmetics. - Primitive::Int(Integer::I8 | Integer::I16, _) => bx.zext(value, bx.cx.type_i32()), - Primitive::F32 => bx.bitcast(value, bx.cx.type_i32()), - Primitive::F64 => bx.bitcast(value, bx.cx.type_i64()), - _ => value, - }, + (InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg), Abi::Scalar(s)) => { + match s.primitive() { + // MIPS only supports register-length arithmetics. + Primitive::Int(Integer::I8 | Integer::I16, _) => bx.zext(value, bx.cx.type_i32()), + Primitive::F32 => bx.bitcast(value, bx.cx.type_i32()), + Primitive::F64 => bx.bitcast(value, bx.cx.type_i64()), + _ => value, + } + } _ => value, } } @@ -852,7 +854,7 @@ fn llvm_fixup_output<'ll, 'tcx>( ) -> &'ll Value { match (reg, layout.abi) { (InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg), Abi::Scalar(s)) => { - if let Primitive::Int(Integer::I8, _) = s.value { + if let Primitive::Int(Integer::I8, _) = s.primitive() { bx.extract_element(value, bx.const_i32(0)) } else { value @@ -860,7 +862,7 @@ fn llvm_fixup_output<'ll, 'tcx>( } (InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16), Abi::Scalar(s)) => { value = bx.extract_element(value, bx.const_i32(0)); - if let Primitive::Pointer = s.value { + if let Primitive::Pointer = s.primitive() { value = bx.inttoptr(value, layout.llvm_type(bx.cx)); } value @@ -875,7 +877,7 @@ fn llvm_fixup_output<'ll, 'tcx>( bx.shuffle_vector(value, bx.const_undef(vec_ty), bx.const_vector(&indices)) } (InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd), Abi::Scalar(s)) - if s.value == Primitive::F64 => + if s.primitive() == Primitive::F64 => { bx.bitcast(value, bx.cx.type_f64()) } @@ -887,7 +889,7 @@ fn llvm_fixup_output<'ll, 'tcx>( InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg | ArmInlineAsmRegClass::sreg_low16), Abi::Scalar(s), ) => { - if let Primitive::Int(Integer::I32, _) = s.value { + if let Primitive::Int(Integer::I32, _) = s.primitive() { bx.bitcast(value, bx.cx.type_i32()) } else { value @@ -901,20 +903,22 @@ fn llvm_fixup_output<'ll, 'tcx>( ), Abi::Scalar(s), ) => { - if let Primitive::Int(Integer::I64, _) = s.value { + if let Primitive::Int(Integer::I64, _) = s.primitive() { bx.bitcast(value, bx.cx.type_i64()) } else { value } } - (InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg), Abi::Scalar(s)) => match s.value { - // MIPS only supports register-length arithmetics. - Primitive::Int(Integer::I8, _) => bx.trunc(value, bx.cx.type_i8()), - Primitive::Int(Integer::I16, _) => bx.trunc(value, bx.cx.type_i16()), - Primitive::F32 => bx.bitcast(value, bx.cx.type_f32()), - Primitive::F64 => bx.bitcast(value, bx.cx.type_f64()), - _ => value, - }, + (InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg), Abi::Scalar(s)) => { + match s.primitive() { + // MIPS only supports register-length arithmetics. + Primitive::Int(Integer::I8, _) => bx.trunc(value, bx.cx.type_i8()), + Primitive::Int(Integer::I16, _) => bx.trunc(value, bx.cx.type_i16()), + Primitive::F32 => bx.bitcast(value, bx.cx.type_f32()), + Primitive::F64 => bx.bitcast(value, bx.cx.type_f64()), + _ => value, + } + } _ => value, } } @@ -927,7 +931,7 @@ fn llvm_fixup_output_type<'ll, 'tcx>( ) -> &'ll Type { match (reg, layout.abi) { (InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg), Abi::Scalar(s)) => { - if let Primitive::Int(Integer::I8, _) = s.value { + if let Primitive::Int(Integer::I8, _) = s.primitive() { cx.type_vector(cx.type_i8(), 8) } else { layout.llvm_type(cx) @@ -946,7 +950,7 @@ fn llvm_fixup_output_type<'ll, 'tcx>( cx.type_vector(elem_ty, count * 2) } (InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd), Abi::Scalar(s)) - if s.value == Primitive::F64 => + if s.primitive() == Primitive::F64 => { cx.type_i64() } @@ -958,7 +962,7 @@ fn llvm_fixup_output_type<'ll, 'tcx>( InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg | ArmInlineAsmRegClass::sreg_low16), Abi::Scalar(s), ) => { - if let Primitive::Int(Integer::I32, _) = s.value { + if let Primitive::Int(Integer::I32, _) = s.primitive() { cx.type_f32() } else { layout.llvm_type(cx) @@ -972,19 +976,21 @@ fn llvm_fixup_output_type<'ll, 'tcx>( ), Abi::Scalar(s), ) => { - if let Primitive::Int(Integer::I64, _) = s.value { + if let Primitive::Int(Integer::I64, _) = s.primitive() { cx.type_f64() } else { layout.llvm_type(cx) } } - (InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg), Abi::Scalar(s)) => match s.value { - // MIPS only supports register-length arithmetics. - Primitive::Int(Integer::I8 | Integer::I16, _) => cx.type_i32(), - Primitive::F32 => cx.type_i32(), - Primitive::F64 => cx.type_i64(), - _ => layout.llvm_type(cx), - }, + (InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg), Abi::Scalar(s)) => { + match s.primitive() { + // MIPS only supports register-length arithmetics. + Primitive::Int(Integer::I8 | Integer::I16, _) => cx.type_i32(), + Primitive::F32 => cx.type_i32(), + Primitive::F64 => cx.type_i64(), + _ => layout.llvm_type(cx), + } + } _ => layout.llvm_type(cx), } }
diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 1bbfc13..88b8795 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs
@@ -484,14 +484,14 @@ fn scalar_load_metadata<'a, 'll, 'tcx>( bx.noundef_metadata(load); } - match scalar.value { + match scalar.primitive() { abi::Int(..) => { if !scalar.is_always_valid(bx) { - bx.range_metadata(load, scalar.valid_range); + bx.range_metadata(load, scalar.valid_range(bx)); } } abi::Pointer => { - if !scalar.valid_range.contains(0) { + if !scalar.valid_range(bx).contains(0) { bx.nonnull_metadata(load); } @@ -525,7 +525,7 @@ fn scalar_load_metadata<'a, 'll, 'tcx>( }); OperandValue::Immediate(self.to_immediate(llval, place.layout)) } else if let abi::Abi::ScalarPair(a, b) = place.layout.abi { - let b_offset = a.value.size(self).align_to(b.value.align(self).abi); + let b_offset = a.size(self).align_to(b.align(self).abi); let pair_ty = place.layout.llvm_type(self); let mut load = |i, scalar: abi::Scalar, layout, align, offset| {
diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs index a85b2e6..b69d7a0 100644 --- a/compiler/rustc_codegen_llvm/src/common.rs +++ b/compiler/rustc_codegen_llvm/src/common.rs
@@ -221,16 +221,16 @@ fn const_to_opt_u128(&self, v: &'ll Value, sign_ext: bool) -> Option<u128> { } fn scalar_to_backend(&self, cv: Scalar, layout: abi::Scalar, llty: &'ll Type) -> &'ll Value { - let bitsize = if layout.is_bool() { 1 } else { layout.value.size(self).bits() }; + let bitsize = if layout.is_bool() { 1 } else { layout.size(self).bits() }; match cv { Scalar::Int(ScalarInt::ZST) => { - assert_eq!(0, layout.value.size(self).bytes()); + assert_eq!(0, layout.size(self).bytes()); self.const_undef(self.type_ix(0)) } Scalar::Int(int) => { - let data = int.assert_bits(layout.value.size(self)); + let data = int.assert_bits(layout.size(self)); let llval = self.const_uint_big(self.type_ix(bitsize), data); - if layout.value == Pointer { + if layout.primitive() == Pointer { unsafe { llvm::LLVMConstIntToPtr(llval, llty) } } else { self.const_bitcast(llval, llty) @@ -269,7 +269,7 @@ fn scalar_to_backend(&self, cv: Scalar, layout: abi::Scalar, llty: &'ll Type) -> 1, ) }; - if layout.value != Pointer { + if layout.primitive() != Pointer { unsafe { llvm::LLVMConstPtrToInt(llval, llty) } } else { self.const_bitcast(llval, llty)
diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index 413ef0b..cb40735 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs
@@ -109,7 +109,10 @@ fn append_chunks_of_init_and_uninit_bytes<'ll, 'a, 'b>( Pointer::new(alloc_id, Size::from_bytes(ptr_offset)), &cx.tcx, ), - Scalar { value: Primitive::Pointer, valid_range: WrappingRange { start: 0, end: !0 } }, + Scalar::Initialized { + value: Primitive::Pointer, + valid_range: WrappingRange::full(dl.pointer_size), + }, cx.type_i8p_ext(address_space), )); next_offset = offset + pointer_size;
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs index 1eafa95..73e01d0 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs
@@ -118,7 +118,7 @@ fn tag_base_type<'ll, 'tcx>( Variants::Multiple { tag_encoding: TagEncoding::Niche { .. }, tag, .. } => { // Niche tags are always normalized to unsized integers of the correct size. - match tag.value { + match tag.primitive() { Primitive::Int(t, _) => t, Primitive::F32 => Integer::I32, Primitive::F64 => Integer::I64, @@ -136,7 +136,7 @@ fn tag_base_type<'ll, 'tcx>( Variants::Multiple { tag_encoding: TagEncoding::Direct, tag, .. } => { // Direct tags preserve the sign. - tag.value.to_ty(cx.tcx) + tag.primitive().to_ty(cx.tcx) } } } @@ -425,7 +425,7 @@ fn compute_discriminant_value<'ll, 'tcx>( let value = (variant_index.as_u32() as u128) .wrapping_sub(niche_variants.start().as_u32() as u128) .wrapping_add(niche_start); - let value = tag.value.size(cx).truncate(value); + let value = tag.size(cx).truncate(value); // NOTE(eddyb) do *NOT* remove this assert, until // we pass the full 128-bit value to LLVM, otherwise // truncation will be silent and remain undetected.
diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index f4dc334..48840c7 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs
@@ -134,7 +134,7 @@ fn codegen_intrinsic_call( sym::va_arg => { match fn_abi.ret.layout.abi { abi::Abi::Scalar(scalar) => { - match scalar.value { + match scalar.primitive() { Primitive::Int(..) => { if self.cx().size_of(ret_ty).bytes() < 4 { // `va_arg` should not be called on an integer type
diff --git a/compiler/rustc_codegen_llvm/src/type_of.rs b/compiler/rustc_codegen_llvm/src/type_of.rs index 757aa9a..8628052 100644 --- a/compiler/rustc_codegen_llvm/src/type_of.rs +++ b/compiler/rustc_codegen_llvm/src/type_of.rs
@@ -309,7 +309,7 @@ fn scalar_llvm_type_at<'a>( scalar: Scalar, offset: Size, ) -> &'a Type { - match scalar.value { + match scalar.primitive() { Int(i, _) => cx.type_from_integer(i), F32 => cx.type_f32(), F64 => cx.type_f64(), @@ -362,8 +362,7 @@ fn scalar_pair_element_llvm_type<'a>( return cx.type_i1(); } - let offset = - if index == 0 { Size::ZERO } else { a.value.size(cx).align_to(b.value.align(cx).abi) }; + let offset = if index == 0 { Size::ZERO } else { a.size(cx).align_to(b.align(cx).abi) }; self.scalar_llvm_type_at(cx, scalar, offset) }
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 84a1043..a727da0 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -2080,9 +2080,14 @@ fn add_local_native_libraries( NativeLibKind::Framework { as_needed } => { cmd.link_framework(name, as_needed.unwrap_or(true)) } - NativeLibKind::Static { whole_archive, .. } => { + NativeLibKind::Static { whole_archive, bundle, .. } => { if whole_archive == Some(true) || (whole_archive == None && default_to_whole_archive(sess, crate_type, cmd)) + // Backward compatibility case: this can be a rlib (so `+whole-archive` cannot + // be added explicitly if necessary, see the error in `fn link_rlib`) compiled + // as an executable due to `--test`. Use whole-archive implicitly, like before + // the introduction of native lib modifiers. + || (bundle != Some(false) && sess.opts.test) { cmd.link_whole_staticlib( name,
diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 9417874..92c4ab7 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs
@@ -1707,23 +1707,33 @@ pub fn fatal(&self, msg: &str) { impl Emitter for SharedEmitter { fn emit_diagnostic(&mut self, diag: &rustc_errors::Diagnostic) { + let fluent_args = self.to_fluent_args(diag.args()); drop(self.sender.send(SharedEmitterMessage::Diagnostic(Diagnostic { - msg: diag.message(), + msg: self.translate_messages(&diag.message, &fluent_args).to_string(), code: diag.code.clone(), lvl: diag.level(), }))); for child in &diag.children { drop(self.sender.send(SharedEmitterMessage::Diagnostic(Diagnostic { - msg: child.message(), + msg: self.translate_messages(&child.message, &fluent_args).to_string(), code: None, lvl: child.level, }))); } drop(self.sender.send(SharedEmitterMessage::AbortIfErrors)); } + fn source_map(&self) -> Option<&Lrc<SourceMap>> { None } + + fn fluent_bundle(&self) -> Option<&Lrc<rustc_errors::FluentBundle>> { + None + } + + fn fallback_fluent_bundle(&self) -> &Lrc<rustc_errors::FluentBundle> { + panic!("shared emitter attempted to translate a diagnostic"); + } } impl SharedEmitterMain { @@ -1754,9 +1764,9 @@ pub fn check(&self, sess: &Session, blocking: bool) { let msg = msg.strip_prefix("error: ").unwrap_or(&msg); let mut err = match level { - Level::Error { lint: false } => sess.struct_err(&msg).forget_guarantee(), - Level::Warning => sess.struct_warn(&msg), - Level::Note => sess.struct_note_without_error(&msg), + Level::Error { lint: false } => sess.struct_err(msg).forget_guarantee(), + Level::Warning => sess.struct_warn(msg), + Level::Note => sess.struct_note_without_error(msg), _ => bug!("Invalid inline asm diagnostic level"), };
diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index ffc8f55..369ca95 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
@@ -464,13 +464,13 @@ fn msvc_enum_fallback<'tcx>( // calculate the range of values for the dataful variant let dataful_discriminant_range = - dataful_variant_layout.largest_niche().unwrap().scalar.valid_range; + dataful_variant_layout.largest_niche().unwrap().valid_range; let min = dataful_discriminant_range.start; - let min = tag.value.size(&tcx).truncate(min); + let min = tag.size(&tcx).truncate(min); let max = dataful_discriminant_range.end; - let max = tag.value.size(&tcx).truncate(max); + let max = tag.size(&tcx).truncate(max); let dataful_variant_name = variant_name(*dataful_variant); write!(output, ", {}, {}, {}", min, max, dataful_variant_name).unwrap();
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index a87daa8..b7d760b 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -1572,7 +1572,9 @@ fn codegen_transmute_into( match (src.layout.abi, dst.layout.abi) { (abi::Abi::Scalar(src_scalar), abi::Abi::Scalar(dst_scalar)) => { // HACK(eddyb) LLVM doesn't like `bitcast`s between pointers and non-pointers. - if (src_scalar.value == abi::Pointer) == (dst_scalar.value == abi::Pointer) { + if (src_scalar.primitive() == abi::Pointer) + == (dst_scalar.primitive() == abi::Pointer) + { assert_eq!(src.layout.size, dst.layout.size); // NOTE(eddyb) the `from_immediate` and `to_immediate_scalar`
diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs index 858f71e..08be4c0 100644 --- a/compiler/rustc_codegen_ssa/src/mir/operand.rs +++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs
@@ -207,11 +207,11 @@ pub fn extract_field<Bx: BuilderMethods<'a, 'tcx, Value = V>>( // Extract a scalar component from a pair. (OperandValue::Pair(a_llval, b_llval), Abi::ScalarPair(a, b)) => { if offset.bytes() == 0 { - assert_eq!(field.size, a.value.size(bx.cx())); + assert_eq!(field.size, a.size(bx.cx())); OperandValue::Immediate(a_llval) } else { - assert_eq!(offset, a.value.size(bx.cx()).align_to(b.value.align(bx.cx()).abi)); - assert_eq!(field.size, b.value.size(bx.cx())); + assert_eq!(offset, a.size(bx.cx()).align_to(b.align(bx.cx()).abi)); + assert_eq!(field.size, b.size(bx.cx())); OperandValue::Immediate(b_llval) } } @@ -316,7 +316,7 @@ fn store_with_flags<Bx: BuilderMethods<'a, 'tcx, Value = V>>( bug!("store_with_flags: invalid ScalarPair layout: {:#?}", dest.layout); }; let ty = bx.backend_type(dest.layout); - let b_offset = a_scalar.value.size(bx).align_to(b_scalar.value.align(bx).abi); + let b_offset = a_scalar.size(bx).align_to(b_scalar.align(bx).abi); let llptr = bx.struct_gep(ty, dest.llval, 0); let val = bx.from_immediate(a);
diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs index 17cfb6c..cf69c8f 100644 --- a/compiler/rustc_codegen_ssa/src/mir/place.rs +++ b/compiler/rustc_codegen_ssa/src/mir/place.rs
@@ -100,7 +100,7 @@ pub fn project_field<Bx: BuilderMethods<'a, 'tcx, Value = V>>( self.llval } Abi::ScalarPair(a, b) - if offset == a.value.size(bx.cx()).align_to(b.value.align(bx.cx()).abi) => + if offset == a.size(bx.cx()).align_to(b.align(bx.cx()).abi) => { // Offset matches second field. let ty = bx.backend_type(self.layout); @@ -234,7 +234,7 @@ pub fn codegen_get_discr<Bx: BuilderMethods<'a, 'tcx, Value = V>>( // Decode the discriminant (specifically if it's niche-encoded). match *tag_encoding { TagEncoding::Direct => { - let signed = match tag_scalar.value { + let signed = match tag_scalar.primitive() { // We use `i1` for bytes that are always `0` or `1`, // e.g., `#[repr(i8)] enum E { A, B }`, but we can't // let LLVM interpret the `i1` as signed, because
diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 68decce..fd29c9e 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
@@ -299,7 +299,7 @@ pub fn codegen_rvalue_operand( let mut signed = false; if let Abi::Scalar(scalar) = operand.layout.abi { - if let Int(_, s) = scalar.value { + if let Int(_, s) = scalar.primitive() { // We use `i1` for bytes that are always `0` or `1`, // e.g., `#[repr(i8)] enum E { A, B }`, but we can't // let LLVM interpret the `i1` as signed, because @@ -307,15 +307,17 @@ pub fn codegen_rvalue_operand( signed = !scalar.is_bool() && s; if !scalar.is_always_valid(bx.cx()) - && scalar.valid_range.end >= scalar.valid_range.start + && scalar.valid_range(bx.cx()).end + >= scalar.valid_range(bx.cx()).start { // We want `table[e as usize ± k]` to not // have bound checks, and this is the most // convenient place to put the `assume`s. - if scalar.valid_range.start > 0 { - let enum_value_lower_bound = bx - .cx() - .const_uint_big(ll_t_in, scalar.valid_range.start); + if scalar.valid_range(bx.cx()).start > 0 { + let enum_value_lower_bound = bx.cx().const_uint_big( + ll_t_in, + scalar.valid_range(bx.cx()).start, + ); let cmp_start = bx.icmp( IntPredicate::IntUGE, llval, @@ -324,8 +326,9 @@ pub fn codegen_rvalue_operand( bx.assume(cmp_start); } - let enum_value_upper_bound = - bx.cx().const_uint_big(ll_t_in, scalar.valid_range.end); + let enum_value_upper_bound = bx + .cx() + .const_uint_big(ll_t_in, scalar.valid_range(bx.cx()).end); let cmp_end = bx.icmp( IntPredicate::IntULE, llval,
diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index 9465462..b856d17 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
@@ -1,4 +1,4 @@ -use super::{CompileTimeEvalContext, CompileTimeInterpreter, ConstEvalErr, MemoryExtra}; +use super::{CompileTimeEvalContext, CompileTimeInterpreter, ConstEvalErr}; use crate::interpret::eval_nullary_intrinsic; use crate::interpret::{ intern_const_alloc_recursive, Allocation, ConstAlloc, ConstValue, CtfeValidationMode, GlobalId, @@ -15,7 +15,7 @@ use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, subst::Subst, TyCtxt}; use rustc_span::source_map::Span; -use rustc_target::abi::Abi; +use rustc_target::abi::{self, Abi}; use std::borrow::Cow; use std::convert::TryInto; @@ -100,8 +100,7 @@ pub(super) fn mk_eval_cx<'mir, 'tcx>( tcx, root_span, param_env, - CompileTimeInterpreter::new(tcx.const_eval_limit()), - MemoryExtra { can_access_statics }, + CompileTimeInterpreter::new(tcx.const_eval_limit(), can_access_statics), ) } @@ -119,7 +118,7 @@ pub(super) fn op_to_const<'tcx>( // the usual cases of extracting e.g. a `usize`, without there being a real use case for the // `Undef` situation. let try_as_immediate = match op.layout.abi { - Abi::Scalar(..) => true, + Abi::Scalar(abi::Scalar::Initialized { .. }) => true, Abi::ScalarPair(..) => match op.layout.ty.kind() { ty::Ref(_, inner, _) => match *inner.kind() { ty::Slice(elem) => elem == ecx.tcx.types.u8, @@ -285,10 +284,9 @@ pub fn eval_to_allocation_raw_provider<'tcx>( tcx, tcx.def_span(def.did), key.param_env, - CompileTimeInterpreter::new(tcx.const_eval_limit()), // Statics (and promoteds inside statics) may access other statics, because unlike consts // they do not have to behave "as if" they were evaluated at runtime. - MemoryExtra { can_access_statics: is_static }, + CompileTimeInterpreter::new(tcx.const_eval_limit(), /*can_access_statics:*/ is_static), ); let res = ecx.load_mir(cid.instance.def, cid.promoted);
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 2b58c1e..c44e27f 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -1,6 +1,6 @@ use rustc_hir::def::DefKind; use rustc_middle::mir; -use rustc_middle::ty::{self, Ty}; +use rustc_middle::ty::{self, Ty, TyCtxt}; use std::borrow::Borrow; use std::collections::hash_map::Entry; use std::hash::Hash; @@ -93,10 +93,7 @@ pub struct CompileTimeInterpreter<'mir, 'tcx> { /// The virtual call stack. pub(crate) stack: Vec<Frame<'mir, 'tcx, AllocId, ()>>, -} -#[derive(Copy, Clone, Debug)] -pub struct MemoryExtra { /// We need to make sure consts never point to anything mutable, even recursively. That is /// relied on for pattern matching on consts with references. /// To achieve this, two pieces have to work together: @@ -107,8 +104,12 @@ pub struct MemoryExtra { } impl<'mir, 'tcx> CompileTimeInterpreter<'mir, 'tcx> { - pub(super) fn new(const_eval_limit: Limit) -> Self { - CompileTimeInterpreter { steps_remaining: const_eval_limit.0, stack: Vec::new() } + pub(super) fn new(const_eval_limit: Limit, can_access_statics: bool) -> Self { + CompileTimeInterpreter { + steps_remaining: const_eval_limit.0, + stack: Vec::new(), + can_access_statics, + } } } @@ -233,8 +234,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, type MemoryKind = MemoryKind; - type MemoryExtra = MemoryExtra; - const PANIC_ON_ALLOC_FAIL: bool = false; // will be raised as a proper error fn load_mir( @@ -345,7 +344,7 @@ fn call_intrinsic( Err(err) => throw_ub_format!("align has to be a power of 2, {}", err), }; - let ptr = ecx.memory.allocate( + let ptr = ecx.allocate_ptr( Size::from_bytes(size as u64), align, interpret::MemoryKind::Machine(MemoryKind::Heap), @@ -365,14 +364,14 @@ fn call_intrinsic( // If an allocation is created in an another const, // we don't deallocate it. - let (alloc_id, _, _) = ecx.memory.ptr_get_alloc(ptr)?; + let (alloc_id, _, _) = ecx.ptr_get_alloc_id(ptr)?; let is_allocated_in_another_const = matches!( ecx.tcx.get_global_alloc(alloc_id), Some(interpret::GlobalAlloc::Memory(_)) ); if !is_allocated_in_another_const { - ecx.memory.deallocate( + ecx.deallocate_ptr( ptr, Some((size, align)), interpret::MemoryKind::Machine(MemoryKind::Heap), @@ -472,7 +471,8 @@ fn stack_mut<'a>( } fn before_access_global( - memory_extra: &MemoryExtra, + _tcx: TyCtxt<'tcx>, + machine: &Self, alloc_id: AllocId, alloc: ConstAllocation<'tcx>, static_def_id: Option<DefId>, @@ -488,7 +488,7 @@ fn before_access_global( } } else { // Read access. These are usually allowed, with some exceptions. - if memory_extra.can_access_statics { + if machine.can_access_statics { // Machine configuration allows us read from anything (e.g., `static` initializer). Ok(()) } else if static_def_id.is_some() {
diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index 5be0a18..a244b79 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs
@@ -56,7 +56,7 @@ pub fn cast( ) .ok_or_else(|| err_inval!(TooGeneric))?; - let fn_ptr = self.memory.create_fn_alloc(FnVal::Instance(instance)); + let fn_ptr = self.create_fn_alloc_ptr(FnVal::Instance(instance)); self.write_pointer(fn_ptr, dest)?; } _ => span_bug!(self.cur_span(), "reify fn pointer on {:?}", src.layout.ty), @@ -87,7 +87,7 @@ pub fn cast( substs, ty::ClosureKind::FnOnce, ); - let fn_ptr = self.memory.create_fn_alloc(FnVal::Instance(instance)); + let fn_ptr = self.create_fn_alloc_ptr(FnVal::Instance(instance)); self.write_pointer(fn_ptr, dest)?; } _ => span_bug!(self.cur_span(), "closure fn pointer on {:?}", src.layout.ty), @@ -153,8 +153,8 @@ pub fn misc_cast( return Ok(**src); } else { // Casting the metadata away from a fat ptr. - assert_eq!(src.layout.size, 2 * self.memory.pointer_size()); - assert_eq!(dest_layout.size, self.memory.pointer_size()); + assert_eq!(src.layout.size, 2 * self.pointer_size()); + assert_eq!(dest_layout.size, self.pointer_size()); assert!(src.layout.ty.is_unsafe_ptr()); return match **src { Immediate::ScalarPair(data, _) => Ok(data.into()),
diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index 1b8186b..a2ea0f5 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs
@@ -22,9 +22,9 @@ use rustc_target::abi::{call::FnAbi, Align, HasDataLayout, Size, TargetDataLayout}; use super::{ - AllocCheck, AllocId, GlobalId, Immediate, InterpErrorInfo, InterpResult, MPlaceTy, Machine, - MemPlace, MemPlaceMeta, Memory, MemoryKind, Operand, Place, PlaceTy, Pointer, - PointerArithmetic, Provenance, Scalar, ScalarMaybeUninit, StackPopJump, + AllocId, GlobalId, Immediate, InterpErrorInfo, InterpResult, MPlaceTy, Machine, MemPlace, + MemPlaceMeta, Memory, MemoryKind, Operand, Place, PlaceTy, PointerArithmetic, Provenance, + Scalar, ScalarMaybeUninit, StackPopJump, }; use crate::transform::validate::equal_up_to_regions; @@ -413,13 +413,12 @@ pub fn new( root_span: Span, param_env: ty::ParamEnv<'tcx>, machine: M, - memory_extra: M::MemoryExtra, ) -> Self { InterpCx { machine, tcx: tcx.at(root_span), param_env, - memory: Memory::new(tcx, memory_extra), + memory: Memory::new(), recursion_limit: tcx.recursion_limit(), } } @@ -434,49 +433,6 @@ pub fn cur_span(&self) -> Span { } #[inline(always)] - pub fn scalar_to_ptr(&self, scalar: Scalar<M::PointerTag>) -> Pointer<Option<M::PointerTag>> { - self.memory.scalar_to_ptr(scalar) - } - - /// Test if this value might be null. - /// If the machine does not support ptr-to-int casts, this is conservative. - pub fn scalar_may_be_null(&self, scalar: Scalar<M::PointerTag>) -> bool { - match scalar.try_to_int() { - Ok(int) => int.is_null(), - Err(_) => { - // Can only happen during CTFE. - let ptr = self.scalar_to_ptr(scalar); - match self.memory.ptr_try_get_alloc(ptr) { - Ok((alloc_id, offset, _)) => { - let (size, _align) = self - .memory - .get_size_and_align(alloc_id, AllocCheck::MaybeDead) - .expect("alloc info with MaybeDead cannot fail"); - // If the pointer is out-of-bounds, it may be null. - // Note that one-past-the-end (offset == size) is still inbounds, and never null. - offset > size - } - Err(_offset) => bug!("a non-int scalar is always a pointer"), - } - } - } - } - - /// Call this to turn untagged "global" pointers (obtained via `tcx`) into - /// the machine pointer to the allocation. Must never be used - /// for any other pointers, nor for TLS statics. - /// - /// Using the resulting pointer represents a *direct* access to that memory - /// (e.g. by directly using a `static`), - /// as opposed to access through a pointer that was created by the program. - /// - /// This function can fail only if `ptr` points to an `extern static`. - #[inline(always)] - pub fn global_base_pointer(&self, ptr: Pointer) -> InterpResult<'tcx, Pointer<M::PointerTag>> { - self.memory.global_base_pointer(ptr) - } - - #[inline(always)] pub(crate) fn stack(&self) -> &[Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra>] { M::stack(self) } @@ -949,9 +905,9 @@ fn deallocate_local(&mut self, local: LocalValue<M::PointerTag>) -> InterpResult trace!( "deallocating local {:?}: {:?}", local, - self.memory.dump_alloc(ptr.provenance.unwrap().get_alloc_id()) + self.dump_alloc(ptr.provenance.unwrap().get_alloc_id()) ); - self.memory.deallocate(ptr, None, MemoryKind::Stack)?; + self.deallocate_ptr(ptr, None, MemoryKind::Stack)?; }; Ok(()) } @@ -1057,7 +1013,7 @@ fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { } } - write!(fmt, ": {:?}", self.ecx.memory.dump_allocs(allocs)) + write!(fmt, ": {:?}", self.ecx.dump_allocs(allocs)) } Place::Ptr(mplace) => match mplace.ptr.provenance.map(Provenance::get_alloc_id) { Some(alloc_id) => write!( @@ -1065,7 +1021,7 @@ fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { "by align({}) ref {:?}: {:?}", mplace.align.bytes(), mplace.ptr, - self.ecx.memory.dump_alloc(alloc_id) + self.ecx.dump_alloc(alloc_id) ), ptr => write!(fmt, " integral by ref: {:?}", ptr), },
diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index c80d7d7..3cc237f 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
@@ -188,7 +188,7 @@ pub fn emulate_intrinsic( let val = self.read_scalar(&args[0])?.check_init()?; let bits = val.to_bits(layout_of.size)?; let kind = match layout_of.abi { - Abi::Scalar(scalar) => scalar.value, + Abi::Scalar(scalar) => scalar.primitive(), _ => span_bug!( self.cur_span(), "{} called on invalid type {:?}", @@ -318,7 +318,7 @@ pub fn emulate_intrinsic( // exception from the exception.) // This is the dual to the special exception for offset-by-0 // in the inbounds pointer offset operation (see `ptr_offset_inbounds` below). - match (self.memory.ptr_try_get_alloc(a), self.memory.ptr_try_get_alloc(b)) { + match (self.ptr_try_get_alloc_id(a), self.ptr_try_get_alloc_id(b)) { (Err(a), Err(b)) if a == b && a != 0 => { // Both are the same non-null integer. self.write_scalar(Scalar::from_machine_isize(0, self), dest)?; @@ -335,13 +335,13 @@ pub fn emulate_intrinsic( ); } // And they must both be valid for zero-sized accesses ("in-bounds or one past the end"). - self.memory.check_ptr_access_align( + self.check_ptr_access_align( a, Size::ZERO, Align::ONE, CheckInAllocMsg::OffsetFromTest, )?; - self.memory.check_ptr_access_align( + self.check_ptr_access_align( b, Size::ZERO, Align::ONE, @@ -545,7 +545,7 @@ pub fn ptr_offset_inbounds( let min_ptr = if offset_bytes >= 0 { ptr } else { offset_ptr }; let size = offset_bytes.unsigned_abs(); // This call handles checking for integer/null pointers. - self.memory.check_ptr_access_align( + self.check_ptr_access_align( min_ptr, Size::from_bytes(size), Align::ONE, @@ -577,7 +577,7 @@ pub(crate) fn copy_intrinsic( let src = self.read_pointer(&src)?; let dst = self.read_pointer(&dst)?; - self.memory.copy(src, align, dst, align, size, nonoverlapping) + self.mem_copy(src, align, dst, align, size, nonoverlapping) } pub(crate) fn write_bytes_intrinsic( @@ -600,7 +600,7 @@ pub(crate) fn write_bytes_intrinsic( .ok_or_else(|| err_ub_format!("overflow computing total size of `write_bytes`"))?; let bytes = std::iter::repeat(byte).take(len.bytes_usize()); - self.memory.write_bytes(dst, bytes) + self.write_bytes_ptr(dst, bytes) } pub(crate) fn raw_eq_intrinsic( @@ -613,8 +613,8 @@ pub(crate) fn raw_eq_intrinsic( let lhs = self.read_pointer(lhs)?; let rhs = self.read_pointer(rhs)?; - let lhs_bytes = self.memory.read_bytes(lhs, layout.size)?; - let rhs_bytes = self.memory.read_bytes(rhs, layout.size)?; + let lhs_bytes = self.read_bytes_ptr(lhs, layout.size)?; + let rhs_bytes = self.read_bytes_ptr(rhs, layout.size)?; Ok(Scalar::from_bool(lhs_bytes == rhs_bytes)) } }
diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index 7d75c84..ddfbcbd 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs
@@ -7,14 +7,14 @@ use std::hash::Hash; use rustc_middle::mir; -use rustc_middle::ty::{self, Ty}; +use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::def_id::DefId; use rustc_target::abi::Size; use rustc_target::spec::abi::Abi; use super::{ AllocId, AllocRange, Allocation, ConstAllocation, Frame, ImmTy, InterpCx, InterpResult, - LocalValue, MemPlace, Memory, MemoryKind, OpTy, Operand, PlaceTy, Pointer, Provenance, Scalar, + LocalValue, MemPlace, MemoryKind, OpTy, Operand, PlaceTy, Pointer, Provenance, Scalar, StackPopUnwind, }; @@ -96,11 +96,6 @@ pub trait Machine<'mir, 'tcx>: Sized { /// Extra data stored in every call frame. type FrameExtra; - /// Extra data stored in memory. A reference to this is available when `AllocExtra` - /// gets initialized, so you can e.g., have an `Rc` here if there is global state you - /// need access to in the `AllocExtra` hooks. - type MemoryExtra; - /// Extra data stored in every allocation. type AllocExtra: Debug + Clone + 'static; @@ -123,11 +118,11 @@ pub trait Machine<'mir, 'tcx>: Sized { const PANIC_ON_ALLOC_FAIL: bool; /// Whether memory accesses should be alignment-checked. - fn enforce_alignment(memory_extra: &Self::MemoryExtra) -> bool; + fn enforce_alignment(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool; /// Whether, when checking alignment, we should `force_int` and thus support /// custom alignment logic based on whatever the integer address happens to be. - fn force_int_for_alignment_check(memory_extra: &Self::MemoryExtra) -> bool; + fn force_int_for_alignment_check(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool; /// Whether to enforce the validity invariant fn enforce_validity(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool; @@ -251,7 +246,8 @@ fn before_terminator(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx /// `def_id` is `Some` if this is the "lazy" allocation of a static. #[inline] fn before_access_global( - _memory_extra: &Self::MemoryExtra, + _tcx: TyCtxt<'tcx>, + _machine: &Self, _alloc_id: AllocId, _allocation: ConstAllocation<'tcx>, _static_def_id: Option<DefId>, @@ -270,7 +266,7 @@ fn thread_local_static_base_pointer( /// Return the root pointer for the given `extern static`. fn extern_static_base_pointer( - mem: &Memory<'mir, 'tcx, Self>, + ecx: &InterpCx<'mir, 'tcx, Self>, def_id: DefId, ) -> InterpResult<'tcx, Pointer<Self::PointerTag>>; @@ -279,19 +275,19 @@ fn extern_static_base_pointer( /// /// Not called on `extern` or thread-local statics (those use the methods above). fn tag_alloc_base_pointer( - mem: &Memory<'mir, 'tcx, Self>, + ecx: &InterpCx<'mir, 'tcx, Self>, ptr: Pointer, ) -> Pointer<Self::PointerTag>; /// "Int-to-pointer cast" fn ptr_from_addr( - mem: &Memory<'mir, 'tcx, Self>, + ecx: &InterpCx<'mir, 'tcx, Self>, addr: u64, ) -> Pointer<Option<Self::PointerTag>>; /// Convert a pointer with provenance into an allocation-offset pair. fn ptr_get_alloc( - mem: &Memory<'mir, 'tcx, Self>, + ecx: &InterpCx<'mir, 'tcx, Self>, ptr: Pointer<Self::PointerTag>, ) -> (AllocId, Size); @@ -309,7 +305,7 @@ fn ptr_get_alloc( /// cache the result. (This relies on `AllocMap::get_or` being able to add the /// owned allocation to the map even when the map is shared.) fn init_allocation_extra<'b>( - mem: &Memory<'mir, 'tcx, Self>, + ecx: &InterpCx<'mir, 'tcx, Self>, id: AllocId, alloc: Cow<'b, Allocation>, kind: Option<MemoryKind<Self::MemoryKind>>, @@ -322,7 +318,8 @@ fn init_allocation_extra<'b>( /// need to mutate. #[inline(always)] fn memory_read( - _memory_extra: &Self::MemoryExtra, + _tcx: TyCtxt<'tcx>, + _machine: &Self, _alloc_extra: &Self::AllocExtra, _tag: Self::PointerTag, _range: AllocRange, @@ -333,7 +330,8 @@ fn memory_read( /// Hook for performing extra checks on a memory write access. #[inline(always)] fn memory_written( - _memory_extra: &mut Self::MemoryExtra, + _tcx: TyCtxt<'tcx>, + _machine: &mut Self, _alloc_extra: &mut Self::AllocExtra, _tag: Self::PointerTag, _range: AllocRange, @@ -344,7 +342,8 @@ fn memory_written( /// Hook for performing extra operations on a memory deallocation. #[inline(always)] fn memory_deallocated( - _memory_extra: &mut Self::MemoryExtra, + _tcx: TyCtxt<'tcx>, + _machine: &mut Self, _alloc_extra: &mut Self::AllocExtra, _tag: Self::PointerTag, _range: AllocRange, @@ -408,14 +407,14 @@ fn after_stack_pop( type FrameExtra = (); #[inline(always)] - fn enforce_alignment(_memory_extra: &Self::MemoryExtra) -> bool { + fn enforce_alignment(_ecx: &InterpCx<$mir, $tcx, Self>) -> bool { // We do not check for alignment to avoid having to carry an `Align` // in `ConstValue::ByRef`. false } #[inline(always)] - fn force_int_for_alignment_check(_memory_extra: &Self::MemoryExtra) -> bool { + fn force_int_for_alignment_check(_ecx: &InterpCx<$mir, $tcx, Self>) -> bool { // We do not support `force_int`. false } @@ -444,7 +443,7 @@ fn call_extra_fn( #[inline(always)] fn init_allocation_extra<'b>( - _mem: &Memory<$mir, $tcx, Self>, + _ecx: &InterpCx<$mir, $tcx, Self>, _id: AllocId, alloc: Cow<'b, Allocation>, _kind: Option<MemoryKind<Self::MemoryKind>>, @@ -454,28 +453,28 @@ fn init_allocation_extra<'b>( } fn extern_static_base_pointer( - mem: &Memory<$mir, $tcx, Self>, + ecx: &InterpCx<$mir, $tcx, Self>, def_id: DefId, ) -> InterpResult<$tcx, Pointer> { // Use the `AllocId` associated with the `DefId`. Any actual *access* will fail. - Ok(Pointer::new(mem.tcx.create_static_alloc(def_id), Size::ZERO)) + Ok(Pointer::new(ecx.tcx.create_static_alloc(def_id), Size::ZERO)) } #[inline(always)] fn tag_alloc_base_pointer( - _mem: &Memory<$mir, $tcx, Self>, + _ecx: &InterpCx<$mir, $tcx, Self>, ptr: Pointer<AllocId>, ) -> Pointer<AllocId> { ptr } #[inline(always)] - fn ptr_from_addr(_mem: &Memory<$mir, $tcx, Self>, addr: u64) -> Pointer<Option<AllocId>> { + fn ptr_from_addr(_ecx: &InterpCx<$mir, $tcx, Self>, addr: u64) -> Pointer<Option<AllocId>> { Pointer::new(None, Size::from_bytes(addr)) } #[inline(always)] - fn ptr_get_alloc(_mem: &Memory<$mir, $tcx, Self>, ptr: Pointer<AllocId>) -> (AllocId, Size) { + fn ptr_get_alloc(_ecx: &InterpCx<$mir, $tcx, Self>, ptr: Pointer<AllocId>) -> (AllocId, Size) { // We know `offset` is relative to the allocation, so we can use `into_parts`. let (alloc_id, offset) = ptr.into_parts(); (alloc_id, offset)
diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 4a23580..a02115a 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs
@@ -17,10 +17,10 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_middle::mir::display_allocation; use rustc_middle::ty::{Instance, ParamEnv, TyCtxt}; -use rustc_target::abi::{Align, HasDataLayout, Size, TargetDataLayout}; +use rustc_target::abi::{Align, HasDataLayout, Size}; use super::{ - alloc_range, AllocId, AllocMap, AllocRange, Allocation, CheckInAllocMsg, GlobalAlloc, + alloc_range, AllocId, AllocMap, AllocRange, Allocation, CheckInAllocMsg, GlobalAlloc, InterpCx, InterpResult, Machine, MayLeak, Pointer, PointerArithmetic, Provenance, Scalar, ScalarMaybeUninit, }; @@ -108,19 +108,6 @@ pub struct Memory<'mir, 'tcx, M: Machine<'mir, 'tcx>> { /// that do not exist any more. // FIXME: this should not be public, but interning currently needs access to it pub(super) dead_alloc_map: FxHashMap<AllocId, (Size, Align)>, - - /// Extra data added by the machine. - pub extra: M::MemoryExtra, - - /// Lets us implement `HasDataLayout`, which is awfully convenient. - pub tcx: TyCtxt<'tcx>, -} - -impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> HasDataLayout for Memory<'mir, 'tcx, M> { - #[inline] - fn data_layout(&self) -> &TargetDataLayout { - &self.tcx.data_layout - } } /// A reference to some allocation that was already bounds-checked for the given region @@ -142,16 +129,21 @@ pub struct AllocRefMut<'a, 'tcx, Tag, Extra> { } impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { - pub fn new(tcx: TyCtxt<'tcx>, extra: M::MemoryExtra) -> Self { + pub fn new() -> Self { Memory { alloc_map: M::MemoryMap::default(), extra_fn_ptr_map: FxHashMap::default(), dead_alloc_map: FxHashMap::default(), - extra, - tcx, } } + /// This is used by [priroda](https://github.com/oli-obk/priroda) + pub fn alloc_map(&self) -> &M::MemoryMap { + &self.alloc_map + } +} + +impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// Call this to turn untagged "global" pointers (obtained via `tcx`) into /// the machine pointer to the allocation. Must never be used /// for any other pointers, nor for TLS statics. @@ -182,7 +174,7 @@ pub fn global_base_pointer( Ok(M::tag_alloc_base_pointer(self, Pointer::new(alloc_id, offset))) } - pub fn create_fn_alloc( + pub fn create_fn_alloc_ptr( &mut self, fn_val: FnVal<'tcx, M::ExtraFnVal>, ) -> Pointer<M::PointerTag> { @@ -191,7 +183,7 @@ pub fn create_fn_alloc( FnVal::Other(extra) => { // FIXME(RalfJung): Should we have a cache here? let id = self.tcx.reserve_alloc_id(); - let old = self.extra_fn_ptr_map.insert(id, extra); + let old = self.memory.extra_fn_ptr_map.insert(id, extra); assert!(old.is_none()); id } @@ -201,17 +193,17 @@ pub fn create_fn_alloc( self.global_base_pointer(Pointer::from(id)).unwrap() } - pub fn allocate( + pub fn allocate_ptr( &mut self, size: Size, align: Align, kind: MemoryKind<M::MemoryKind>, ) -> InterpResult<'static, Pointer<M::PointerTag>> { let alloc = Allocation::uninit(size, align, M::PANIC_ON_ALLOC_FAIL)?; - Ok(self.allocate_with(alloc, kind)) + Ok(self.allocate_raw_ptr(alloc, kind)) } - pub fn allocate_bytes( + pub fn allocate_bytes_ptr( &mut self, bytes: &[u8], align: Align, @@ -219,10 +211,10 @@ pub fn allocate_bytes( mutability: Mutability, ) -> Pointer<M::PointerTag> { let alloc = Allocation::from_bytes(bytes, align, mutability); - self.allocate_with(alloc, kind) + self.allocate_raw_ptr(alloc, kind) } - pub fn allocate_with( + pub fn allocate_raw_ptr( &mut self, alloc: Allocation, kind: MemoryKind<M::MemoryKind>, @@ -234,11 +226,11 @@ pub fn allocate_with( "dynamically allocating global memory" ); let alloc = M::init_allocation_extra(self, id, Cow::Owned(alloc), Some(kind)); - self.alloc_map.insert(id, (kind, alloc.into_owned())); + self.memory.alloc_map.insert(id, (kind, alloc.into_owned())); M::tag_alloc_base_pointer(self, Pointer::from(id)) } - pub fn reallocate( + pub fn reallocate_ptr( &mut self, ptr: Pointer<Option<M::PointerTag>>, old_size_and_align: Option<(Size, Align)>, @@ -246,7 +238,7 @@ pub fn reallocate( new_align: Align, kind: MemoryKind<M::MemoryKind>, ) -> InterpResult<'tcx, Pointer<M::PointerTag>> { - let (alloc_id, offset, ptr) = self.ptr_get_alloc(ptr)?; + let (alloc_id, offset, ptr) = self.ptr_get_alloc_id(ptr)?; if offset.bytes() != 0 { throw_ub_format!( "reallocating {:?} which does not point to the beginning of an object", @@ -256,13 +248,13 @@ pub fn reallocate( // For simplicities' sake, we implement reallocate as "alloc, copy, dealloc". // This happens so rarely, the perf advantage is outweighed by the maintenance cost. - let new_ptr = self.allocate(new_size, new_align, kind)?; + let new_ptr = self.allocate_ptr(new_size, new_align, kind)?; let old_size = match old_size_and_align { Some((size, _align)) => size, - None => self.get_raw(alloc_id)?.size(), + None => self.get_alloc_raw(alloc_id)?.size(), }; // This will also call the access hooks. - self.copy( + self.mem_copy( ptr.into(), Align::ONE, new_ptr.into(), @@ -270,19 +262,19 @@ pub fn reallocate( old_size.min(new_size), /*nonoverlapping*/ true, )?; - self.deallocate(ptr.into(), old_size_and_align, kind)?; + self.deallocate_ptr(ptr.into(), old_size_and_align, kind)?; Ok(new_ptr) } #[instrument(skip(self), level = "debug")] - pub fn deallocate( + pub fn deallocate_ptr( &mut self, ptr: Pointer<Option<M::PointerTag>>, old_size_and_align: Option<(Size, Align)>, kind: MemoryKind<M::MemoryKind>, ) -> InterpResult<'tcx> { - let (alloc_id, offset, ptr) = self.ptr_get_alloc(ptr)?; + let (alloc_id, offset, ptr) = self.ptr_get_alloc_id(ptr)?; trace!("deallocating: {}", alloc_id); if offset.bytes() != 0 { @@ -292,7 +284,7 @@ pub fn deallocate( ); } - let Some((alloc_kind, mut alloc)) = self.alloc_map.remove(&alloc_id) else { + let Some((alloc_kind, mut alloc)) = self.memory.alloc_map.remove(&alloc_id) else { // Deallocating global memory -- always an error return Err(match self.tcx.get_global_alloc(alloc_id) { Some(GlobalAlloc::Function(..)) => { @@ -335,14 +327,15 @@ pub fn deallocate( // Let the machine take some extra action let size = alloc.size(); M::memory_deallocated( - &mut self.extra, + *self.tcx, + &mut self.machine, &mut alloc.extra, ptr.provenance, alloc_range(Size::ZERO, size), )?; // Don't forget to remember size and align of this now-dead allocation - let old = self.dead_alloc_map.insert(alloc_id, (size, alloc.align)); + let old = self.memory.dead_alloc_map.insert(alloc_id, (size, alloc.align)); if old.is_some() { bug!("Nothing can be deallocated twice"); } @@ -358,7 +351,7 @@ fn get_ptr_access( size: Size, align: Align, ) -> InterpResult<'tcx, Option<(AllocId, Size, Pointer<M::PointerTag>)>> { - let align = M::enforce_alignment(&self.extra).then_some(align); + let align = M::enforce_alignment(&self).then_some(align); self.check_and_deref_ptr( ptr, size, @@ -366,7 +359,7 @@ fn get_ptr_access( CheckInAllocMsg::MemoryAccessTest, |alloc_id, offset, ptr| { let (size, align) = - self.get_size_and_align(alloc_id, AllocCheck::Dereferenceable)?; + self.get_alloc_size_and_align(alloc_id, AllocCheck::Dereferenceable)?; Ok((size, align, (alloc_id, offset, ptr))) }, ) @@ -392,7 +385,7 @@ pub fn check_ptr_access_align( | CheckInAllocMsg::OffsetFromTest | CheckInAllocMsg::InboundsTest => AllocCheck::Live, }; - let (size, align) = self.get_size_and_align(alloc_id, check)?; + let (size, align) = self.get_alloc_size_and_align(alloc_id, check)?; Ok((size, align, ())) })?; Ok(()) @@ -427,7 +420,7 @@ fn check_offset_align(offset: u64, align: Align) -> InterpResult<'static> { } } - Ok(match self.ptr_try_get_alloc(ptr) { + Ok(match self.ptr_try_get_alloc_id(ptr) { Err(addr) => { // We couldn't get a proper allocation. This is only okay if the access size is 0, // and the address is not null. @@ -456,7 +449,7 @@ fn check_offset_align(offset: u64, align: Align) -> InterpResult<'static> { // Test align. Check this last; if both bounds and alignment are violated // we want the error to be about the bounds. if let Some(align) = align { - if M::force_int_for_alignment_check(&self.extra) { + if M::force_int_for_alignment_check(self) { let addr = Scalar::from_pointer(ptr, &self.tcx) .to_machine_usize(&self.tcx) .expect("ptr-to-int cast for align check should never fail"); @@ -479,7 +472,7 @@ fn check_offset_align(offset: u64, align: Align) -> InterpResult<'static> { } /// Allocation accessors -impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { +impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// Helper function to obtain a global (tcx) allocation. /// This attempts to return a reference to an existing allocation if /// one can be found in `tcx`. That, however, is only possible if `tcx` and @@ -517,7 +510,7 @@ fn get_global_alloc( (self.tcx.eval_static_initializer(def_id)?, Some(def_id)) } }; - M::before_access_global(&self.extra, id, alloc, def_id, is_write)?; + M::before_access_global(*self.tcx, &self.machine, id, alloc, def_id, is_write)?; // We got tcx memory. Let the machine initialize its "extra" stuff. let alloc = M::init_allocation_extra( self, @@ -530,7 +523,7 @@ fn get_global_alloc( /// Gives raw access to the `Allocation`, without bounds or alignment checks. /// The caller is responsible for calling the access hooks! - fn get_raw( + fn get_alloc_raw( &self, id: AllocId, ) -> InterpResult<'tcx, &Allocation<M::PointerTag, M::AllocExtra>> { @@ -538,7 +531,7 @@ fn get_raw( // ways of "erroring": An actual error, or because we got a reference from // `get_global_alloc` that we can actually use directly without inserting anything anywhere. // So the error type is `InterpResult<'tcx, &Allocation<M::PointerTag>>`. - let a = self.alloc_map.get_or(id, || { + let a = self.memory.alloc_map.get_or(id, || { let alloc = self.get_global_alloc(id, /*is_write*/ false).map_err(Err)?; match alloc { Cow::Borrowed(alloc) => { @@ -564,27 +557,27 @@ fn get_raw( } /// "Safe" (bounds and align-checked) allocation access. - pub fn get<'a>( + pub fn get_ptr_alloc<'a>( &'a self, ptr: Pointer<Option<M::PointerTag>>, size: Size, align: Align, ) -> InterpResult<'tcx, Option<AllocRef<'a, 'tcx, M::PointerTag, M::AllocExtra>>> { - let align = M::enforce_alignment(&self.extra).then_some(align); + let align = M::enforce_alignment(self).then_some(align); let ptr_and_alloc = self.check_and_deref_ptr( ptr, size, align, CheckInAllocMsg::MemoryAccessTest, |alloc_id, offset, ptr| { - let alloc = self.get_raw(alloc_id)?; + let alloc = self.get_alloc_raw(alloc_id)?; Ok((alloc.size(), alloc.align, (alloc_id, offset, ptr, alloc))) }, )?; if let Some((alloc_id, offset, ptr, alloc)) = ptr_and_alloc { let range = alloc_range(offset, size); - M::memory_read(&self.extra, &alloc.extra, ptr.provenance, range)?; - Ok(Some(AllocRef { alloc, range, tcx: self.tcx, alloc_id })) + M::memory_read(*self.tcx, &self.machine, &alloc.extra, ptr.provenance, range)?; + Ok(Some(AllocRef { alloc, range, tcx: *self.tcx, alloc_id })) } else { // Even in this branch we have to be sure that we actually access the allocation, in // order to ensure that `static FOO: Type = FOO;` causes a cycle error instead of @@ -596,7 +589,7 @@ pub fn get<'a>( /// Return the `extra` field of the given allocation. pub fn get_alloc_extra<'a>(&'a self, id: AllocId) -> InterpResult<'tcx, &'a M::AllocExtra> { - Ok(&self.get_raw(id)?.extra) + Ok(&self.get_alloc_raw(id)?.extra) } /// Gives raw mutable access to the `Allocation`, without bounds or alignment checks. @@ -604,16 +597,15 @@ pub fn get_alloc_extra<'a>(&'a self, id: AllocId) -> InterpResult<'tcx, &'a M::A /// /// Also returns a ptr to `self.extra` so that the caller can use it in parallel with the /// allocation. - fn get_raw_mut( + fn get_alloc_raw_mut( &mut self, id: AllocId, - ) -> InterpResult<'tcx, (&mut Allocation<M::PointerTag, M::AllocExtra>, &mut M::MemoryExtra)> - { + ) -> InterpResult<'tcx, (&mut Allocation<M::PointerTag, M::AllocExtra>, &mut M)> { // We have "NLL problem case #3" here, which cannot be worked around without loss of // efficiency even for the common case where the key is in the map. // <https://rust-lang.github.io/rfcs/2094-nll.html#problem-case-3-conditional-control-flow-across-functions> // (Cannot use `get_mut_or` since `get_global_alloc` needs `&self`.) - if self.alloc_map.get_mut(id).is_none() { + if self.memory.alloc_map.get_mut(id).is_none() { // Slow path. // Allocation not found locally, go look global. let alloc = self.get_global_alloc(id, /*is_write*/ true)?; @@ -621,18 +613,18 @@ fn get_raw_mut( "I got a global allocation that I have to copy but the machine does \ not expect that to happen", ); - self.alloc_map.insert(id, (MemoryKind::Machine(kind), alloc.into_owned())); + self.memory.alloc_map.insert(id, (MemoryKind::Machine(kind), alloc.into_owned())); } - let (_kind, alloc) = self.alloc_map.get_mut(id).unwrap(); + let (_kind, alloc) = self.memory.alloc_map.get_mut(id).unwrap(); if alloc.mutability == Mutability::Not { throw_ub!(WriteToReadOnly(id)) } - Ok((alloc, &mut self.extra)) + Ok((alloc, &mut self.machine)) } /// "Safe" (bounds and align-checked) allocation access. - pub fn get_mut<'a>( + pub fn get_ptr_alloc_mut<'a>( &'a mut self, ptr: Pointer<Option<M::PointerTag>>, size: Size, @@ -640,12 +632,12 @@ pub fn get_mut<'a>( ) -> InterpResult<'tcx, Option<AllocRefMut<'a, 'tcx, M::PointerTag, M::AllocExtra>>> { let parts = self.get_ptr_access(ptr, size, align)?; if let Some((alloc_id, offset, ptr)) = parts { - let tcx = self.tcx; + let tcx = *self.tcx; // FIXME: can we somehow avoid looking up the allocation twice here? // We cannot call `get_raw_mut` inside `check_and_deref_ptr` as that would duplicate `&mut self`. - let (alloc, extra) = self.get_raw_mut(alloc_id)?; + let (alloc, machine) = self.get_alloc_raw_mut(alloc_id)?; let range = alloc_range(offset, size); - M::memory_written(extra, &mut alloc.extra, ptr.provenance, range)?; + M::memory_written(tcx, machine, &mut alloc.extra, ptr.provenance, range)?; Ok(Some(AllocRefMut { alloc, range, tcx, alloc_id })) } else { Ok(None) @@ -656,16 +648,16 @@ pub fn get_mut<'a>( pub fn get_alloc_extra_mut<'a>( &'a mut self, id: AllocId, - ) -> InterpResult<'tcx, (&'a mut M::AllocExtra, &'a mut M::MemoryExtra)> { - let (alloc, memory_extra) = self.get_raw_mut(id)?; - Ok((&mut alloc.extra, memory_extra)) + ) -> InterpResult<'tcx, (&'a mut M::AllocExtra, &'a mut M)> { + let (alloc, machine) = self.get_alloc_raw_mut(id)?; + Ok((&mut alloc.extra, machine)) } /// Obtain the size and alignment of an allocation, even if that allocation has /// been deallocated. /// /// If `liveness` is `AllocCheck::MaybeDead`, this function always returns `Ok`. - pub fn get_size_and_align( + pub fn get_alloc_size_and_align( &self, id: AllocId, liveness: AllocCheck, @@ -674,7 +666,7 @@ pub fn get_size_and_align( // Don't use `self.get_raw` here as that will // a) cause cycles in case `id` refers to a static // b) duplicate a global's allocation in miri - if let Some((_, alloc)) = self.alloc_map.get(id) { + if let Some((_, alloc)) = self.memory.alloc_map.get(id) { return Ok((alloc.size(), alloc.align)); } @@ -713,6 +705,7 @@ pub fn get_size_and_align( // Deallocated pointers are allowed, we should be able to find // them in the map. Ok(*self + .memory .dead_alloc_map .get(&id) .expect("deallocated pointers should all be recorded in `dead_alloc_map`")) @@ -724,7 +717,7 @@ pub fn get_size_and_align( } fn get_fn_alloc(&self, id: AllocId) -> Option<FnVal<'tcx, M::ExtraFnVal>> { - if let Some(extra) = self.extra_fn_ptr_map.get(&id) { + if let Some(extra) = self.memory.extra_fn_ptr_map.get(&id) { Some(FnVal::Other(*extra)) } else { match self.tcx.get_global_alloc(id) { @@ -734,12 +727,12 @@ fn get_fn_alloc(&self, id: AllocId) -> Option<FnVal<'tcx, M::ExtraFnVal>> { } } - pub fn get_fn( + pub fn get_ptr_fn( &self, ptr: Pointer<Option<M::PointerTag>>, ) -> InterpResult<'tcx, FnVal<'tcx, M::ExtraFnVal>> { trace!("get_fn({:?})", ptr); - let (alloc_id, offset, _ptr) = self.ptr_get_alloc(ptr)?; + let (alloc_id, offset, _ptr) = self.ptr_get_alloc_id(ptr)?; if offset.bytes() != 0 { throw_ub!(InvalidFunctionPointer(Pointer::new(alloc_id, offset))) } @@ -747,8 +740,8 @@ pub fn get_fn( .ok_or_else(|| err_ub!(InvalidFunctionPointer(Pointer::new(alloc_id, offset))).into()) } - pub fn mark_immutable(&mut self, id: AllocId) -> InterpResult<'tcx> { - self.get_raw_mut(id)?.0.mutability = Mutability::Not; + pub fn alloc_mark_immutable(&mut self, id: AllocId) -> InterpResult<'tcx> { + self.get_alloc_raw_mut(id)?.0.mutability = Mutability::Not; Ok(()) } @@ -765,7 +758,7 @@ pub fn dump_alloc<'a>(&'a self, id: AllocId) -> DumpAllocs<'a, 'mir, 'tcx, M> { pub fn dump_allocs<'a>(&'a self, mut allocs: Vec<AllocId>) -> DumpAllocs<'a, 'mir, 'tcx, M> { allocs.sort(); allocs.dedup(); - DumpAllocs { mem: self, allocs } + DumpAllocs { ecx: self, allocs } } /// Print leaked memory. Allocations reachable from `static_roots` or a `Global` allocation @@ -775,14 +768,15 @@ pub fn leak_report(&self, static_roots: &[AllocId]) -> usize { let reachable = { let mut reachable = FxHashSet::default(); let global_kind = M::GLOBAL_KIND.map(MemoryKind::Machine); - let mut todo: Vec<_> = self.alloc_map.filter_map_collect(move |&id, &(kind, _)| { - if Some(kind) == global_kind { Some(id) } else { None } - }); + let mut todo: Vec<_> = + self.memory.alloc_map.filter_map_collect(move |&id, &(kind, _)| { + if Some(kind) == global_kind { Some(id) } else { None } + }); todo.extend(static_roots); while let Some(id) = todo.pop() { if reachable.insert(id) { // This is a new allocation, add its relocations to `todo`. - if let Some((_, alloc)) = self.alloc_map.get(id) { + if let Some((_, alloc)) = self.memory.alloc_map.get(id) { todo.extend(alloc.relocations().values().map(|tag| tag.get_alloc_id())); } } @@ -791,7 +785,7 @@ pub fn leak_report(&self, static_roots: &[AllocId]) -> usize { }; // All allocations that are *not* `reachable` and *not* `may_leak` are considered leaking. - let leaks: Vec<_> = self.alloc_map.filter_map_collect(|&id, &(kind, _)| { + let leaks: Vec<_> = self.memory.alloc_map.filter_map_collect(|&id, &(kind, _)| { if kind.may_leak() || reachable.contains(&id) { None } else { Some(id) } }); let n = leaks.len(); @@ -800,17 +794,12 @@ pub fn leak_report(&self, static_roots: &[AllocId]) -> usize { } n } - - /// This is used by [priroda](https://github.com/oli-obk/priroda) - pub fn alloc_map(&self) -> &M::MemoryMap { - &self.alloc_map - } } #[doc(hidden)] /// There's no way to use this directly, it's just a helper struct for the `dump_alloc(s)` methods. pub struct DumpAllocs<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> { - mem: &'a Memory<'mir, 'tcx, M>, + ecx: &'a InterpCx<'mir, 'tcx, M>, allocs: Vec<AllocId>, } @@ -840,25 +829,25 @@ fn write_allocation_track_relocs<'tcx, Tag: Provenance, Extra>( } write!(fmt, "{}", id)?; - match self.mem.alloc_map.get(id) { + match self.ecx.memory.alloc_map.get(id) { Some(&(kind, ref alloc)) => { // normal alloc write!(fmt, " ({}, ", kind)?; write_allocation_track_relocs( &mut *fmt, - self.mem.tcx, + *self.ecx.tcx, &mut allocs_to_print, alloc, )?; } None => { // global alloc - match self.mem.tcx.get_global_alloc(id) { + match self.ecx.tcx.get_global_alloc(id) { Some(GlobalAlloc::Memory(alloc)) => { write!(fmt, " (unchanged global, ")?; write_allocation_track_relocs( &mut *fmt, - self.mem.tcx, + *self.ecx.tcx, &mut allocs_to_print, alloc.inner(), )?; @@ -867,7 +856,7 @@ fn write_allocation_track_relocs<'tcx, Tag: Provenance, Extra>( write!(fmt, " (fn: {})", func)?; } Some(GlobalAlloc::Static(did)) => { - write!(fmt, " (static: {})", self.mem.tcx.def_path_str(did))?; + write!(fmt, " (static: {})", self.ecx.tcx.def_path_str(did))?; } None => { write!(fmt, " (deallocated)")?; @@ -923,16 +912,16 @@ pub fn check_bytes(&self, range: AllocRange, allow_uninit_and_ptr: bool) -> Inte } } -impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { +impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// Reads the given number of bytes from memory. Returns them as a slice. /// /// Performs appropriate bounds checks. - pub fn read_bytes( + pub fn read_bytes_ptr( &self, ptr: Pointer<Option<M::PointerTag>>, size: Size, ) -> InterpResult<'tcx, &[u8]> { - let Some(alloc_ref) = self.get(ptr, size, Align::ONE)? else { + let Some(alloc_ref) = self.get_ptr_alloc(ptr, size, Align::ONE)? else { // zero-sized access return Ok(&[]); }; @@ -947,7 +936,7 @@ pub fn read_bytes( /// Writes the given stream of bytes into memory. /// /// Performs appropriate bounds checks. - pub fn write_bytes( + pub fn write_bytes_ptr( &mut self, ptr: Pointer<Option<M::PointerTag>>, src: impl IntoIterator<Item = u8>, @@ -958,7 +947,7 @@ pub fn write_bytes( assert_eq!(lower, len, "can only write iterators with a precise length"); let size = Size::from_bytes(len); - let Some(alloc_ref) = self.get_mut(ptr, size, Align::ONE)? else { + let Some(alloc_ref) = self.get_ptr_alloc_mut(ptr, size, Align::ONE)? else { // zero-sized access assert_matches!( src.next(), @@ -984,7 +973,7 @@ pub fn write_bytes( Ok(()) } - pub fn copy( + pub fn mem_copy( &mut self, src: Pointer<Option<M::PointerTag>>, src_align: Align, @@ -993,10 +982,10 @@ pub fn copy( size: Size, nonoverlapping: bool, ) -> InterpResult<'tcx> { - self.copy_repeatedly(src, src_align, dest, dest_align, size, 1, nonoverlapping) + self.mem_copy_repeatedly(src, src_align, dest, dest_align, size, 1, nonoverlapping) } - pub fn copy_repeatedly( + pub fn mem_copy_repeatedly( &mut self, src: Pointer<Option<M::PointerTag>>, src_align: Align, @@ -1019,9 +1008,9 @@ pub fn copy_repeatedly( // Zero-sized *source*, that means dst is also zero-sized and we have nothing to do. return Ok(()); }; - let src_alloc = self.get_raw(src_alloc_id)?; + let src_alloc = self.get_alloc_raw(src_alloc_id)?; let src_range = alloc_range(src_offset, size); - M::memory_read(&self.extra, &src_alloc.extra, src.provenance, src_range)?; + M::memory_read(*tcx, &self.machine, &src_alloc.extra, src.provenance, src_range)?; // We need the `dest` ptr for the next operation, so we get it now. // We already did the source checks and called the hooks so we are good to return early. let Some((dest_alloc_id, dest_offset, dest)) = dest_parts else { @@ -1044,9 +1033,9 @@ pub fn copy_repeatedly( let compressed = src_alloc.compress_uninit_range(src_range); // Destination alloc preparations and access hooks. - let (dest_alloc, extra) = self.get_raw_mut(dest_alloc_id)?; + let (dest_alloc, extra) = self.get_alloc_raw_mut(dest_alloc_id)?; let dest_range = alloc_range(dest_offset, size * num_copies); - M::memory_written(extra, &mut dest_alloc.extra, dest.provenance, dest_range)?; + M::memory_written(*tcx, extra, &mut dest_alloc.extra, dest.provenance, dest_range)?; let dest_bytes = dest_alloc .get_bytes_mut_ptr(&tcx, dest_range) .map_err(|e| e.to_interp_error(dest_alloc_id))? @@ -1112,7 +1101,7 @@ pub fn copy_repeatedly( } /// Machine pointer introspection. -impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { +impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { pub fn scalar_to_ptr(&self, scalar: Scalar<M::PointerTag>) -> Pointer<Option<M::PointerTag>> { // We use `to_bits_or_ptr_internal` since we are just implementing the method people need to // call to force getting out a pointer. @@ -1129,9 +1118,32 @@ pub fn scalar_to_ptr(&self, scalar: Scalar<M::PointerTag>) -> Pointer<Option<M:: } } + /// Test if this value might be null. + /// If the machine does not support ptr-to-int casts, this is conservative. + pub fn scalar_may_be_null(&self, scalar: Scalar<M::PointerTag>) -> bool { + match scalar.try_to_int() { + Ok(int) => int.is_null(), + Err(_) => { + // Can only happen during CTFE. + let ptr = self.scalar_to_ptr(scalar); + match self.ptr_try_get_alloc_id(ptr) { + Ok((alloc_id, offset, _)) => { + let (size, _align) = self + .get_alloc_size_and_align(alloc_id, AllocCheck::MaybeDead) + .expect("alloc info with MaybeDead cannot fail"); + // If the pointer is out-of-bounds, it may be null. + // Note that one-past-the-end (offset == size) is still inbounds, and never null. + offset > size + } + Err(_offset) => bug!("a non-int scalar is always a pointer"), + } + } + } + } + /// Turning a "maybe pointer" into a proper pointer (and some information /// about where it points), or an absolute address. - pub fn ptr_try_get_alloc( + pub fn ptr_try_get_alloc_id( &self, ptr: Pointer<Option<M::PointerTag>>, ) -> Result<(AllocId, Size, Pointer<M::PointerTag>), u64> { @@ -1146,11 +1158,11 @@ pub fn ptr_try_get_alloc( /// Turning a "maybe pointer" into a proper pointer (and some information about where it points). #[inline(always)] - pub fn ptr_get_alloc( + pub fn ptr_get_alloc_id( &self, ptr: Pointer<Option<M::PointerTag>>, ) -> InterpResult<'tcx, (AllocId, Size, Pointer<M::PointerTag>)> { - self.ptr_try_get_alloc(ptr).map_err(|offset| { + self.ptr_try_get_alloc_id(ptr).map_err(|offset| { err_ub!(DanglingIntPointer(offset, CheckInAllocMsg::InboundsTest)).into() }) }
diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index 9000567..ee1ba60 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs
@@ -10,7 +10,7 @@ use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Printer}; use rustc_middle::ty::{ConstInt, DelaySpanBugEmitted, Ty}; use rustc_middle::{mir, ty}; -use rustc_target::abi::{Abi, HasDataLayout, Size, TagEncoding}; +use rustc_target::abi::{self, Abi, HasDataLayout, Size, TagEncoding}; use rustc_target::abi::{VariantIdx, Variants}; use super::{ @@ -257,7 +257,7 @@ fn try_read_immediate_from_mplace( return Ok(None); } - let Some(alloc) = self.get_alloc(mplace)? else { + let Some(alloc) = self.get_place_alloc(mplace)? else { return Ok(Some(ImmTy { // zero-sized type imm: Scalar::ZST.into(), @@ -265,16 +265,24 @@ fn try_read_immediate_from_mplace( })); }; + // It may seem like all types with `Scalar` or `ScalarPair` ABI are fair game at this point. + // However, `MaybeUninit<u64>` is considered a `Scalar` as far as its layout is concerned -- + // and yet cannot be represented by an interpreter `Scalar`, since we have to handle the + // case where some of the bytes are initialized and others are not. So, we need an extra + // check that walks over the type of `mplace` to make sure it is truly correct to treat this + // like a `Scalar` (or `ScalarPair`). match mplace.layout.abi { - Abi::Scalar(..) => { + Abi::Scalar(abi::Scalar::Initialized { .. }) => { let scalar = alloc.read_scalar(alloc_range(Size::ZERO, mplace.layout.size))?; Ok(Some(ImmTy { imm: scalar.into(), layout: mplace.layout })) } - Abi::ScalarPair(a, b) => { + Abi::ScalarPair( + abi::Scalar::Initialized { value: a, .. }, + abi::Scalar::Initialized { value: b, .. }, + ) => { // We checked `ptr_align` above, so all fields will have the alignment they need. // We would anyway check against `ptr_align.restrict_for_offset(b_offset)`, // which `ptr.offset(b_offset)` cannot possibly fail to satisfy. - let (a, b) = (a.value, b.value); let (a_size, b_size) = (a.size(self), b.size(self)); let b_offset = a_size.align_to(b.align(self).abi); assert!(b_offset.bytes() > 0); // we later use the offset to tell apart the fields @@ -340,7 +348,7 @@ pub fn read_pointer( // Turn the wide MPlace into a string (must already be dereferenced!) pub fn read_str(&self, mplace: &MPlaceTy<'tcx, M::PointerTag>) -> InterpResult<'tcx, &str> { let len = mplace.len(self)?; - let bytes = self.memory.read_bytes(mplace.ptr, Size::from_bytes(len))?; + let bytes = self.read_bytes_ptr(mplace.ptr, Size::from_bytes(len))?; let str = std::str::from_utf8(bytes).map_err(|err| err_ub!(InvalidStr(err)))?; Ok(str) } @@ -676,7 +684,7 @@ pub fn read_discriminant( // may be a pointer. This is `tag_val.layout`; we just use it for sanity checks. // Get layout for tag. - let tag_layout = self.layout_of(tag_scalar_layout.value.to_int_ty(*self.tcx))?; + let tag_layout = self.layout_of(tag_scalar_layout.primitive().to_int_ty(*self.tcx))?; // Read tag and sanity-check `tag_layout`. let tag_val = self.read_immediate(&self.operand_field(op, tag_field)?)?;
diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 5b8d74b..5f7f52e 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs
@@ -306,25 +306,25 @@ pub fn deref_operand( } #[inline] - pub(super) fn get_alloc( + pub(super) fn get_place_alloc( &self, place: &MPlaceTy<'tcx, M::PointerTag>, ) -> InterpResult<'tcx, Option<AllocRef<'_, 'tcx, M::PointerTag, M::AllocExtra>>> { assert!(!place.layout.is_unsized()); assert!(!place.meta.has_meta()); let size = place.layout.size; - self.memory.get(place.ptr, size, place.align) + self.get_ptr_alloc(place.ptr, size, place.align) } #[inline] - pub(super) fn get_alloc_mut( + pub(super) fn get_place_alloc_mut( &mut self, place: &MPlaceTy<'tcx, M::PointerTag>, ) -> InterpResult<'tcx, Option<AllocRefMut<'_, 'tcx, M::PointerTag, M::AllocExtra>>> { assert!(!place.layout.is_unsized()); assert!(!place.meta.has_meta()); let size = place.layout.size; - self.memory.get_mut(place.ptr, size, place.align) + self.get_ptr_alloc_mut(place.ptr, size, place.align) } /// Check if this mplace is dereferenceable and sufficiently aligned. @@ -337,8 +337,8 @@ fn check_mplace_access( .size_and_align_of_mplace(&mplace)? .unwrap_or((mplace.layout.size, mplace.layout.align.abi)); assert!(mplace.mplace.align <= align, "dynamic alignment less strict than static one?"); - let align = M::enforce_alignment(&self.memory.extra).then_some(align); - self.memory.check_ptr_access_align(mplace.ptr, size, align.unwrap_or(Align::ONE), msg)?; + let align = M::enforce_alignment(self).then_some(align); + self.check_ptr_access_align(mplace.ptr, size, align.unwrap_or(Align::ONE), msg)?; Ok(()) } @@ -748,7 +748,7 @@ fn write_immediate_to_mplace_no_validate( // Invalid places are a thing: the return place of a diverging function let tcx = *self.tcx; - let Some(mut alloc) = self.get_alloc_mut(dest)? else { + let Some(mut alloc) = self.get_place_alloc_mut(dest)? else { // zero-sized access return Ok(()); }; @@ -772,13 +772,11 @@ fn write_immediate_to_mplace_no_validate( // We checked `ptr_align` above, so all fields will have the alignment they need. // We would anyway check against `ptr_align.restrict_for_offset(b_offset)`, // which `ptr.offset(b_offset)` cannot possibly fail to satisfy. - let (a, b) = match dest.layout.abi { - Abi::ScalarPair(a, b) => (a.value, b.value), - _ => span_bug!( + let Abi::ScalarPair(a, b) = dest.layout.abi else { span_bug!( self.cur_span(), "write_immediate_to_mplace: invalid ScalarPair layout: {:#?}", dest.layout - ), + ) }; let (a_size, b_size) = (a.size(&tcx), b.size(&tcx)); let b_offset = a_size.align_to(b.align(&tcx).abi); @@ -857,8 +855,7 @@ fn copy_op_no_validate( }); assert_eq!(src.meta, dest.meta, "Can only copy between equally-sized instances"); - self.memory - .copy(src.ptr, src.align, dest.ptr, dest.align, size, /*nonoverlapping*/ true) + self.mem_copy(src.ptr, src.align, dest.ptr, dest.align, size, /*nonoverlapping*/ true) } /// Copies the data from an operand to a place. The layouts may disagree, but they must @@ -942,7 +939,7 @@ pub fn force_allocation_maybe_sized( let (size, align) = self .size_and_align_of(&meta, &local_layout)? .expect("Cannot allocate for non-dyn-sized type"); - let ptr = self.memory.allocate(size, align, MemoryKind::Stack)?; + let ptr = self.allocate_ptr(size, align, MemoryKind::Stack)?; let mplace = MemPlace { ptr: ptr.into(), align, meta }; if let LocalValue::Live(Operand::Immediate(value)) = local_val { // Preserve old value. @@ -979,7 +976,7 @@ pub fn allocate( layout: TyAndLayout<'tcx>, kind: MemoryKind<M::MemoryKind>, ) -> InterpResult<'static, MPlaceTy<'tcx, M::PointerTag>> { - let ptr = self.memory.allocate(layout.size, layout.align.abi, kind)?; + let ptr = self.allocate_ptr(layout.size, layout.align.abi, kind)?; Ok(MPlaceTy::from_aligned_ptr(ptr.into(), layout)) } @@ -990,7 +987,7 @@ pub fn allocate_str( kind: MemoryKind<M::MemoryKind>, mutbl: Mutability, ) -> MPlaceTy<'tcx, M::PointerTag> { - let ptr = self.memory.allocate_bytes(str.as_bytes(), Align::ONE, kind, mutbl); + let ptr = self.allocate_bytes_ptr(str.as_bytes(), Align::ONE, kind, mutbl); let meta = Scalar::from_machine_usize(u64::try_from(str.len()).unwrap(), self); let mplace = MemPlace { ptr: ptr.into(), align: Align::ONE, meta: MemPlaceMeta::Meta(meta) }; @@ -1047,7 +1044,7 @@ pub fn write_discriminant( // raw discriminants for enums are isize or bigger during // their computation, but the in-memory tag is the smallest possible // representation - let size = tag_layout.value.size(self); + let size = tag_layout.size(self); let tag_val = size.truncate(discr_val); let tag_dest = self.place_field(dest, tag_field)?; @@ -1071,7 +1068,7 @@ pub fn write_discriminant( .expect("overflow computing relative variant idx"); // We need to use machine arithmetic when taking into account `niche_start`: // tag_val = variant_index_relative + niche_start_val - let tag_layout = self.layout_of(tag_layout.value.to_int_ty(*self.tcx))?; + let tag_layout = self.layout_of(tag_layout.primitive().to_int_ty(*self.tcx))?; let niche_start_val = ImmTy::from_uint(niche_start, tag_layout); let variant_index_relative_val = ImmTy::from_uint(variant_index_relative, tag_layout);
diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index 4272bfd..84563daa 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs
@@ -225,7 +225,7 @@ pub fn eval_rvalue_into_place( if length == 0 { // Nothing to copy... but let's still make sure that `dest` as a place is valid. - self.get_alloc_mut(&dest)?; + self.get_place_alloc_mut(&dest)?; } else { // Write the src to the first element. let first = self.mplace_field(&dest, 0)?; @@ -241,7 +241,7 @@ pub fn eval_rvalue_into_place( // that place might be more aligned than its type mandates (a `u8` array could // be 4-aligned if it sits at the right spot in a struct). Instead we use // `first.layout.align`, i.e., the alignment given by the type. - self.memory.copy_repeatedly( + self.mem_copy_repeatedly( first_ptr, first.align, rest_ptr,
diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs index d333584..c2a38c6 100644 --- a/compiler/rustc_const_eval/src/interpret/terminator.rs +++ b/compiler/rustc_const_eval/src/interpret/terminator.rs
@@ -72,7 +72,7 @@ pub(super) fn eval_terminator( let (fn_val, fn_abi, with_caller_location) = match *func.layout.ty.kind() { ty::FnPtr(_sig) => { let fn_ptr = self.read_pointer(&func)?; - let fn_val = self.memory.get_fn(fn_ptr)?; + let fn_val = self.get_ptr_fn(fn_ptr)?; (fn_val, self.fn_abi_of_fn_ptr(fn_sig_binder, extra_args)?, false) } ty::FnDef(def_id, substs) => { @@ -189,12 +189,15 @@ fn check_argument_compat( // that will take care to make it UB to leave the range, just // like for transmute). (abi::Abi::Scalar(caller), abi::Abi::Scalar(callee)) => { - caller.value == callee.value + caller.primitive() == callee.primitive() } ( abi::Abi::ScalarPair(caller1, caller2), abi::Abi::ScalarPair(callee1, callee2), - ) => caller1.value == callee1.value && caller2.value == callee2.value, + ) => { + caller1.primitive() == callee1.primitive() + && caller2.primitive() == callee2.primitive() + } // Be conservative _ => false, }
diff --git a/compiler/rustc_const_eval/src/interpret/traits.rs b/compiler/rustc_const_eval/src/interpret/traits.rs index fc60a40..5cf3807 100644 --- a/compiler/rustc_const_eval/src/interpret/traits.rs +++ b/compiler/rustc_const_eval/src/interpret/traits.rs
@@ -32,7 +32,7 @@ pub fn get_vtable( let vtable_allocation = self.tcx.vtable_allocation((ty, poly_trait_ref)); - let vtable_ptr = self.memory.global_base_pointer(Pointer::from(vtable_allocation))?; + let vtable_ptr = self.global_base_pointer(Pointer::from(vtable_allocation))?; Ok(vtable_ptr.into()) } @@ -48,11 +48,10 @@ pub fn get_vtable_slot( let ptr_size = self.pointer_size(); let vtable_slot = vtable.offset(ptr_size * idx, self)?; let vtable_slot = self - .memory - .get(vtable_slot, ptr_size, self.tcx.data_layout.pointer_align.abi)? + .get_ptr_alloc(vtable_slot, ptr_size, self.tcx.data_layout.pointer_align.abi)? .expect("cannot be a ZST"); let fn_ptr = self.scalar_to_ptr(vtable_slot.read_ptr_sized(Size::ZERO)?.check_init()?); - self.memory.get_fn(fn_ptr) + self.get_ptr_fn(fn_ptr) } /// Returns the drop fn instance as well as the actual dynamic type. @@ -63,8 +62,7 @@ pub fn read_drop_type_from_vtable( let pointer_size = self.pointer_size(); // We don't care about the pointee type; we just want a pointer. let vtable = self - .memory - .get( + .get_ptr_alloc( vtable, pointer_size * u64::try_from(COMMON_VTABLE_ENTRIES.len()).unwrap(), self.tcx.data_layout.pointer_align.abi, @@ -77,7 +75,7 @@ pub fn read_drop_type_from_vtable( .check_init()?; // We *need* an instance here, no other kind of function value, to be able // to determine the type. - let drop_instance = self.memory.get_fn(self.scalar_to_ptr(drop_fn))?.as_instance()?; + let drop_instance = self.get_ptr_fn(self.scalar_to_ptr(drop_fn))?.as_instance()?; trace!("Found drop fn: {:?}", drop_instance); let fn_sig = drop_instance.ty(*self.tcx, self.param_env).fn_sig(*self.tcx); let fn_sig = self.tcx.normalize_erasing_late_bound_regions(self.param_env, fn_sig); @@ -99,8 +97,7 @@ pub fn read_size_and_align_from_vtable( // We check for `size = 3 * ptr_size`, which covers the drop fn (unused here), // the size, and the align (which we read below). let vtable = self - .memory - .get( + .get_ptr_alloc( vtable, pointer_size * u64::try_from(COMMON_VTABLE_ENTRIES.len()).unwrap(), self.tcx.data_layout.pointer_align.abi, @@ -132,8 +129,7 @@ pub fn read_new_vtable_after_trait_upcasting_from_vtable( let vtable_slot = vtable.offset(pointer_size * idx, self)?; let new_vtable = self - .memory - .get(vtable_slot, pointer_size, self.tcx.data_layout.pointer_align.abi)? + .get_ptr_alloc(vtable_slot, pointer_size, self.tcx.data_layout.pointer_align.abi)? .expect("cannot be a ZST"); let new_vtable = self.scalar_to_ptr(new_vtable.read_ptr_sized(Size::ZERO)?.check_init()?);
diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 9da7f5e..349806d 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs
@@ -315,7 +315,7 @@ fn check_wide_ptr_meta( let vtable = self.ecx.scalar_to_ptr(meta.unwrap_meta()); // Direct call to `check_ptr_access_align` checks alignment even on CTFE machines. try_validation!( - self.ecx.memory.check_ptr_access_align( + self.ecx.check_ptr_access_align( vtable, 3 * self.ecx.tcx.data_layout.pointer_size, // drop, size, align self.ecx.tcx.data_layout.pointer_align.abi, @@ -403,7 +403,7 @@ fn check_safe_pointer( .unwrap_or_else(|| (place.layout.size, place.layout.align.abi)); // Direct call to `check_ptr_access_align` checks alignment even on CTFE machines. try_validation!( - self.ecx.memory.check_ptr_access_align( + self.ecx.check_ptr_access_align( place.ptr, size, align, @@ -432,7 +432,7 @@ fn check_safe_pointer( if let Some(ref mut ref_tracking) = self.ref_tracking { // Proceed recursively even for ZST, no reason to skip them! // `!` is a ZST and we want to validate it. - if let Ok((alloc_id, _offset, _ptr)) = self.ecx.memory.ptr_try_get_alloc(place.ptr) { + if let Ok((alloc_id, _offset, _ptr)) = self.ecx.ptr_try_get_alloc_id(place.ptr) { // Special handling for pointers to statics (irrespective of their type). let alloc_kind = self.ecx.tcx.get_global_alloc(alloc_id); if let Some(GlobalAlloc::Static(did)) = alloc_kind { @@ -579,7 +579,7 @@ fn try_visit_primitive( if let Some(_) = self.ref_tracking { let ptr = self.ecx.scalar_to_ptr(value); let _fn = try_validation!( - self.ecx.memory.get_fn(ptr), + self.ecx.get_ptr_fn(ptr), self.path, err_ub!(DanglingIntPointer(0, _)) => { "a null function pointer" }, @@ -629,12 +629,25 @@ fn visit_scalar( op: &OpTy<'tcx, M::PointerTag>, scalar_layout: ScalarAbi, ) -> InterpResult<'tcx> { - if scalar_layout.valid_range.is_full_for(op.layout.size) { + // We check `is_full_range` in a slightly complicated way because *if* we are checking + // number validity, then we want to ensure that `Scalar::Initialized` is indeed initialized, + // i.e. that we go over the `check_init` below. + let is_full_range = match scalar_layout { + ScalarAbi::Initialized { valid_range, .. } => { + if M::enforce_number_validity(self.ecx) { + false // not "full" since uninit is not accepted + } else { + valid_range.is_full_for(op.layout.size) + } + } + ScalarAbi::Union { .. } => true, + }; + if is_full_range { // Nothing to check return Ok(()); } - // At least one value is excluded. - let valid_range = scalar_layout.valid_range; + // We have something to check. + let valid_range = scalar_layout.valid_range(self.ecx); let WrappingRange { start, end } = valid_range; let max_value = op.layout.size.unsigned_int_max(); assert!(end <= max_value); @@ -647,9 +660,11 @@ fn visit_scalar( expected { "something {}", wrapping_range_format(valid_range, max_value) }, ); let bits = match value.try_to_int() { + Ok(int) => int.assert_bits(op.layout.size), Err(_) => { // So this is a pointer then, and casting to an int failed. // Can only happen during CTFE. + // We support 2 kinds of ranges here: full range, and excluding zero. if start == 1 && end == max_value { // Only null is the niche. So make sure the ptr is NOT null. if self.ecx.scalar_may_be_null(value) { @@ -660,7 +675,11 @@ fn visit_scalar( wrapping_range_format(valid_range, max_value) } ) + } else { + return Ok(()); } + } else if scalar_layout.valid_range(self.ecx).is_full_for(op.layout.size) { + // Easy. (This is reachable if `enforce_number_validity` is set.) return Ok(()); } else { // Conservatively, we reject, because the pointer *could* have a bad @@ -674,9 +693,8 @@ fn visit_scalar( ) } } - Ok(int) => int.assert_bits(op.layout.size), }; - // Now compare. This is slightly subtle because this is a special "wrap-around" range. + // Now compare. if valid_range.contains(bits) { Ok(()) } else { @@ -825,7 +843,7 @@ fn visit_aggregate( let mplace = op.assert_mem_place(); // strings are never immediate let len = mplace.len(self.ecx)?; try_validation!( - self.ecx.memory.read_bytes(mplace.ptr, Size::from_bytes(len)), + self.ecx.read_bytes_ptr(mplace.ptr, Size::from_bytes(len)), self.path, err_ub!(InvalidUninitBytes(..)) => { "uninitialized data in `str`" }, err_unsup!(ReadPointerAsBytes) => { "a pointer in `str`" }, @@ -861,7 +879,7 @@ fn visit_aggregate( // to reject those pointers, we just do not have the machinery to // talk about parts of a pointer. // We also accept uninit, for consistency with the slow path. - let Some(alloc) = self.ecx.memory.get(mplace.ptr, size, mplace.align)? else { + let Some(alloc) = self.ecx.get_ptr_alloc(mplace.ptr, size, mplace.align)? else { // Size 0, nothing more to check. return Ok(()); };
diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index 69f96d0..febdd0e 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs
@@ -1172,9 +1172,13 @@ pub fn catch_with_exit_code(f: impl FnOnce() -> interface::Result<()>) -> i32 { /// When `install_ice_hook` is called, this function will be called as the panic /// hook. pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) { + let fallback_bundle = + rustc_errors::fallback_fluent_bundle(false).expect("failed to load fallback fluent bundle"); let emitter = Box::new(rustc_errors::emitter::EmitterWriter::stderr( rustc_errors::ColorConfig::Auto, None, + None, + fallback_bundle, false, false, None, @@ -1209,7 +1213,7 @@ pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) { } for note in &xs { - handler.note_without_error(note); + handler.note_without_error(note.as_ref()); } // If backtraces are enabled, also print the query stack
diff --git a/compiler/rustc_error_messages/Cargo.toml b/compiler/rustc_error_messages/Cargo.toml new file mode 100644 index 0000000..fc84c7c --- /dev/null +++ b/compiler/rustc_error_messages/Cargo.toml
@@ -0,0 +1,18 @@ +[package] +name = "rustc_error_messages" +version = "0.0.0" +edition = "2021" + +[lib] +doctest = false + +[dependencies] +fluent-bundle = "0.15.2" +fluent-syntax = "0.11" +intl-memoizer = "0.5.1" +rustc_data_structures = { path = "../rustc_data_structures" } +rustc_serialize = { path = "../rustc_serialize" } +rustc_span = { path = "../rustc_span" } +rustc_macros = { path = "../rustc_macros" } +tracing = "0.1" +unic-langid = { version = "0.9.0", features = ["macros"] }
diff --git a/compiler/rustc_error_messages/locales/en-US/diagnostics.ftl b/compiler/rustc_error_messages/locales/en-US/diagnostics.ftl new file mode 100644 index 0000000..336e7a6 --- /dev/null +++ b/compiler/rustc_error_messages/locales/en-US/diagnostics.ftl
@@ -0,0 +1,87 @@ +parser-struct-literal-body-without-path = + struct literal body without path + .suggestion = you might have forgotten to add the struct literal inside the block + +typeck-field-multiply-specified-in-initializer = + field `{$ident}` specified more than once + .label = used more than once + .previous-use-label = first use of `{$ident}` + +typeck-unrecognized-atomic-operation = + unrecognized atomic operation function: `{$op}` + .label = unrecognized atomic operation + +typeck-wrong-number-of-generic-arguments-to-intrinsic = + intrinsic has wrong number of {$descr} parameters: found {$found}, expected {$expected} + .label = expected {$expected} {$descr} {$expected -> + [one] parameter + *[other] parameters + } + +typeck-unrecognized-intrinsic-function = + unrecognized intrinsic function: `{$name}` + .label = unrecognized intrinsic + +typeck-lifetimes-or-bounds-mismatch-on-trait = + lifetime parameters or bounds on {$item_kind} `{$ident}` do not match the trait declaration + .label = lifetimes do not match {$item_kind} in trait + .generics-label = lifetimes in impl do not match this {$item_kind} in trait + +typeck-drop-impl-on-wrong-item = + the `Drop` trait may only be implemented for structs, enums, and unions + .label = must be a struct, enum, or union + +typeck-field-already-declared = + field `{$field_name}` is already declared + .label = field already declared + .previous-decl-label = `{$field_name}` first declared here + +typeck-copy-impl-on-type-with-dtor = + the trait `Copy` may not be implemented for this type; the type has a destructor + .label = `Copy` not allowed on types with destructors + +typeck-multiple-relaxed-default-bounds = + type parameter has more than one relaxed default bound, only one is supported + +typeck-copy-impl-on-non-adt = + the trait `Copy` may not be implemented for this type + .label = type is not a structure or enumeration + +typeck-trait-object-declared-with-no-traits = + at least one trait is required for an object type + +typeck-ambiguous-lifetime-bound = + ambiguous lifetime bound, explicit lifetime bound required + +typeck-assoc-type-binding-not-allowed = + associated type bindings are not allowed here + .label = associated type not allowed here + +typeck-functional-record-update-on-non-struct = + functional record update syntax requires a struct + +typeck-typeof-reserved-keyword-used = + `typeof` is a reserved keyword but unimplemented + .label = reserved keyword + +typeck-return-stmt-outside-of-fn-body = + return statement outside of function body + .encl-body-label = the return is part of this body... + .encl-fn-label = ...not the enclosing function body + +typeck-yield-expr-outside-of-generator = + yield expression outside of generator literal + +typeck-struct-expr-non-exhaustive = + cannot create non-exhaustive {$what} using struct expression + +typeck-method-call-on-unknown-type = + the type of this value must be known to call a method on a raw pointer on it + +typeck-value-of-associated-struct-already-specified = + the value of the associated type `{$item_name}` (from trait `{$def_path}`) is already specified + .label = re-bound here + .previous-bound-label = `{$item_name}` bound here first + +typeck-address-of-temporary-taken = cannot take address of a temporary + .label = temporary value
diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs new file mode 100644 index 0000000..88f3b54 --- /dev/null +++ b/compiler/rustc_error_messages/src/lib.rs
@@ -0,0 +1,390 @@ +#![feature(let_chains)] +#![feature(path_try_exists)] + +use fluent_bundle::FluentResource; +use fluent_syntax::parser::ParserError; +use rustc_data_structures::sync::Lrc; +use rustc_macros::{Decodable, Encodable}; +use rustc_span::Span; +use std::borrow::Cow; +use std::error::Error; +use std::fmt; +use std::fs; +use std::io; +use std::path::Path; +use tracing::{instrument, trace}; + +#[cfg(parallel_compiler)] +use intl_memoizer::concurrent::IntlLangMemoizer; +#[cfg(not(parallel_compiler))] +use intl_memoizer::IntlLangMemoizer; + +pub use fluent_bundle::{FluentArgs, FluentError, FluentValue}; +pub use unic_langid::{langid, LanguageIdentifier}; + +static FALLBACK_FLUENT_RESOURCE: &'static str = include_str!("../locales/en-US/diagnostics.ftl"); + +pub type FluentBundle = fluent_bundle::bundle::FluentBundle<FluentResource, IntlLangMemoizer>; + +#[cfg(parallel_compiler)] +fn new_bundle(locales: Vec<LanguageIdentifier>) -> FluentBundle { + FluentBundle::new_concurrent(locales) +} + +#[cfg(not(parallel_compiler))] +fn new_bundle(locales: Vec<LanguageIdentifier>) -> FluentBundle { + FluentBundle::new(locales) +} + +#[derive(Debug)] +pub enum TranslationBundleError { + /// Failed to read from `.ftl` file. + ReadFtl(io::Error), + /// Failed to parse contents of `.ftl` file. + ParseFtl(ParserError), + /// Failed to add `FluentResource` to `FluentBundle`. + AddResource(FluentError), + /// `$sysroot/share/locale/$locale` does not exist. + MissingLocale(io::Error), + /// Cannot read directory entries of `$sysroot/share/locale/$locale`. + ReadLocalesDir(io::Error), + /// Cannot read directory entry of `$sysroot/share/locale/$locale`. + ReadLocalesDirEntry(io::Error), + /// `$sysroot/share/locale/$locale` is not a directory. + LocaleIsNotDir, +} + +impl fmt::Display for TranslationBundleError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + TranslationBundleError::ReadFtl(e) => write!(f, "could not read ftl file: {}", e), + TranslationBundleError::ParseFtl(e) => { + write!(f, "could not parse ftl file: {}", e) + } + TranslationBundleError::AddResource(e) => write!(f, "failed to add resource: {}", e), + TranslationBundleError::MissingLocale(e) => { + write!(f, "missing locale directory: {}", e) + } + TranslationBundleError::ReadLocalesDir(e) => { + write!(f, "could not read locales dir: {}", e) + } + TranslationBundleError::ReadLocalesDirEntry(e) => { + write!(f, "could not read locales dir entry: {}", e) + } + TranslationBundleError::LocaleIsNotDir => { + write!(f, "`$sysroot/share/locales/$locale` is not a directory") + } + } + } +} + +impl Error for TranslationBundleError { + fn source(&self) -> Option<&(dyn Error + 'static)> { + match self { + TranslationBundleError::ReadFtl(e) => Some(e), + TranslationBundleError::ParseFtl(e) => Some(e), + TranslationBundleError::AddResource(e) => Some(e), + TranslationBundleError::MissingLocale(e) => Some(e), + TranslationBundleError::ReadLocalesDir(e) => Some(e), + TranslationBundleError::ReadLocalesDirEntry(e) => Some(e), + TranslationBundleError::LocaleIsNotDir => None, + } + } +} + +impl From<(FluentResource, Vec<ParserError>)> for TranslationBundleError { + fn from((_, mut errs): (FluentResource, Vec<ParserError>)) -> Self { + TranslationBundleError::ParseFtl(errs.pop().expect("failed ftl parse with no errors")) + } +} + +impl From<Vec<FluentError>> for TranslationBundleError { + fn from(mut errs: Vec<FluentError>) -> Self { + TranslationBundleError::AddResource( + errs.pop().expect("failed adding resource to bundle with no errors"), + ) + } +} + +/// Returns Fluent bundle with the user's locale resources from +/// `$sysroot/share/locale/$requested_locale/*.ftl`. +/// +/// If `-Z additional-ftl-path` was provided, load that resource and add it to the bundle +/// (overriding any conflicting messages). +#[instrument(level = "trace")] +pub fn fluent_bundle( + sysroot: &Path, + requested_locale: Option<LanguageIdentifier>, + additional_ftl_path: Option<&Path>, + with_directionality_markers: bool, +) -> Result<Option<Lrc<FluentBundle>>, TranslationBundleError> { + if requested_locale.is_none() && additional_ftl_path.is_none() { + return Ok(None); + } + + let fallback_locale = langid!("en-US"); + let requested_fallback_locale = requested_locale.as_ref() == Some(&fallback_locale); + + // If there is only `-Z additional-ftl-path`, assume locale is "en-US", otherwise use user + // provided locale. + let locale = requested_locale.clone().unwrap_or(fallback_locale); + trace!(?locale); + let mut bundle = new_bundle(vec![locale]); + + // Fluent diagnostics can insert directionality isolation markers around interpolated variables + // indicating that there may be a shift from right-to-left to left-to-right text (or + // vice-versa). These are disabled because they are sometimes visible in the error output, but + // may be worth investigating in future (for example: if type names are left-to-right and the + // surrounding diagnostic messages are right-to-left, then these might be helpful). + bundle.set_use_isolating(with_directionality_markers); + + // If the user requests the default locale then don't try to load anything. + if !requested_fallback_locale && let Some(requested_locale) = requested_locale { + let mut sysroot = sysroot.to_path_buf(); + sysroot.push("share"); + sysroot.push("locale"); + sysroot.push(requested_locale.to_string()); + trace!(?sysroot); + + let _ = sysroot.try_exists().map_err(TranslationBundleError::MissingLocale)?; + + if !sysroot.is_dir() { + return Err(TranslationBundleError::LocaleIsNotDir); + } + + for entry in sysroot.read_dir().map_err(TranslationBundleError::ReadLocalesDir)? { + let entry = entry.map_err(TranslationBundleError::ReadLocalesDirEntry)?; + let path = entry.path(); + trace!(?path); + if path.extension().and_then(|s| s.to_str()) != Some("ftl") { + trace!("skipping"); + continue; + } + + let resource_str = + fs::read_to_string(path).map_err(TranslationBundleError::ReadFtl)?; + let resource = + FluentResource::try_new(resource_str).map_err(TranslationBundleError::from)?; + trace!(?resource); + bundle.add_resource(resource).map_err(TranslationBundleError::from)?; + } + } + + if let Some(additional_ftl_path) = additional_ftl_path { + let resource_str = + fs::read_to_string(additional_ftl_path).map_err(TranslationBundleError::ReadFtl)?; + let resource = + FluentResource::try_new(resource_str).map_err(TranslationBundleError::from)?; + trace!(?resource); + bundle.add_resource_overriding(resource); + } + + let bundle = Lrc::new(bundle); + Ok(Some(bundle)) +} + +/// Return the default `FluentBundle` with standard "en-US" diagnostic messages. +#[instrument(level = "trace")] +pub fn fallback_fluent_bundle( + with_directionality_markers: bool, +) -> Result<Lrc<FluentBundle>, TranslationBundleError> { + let fallback_resource = FluentResource::try_new(FALLBACK_FLUENT_RESOURCE.to_string()) + .map_err(TranslationBundleError::from)?; + trace!(?fallback_resource); + let mut fallback_bundle = new_bundle(vec![langid!("en-US")]); + // See comment in `fluent_bundle`. + fallback_bundle.set_use_isolating(with_directionality_markers); + fallback_bundle.add_resource(fallback_resource).map_err(TranslationBundleError::from)?; + let fallback_bundle = Lrc::new(fallback_bundle); + Ok(fallback_bundle) +} + +/// Identifier for the Fluent message/attribute corresponding to a diagnostic message. +type FluentId = Cow<'static, str>; + +/// Abstraction over a message in a diagnostic to support both translatable and non-translatable +/// diagnostic messages. +/// +/// Intended to be removed once diagnostics are entirely translatable. +#[derive(Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)] +pub enum DiagnosticMessage { + /// Non-translatable diagnostic message. + // FIXME(davidtwco): can a `Cow<'static, str>` be used here? + Str(String), + /// Identifier for a Fluent message (with optional attribute) corresponding to the diagnostic + /// message. + /// + /// <https://projectfluent.org/fluent/guide/hello.html> + /// <https://projectfluent.org/fluent/guide/attributes.html> + FluentIdentifier(FluentId, Option<FluentId>), +} + +impl DiagnosticMessage { + /// Returns the `String` contained within the `DiagnosticMessage::Str` variant, assuming that + /// this diagnostic message is of the legacy, non-translatable variety. Panics if this + /// assumption does not hold. + /// + /// Don't use this - it exists to support some places that do comparison with diagnostic + /// strings. + pub fn expect_str(&self) -> &str { + match self { + DiagnosticMessage::Str(s) => s, + _ => panic!("expected non-translatable diagnostic message"), + } + } + + /// Create a `DiagnosticMessage` for the provided Fluent identifier. + pub fn fluent(id: impl Into<FluentId>) -> Self { + DiagnosticMessage::FluentIdentifier(id.into(), None) + } + + /// Create a `DiagnosticMessage` for the provided Fluent identifier and attribute. + pub fn fluent_attr(id: impl Into<FluentId>, attr: impl Into<FluentId>) -> Self { + DiagnosticMessage::FluentIdentifier(id.into(), Some(attr.into())) + } +} + +/// `From` impl that enables existing diagnostic calls to functions which now take +/// `impl Into<DiagnosticMessage>` to continue to work as before. +impl<S: Into<String>> From<S> for DiagnosticMessage { + fn from(s: S) -> Self { + DiagnosticMessage::Str(s.into()) + } +} + +/// A span together with some additional data. +#[derive(Clone, Debug)] +pub struct SpanLabel { + /// The span we are going to include in the final snippet. + pub span: Span, + + /// Is this a primary span? This is the "locus" of the message, + /// and is indicated with a `^^^^` underline, versus `----`. + pub is_primary: bool, + + /// What label should we attach to this span (if any)? + pub label: Option<DiagnosticMessage>, +} + +/// A collection of `Span`s. +/// +/// Spans have two orthogonal attributes: +/// +/// - They can be *primary spans*. In this case they are the locus of +/// the error, and would be rendered with `^^^`. +/// - They can have a *label*. In this case, the label is written next +/// to the mark in the snippet when we render. +#[derive(Clone, Debug, Hash, PartialEq, Eq, Encodable, Decodable)] +pub struct MultiSpan { + primary_spans: Vec<Span>, + span_labels: Vec<(Span, DiagnosticMessage)>, +} + +impl MultiSpan { + #[inline] + pub fn new() -> MultiSpan { + MultiSpan { primary_spans: vec![], span_labels: vec![] } + } + + pub fn from_span(primary_span: Span) -> MultiSpan { + MultiSpan { primary_spans: vec![primary_span], span_labels: vec![] } + } + + pub fn from_spans(mut vec: Vec<Span>) -> MultiSpan { + vec.sort(); + MultiSpan { primary_spans: vec, span_labels: vec![] } + } + + pub fn push_span_label(&mut self, span: Span, label: impl Into<DiagnosticMessage>) { + self.span_labels.push((span, label.into())); + } + + /// Selects the first primary span (if any). + pub fn primary_span(&self) -> Option<Span> { + self.primary_spans.first().cloned() + } + + /// Returns all primary spans. + pub fn primary_spans(&self) -> &[Span] { + &self.primary_spans + } + + /// Returns `true` if any of the primary spans are displayable. + pub fn has_primary_spans(&self) -> bool { + self.primary_spans.iter().any(|sp| !sp.is_dummy()) + } + + /// Returns `true` if this contains only a dummy primary span with any hygienic context. + pub fn is_dummy(&self) -> bool { + let mut is_dummy = true; + for span in &self.primary_spans { + if !span.is_dummy() { + is_dummy = false; + } + } + is_dummy + } + + /// Replaces all occurrences of one Span with another. Used to move `Span`s in areas that don't + /// display well (like std macros). Returns whether replacements occurred. + pub fn replace(&mut self, before: Span, after: Span) -> bool { + let mut replacements_occurred = false; + for primary_span in &mut self.primary_spans { + if *primary_span == before { + *primary_span = after; + replacements_occurred = true; + } + } + for span_label in &mut self.span_labels { + if span_label.0 == before { + span_label.0 = after; + replacements_occurred = true; + } + } + replacements_occurred + } + + /// Returns the strings to highlight. We always ensure that there + /// is an entry for each of the primary spans -- for each primary + /// span `P`, if there is at least one label with span `P`, we return + /// those labels (marked as primary). But otherwise we return + /// `SpanLabel` instances with empty labels. + pub fn span_labels(&self) -> Vec<SpanLabel> { + let is_primary = |span| self.primary_spans.contains(&span); + + let mut span_labels = self + .span_labels + .iter() + .map(|&(span, ref label)| SpanLabel { + span, + is_primary: is_primary(span), + label: Some(label.clone()), + }) + .collect::<Vec<_>>(); + + for &span in &self.primary_spans { + if !span_labels.iter().any(|sl| sl.span == span) { + span_labels.push(SpanLabel { span, is_primary: true, label: None }); + } + } + + span_labels + } + + /// Returns `true` if any of the span labels is displayable. + pub fn has_span_labels(&self) -> bool { + self.span_labels.iter().any(|(sp, _)| !sp.is_dummy()) + } +} + +impl From<Span> for MultiSpan { + fn from(span: Span) -> MultiSpan { + MultiSpan::from_span(span) + } +} + +impl From<Vec<Span>> for MultiSpan { + fn from(spans: Vec<Span>) -> MultiSpan { + MultiSpan::from_spans(spans) + } +}
diff --git a/compiler/rustc_errors/Cargo.toml b/compiler/rustc_errors/Cargo.toml index 4846dc4..5f91998 100644 --- a/compiler/rustc_errors/Cargo.toml +++ b/compiler/rustc_errors/Cargo.toml
@@ -8,6 +8,7 @@ [dependencies] tracing = "0.1" +rustc_error_messages = { path = "../rustc_error_messages" } rustc_serialize = { path = "../rustc_serialize" } rustc_span = { path = "../rustc_span" } rustc_macros = { path = "../rustc_macros" }
diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs index 5f59eba..003fd1e 100644 --- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs +++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs
@@ -7,16 +7,23 @@ use crate::emitter::FileWithAnnotatedLines; use crate::snippet::Line; -use crate::{CodeSuggestion, Diagnostic, DiagnosticId, Emitter, Level, SubDiagnostic}; +use crate::{ + CodeSuggestion, Diagnostic, DiagnosticId, DiagnosticMessage, Emitter, FluentBundle, Level, + MultiSpan, Style, SubDiagnostic, +}; use annotate_snippets::display_list::{DisplayList, FormatOptions}; use annotate_snippets::snippet::*; use rustc_data_structures::sync::Lrc; +use rustc_error_messages::FluentArgs; use rustc_span::source_map::SourceMap; -use rustc_span::{MultiSpan, SourceFile}; +use rustc_span::SourceFile; /// Generates diagnostics using annotate-snippet pub struct AnnotateSnippetEmitterWriter { source_map: Option<Lrc<SourceMap>>, + fluent_bundle: Option<Lrc<FluentBundle>>, + fallback_bundle: Lrc<FluentBundle>, + /// If true, hides the longer explanation text short_message: bool, /// If true, will normalize line numbers with `LL` to prevent noise in UI test diffs. @@ -28,8 +35,10 @@ pub struct AnnotateSnippetEmitterWriter { impl Emitter for AnnotateSnippetEmitterWriter { /// The entry point for the diagnostics generation fn emit_diagnostic(&mut self, diag: &Diagnostic) { + let fluent_args = self.to_fluent_args(diag.args()); + let mut children = diag.children.clone(); - let (mut primary_span, suggestions) = self.primary_span_formatted(&diag); + let (mut primary_span, suggestions) = self.primary_span_formatted(&diag, &fluent_args); self.fix_multispans_in_extern_macros_and_render_macro_backtrace( &self.source_map, @@ -41,7 +50,8 @@ fn emit_diagnostic(&mut self, diag: &Diagnostic) { self.emit_messages_default( &diag.level, - diag.message(), + &diag.message, + &fluent_args, &diag.code, &primary_span, &children, @@ -53,6 +63,14 @@ fn source_map(&self) -> Option<&Lrc<SourceMap>> { self.source_map.as_ref() } + fn fluent_bundle(&self) -> Option<&Lrc<FluentBundle>> { + self.fluent_bundle.as_ref() + } + + fn fallback_fluent_bundle(&self) -> &Lrc<FluentBundle> { + &self.fallback_bundle + } + fn should_show_explain(&self) -> bool { !self.short_message } @@ -82,10 +100,19 @@ fn annotation_type_for_level(level: Level) -> AnnotationType { impl AnnotateSnippetEmitterWriter { pub fn new( source_map: Option<Lrc<SourceMap>>, + fluent_bundle: Option<Lrc<FluentBundle>>, + fallback_bundle: Lrc<FluentBundle>, short_message: bool, macro_backtrace: bool, ) -> Self { - Self { source_map, short_message, ui_testing: false, macro_backtrace } + Self { + source_map, + fluent_bundle, + fallback_bundle, + short_message, + ui_testing: false, + macro_backtrace, + } } /// Allows to modify `Self` to enable or disable the `ui_testing` flag. @@ -99,12 +126,14 @@ pub fn ui_testing(mut self, ui_testing: bool) -> Self { fn emit_messages_default( &mut self, level: &Level, - message: String, + messages: &[(DiagnosticMessage, Style)], + args: &FluentArgs<'_>, code: &Option<DiagnosticId>, msp: &MultiSpan, _children: &[SubDiagnostic], _suggestions: &[CodeSuggestion], ) { + let message = self.translate_messages(messages, args); if let Some(source_map) = &self.source_map { // Make sure our primary file comes first let primary_lo = if let Some(ref primary_span) = msp.primary_span().as_ref() { @@ -120,8 +149,7 @@ fn emit_messages_default( // should be done if it happens return; }; - let mut annotated_files = - FileWithAnnotatedLines::collect_annotations(msp, &self.source_map); + let mut annotated_files = FileWithAnnotatedLines::collect_annotations(self, args, msp); if let Ok(pos) = annotated_files.binary_search_by(|x| x.file.name.cmp(&primary_lo.file.name)) {
diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 00ecbbb..ecb3cdd 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs
@@ -1,15 +1,16 @@ use crate::snippet::Style; -use crate::CodeSuggestion; -use crate::Level; -use crate::Substitution; -use crate::SubstitutionPart; -use crate::SuggestionStyle; -use crate::ToolMetadata; +use crate::{ + CodeSuggestion, DiagnosticMessage, Level, MultiSpan, Substitution, SubstitutionPart, + SuggestionStyle, ToolMetadata, +}; use rustc_data_structures::stable_map::FxHashMap; +use rustc_error_messages::FluentValue; use rustc_lint_defs::{Applicability, LintExpectationId}; use rustc_serialize::json::Json; use rustc_span::edition::LATEST_STABLE_EDITION; -use rustc_span::{MultiSpan, Span, DUMMY_SP}; +use rustc_span::symbol::{Ident, Symbol}; +use rustc_span::{Span, DUMMY_SP}; +use std::borrow::Cow; use std::fmt; use std::hash::{Hash, Hasher}; @@ -18,6 +19,66 @@ #[derive(Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)] pub struct SuggestionsDisabled; +/// Simplified version of `FluentArg` that can implement `Encodable` and `Decodable`. Collection of +/// `DiagnosticArg` are converted to `FluentArgs` (consuming the collection) at the start of +/// diagnostic emission. +pub type DiagnosticArg<'source> = (Cow<'source, str>, DiagnosticArgValue<'source>); + +/// Simplified version of `FluentValue` that can implement `Encodable` and `Decodable`. Converted +/// to a `FluentValue` by the emitter to be used in diagnostic translation. +#[derive(Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)] +pub enum DiagnosticArgValue<'source> { + Str(Cow<'source, str>), + Number(usize), +} + +/// Converts a value of a type into a `DiagnosticArg` (typically a field of a `SessionDiagnostic` +/// struct). Implemented as a custom trait rather than `From` so that it is implemented on the type +/// being converted rather than on `DiagnosticArgValue`, which enables types from other `rustc_*` +/// crates to implement this. +pub trait IntoDiagnosticArg { + fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static>; +} + +impl IntoDiagnosticArg for String { + fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + DiagnosticArgValue::Str(Cow::Owned(self)) + } +} + +impl IntoDiagnosticArg for Symbol { + fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + self.to_ident_string().into_diagnostic_arg() + } +} + +impl IntoDiagnosticArg for Ident { + fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + self.to_string().into_diagnostic_arg() + } +} + +impl<'a> IntoDiagnosticArg for &'a str { + fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + self.to_string().into_diagnostic_arg() + } +} + +impl IntoDiagnosticArg for usize { + fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + DiagnosticArgValue::Number(self) + } +} + +impl<'source> Into<FluentValue<'source>> for DiagnosticArgValue<'source> { + fn into(self) -> FluentValue<'source> { + match self { + DiagnosticArgValue::Str(s) => From::from(s), + DiagnosticArgValue::Number(n) => From::from(n), + } + } +} + #[must_use] #[derive(Clone, Debug, Encodable, Decodable)] pub struct Diagnostic { @@ -25,11 +86,12 @@ pub struct Diagnostic { // outside of what methods in this crate themselves allow. crate level: Level, - pub message: Vec<(String, Style)>, + pub message: Vec<(DiagnosticMessage, Style)>, pub code: Option<DiagnosticId>, pub span: MultiSpan, pub children: Vec<SubDiagnostic>, pub suggestions: Result<Vec<CodeSuggestion>, SuggestionsDisabled>, + args: Vec<DiagnosticArg<'static>>, /// This is not used for highlighting or rendering any error message. Rather, it can be used /// as a sort key to sort a buffer of diagnostics. By default, it is the primary span of @@ -52,7 +114,7 @@ pub enum DiagnosticId { #[derive(Clone, Debug, PartialEq, Hash, Encodable, Decodable)] pub struct SubDiagnostic { pub level: Level, - pub message: Vec<(String, Style)>, + pub message: Vec<(DiagnosticMessage, Style)>, pub span: MultiSpan, pub render_span: Option<MultiSpan>, } @@ -105,18 +167,23 @@ pub fn content(&self) -> &str { } impl Diagnostic { - pub fn new(level: Level, message: &str) -> Self { + pub fn new<M: Into<DiagnosticMessage>>(level: Level, message: M) -> Self { Diagnostic::new_with_code(level, None, message) } - pub fn new_with_code(level: Level, code: Option<DiagnosticId>, message: &str) -> Self { + pub fn new_with_code<M: Into<DiagnosticMessage>>( + level: Level, + code: Option<DiagnosticId>, + message: M, + ) -> Self { Diagnostic { level, - message: vec![(message.to_owned(), Style::NoStyle)], + message: vec![(message.into(), Style::NoStyle)], code, span: MultiSpan::new(), children: vec![], suggestions: Ok(vec![]), + args: vec![], sort_span: DUMMY_SP, is_lint: false, } @@ -210,7 +277,7 @@ pub fn downgrade_to_delayed_bug(&mut self) -> &mut Self { /// /// This span is *not* considered a ["primary span"][`MultiSpan`]; only /// the `Span` supplied when creating the diagnostic is primary. - pub fn span_label<T: Into<String>>(&mut self, span: Span, label: T) -> &mut Self { + pub fn span_label(&mut self, span: Span, label: impl Into<DiagnosticMessage>) -> &mut Self { self.span.push_span_label(span, label.into()); self } @@ -234,7 +301,7 @@ pub fn replace_span_with(&mut self, after: Span) -> &mut Self { self.set_span(after); for span_label in before.span_labels() { if let Some(label) = span_label.label { - self.span_label(after, label); + self.span.push_span_label(after, label); } } self @@ -328,59 +395,84 @@ pub fn note_trait_signature(&mut self, name: String, signature: String) -> &mut } /// Add a note attached to this diagnostic. - pub fn note(&mut self, msg: &str) -> &mut Self { + pub fn note(&mut self, msg: impl Into<DiagnosticMessage>) -> &mut Self { self.sub(Level::Note, msg, MultiSpan::new(), None); self } - pub fn highlighted_note(&mut self, msg: Vec<(String, Style)>) -> &mut Self { + pub fn highlighted_note<M: Into<DiagnosticMessage>>( + &mut self, + msg: Vec<(M, Style)>, + ) -> &mut Self { self.sub_with_highlights(Level::Note, msg, MultiSpan::new(), None); self } /// Prints the span with a note above it. /// This is like [`Diagnostic::note()`], but it gets its own span. - pub fn note_once(&mut self, msg: &str) -> &mut Self { + pub fn note_once(&mut self, msg: impl Into<DiagnosticMessage>) -> &mut Self { self.sub(Level::OnceNote, msg, MultiSpan::new(), None); self } /// Prints the span with a note above it. /// This is like [`Diagnostic::note()`], but it gets its own span. - pub fn span_note<S: Into<MultiSpan>>(&mut self, sp: S, msg: &str) -> &mut Self { + pub fn span_note<S: Into<MultiSpan>>( + &mut self, + sp: S, + msg: impl Into<DiagnosticMessage>, + ) -> &mut Self { self.sub(Level::Note, msg, sp.into(), None); self } /// Prints the span with a note above it. /// This is like [`Diagnostic::note()`], but it gets its own span. - pub fn span_note_once<S: Into<MultiSpan>>(&mut self, sp: S, msg: &str) -> &mut Self { + pub fn span_note_once<S: Into<MultiSpan>>( + &mut self, + sp: S, + msg: impl Into<DiagnosticMessage>, + ) -> &mut Self { self.sub(Level::OnceNote, msg, sp.into(), None); self } /// Add a warning attached to this diagnostic. - pub fn warn(&mut self, msg: &str) -> &mut Self { + pub fn warn(&mut self, msg: impl Into<DiagnosticMessage>) -> &mut Self { self.sub(Level::Warning, msg, MultiSpan::new(), None); self } /// Prints the span with a warning above it. /// This is like [`Diagnostic::warn()`], but it gets its own span. - pub fn span_warn<S: Into<MultiSpan>>(&mut self, sp: S, msg: &str) -> &mut Self { + pub fn span_warn<S: Into<MultiSpan>>( + &mut self, + sp: S, + msg: impl Into<DiagnosticMessage>, + ) -> &mut Self { self.sub(Level::Warning, msg, sp.into(), None); self } /// Add a help message attached to this diagnostic. - pub fn help(&mut self, msg: &str) -> &mut Self { + pub fn help(&mut self, msg: impl Into<DiagnosticMessage>) -> &mut Self { self.sub(Level::Help, msg, MultiSpan::new(), None); self } + /// Add a help message attached to this diagnostic with a customizable highlighted message. + pub fn highlighted_help(&mut self, msg: Vec<(String, Style)>) -> &mut Self { + self.sub_with_highlights(Level::Help, msg, MultiSpan::new(), None); + self + } + /// Prints the span with some help above it. /// This is like [`Diagnostic::help()`], but it gets its own span. - pub fn span_help<S: Into<MultiSpan>>(&mut self, sp: S, msg: &str) -> &mut Self { + pub fn span_help<S: Into<MultiSpan>>( + &mut self, + sp: S, + msg: impl Into<DiagnosticMessage>, + ) -> &mut Self { self.sub(Level::Help, msg, sp.into(), None); self } @@ -416,7 +508,7 @@ fn push_suggestion(&mut self, suggestion: CodeSuggestion) { /// In other words, multiple changes need to be applied as part of this suggestion. pub fn multipart_suggestion( &mut self, - msg: &str, + msg: impl Into<DiagnosticMessage>, suggestion: Vec<(Span, String)>, applicability: Applicability, ) -> &mut Self { @@ -432,7 +524,7 @@ pub fn multipart_suggestion( /// In other words, multiple changes need to be applied as part of this suggestion. pub fn multipart_suggestion_verbose( &mut self, - msg: &str, + msg: impl Into<DiagnosticMessage>, suggestion: Vec<(Span, String)>, applicability: Applicability, ) -> &mut Self { @@ -446,7 +538,7 @@ pub fn multipart_suggestion_verbose( /// [`Diagnostic::multipart_suggestion()`] but you can set the [`SuggestionStyle`]. pub fn multipart_suggestion_with_style( &mut self, - msg: &str, + msg: impl Into<DiagnosticMessage>, suggestion: Vec<(Span, String)>, applicability: Applicability, style: SuggestionStyle, @@ -459,7 +551,7 @@ pub fn multipart_suggestion_with_style( .map(|(span, snippet)| SubstitutionPart { snippet, span }) .collect(), }], - msg: msg.to_owned(), + msg: msg.into(), style, applicability, tool_metadata: Default::default(), @@ -475,7 +567,7 @@ pub fn multipart_suggestion_with_style( /// improve understandability. pub fn tool_only_multipart_suggestion( &mut self, - msg: &str, + msg: impl Into<DiagnosticMessage>, suggestion: Vec<(Span, String)>, applicability: Applicability, ) -> &mut Self { @@ -487,7 +579,7 @@ pub fn tool_only_multipart_suggestion( .map(|(span, snippet)| SubstitutionPart { snippet, span }) .collect(), }], - msg: msg.to_owned(), + msg: msg.into(), style: SuggestionStyle::CompletelyHidden, applicability, tool_metadata: Default::default(), @@ -515,7 +607,7 @@ pub fn tool_only_multipart_suggestion( pub fn span_suggestion( &mut self, sp: Span, - msg: &str, + msg: impl Into<DiagnosticMessage>, suggestion: String, applicability: Applicability, ) -> &mut Self { @@ -533,7 +625,7 @@ pub fn span_suggestion( pub fn span_suggestion_with_style( &mut self, sp: Span, - msg: &str, + msg: impl Into<DiagnosticMessage>, suggestion: String, applicability: Applicability, style: SuggestionStyle, @@ -542,7 +634,7 @@ pub fn span_suggestion_with_style( substitutions: vec![Substitution { parts: vec![SubstitutionPart { snippet: suggestion, span: sp }], }], - msg: msg.to_owned(), + msg: msg.into(), style, applicability, tool_metadata: Default::default(), @@ -554,7 +646,7 @@ pub fn span_suggestion_with_style( pub fn span_suggestion_verbose( &mut self, sp: Span, - msg: &str, + msg: impl Into<DiagnosticMessage>, suggestion: String, applicability: Applicability, ) -> &mut Self { @@ -573,7 +665,7 @@ pub fn span_suggestion_verbose( pub fn span_suggestions( &mut self, sp: Span, - msg: &str, + msg: impl Into<DiagnosticMessage>, suggestions: impl Iterator<Item = String>, applicability: Applicability, ) -> &mut Self { @@ -585,7 +677,7 @@ pub fn span_suggestions( .collect(); self.push_suggestion(CodeSuggestion { substitutions, - msg: msg.to_owned(), + msg: msg.into(), style: SuggestionStyle::ShowCode, applicability, tool_metadata: Default::default(), @@ -597,7 +689,7 @@ pub fn span_suggestions( /// See also [`Diagnostic::span_suggestion()`]. pub fn multipart_suggestions( &mut self, - msg: &str, + msg: impl Into<DiagnosticMessage>, suggestions: impl Iterator<Item = Vec<(Span, String)>>, applicability: Applicability, ) -> &mut Self { @@ -610,7 +702,7 @@ pub fn multipart_suggestions( .collect(), }) .collect(), - msg: msg.to_owned(), + msg: msg.into(), style: SuggestionStyle::ShowCode, applicability, tool_metadata: Default::default(), @@ -624,7 +716,7 @@ pub fn multipart_suggestions( pub fn span_suggestion_short( &mut self, sp: Span, - msg: &str, + msg: impl Into<DiagnosticMessage>, suggestion: String, applicability: Applicability, ) -> &mut Self { @@ -647,7 +739,7 @@ pub fn span_suggestion_short( pub fn span_suggestion_hidden( &mut self, sp: Span, - msg: &str, + msg: impl Into<DiagnosticMessage>, suggestion: String, applicability: Applicability, ) -> &mut Self { @@ -668,7 +760,7 @@ pub fn span_suggestion_hidden( pub fn tool_only_span_suggestion( &mut self, sp: Span, - msg: &str, + msg: impl Into<DiagnosticMessage>, suggestion: String, applicability: Applicability, ) -> &mut Self { @@ -686,13 +778,13 @@ pub fn tool_only_span_suggestion( /// the suggestion in a tool-specific way, as it may not even directly involve Rust code. pub fn tool_only_suggestion_with_metadata( &mut self, - msg: &str, + msg: impl Into<DiagnosticMessage>, applicability: Applicability, tool_metadata: Json, ) { self.push_suggestion(CodeSuggestion { substitutions: vec![], - msg: msg.to_owned(), + msg: msg.into(), style: SuggestionStyle::CompletelyHidden, applicability, tool_metadata: ToolMetadata::new(tool_metadata), @@ -726,16 +818,25 @@ pub fn get_code(&self) -> Option<DiagnosticId> { self.code.clone() } - pub fn set_primary_message<M: Into<String>>(&mut self, msg: M) -> &mut Self { + pub fn set_primary_message(&mut self, msg: impl Into<DiagnosticMessage>) -> &mut Self { self.message[0] = (msg.into(), Style::NoStyle); self } - pub fn message(&self) -> String { - self.message.iter().map(|i| i.0.as_str()).collect::<String>() + pub fn args(&self) -> &[DiagnosticArg<'static>] { + &self.args } - pub fn styled_message(&self) -> &Vec<(String, Style)> { + pub fn set_arg( + &mut self, + name: impl Into<Cow<'static, str>>, + arg: DiagnosticArgValue<'static>, + ) -> &mut Self { + self.args.push((name.into(), arg.into())); + self + } + + pub fn styled_message(&self) -> &Vec<(DiagnosticMessage, Style)> { &self.message } @@ -746,13 +847,13 @@ pub fn styled_message(&self) -> &Vec<(String, Style)> { pub fn sub( &mut self, level: Level, - message: &str, + message: impl Into<DiagnosticMessage>, span: MultiSpan, render_span: Option<MultiSpan>, ) { let sub = SubDiagnostic { level, - message: vec![(message.to_owned(), Style::NoStyle)], + message: vec![(message.into(), Style::NoStyle)], span, render_span, }; @@ -761,13 +862,14 @@ pub fn sub( /// Convenience function for internal use, clients should use one of the /// public methods above. - fn sub_with_highlights( + fn sub_with_highlights<M: Into<DiagnosticMessage>>( &mut self, level: Level, - message: Vec<(String, Style)>, + mut message: Vec<(M, Style)>, span: MultiSpan, render_span: Option<MultiSpan>, ) { + let message = message.drain(..).map(|m| (m.0.into(), m.1)).collect(); let sub = SubDiagnostic { level, message, span, render_span }; self.children.push(sub); } @@ -777,7 +879,7 @@ fn keys( &self, ) -> ( &Level, - &Vec<(String, Style)>, + &Vec<(DiagnosticMessage, Style)>, &Option<DiagnosticId>, &MultiSpan, &Result<Vec<CodeSuggestion>, SuggestionsDisabled>, @@ -808,13 +910,3 @@ fn eq(&self, other: &Self) -> bool { self.keys() == other.keys() } } - -impl SubDiagnostic { - pub fn message(&self) -> String { - self.message.iter().map(|i| i.0.as_str()).collect::<String>() - } - - pub fn styled_message(&self) -> &Vec<(String, Style)> { - &self.message - } -}
diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index 853243e..74e0f74 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs
@@ -1,8 +1,10 @@ -use crate::{Diagnostic, DiagnosticId, DiagnosticStyledString, ErrorGuaranteed}; -use crate::{Handler, Level, StashKey}; +use crate::diagnostic::DiagnosticArgValue; +use crate::{Diagnostic, DiagnosticId, DiagnosticMessage, DiagnosticStyledString, ErrorGuaranteed}; +use crate::{Handler, Level, MultiSpan, StashKey}; use rustc_lint_defs::Applicability; -use rustc_span::{MultiSpan, Span}; +use rustc_span::Span; +use std::borrow::Cow; use std::fmt::{self, Debug}; use std::marker::PhantomData; use std::ops::{Deref, DerefMut}; @@ -99,7 +101,10 @@ impl IsError<{ Level::Error { lint: false } }> for () {} impl<'a> DiagnosticBuilder<'a, ErrorGuaranteed> { /// Convenience function for internal use, clients should use one of the /// `struct_*` methods on [`Handler`]. - crate fn new_guaranteeing_error<const L: Level>(handler: &'a Handler, message: &str) -> Self + crate fn new_guaranteeing_error<M: Into<DiagnosticMessage>, const L: Level>( + handler: &'a Handler, + message: M, + ) -> Self where (): sealed_level_is_error::IsError<L>, { @@ -163,7 +168,11 @@ fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Se impl<'a> DiagnosticBuilder<'a, ()> { /// Convenience function for internal use, clients should use one of the /// `struct_*` methods on [`Handler`]. - crate fn new(handler: &'a Handler, level: Level, message: &str) -> Self { + crate fn new<M: Into<DiagnosticMessage>>( + handler: &'a Handler, + level: Level, + message: M, + ) -> Self { let diagnostic = Diagnostic::new_with_code(level, None, message); Self::new_diagnostic(handler, diagnostic) } @@ -201,7 +210,7 @@ fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Se impl<'a> DiagnosticBuilder<'a, !> { /// Convenience function for internal use, clients should use one of the /// `struct_*` methods on [`Handler`]. - crate fn new_fatal(handler: &'a Handler, message: &str) -> Self { + crate fn new_fatal(handler: &'a Handler, message: impl Into<DiagnosticMessage>) -> Self { let diagnostic = Diagnostic::new_with_code(Level::Fatal, None, message); Self::new_diagnostic_fatal(handler, diagnostic) } @@ -346,7 +355,7 @@ pub fn into_diagnostic(mut self) -> Option<(Diagnostic, &'a Handler)> { } // Take the `Diagnostic` by replacing it with a dummy. - let dummy = Diagnostic::new(Level::Allow, ""); + let dummy = Diagnostic::new(Level::Allow, DiagnosticMessage::Str("".to_string())); let diagnostic = std::mem::replace(&mut *self.inner.diagnostic, dummy); // Disable the ICE on `Drop`. @@ -399,7 +408,7 @@ pub fn downgrade_to_delayed_bug(&mut self,) -> &mut Self /// the diagnostic was constructed. However, the label span is *not* considered a /// ["primary span"][`MultiSpan`]; only the `Span` supplied when creating the diagnostic is /// primary. - pub fn span_label(&mut self, span: Span, label: impl Into<String>) -> &mut Self); + pub fn span_label(&mut self, span: Span, label: impl Into<DiagnosticMessage>) -> &mut Self); forward!( /// Labels all the given spans with the provided label. @@ -434,25 +443,25 @@ pub fn span_labels( found: DiagnosticStyledString, ) -> &mut Self); - forward!(pub fn note(&mut self, msg: &str) -> &mut Self); - forward!(pub fn note_once(&mut self, msg: &str) -> &mut Self); + forward!(pub fn note(&mut self, msg: impl Into<DiagnosticMessage>) -> &mut Self); + forward!(pub fn note_once(&mut self, msg: impl Into<DiagnosticMessage>) -> &mut Self); forward!(pub fn span_note( &mut self, sp: impl Into<MultiSpan>, - msg: &str, + msg: impl Into<DiagnosticMessage>, ) -> &mut Self); forward!(pub fn span_note_once( &mut self, sp: impl Into<MultiSpan>, - msg: &str, + msg: impl Into<DiagnosticMessage>, ) -> &mut Self); - forward!(pub fn warn(&mut self, msg: &str) -> &mut Self); + forward!(pub fn warn(&mut self, msg: impl Into<DiagnosticMessage>) -> &mut Self); forward!(pub fn span_warn(&mut self, sp: impl Into<MultiSpan>, msg: &str) -> &mut Self); - forward!(pub fn help(&mut self, msg: &str) -> &mut Self); + forward!(pub fn help(&mut self, msg: impl Into<DiagnosticMessage>) -> &mut Self); forward!(pub fn span_help( &mut self, sp: impl Into<MultiSpan>, - msg: &str, + msg: impl Into<DiagnosticMessage>, ) -> &mut Self); forward!(pub fn help_use_latest_edition(&mut self,) -> &mut Self); forward!(pub fn set_is_lint(&mut self,) -> &mut Self); @@ -461,67 +470,67 @@ pub fn span_labels( forward!(pub fn multipart_suggestion( &mut self, - msg: &str, + msg: impl Into<DiagnosticMessage>, suggestion: Vec<(Span, String)>, applicability: Applicability, ) -> &mut Self); forward!(pub fn multipart_suggestion_verbose( &mut self, - msg: &str, + msg: impl Into<DiagnosticMessage>, suggestion: Vec<(Span, String)>, applicability: Applicability, ) -> &mut Self); forward!(pub fn tool_only_multipart_suggestion( &mut self, - msg: &str, + msg: impl Into<DiagnosticMessage>, suggestion: Vec<(Span, String)>, applicability: Applicability, ) -> &mut Self); forward!(pub fn span_suggestion( &mut self, sp: Span, - msg: &str, + msg: impl Into<DiagnosticMessage>, suggestion: String, applicability: Applicability, ) -> &mut Self); forward!(pub fn span_suggestions( &mut self, sp: Span, - msg: &str, + msg: impl Into<DiagnosticMessage>, suggestions: impl Iterator<Item = String>, applicability: Applicability, ) -> &mut Self); forward!(pub fn multipart_suggestions( &mut self, - msg: &str, + msg: impl Into<DiagnosticMessage>, suggestions: impl Iterator<Item = Vec<(Span, String)>>, applicability: Applicability, ) -> &mut Self); forward!(pub fn span_suggestion_short( &mut self, sp: Span, - msg: &str, + msg: impl Into<DiagnosticMessage>, suggestion: String, applicability: Applicability, ) -> &mut Self); forward!(pub fn span_suggestion_verbose( &mut self, sp: Span, - msg: &str, + msg: impl Into<DiagnosticMessage>, suggestion: String, applicability: Applicability, ) -> &mut Self); forward!(pub fn span_suggestion_hidden( &mut self, sp: Span, - msg: &str, + msg: impl Into<DiagnosticMessage>, suggestion: String, applicability: Applicability, ) -> &mut Self); forward!(pub fn tool_only_span_suggestion( &mut self, sp: Span, - msg: &str, + msg: impl Into<DiagnosticMessage>, suggestion: String, applicability: Applicability, ) -> &mut Self); @@ -529,6 +538,11 @@ pub fn span_labels( forward!(pub fn set_primary_message(&mut self, msg: impl Into<String>) -> &mut Self); forward!(pub fn set_span(&mut self, sp: impl Into<MultiSpan>) -> &mut Self); forward!(pub fn code(&mut self, s: DiagnosticId) -> &mut Self); + forward!(pub fn set_arg( + &mut self, + name: impl Into<Cow<'static, str>>, + arg: DiagnosticArgValue<'static>, + ) -> &mut Self); } impl<G: EmissionGuarantee> Debug for DiagnosticBuilder<'_, G> { @@ -547,7 +561,9 @@ fn drop(&mut self) { if !panicking() { handler.emit_diagnostic(&mut Diagnostic::new( Level::Bug, - "the following error was constructed but not emitted", + DiagnosticMessage::Str( + "the following error was constructed but not emitted".to_string(), + ), )); handler.emit_diagnostic(&mut self.diagnostic); panic!();
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 93b7201..6a763d4 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs
@@ -10,19 +10,20 @@ use Destination::*; use rustc_span::source_map::SourceMap; -use rustc_span::{MultiSpan, SourceFile, Span}; +use rustc_span::{SourceFile, Span}; use crate::snippet::{Annotation, AnnotationType, Line, MultilineAnnotation, Style, StyledString}; use crate::styled_buffer::StyledBuffer; use crate::{ - CodeSuggestion, Diagnostic, DiagnosticId, Handler, Level, SubDiagnostic, SubstitutionHighlight, - SuggestionStyle, + CodeSuggestion, Diagnostic, DiagnosticArg, DiagnosticId, DiagnosticMessage, FluentBundle, + Handler, Level, MultiSpan, SubDiagnostic, SubstitutionHighlight, SuggestionStyle, }; use rustc_lint_defs::pluralize; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; +use rustc_error_messages::FluentArgs; use rustc_span::hygiene::{ExpnKind, MacroKind}; use std::borrow::Cow; use std::cmp::{max, min, Reverse}; @@ -58,13 +59,25 @@ pub fn new_emitter( self, dst: Box<dyn Write + Send>, source_map: Option<Lrc<SourceMap>>, + bundle: Option<Lrc<FluentBundle>>, + fallback_bundle: Lrc<FluentBundle>, teach: bool, terminal_width: Option<usize>, macro_backtrace: bool, ) -> EmitterWriter { let (short, color_config) = self.unzip(); let color = color_config.suggests_using_colors(); - EmitterWriter::new(dst, source_map, short, teach, color, terminal_width, macro_backtrace) + EmitterWriter::new( + dst, + source_map, + bundle, + fallback_bundle, + short, + teach, + color, + terminal_width, + macro_backtrace, + ) } } @@ -212,6 +225,74 @@ fn supports_color(&self) -> bool { fn source_map(&self) -> Option<&Lrc<SourceMap>>; + /// Return `FluentBundle` with localized diagnostics for the locale requested by the user. If no + /// language was requested by the user then this will be `None` and `fallback_fluent_bundle` + /// should be used. + fn fluent_bundle(&self) -> Option<&Lrc<FluentBundle>>; + + /// Return `FluentBundle` with localized diagnostics for the default locale of the compiler. + /// Used when the user has not requested a specific language or when a localized diagnostic is + /// unavailable for the requested locale. + fn fallback_fluent_bundle(&self) -> &Lrc<FluentBundle>; + + /// Convert diagnostic arguments (a rustc internal type that exists to implement + /// `Encodable`/`Decodable`) into `FluentArgs` which is necessary to perform translation. + /// + /// Typically performed once for each diagnostic at the start of `emit_diagnostic` and then + /// passed around as a reference thereafter. + fn to_fluent_args<'arg>(&self, args: &[DiagnosticArg<'arg>]) -> FluentArgs<'arg> { + FromIterator::from_iter(args.to_vec().drain(..)) + } + + /// Convert `DiagnosticMessage`s to a string, performing translation if necessary. + fn translate_messages( + &self, + messages: &[(DiagnosticMessage, Style)], + args: &FluentArgs<'_>, + ) -> Cow<'_, str> { + Cow::Owned( + messages.iter().map(|(m, _)| self.translate_message(m, args)).collect::<String>(), + ) + } + + /// Convert a `DiagnosticMessage` to a string, performing translation if necessary. + fn translate_message<'a>( + &'a self, + message: &'a DiagnosticMessage, + args: &'a FluentArgs<'_>, + ) -> Cow<'_, str> { + trace!(?message, ?args); + let (identifier, attr) = match message { + DiagnosticMessage::Str(msg) => return Cow::Borrowed(&msg), + DiagnosticMessage::FluentIdentifier(identifier, attr) => (identifier, attr), + }; + + let bundle = match self.fluent_bundle() { + Some(bundle) if bundle.has_message(&identifier) => bundle, + _ => self.fallback_fluent_bundle(), + }; + + let message = bundle.get_message(&identifier).expect("missing diagnostic in fluent bundle"); + let value = match attr { + Some(attr) => { + message.get_attribute(attr).expect("missing attribute in fluent message").value() + } + None => message.value().expect("missing value in fluent message"), + }; + + let mut err = vec![]; + let translated = bundle.format_pattern(value, Some(&args), &mut err); + trace!(?translated, ?err); + debug_assert!( + err.is_empty(), + "identifier: {:?}, args: {:?}, errors: {:?}", + identifier, + args, + err + ); + translated + } + /// Formats the substitutions of the primary_span /// /// There are a lot of conditions to this method, but in short: @@ -225,10 +306,12 @@ fn supports_color(&self) -> bool { fn primary_span_formatted<'a>( &mut self, diag: &'a Diagnostic, + fluent_args: &FluentArgs<'_>, ) -> (MultiSpan, &'a [CodeSuggestion]) { let mut primary_span = diag.span.clone(); let suggestions = diag.suggestions.as_ref().map_or(&[][..], |suggestions| &suggestions[..]); if let Some((sugg, rest)) = suggestions.split_first() { + let msg = self.translate_message(&sugg.msg, fluent_args); if rest.is_empty() && // ^ if there is only one suggestion // don't display multi-suggestions as labels @@ -236,7 +319,7 @@ fn primary_span_formatted<'a>( // don't display multipart suggestions as labels sugg.substitutions[0].parts.len() == 1 && // don't display long messages as labels - sugg.msg.split_whitespace().count() < 10 && + msg.split_whitespace().count() < 10 && // don't display multiline suggestions as labels !sugg.substitutions[0].parts[0].snippet.contains('\n') && ![ @@ -252,12 +335,12 @@ fn primary_span_formatted<'a>( let msg = if substitution.is_empty() || sugg.style.hide_inline() { // This substitution is only removal OR we explicitly don't want to show the // code inline (`hide_inline`). Therefore, we don't show the substitution. - format!("help: {}", sugg.msg) + format!("help: {}", &msg) } else { // Show the default suggestion text with the substitution format!( "help: {}{}: `{}`", - sugg.msg, + &msg, if self .source_map() .map(|sm| is_case_difference( @@ -333,7 +416,7 @@ fn fix_multispans_in_extern_macros_and_render_macro_backtrace( children.push(SubDiagnostic { level: Level::Note, - message: vec![(msg, Style::NoStyle)], + message: vec![(DiagnosticMessage::Str(msg), Style::NoStyle)], span: MultiSpan::new(), render_span: None, }); @@ -492,9 +575,19 @@ fn source_map(&self) -> Option<&Lrc<SourceMap>> { self.sm.as_ref() } + fn fluent_bundle(&self) -> Option<&Lrc<FluentBundle>> { + self.fluent_bundle.as_ref() + } + + fn fallback_fluent_bundle(&self) -> &Lrc<FluentBundle> { + &self.fallback_bundle + } + fn emit_diagnostic(&mut self, diag: &Diagnostic) { + let fluent_args = self.to_fluent_args(diag.args()); + let mut children = diag.children.clone(); - let (mut primary_span, suggestions) = self.primary_span_formatted(&diag); + let (mut primary_span, suggestions) = self.primary_span_formatted(&diag, &fluent_args); debug!("emit_diagnostic: suggestions={:?}", suggestions); self.fix_multispans_in_extern_macros_and_render_macro_backtrace( @@ -507,7 +600,8 @@ fn emit_diagnostic(&mut self, diag: &Diagnostic) { self.emit_messages_default( &diag.level, - &diag.styled_message(), + &diag.message, + &fluent_args, &diag.code, &primary_span, &children, @@ -536,6 +630,15 @@ impl Emitter for SilentEmitter { fn source_map(&self) -> Option<&Lrc<SourceMap>> { None } + + fn fluent_bundle(&self) -> Option<&Lrc<FluentBundle>> { + None + } + + fn fallback_fluent_bundle(&self) -> &Lrc<FluentBundle> { + panic!("silent emitter attempted to translate message") + } + fn emit_diagnostic(&mut self, d: &Diagnostic) { if d.level == Level::Fatal { let mut d = d.clone(); @@ -591,6 +694,8 @@ fn suggests_using_colors(self) -> bool { pub struct EmitterWriter { dst: Destination, sm: Option<Lrc<SourceMap>>, + fluent_bundle: Option<Lrc<FluentBundle>>, + fallback_bundle: Lrc<FluentBundle>, short_message: bool, teach: bool, ui_testing: bool, @@ -610,6 +715,8 @@ impl EmitterWriter { pub fn stderr( color_config: ColorConfig, source_map: Option<Lrc<SourceMap>>, + fluent_bundle: Option<Lrc<FluentBundle>>, + fallback_bundle: Lrc<FluentBundle>, short_message: bool, teach: bool, terminal_width: Option<usize>, @@ -619,6 +726,8 @@ pub fn stderr( EmitterWriter { dst, sm: source_map, + fluent_bundle, + fallback_bundle, short_message, teach, ui_testing: false, @@ -630,6 +739,8 @@ pub fn stderr( pub fn new( dst: Box<dyn Write + Send>, source_map: Option<Lrc<SourceMap>>, + fluent_bundle: Option<Lrc<FluentBundle>>, + fallback_bundle: Lrc<FluentBundle>, short_message: bool, teach: bool, colored: bool, @@ -639,6 +750,8 @@ pub fn new( EmitterWriter { dst: Raw(dst, colored), sm: source_map, + fluent_bundle, + fallback_bundle, short_message, teach, ui_testing: false, @@ -1176,7 +1289,8 @@ fn get_max_line_num(&mut self, span: &MultiSpan, children: &[SubDiagnostic]) -> fn msg_to_buffer( &self, buffer: &mut StyledBuffer, - msg: &[(String, Style)], + msg: &[(DiagnosticMessage, Style)], + args: &FluentArgs<'_>, padding: usize, label: &str, override_style: Option<Style>, @@ -1229,6 +1343,7 @@ fn style_or_override(style: Style, override_: Option<Style>) -> Style { // very *weird* formats // see? for &(ref text, ref style) in msg.iter() { + let text = self.translate_message(text, args); let lines = text.split('\n').collect::<Vec<_>>(); if lines.len() > 1 { for (i, line) in lines.iter().enumerate() { @@ -1239,7 +1354,7 @@ fn style_or_override(style: Style, override_: Option<Style>) -> Style { buffer.append(line_number, line, style_or_override(*style, override_style)); } } else { - buffer.append(line_number, text, style_or_override(*style, override_style)); + buffer.append(line_number, &text, style_or_override(*style, override_style)); } } } @@ -1247,7 +1362,8 @@ fn style_or_override(style: Style, override_: Option<Style>) -> Style { fn emit_message_default( &mut self, msp: &MultiSpan, - msg: &[(String, Style)], + msg: &[(DiagnosticMessage, Style)], + args: &FluentArgs<'_>, code: &Option<DiagnosticId>, level: &Level, max_line_num_len: usize, @@ -1266,7 +1382,7 @@ fn emit_message_default( buffer.append(0, level.to_str(), Style::MainHeaderMsg); buffer.append(0, ": ", Style::NoStyle); } - self.msg_to_buffer(&mut buffer, msg, max_line_num_len, "note", None); + self.msg_to_buffer(&mut buffer, msg, args, max_line_num_len, "note", None); } else { let mut label_width = 0; // The failure note level itself does not provide any useful diagnostic information @@ -1287,8 +1403,9 @@ fn emit_message_default( label_width += 2; } for &(ref text, _) in msg.iter() { + let text = self.translate_message(text, args); // Account for newlines to align output to its label. - for (line, text) in normalize_whitespace(text).lines().enumerate() { + for (line, text) in normalize_whitespace(&text).lines().enumerate() { buffer.append( 0 + line, &format!( @@ -1302,7 +1419,7 @@ fn emit_message_default( } } - let mut annotated_files = FileWithAnnotatedLines::collect_annotations(msp, &self.sm); + let mut annotated_files = FileWithAnnotatedLines::collect_annotations(self, args, msp); // Make sure our primary file comes first let (primary_lo, sm) = if let (Some(sm), Some(ref primary_span)) = @@ -1586,6 +1703,7 @@ fn emit_message_default( fn emit_suggestion_default( &mut self, suggestion: &CodeSuggestion, + args: &FluentArgs<'_>, level: &Level, max_line_num_len: usize, ) -> io::Result<()> { @@ -1612,6 +1730,7 @@ fn emit_suggestion_default( self.msg_to_buffer( &mut buffer, &[(suggestion.msg.to_owned(), Style::NoStyle)], + args, max_line_num_len, "suggestion", Some(Style::HeaderMsg), @@ -1852,7 +1971,8 @@ enum DisplaySuggestion { fn emit_messages_default( &mut self, level: &Level, - message: &[(String, Style)], + message: &[(DiagnosticMessage, Style)], + args: &FluentArgs<'_>, code: &Option<DiagnosticId>, span: &MultiSpan, children: &[SubDiagnostic], @@ -1865,7 +1985,7 @@ fn emit_messages_default( num_decimal_digits(n) }; - match self.emit_message_default(span, message, code, level, max_line_num_len, false) { + match self.emit_message_default(span, message, args, code, level, max_line_num_len, false) { Ok(()) => { if !children.is_empty() || suggestions.iter().any(|s| s.style != SuggestionStyle::CompletelyHidden) @@ -1888,7 +2008,8 @@ fn emit_messages_default( let span = child.render_span.as_ref().unwrap_or(&child.span); if let Err(err) = self.emit_message_default( &span, - &child.styled_message(), + &child.message, + args, &None, &child.level, max_line_num_len, @@ -1904,6 +2025,7 @@ fn emit_messages_default( if let Err(e) = self.emit_message_default( &MultiSpan::new(), &[(sugg.msg.to_owned(), Style::HeaderMsg)], + args, &None, &Level::Help, max_line_num_len, @@ -1912,7 +2034,7 @@ fn emit_messages_default( panic!("failed to emit error: {}", e); } } else if let Err(e) = - self.emit_suggestion_default(sugg, &Level::Help, max_line_num_len) + self.emit_suggestion_default(sugg, args, &Level::Help, max_line_num_len) { panic!("failed to emit error: {}", e); }; @@ -1938,8 +2060,9 @@ impl FileWithAnnotatedLines { /// Preprocess all the annotations so that they are grouped by file and by line number /// This helps us quickly iterate over the whole message (including secondary file spans) pub fn collect_annotations( + emitter: &dyn Emitter, + args: &FluentArgs<'_>, msp: &MultiSpan, - source_map: &Option<Lrc<SourceMap>>, ) -> Vec<FileWithAnnotatedLines> { fn add_annotation_to_file( file_vec: &mut Vec<FileWithAnnotatedLines>, @@ -1974,7 +2097,7 @@ fn add_annotation_to_file( let mut output = vec![]; let mut multiline_annotations = vec![]; - if let Some(ref sm) = source_map { + if let Some(ref sm) = emitter.source_map() { for span_label in msp.span_labels() { if span_label.span.is_dummy() { continue; @@ -2001,7 +2124,10 @@ fn add_annotation_to_file( start_col: lo.col_display, end_col: hi.col_display, is_primary: span_label.is_primary, - label: span_label.label, + label: span_label + .label + .as_ref() + .map(|m| emitter.translate_message(m, args).to_string()), overlaps_exactly: false, }; multiline_annotations.push((lo.file, ml)); @@ -2010,7 +2136,10 @@ fn add_annotation_to_file( start_col: lo.col_display, end_col: hi.col_display, is_primary: span_label.is_primary, - label: span_label.label, + label: span_label + .label + .as_ref() + .map(|m| emitter.translate_message(m, args).to_string()), annotation_type: AnnotationType::Singleline, }; add_annotation_to_file(&mut output, lo.file, lo.line, ann);
diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs index dc28d1b..f78490d 100644 --- a/compiler/rustc_errors/src/json.rs +++ b/compiler/rustc_errors/src/json.rs
@@ -15,12 +15,13 @@ use crate::registry::Registry; use crate::DiagnosticId; use crate::ToolMetadata; -use crate::{CodeSuggestion, SubDiagnostic}; +use crate::{CodeSuggestion, FluentBundle, MultiSpan, SpanLabel, SubDiagnostic}; use rustc_lint_defs::Applicability; use rustc_data_structures::sync::Lrc; +use rustc_error_messages::FluentArgs; use rustc_span::hygiene::ExpnData; -use rustc_span::{MultiSpan, Span, SpanLabel}; +use rustc_span::Span; use std::io::{self, Write}; use std::path::Path; use std::sync::{Arc, Mutex}; @@ -36,6 +37,8 @@ pub struct JsonEmitter { dst: Box<dyn Write + Send>, registry: Option<Registry>, sm: Lrc<SourceMap>, + fluent_bundle: Option<Lrc<FluentBundle>>, + fallback_bundle: Lrc<FluentBundle>, pretty: bool, ui_testing: bool, json_rendered: HumanReadableErrorType, @@ -47,6 +50,8 @@ impl JsonEmitter { pub fn stderr( registry: Option<Registry>, source_map: Lrc<SourceMap>, + fluent_bundle: Option<Lrc<FluentBundle>>, + fallback_bundle: Lrc<FluentBundle>, pretty: bool, json_rendered: HumanReadableErrorType, terminal_width: Option<usize>, @@ -56,6 +61,8 @@ pub fn stderr( dst: Box::new(io::BufWriter::new(io::stderr())), registry, sm: source_map, + fluent_bundle, + fallback_bundle, pretty, ui_testing: false, json_rendered, @@ -67,6 +74,8 @@ pub fn stderr( pub fn basic( pretty: bool, json_rendered: HumanReadableErrorType, + fluent_bundle: Option<Lrc<FluentBundle>>, + fallback_bundle: Lrc<FluentBundle>, terminal_width: Option<usize>, macro_backtrace: bool, ) -> JsonEmitter { @@ -74,6 +83,8 @@ pub fn basic( JsonEmitter::stderr( None, Lrc::new(SourceMap::new(file_path_mapping)), + fluent_bundle, + fallback_bundle, pretty, json_rendered, terminal_width, @@ -85,6 +96,8 @@ pub fn new( dst: Box<dyn Write + Send>, registry: Option<Registry>, source_map: Lrc<SourceMap>, + fluent_bundle: Option<Lrc<FluentBundle>>, + fallback_bundle: Lrc<FluentBundle>, pretty: bool, json_rendered: HumanReadableErrorType, terminal_width: Option<usize>, @@ -94,6 +107,8 @@ pub fn new( dst, registry, sm: source_map, + fluent_bundle, + fallback_bundle, pretty, ui_testing: false, json_rendered, @@ -173,6 +188,14 @@ fn source_map(&self) -> Option<&Lrc<SourceMap>> { Some(&self.sm) } + fn fluent_bundle(&self) -> Option<&Lrc<FluentBundle>> { + self.fluent_bundle.as_ref() + } + + fn fallback_fluent_bundle(&self) -> &Lrc<FluentBundle> { + &self.fallback_bundle + } + fn should_show_explain(&self) -> bool { !matches!(self.json_rendered, HumanReadableErrorType::Short(_)) } @@ -345,14 +368,18 @@ struct UnusedExterns<'a, 'b, 'c> { impl Diagnostic { fn from_errors_diagnostic(diag: &crate::Diagnostic, je: &JsonEmitter) -> Diagnostic { - let sugg = diag.suggestions.iter().flatten().map(|sugg| Diagnostic { - message: sugg.msg.clone(), - code: None, - level: "help", - spans: DiagnosticSpan::from_suggestion(sugg, je), - children: vec![], - rendered: None, - tool_metadata: sugg.tool_metadata.clone(), + let args = je.to_fluent_args(diag.args()); + let sugg = diag.suggestions.iter().flatten().map(|sugg| { + let translated_message = je.translate_message(&sugg.msg, &args); + Diagnostic { + message: translated_message.to_string(), + code: None, + level: "help", + spans: DiagnosticSpan::from_suggestion(sugg, &args, je), + children: vec![], + rendered: None, + tool_metadata: sugg.tool_metadata.clone(), + } }); // generate regular command line output and store it in the json @@ -375,6 +402,8 @@ fn flush(&mut self) -> io::Result<()> { .new_emitter( Box::new(buf), Some(je.sm.clone()), + je.fluent_bundle.clone(), + je.fallback_bundle.clone(), false, je.terminal_width, je.macro_backtrace, @@ -384,15 +413,16 @@ fn flush(&mut self) -> io::Result<()> { let output = Arc::try_unwrap(output.0).unwrap().into_inner().unwrap(); let output = String::from_utf8(output).unwrap(); + let translated_message = je.translate_messages(&diag.message, &args); Diagnostic { - message: diag.message(), + message: translated_message.to_string(), code: DiagnosticCode::map_opt_string(diag.code.clone(), je), level: diag.level.to_str(), - spans: DiagnosticSpan::from_multispan(&diag.span, je), + spans: DiagnosticSpan::from_multispan(&diag.span, &args, je), children: diag .children .iter() - .map(|c| Diagnostic::from_sub_diagnostic(c, je)) + .map(|c| Diagnostic::from_sub_diagnostic(c, &args, je)) .chain(sugg) .collect(), rendered: Some(output), @@ -400,16 +430,21 @@ fn flush(&mut self) -> io::Result<()> { } } - fn from_sub_diagnostic(diag: &SubDiagnostic, je: &JsonEmitter) -> Diagnostic { + fn from_sub_diagnostic( + diag: &SubDiagnostic, + args: &FluentArgs<'_>, + je: &JsonEmitter, + ) -> Diagnostic { + let translated_message = je.translate_messages(&diag.message, args); Diagnostic { - message: diag.message(), + message: translated_message.to_string(), code: None, level: diag.level.to_str(), spans: diag .render_span .as_ref() - .map(|sp| DiagnosticSpan::from_multispan(sp, je)) - .unwrap_or_else(|| DiagnosticSpan::from_multispan(&diag.span, je)), + .map(|sp| DiagnosticSpan::from_multispan(sp, args, je)) + .unwrap_or_else(|| DiagnosticSpan::from_multispan(&diag.span, args, je)), children: vec![], rendered: None, tool_metadata: ToolMetadata::default(), @@ -421,9 +456,16 @@ impl DiagnosticSpan { fn from_span_label( span: SpanLabel, suggestion: Option<(&String, Applicability)>, + args: &FluentArgs<'_>, je: &JsonEmitter, ) -> DiagnosticSpan { - Self::from_span_etc(span.span, span.is_primary, span.label, suggestion, je) + Self::from_span_etc( + span.span, + span.is_primary, + span.label.as_ref().map(|m| je.translate_message(m, args)).map(|m| m.to_string()), + suggestion, + je, + ) } fn from_span_etc( @@ -486,14 +528,22 @@ fn from_span_full( } } - fn from_multispan(msp: &MultiSpan, je: &JsonEmitter) -> Vec<DiagnosticSpan> { + fn from_multispan( + msp: &MultiSpan, + args: &FluentArgs<'_>, + je: &JsonEmitter, + ) -> Vec<DiagnosticSpan> { msp.span_labels() .into_iter() - .map(|span_str| Self::from_span_label(span_str, None, je)) + .map(|span_str| Self::from_span_label(span_str, None, args, je)) .collect() } - fn from_suggestion(suggestion: &CodeSuggestion, je: &JsonEmitter) -> Vec<DiagnosticSpan> { + fn from_suggestion( + suggestion: &CodeSuggestion, + args: &FluentArgs<'_>, + je: &JsonEmitter, + ) -> Vec<DiagnosticSpan> { suggestion .substitutions .iter() @@ -504,6 +554,7 @@ fn from_suggestion(suggestion: &CodeSuggestion, je: &JsonEmitter) -> Vec<Diagnos DiagnosticSpan::from_span_label( span_label, Some((&suggestion_inner.snippet, suggestion.applicability)), + args, je, ) })
diff --git a/compiler/rustc_errors/src/json/tests.rs b/compiler/rustc_errors/src/json/tests.rs index ed01afe..0f175c7 100644 --- a/compiler/rustc_errors/src/json/tests.rs +++ b/compiler/rustc_errors/src/json/tests.rs
@@ -39,12 +39,16 @@ fn test_positions(code: &str, span: (u32, u32), expected_output: SpanTestData) { rustc_span::create_default_session_globals_then(|| { let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); sm.new_source_file(Path::new("test.rs").to_owned().into(), code.to_owned()); + let fallback_bundle = + crate::fallback_fluent_bundle(false).expect("failed to load fallback fluent bundle"); let output = Arc::new(Mutex::new(Vec::new())); let je = JsonEmitter::new( Box::new(Shared { data: output.clone() }), None, sm, + None, + fallback_bundle, true, HumanReadableErrorType::Short(ColorConfig::Never), None,
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index ec00910..c927fcb 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs
@@ -31,11 +31,15 @@ use rustc_data_structures::stable_hasher::StableHasher; use rustc_data_structures::sync::{self, Lock, Lrc}; use rustc_data_structures::AtomicRef; +pub use rustc_error_messages::{ + fallback_fluent_bundle, fluent_bundle, DiagnosticMessage, FluentBundle, LanguageIdentifier, + MultiSpan, SpanLabel, +}; pub use rustc_lint_defs::{pluralize, Applicability}; use rustc_serialize::json::Json; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use rustc_span::source_map::SourceMap; -use rustc_span::{Loc, MultiSpan, Span}; +use rustc_span::{Loc, Span}; use std::borrow::Cow; use std::hash::{Hash, Hasher}; @@ -55,6 +59,7 @@ pub mod registry; mod snippet; mod styled_buffer; + pub use snippet::Style; pub type PResult<'a, T> = Result<T, DiagnosticBuilder<'a, ErrorGuaranteed>>; @@ -145,7 +150,7 @@ pub struct CodeSuggestion { /// ] /// ``` pub substitutions: Vec<Substitution>, - pub msg: String, + pub msg: DiagnosticMessage, /// Visual representation of this suggestion. pub style: SuggestionStyle, /// Whether or not the suggestion is approximate @@ -400,7 +405,10 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { impl error::Error for ExplicitBug {} -pub use diagnostic::{Diagnostic, DiagnosticId, DiagnosticStyledString, SubDiagnostic}; +pub use diagnostic::{ + Diagnostic, DiagnosticArg, DiagnosticArgValue, DiagnosticId, DiagnosticStyledString, + IntoDiagnosticArg, SubDiagnostic, +}; pub use diagnostic_builder::{DiagnosticBuilder, EmissionGuarantee}; use std::backtrace::Backtrace; @@ -538,10 +546,14 @@ pub fn with_tty_emitter( can_emit_warnings: bool, treat_err_as_bug: Option<NonZeroUsize>, sm: Option<Lrc<SourceMap>>, + fluent_bundle: Option<Lrc<FluentBundle>>, + fallback_bundle: Lrc<FluentBundle>, ) -> Self { Self::with_tty_emitter_and_flags( color_config, sm, + fluent_bundle, + fallback_bundle, HandlerFlags { can_emit_warnings, treat_err_as_bug, ..Default::default() }, ) } @@ -549,11 +561,15 @@ pub fn with_tty_emitter( pub fn with_tty_emitter_and_flags( color_config: ColorConfig, sm: Option<Lrc<SourceMap>>, + fluent_bundle: Option<Lrc<FluentBundle>>, + fallback_bundle: Lrc<FluentBundle>, flags: HandlerFlags, ) -> Self { let emitter = Box::new(EmitterWriter::stderr( color_config, sm, + fluent_bundle, + fallback_bundle, false, false, None, @@ -658,7 +674,7 @@ pub fn emit_stashed_diagnostics(&self) -> Option<ErrorGuaranteed> { pub fn struct_span_warn( &self, span: impl Into<MultiSpan>, - msg: &str, + msg: impl Into<DiagnosticMessage>, ) -> DiagnosticBuilder<'_, ()> { let mut result = self.struct_warn(msg); result.set_span(span); @@ -669,7 +685,7 @@ pub fn struct_span_warn( pub fn struct_span_allow( &self, span: impl Into<MultiSpan>, - msg: &str, + msg: impl Into<DiagnosticMessage>, ) -> DiagnosticBuilder<'_, ()> { let mut result = self.struct_allow(msg); result.set_span(span); @@ -681,7 +697,7 @@ pub fn struct_span_allow( pub fn struct_span_warn_with_code( &self, span: impl Into<MultiSpan>, - msg: &str, + msg: impl Into<DiagnosticMessage>, code: DiagnosticId, ) -> DiagnosticBuilder<'_, ()> { let mut result = self.struct_span_warn(span, msg); @@ -694,17 +710,21 @@ pub fn struct_span_warn_with_code( /// Attempting to `.emit()` the builder will only emit if either: /// * `can_emit_warnings` is `true` /// * `is_force_warn` was set in `DiagnosticId::Lint` - pub fn struct_warn(&self, msg: &str) -> DiagnosticBuilder<'_, ()> { + pub fn struct_warn(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> { DiagnosticBuilder::new(self, Level::Warning, msg) } /// Construct a builder at the `Allow` level with the `msg`. - pub fn struct_allow(&self, msg: &str) -> DiagnosticBuilder<'_, ()> { + pub fn struct_allow(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> { DiagnosticBuilder::new(self, Level::Allow, msg) } /// Construct a builder at the `Expect` level with the `msg`. - pub fn struct_expect(&self, msg: &str, id: LintExpectationId) -> DiagnosticBuilder<'_, ()> { + pub fn struct_expect( + &self, + msg: impl Into<DiagnosticMessage>, + id: LintExpectationId, + ) -> DiagnosticBuilder<'_, ()> { DiagnosticBuilder::new(self, Level::Expect(id), msg) } @@ -712,7 +732,7 @@ pub fn struct_expect(&self, msg: &str, id: LintExpectationId) -> DiagnosticBuild pub fn struct_span_err( &self, span: impl Into<MultiSpan>, - msg: &str, + msg: impl Into<DiagnosticMessage>, ) -> DiagnosticBuilder<'_, ErrorGuaranteed> { let mut result = self.struct_err(msg); result.set_span(span); @@ -723,7 +743,7 @@ pub fn struct_span_err( pub fn struct_span_err_with_code( &self, span: impl Into<MultiSpan>, - msg: &str, + msg: impl Into<DiagnosticMessage>, code: DiagnosticId, ) -> DiagnosticBuilder<'_, ErrorGuaranteed> { let mut result = self.struct_span_err(span, msg); @@ -733,20 +753,23 @@ pub fn struct_span_err_with_code( /// Construct a builder at the `Error` level with the `msg`. // FIXME: This method should be removed (every error should have an associated error code). - pub fn struct_err(&self, msg: &str) -> DiagnosticBuilder<'_, ErrorGuaranteed> { - DiagnosticBuilder::new_guaranteeing_error::<{ Level::Error { lint: false } }>(self, msg) + pub fn struct_err( + &self, + msg: impl Into<DiagnosticMessage>, + ) -> DiagnosticBuilder<'_, ErrorGuaranteed> { + DiagnosticBuilder::new_guaranteeing_error::<_, { Level::Error { lint: false } }>(self, msg) } /// This should only be used by `rustc_middle::lint::struct_lint_level`. Do not use it for hard errors. #[doc(hidden)] - pub fn struct_err_lint(&self, msg: &str) -> DiagnosticBuilder<'_, ()> { + pub fn struct_err_lint(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> { DiagnosticBuilder::new(self, Level::Error { lint: true }, msg) } /// Construct a builder at the `Error` level with the `msg` and the `code`. pub fn struct_err_with_code( &self, - msg: &str, + msg: impl Into<DiagnosticMessage>, code: DiagnosticId, ) -> DiagnosticBuilder<'_, ErrorGuaranteed> { let mut result = self.struct_err(msg); @@ -754,11 +777,22 @@ pub fn struct_err_with_code( result } + /// Construct a builder at the `Warn` level with the `msg` and the `code`. + pub fn struct_warn_with_code( + &self, + msg: impl Into<DiagnosticMessage>, + code: DiagnosticId, + ) -> DiagnosticBuilder<'_, ()> { + let mut result = self.struct_warn(msg); + result.code(code); + result + } + /// Construct a builder at the `Fatal` level at the given `span` and with the `msg`. pub fn struct_span_fatal( &self, span: impl Into<MultiSpan>, - msg: &str, + msg: impl Into<DiagnosticMessage>, ) -> DiagnosticBuilder<'_, !> { let mut result = self.struct_fatal(msg); result.set_span(span); @@ -769,7 +803,7 @@ pub fn struct_span_fatal( pub fn struct_span_fatal_with_code( &self, span: impl Into<MultiSpan>, - msg: &str, + msg: impl Into<DiagnosticMessage>, code: DiagnosticId, ) -> DiagnosticBuilder<'_, !> { let mut result = self.struct_span_fatal(span, msg); @@ -778,21 +812,24 @@ pub fn struct_span_fatal_with_code( } /// Construct a builder at the `Error` level with the `msg`. - pub fn struct_fatal(&self, msg: &str) -> DiagnosticBuilder<'_, !> { + pub fn struct_fatal(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, !> { DiagnosticBuilder::new_fatal(self, msg) } /// Construct a builder at the `Help` level with the `msg`. - pub fn struct_help(&self, msg: &str) -> DiagnosticBuilder<'_, ()> { + pub fn struct_help(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> { DiagnosticBuilder::new(self, Level::Help, msg) } /// Construct a builder at the `Note` level with the `msg`. - pub fn struct_note_without_error(&self, msg: &str) -> DiagnosticBuilder<'_, ()> { + pub fn struct_note_without_error( + &self, + msg: impl Into<DiagnosticMessage>, + ) -> DiagnosticBuilder<'_, ()> { DiagnosticBuilder::new(self, Level::Note, msg) } - pub fn span_fatal(&self, span: impl Into<MultiSpan>, msg: &str) -> ! { + pub fn span_fatal(&self, span: impl Into<MultiSpan>, msg: impl Into<DiagnosticMessage>) -> ! { self.emit_diag_at_span(Diagnostic::new(Fatal, msg), span); FatalError.raise() } @@ -800,80 +837,106 @@ pub fn span_fatal(&self, span: impl Into<MultiSpan>, msg: &str) -> ! { pub fn span_fatal_with_code( &self, span: impl Into<MultiSpan>, - msg: &str, + msg: impl Into<DiagnosticMessage>, code: DiagnosticId, ) -> ! { self.emit_diag_at_span(Diagnostic::new_with_code(Fatal, Some(code), msg), span); FatalError.raise() } - pub fn span_err(&self, span: impl Into<MultiSpan>, msg: &str) -> ErrorGuaranteed { + pub fn span_err( + &self, + span: impl Into<MultiSpan>, + msg: impl Into<DiagnosticMessage>, + ) -> ErrorGuaranteed { self.emit_diag_at_span(Diagnostic::new(Error { lint: false }, msg), span).unwrap() } - pub fn span_err_with_code(&self, span: impl Into<MultiSpan>, msg: &str, code: DiagnosticId) { + pub fn span_err_with_code( + &self, + span: impl Into<MultiSpan>, + msg: impl Into<DiagnosticMessage>, + code: DiagnosticId, + ) { self.emit_diag_at_span( Diagnostic::new_with_code(Error { lint: false }, Some(code), msg), span, ); } - pub fn span_warn(&self, span: impl Into<MultiSpan>, msg: &str) { + pub fn span_warn(&self, span: impl Into<MultiSpan>, msg: impl Into<DiagnosticMessage>) { self.emit_diag_at_span(Diagnostic::new(Warning, msg), span); } - pub fn span_warn_with_code(&self, span: impl Into<MultiSpan>, msg: &str, code: DiagnosticId) { + pub fn span_warn_with_code( + &self, + span: impl Into<MultiSpan>, + msg: impl Into<DiagnosticMessage>, + code: DiagnosticId, + ) { self.emit_diag_at_span(Diagnostic::new_with_code(Warning, Some(code), msg), span); } - pub fn span_bug(&self, span: impl Into<MultiSpan>, msg: &str) -> ! { + pub fn span_bug(&self, span: impl Into<MultiSpan>, msg: impl Into<DiagnosticMessage>) -> ! { self.inner.borrow_mut().span_bug(span, msg) } #[track_caller] - pub fn delay_span_bug(&self, span: impl Into<MultiSpan>, msg: &str) -> ErrorGuaranteed { + pub fn delay_span_bug( + &self, + span: impl Into<MultiSpan>, + msg: impl Into<DiagnosticMessage>, + ) -> ErrorGuaranteed { self.inner.borrow_mut().delay_span_bug(span, msg) } // FIXME(eddyb) note the comment inside `impl Drop for HandlerInner`, that's // where the explanation of what "good path" is (also, it should be renamed). - pub fn delay_good_path_bug(&self, msg: &str) { + pub fn delay_good_path_bug(&self, msg: impl Into<DiagnosticMessage>) { self.inner.borrow_mut().delay_good_path_bug(msg) } - pub fn span_bug_no_panic(&self, span: impl Into<MultiSpan>, msg: &str) { + pub fn span_bug_no_panic(&self, span: impl Into<MultiSpan>, msg: impl Into<DiagnosticMessage>) { self.emit_diag_at_span(Diagnostic::new(Bug, msg), span); } - pub fn span_note_without_error(&self, span: impl Into<MultiSpan>, msg: &str) { + pub fn span_note_without_error( + &self, + span: impl Into<MultiSpan>, + msg: impl Into<DiagnosticMessage>, + ) { self.emit_diag_at_span(Diagnostic::new(Note, msg), span); } - pub fn span_note_diag(&self, span: Span, msg: &str) -> DiagnosticBuilder<'_, ()> { + pub fn span_note_diag( + &self, + span: Span, + msg: impl Into<DiagnosticMessage>, + ) -> DiagnosticBuilder<'_, ()> { let mut db = DiagnosticBuilder::new(self, Note, msg); db.set_span(span); db } // NOTE: intentionally doesn't raise an error so rustc_codegen_ssa only reports fatal errors in the main thread - pub fn fatal(&self, msg: &str) -> FatalError { + pub fn fatal(&self, msg: impl Into<DiagnosticMessage>) -> FatalError { self.inner.borrow_mut().fatal(msg) } - pub fn err(&self, msg: &str) -> ErrorGuaranteed { + pub fn err(&self, msg: impl Into<DiagnosticMessage>) -> ErrorGuaranteed { self.inner.borrow_mut().err(msg) } - pub fn warn(&self, msg: &str) { + pub fn warn(&self, msg: impl Into<DiagnosticMessage>) { let mut db = DiagnosticBuilder::new(self, Warning, msg); db.emit(); } - pub fn note_without_error(&self, msg: &str) { + pub fn note_without_error(&self, msg: impl Into<DiagnosticMessage>) { DiagnosticBuilder::new(self, Note, msg).emit(); } - pub fn bug(&self, msg: &str) -> ! { + pub fn bug(&self, msg: impl Into<DiagnosticMessage>) -> ! { self.inner.borrow_mut().bug(msg) } @@ -1143,7 +1206,10 @@ fn print_error_count(&mut self, registry: &Registry) { match (errors.len(), warnings.len()) { (0, 0) => return, - (0, _) => self.emitter.emit_diagnostic(&Diagnostic::new(Level::Warning, &warnings)), + (0, _) => self.emitter.emit_diagnostic(&Diagnostic::new( + Level::Warning, + DiagnosticMessage::Str(warnings.to_owned()), + )), (_, 0) => { let _ = self.fatal(&errors); } @@ -1218,7 +1284,7 @@ fn abort_if_errors(&mut self) { } } - fn span_bug(&mut self, sp: impl Into<MultiSpan>, msg: &str) -> ! { + fn span_bug(&mut self, sp: impl Into<MultiSpan>, msg: impl Into<DiagnosticMessage>) -> ! { self.emit_diag_at_span(Diagnostic::new(Bug, msg), sp); panic::panic_any(ExplicitBug); } @@ -1228,7 +1294,11 @@ fn emit_diag_at_span(&mut self, mut diag: Diagnostic, sp: impl Into<MultiSpan>) } #[track_caller] - fn delay_span_bug(&mut self, sp: impl Into<MultiSpan>, msg: &str) -> ErrorGuaranteed { + fn delay_span_bug( + &mut self, + sp: impl Into<MultiSpan>, + msg: impl Into<DiagnosticMessage>, + ) -> ErrorGuaranteed { // This is technically `self.treat_err_as_bug()` but `delay_span_bug` is called before // incrementing `err_count` by one, so we need to +1 the comparing. // FIXME: Would be nice to increment err_count in a more coherent way. @@ -1244,7 +1314,7 @@ fn delay_span_bug(&mut self, sp: impl Into<MultiSpan>, msg: &str) -> ErrorGuaran // FIXME(eddyb) note the comment inside `impl Drop for HandlerInner`, that's // where the explanation of what "good path" is (also, it should be renamed). - fn delay_good_path_bug(&mut self, msg: &str) { + fn delay_good_path_bug(&mut self, msg: impl Into<DiagnosticMessage>) { let mut diagnostic = Diagnostic::new(Level::DelayedBug, msg); if self.flags.report_delayed_bugs { self.emit_diagnostic(&mut diagnostic); @@ -1253,33 +1323,37 @@ fn delay_good_path_bug(&mut self, msg: &str) { self.delayed_good_path_bugs.push(DelayedDiagnostic::with_backtrace(diagnostic, backtrace)); } - fn failure(&mut self, msg: &str) { + fn failure(&mut self, msg: impl Into<DiagnosticMessage>) { self.emit_diagnostic(&mut Diagnostic::new(FailureNote, msg)); } - fn fatal(&mut self, msg: &str) -> FatalError { + fn fatal(&mut self, msg: impl Into<DiagnosticMessage>) -> FatalError { self.emit(Fatal, msg); FatalError } - fn err(&mut self, msg: &str) -> ErrorGuaranteed { + fn err(&mut self, msg: impl Into<DiagnosticMessage>) -> ErrorGuaranteed { self.emit(Error { lint: false }, msg) } /// Emit an error; level should be `Error` or `Fatal`. - fn emit(&mut self, level: Level, msg: &str) -> ErrorGuaranteed { + fn emit(&mut self, level: Level, msg: impl Into<DiagnosticMessage>) -> ErrorGuaranteed { if self.treat_err_as_bug() { self.bug(msg); } self.emit_diagnostic(&mut Diagnostic::new(level, msg)).unwrap() } - fn bug(&mut self, msg: &str) -> ! { + fn bug(&mut self, msg: impl Into<DiagnosticMessage>) -> ! { self.emit_diagnostic(&mut Diagnostic::new(Bug, msg)); panic::panic_any(ExplicitBug); } - fn flush_delayed(&mut self, bugs: impl IntoIterator<Item = Diagnostic>, explanation: &str) { + fn flush_delayed( + &mut self, + bugs: impl IntoIterator<Item = Diagnostic>, + explanation: impl Into<DiagnosticMessage> + Copy, + ) { let mut no_bugs = true; for mut bug in bugs { if no_bugs {
diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 7f569af..12b117d 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs
@@ -10,7 +10,7 @@ use rustc_attr::{self as attr, Deprecation, Stability}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::{self, Lrc}; -use rustc_errors::{Applicability, DiagnosticBuilder, ErrorGuaranteed}; +use rustc_errors::{Applicability, DiagnosticBuilder, ErrorGuaranteed, MultiSpan}; use rustc_lint_defs::builtin::PROC_MACRO_BACK_COMPAT; use rustc_lint_defs::BuiltinLintDiagnostics; use rustc_parse::{self, nt_to_tokenstream, parser, MACRO_ARGUMENTS}; @@ -20,7 +20,7 @@ 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::{MultiSpan, Span, DUMMY_SP}; +use rustc_span::{Span, DUMMY_SP}; use smallvec::{smallvec, SmallVec}; use std::default::Default; @@ -118,7 +118,7 @@ pub fn into_nonterminal(self) -> Nonterminal { Annotatable::ForeignItem(item) => { token::NtItem(P(item.and_then(ast::ForeignItem::into_item))) } - Annotatable::Stmt(stmt) => token::NtStmt(stmt.into_inner()), + Annotatable::Stmt(stmt) => token::NtStmt(stmt), Annotatable::Expr(expr) => token::NtExpr(expr), Annotatable::Arm(..) | Annotatable::ExprField(..) @@ -1047,6 +1047,12 @@ pub fn call_site(&self) -> Span { self.current_expansion.id.expn_data().call_site } + /// Returns the current expansion kind's description. + pub(crate) fn expansion_descr(&self) -> String { + let expn_data = self.current_expansion.id.expn_data(); + expn_data.kind.descr() + } + /// Equivalent of `Span::def_site` from the proc macro API, /// except that the location is taken from the span passed as an argument. pub fn with_def_site_ctxt(&self, span: Span) -> Span {
diff --git a/compiler/rustc_expand/src/lib.rs b/compiler/rustc_expand/src/lib.rs index f5a9390..cd5bb93 100644 --- a/compiler/rustc_expand/src/lib.rs +++ b/compiler/rustc_expand/src/lib.rs
@@ -1,7 +1,5 @@ #![feature(associated_type_bounds)] #![feature(associated_type_defaults)] -#![feature(box_patterns)] -#![feature(box_syntax)] #![feature(crate_visibility_modifier)] #![feature(decl_macro)] #![feature(if_let_guard)]
diff --git a/compiler/rustc_expand/src/mbe/macro_check.rs b/compiler/rustc_expand/src/mbe/macro_check.rs index b55a40c..0e20e09 100644 --- a/compiler/rustc_expand/src/mbe/macro_check.rs +++ b/compiler/rustc_expand/src/mbe/macro_check.rs
@@ -109,10 +109,11 @@ use rustc_ast::token::{DelimToken, Token, TokenKind}; use rustc_ast::{NodeId, DUMMY_NODE_ID}; use rustc_data_structures::fx::FxHashMap; +use rustc_errors::MultiSpan; use rustc_session::lint::builtin::META_VARIABLE_MISUSE; use rustc_session::parse::ParseSess; use rustc_span::symbol::kw; -use rustc_span::{symbol::MacroRulesNormalizedIdent, MultiSpan, Span}; +use rustc_span::{symbol::MacroRulesNormalizedIdent, Span}; use smallvec::SmallVec; @@ -249,7 +250,7 @@ fn check_binders( if let Some(prev_info) = binders.get(&name) { // 1. The meta-variable is already bound in the current LHS: This is an error. let mut span = MultiSpan::from_span(span); - span.push_span_label(prev_info.span, "previous declaration".into()); + span.push_span_label(prev_info.span, "previous declaration"); buffer_lint(sess, span, node_id, "duplicate matcher binding"); } else if get_binder_info(macros, binders, name).is_none() { // 2. The meta-variable is free: This is a binder. @@ -621,7 +622,7 @@ fn ops_is_prefix( for (i, binder) in binder_ops.iter().enumerate() { if i >= occurrence_ops.len() { let mut span = MultiSpan::from_span(span); - span.push_span_label(binder.span, "expected repetition".into()); + span.push_span_label(binder.span, "expected repetition"); let message = &format!("variable '{}' is still repeating at this depth", name); buffer_lint(sess, span, node_id, message); return; @@ -629,8 +630,8 @@ fn ops_is_prefix( let occurrence = &occurrence_ops[i]; if occurrence.op != binder.op { let mut span = MultiSpan::from_span(span); - span.push_span_label(binder.span, "expected repetition".into()); - span.push_span_label(occurrence.span, "conflicting repetition".into()); + span.push_span_label(binder.span, "expected repetition"); + span.push_span_label(occurrence.span, "conflicting repetition"); let message = "meta-variable repeats with different Kleene operator"; buffer_lint(sess, span, node_id, message); return;
diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs index 7d4de72..604e25a 100644 --- a/compiler/rustc_expand/src/mbe/macro_parser.rs +++ b/compiler/rustc_expand/src/mbe/macro_parser.rs
@@ -17,7 +17,7 @@ //! A "matcher position" (a.k.a. "position" or "mp") is a dot in the middle of a matcher, usually //! written as a `·`. For example `· a $( a )* a b` is one, as is `a $( · a )* a b`. //! -//! The parser walks through the input a character at a time, maintaining a list +//! The parser walks through the input a token at a time, maintaining a list //! of threads consistent with the current position in the input string: `cur_mps`. //! //! As it processes them, it fills up `eof_mps` with threads that would be valid if @@ -73,12 +73,13 @@ crate use NamedMatch::*; crate use ParseResult::*; -use crate::mbe::{self, SequenceRepetition, TokenTree}; +use crate::mbe::{KleeneOp, TokenTree}; -use rustc_ast::token::{self, DocComment, Nonterminal, Token, TokenKind}; +use rustc_ast::token::{self, DocComment, Nonterminal, NonterminalKind, Token}; use rustc_parse::parser::{NtOrTt, Parser}; use rustc_session::parse::ParseSess; use rustc_span::symbol::MacroRulesNormalizedIdent; +use rustc_span::Span; use smallvec::{smallvec, SmallVec}; @@ -88,153 +89,160 @@ use std::borrow::Cow; use std::collections::hash_map::Entry::{Occupied, Vacant}; -// One element is enough to cover 95-99% of vectors for most benchmarks. Also, -// vectors longer than one frequently have many elements, not just two or -// three. +// One element is enough to cover 95-99% of vectors for most benchmarks. Also, vectors longer than +// one frequently have many elements, not just two or three. type NamedMatchVec = SmallVec<[NamedMatch; 1]>; // This type is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] rustc_data_structures::static_assert_size!(NamedMatchVec, 48); -#[derive(Clone)] -enum MatcherKind<'tt> { - TopLevel, - Delimited(Box<DelimitedSubmatcher<'tt>>), - Sequence(Box<SequenceSubmatcher<'tt>>), +/// A unit within a matcher that a `MatcherPos` can refer to. Similar to (and derived from) +/// `mbe::TokenTree`, but designed specifically for fast and easy traversal during matching. +/// Notable differences to `mbe::TokenTree`: +/// - It is non-recursive, i.e. there is no nesting. +/// - The end pieces of each sequence (the separator, if present, and the Kleene op) are +/// represented explicitly, as is the very end of the matcher. +/// +/// This means a matcher can be represented by `&[MatcherLoc]`, and traversal mostly involves +/// simply incrementing the current matcher position index by one. +pub(super) enum MatcherLoc { + Token { + token: Token, + }, + Delimited, + Sequence { + op: KleeneOp, + num_metavar_decls: usize, + idx_first_after: usize, + next_metavar: usize, + seq_depth: usize, + }, + SequenceKleeneOpNoSep { + op: KleeneOp, + idx_first: usize, + }, + SequenceSep { + separator: Token, + }, + SequenceKleeneOpAfterSep { + idx_first: usize, + }, + MetaVarDecl { + span: Span, + bind: Ident, + kind: Option<NonterminalKind>, + next_metavar: usize, + seq_depth: usize, + }, + Eof, } -#[derive(Clone)] -struct DelimitedSubmatcher<'tt> { - parent: Parent<'tt>, +pub(super) fn compute_locs(sess: &ParseSess, matcher: &[TokenTree]) -> Vec<MatcherLoc> { + fn inner( + sess: &ParseSess, + tts: &[TokenTree], + locs: &mut Vec<MatcherLoc>, + next_metavar: &mut usize, + seq_depth: usize, + ) { + for tt in tts { + match tt { + TokenTree::Token(token) => { + locs.push(MatcherLoc::Token { token: token.clone() }); + } + TokenTree::Delimited(_, delimited) => { + locs.push(MatcherLoc::Delimited); + inner(sess, &delimited.all_tts, locs, next_metavar, seq_depth); + } + TokenTree::Sequence(_, seq) => { + // We can't determine `idx_first_after` and construct the final + // `MatcherLoc::Sequence` until after `inner()` is called and the sequence end + // pieces are processed. So we push a dummy value (`Eof` is cheapest to + // construct) now, and overwrite it with the proper value below. + let dummy = MatcherLoc::Eof; + locs.push(dummy); + + let next_metavar_orig = *next_metavar; + let op = seq.kleene.op; + let idx_first = locs.len(); + let idx_seq = idx_first - 1; + inner(sess, &seq.tts, locs, next_metavar, seq_depth + 1); + + if let Some(separator) = &seq.separator { + locs.push(MatcherLoc::SequenceSep { separator: separator.clone() }); + locs.push(MatcherLoc::SequenceKleeneOpAfterSep { idx_first }); + } else { + locs.push(MatcherLoc::SequenceKleeneOpNoSep { op, idx_first }); + } + + // Overwrite the dummy value pushed above with the proper value. + locs[idx_seq] = MatcherLoc::Sequence { + op, + num_metavar_decls: seq.num_captures, + idx_first_after: locs.len(), + next_metavar: next_metavar_orig, + seq_depth, + }; + } + &TokenTree::MetaVarDecl(span, bind, kind) => { + locs.push(MatcherLoc::MetaVarDecl { + span, + bind, + kind, + next_metavar: *next_metavar, + seq_depth, + }); + *next_metavar += 1; + } + TokenTree::MetaVar(..) | TokenTree::MetaVarExpr(..) => unreachable!(), + } + } + } + + let mut locs = vec![]; + let mut next_metavar = 0; + inner(sess, matcher, &mut locs, &mut next_metavar, /* seq_depth */ 0); + + // A final entry is needed for eof. + locs.push(MatcherLoc::Eof); + + locs } -#[derive(Clone)] -struct SequenceSubmatcher<'tt> { - parent: Parent<'tt>, - seq: &'tt SequenceRepetition, -} - -/// Data used to ascend from a submatcher back to its parent matcher. A subset of the fields from -/// `MathcherPos`. -#[derive(Clone)] -struct Parent<'tt> { - tts: &'tt [TokenTree], - idx: usize, - kind: MatcherKind<'tt>, -} - -/// A single matcher position, which could be within the top-level matcher, a submatcher, a -/// subsubmatcher, etc. For example: -/// ```text -/// macro_rules! m { $id:ident ( $($e:expr),* ) } => { ... } -/// <----------> second submatcher; one tt, one metavar -/// <--------------> first submatcher; three tts, zero metavars -/// <--------------------------> top-level matcher; two tts, one metavar -/// ``` -struct MatcherPos<'tt> { - /// The tokens that make up the current matcher. When we are within a `Sequence` or `Delimited` - /// submatcher, this is just the contents of that submatcher. - tts: &'tt [TokenTree], - - /// The "dot" position within the current submatcher, i.e. the index into `tts`. Can go one or - /// two positions past the final elements in `tts` when dealing with sequences, see - /// `parse_tt_inner` for details. +/// A single matcher position, representing the state of matching. +struct MatcherPos { + /// The index into `TtParser::locs`, which represents the "dot". idx: usize, - /// This vector ends up with one element per metavar in the *top-level* matcher, even when this - /// `MatcherPos` is for a submatcher. Each element records token trees matched against the - /// relevant metavar by the black box parser. The element will be a `MatchedSeq` if the - /// corresponding metavar is within a sequence. + /// The matches made against metavar decls so far. On a successful match, this vector ends up + /// with one element per metavar decl in the matcher. Each element records token trees matched + /// against the relevant metavar by the black box parser. An element will be a `MatchedSeq` if + /// the corresponding metavar decl is within a sequence. matches: Lrc<NamedMatchVec>, - - /// The number of sequences this mp is within. - seq_depth: usize, - - /// The position in `matches` of the next metavar to be matched against the source token - /// stream. Should not be used if there are no metavars. - match_cur: usize, - - /// What kind of matcher we are in. For submatchers, this contains enough information to - /// reconstitute a `MatcherPos` within the parent once we ascend out of the submatcher. - kind: MatcherKind<'tt>, } // This type is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(MatcherPos<'_>, 64); +rustc_data_structures::static_assert_size!(MatcherPos, 16); -impl<'tt> MatcherPos<'tt> { - fn top_level(matcher: &'tt [TokenTree], empty_matches: Lrc<NamedMatchVec>) -> Self { - MatcherPos { - tts: matcher, - idx: 0, - matches: empty_matches, - seq_depth: 0, - match_cur: 0, - kind: MatcherKind::TopLevel, - } - } - - fn empty_sequence( - parent_mp: &MatcherPos<'tt>, - seq: &'tt SequenceRepetition, - empty_matches: Lrc<NamedMatchVec>, - ) -> Self { - let mut mp = MatcherPos { - tts: parent_mp.tts, - idx: parent_mp.idx + 1, - matches: parent_mp.matches.clone(), // a cheap clone - seq_depth: parent_mp.seq_depth, - match_cur: parent_mp.match_cur + seq.num_captures, - kind: parent_mp.kind.clone(), // an expensive clone - }; - for idx in parent_mp.match_cur..parent_mp.match_cur + seq.num_captures { - mp.push_match(idx, MatchedSeq(empty_matches.clone())); - } - mp - } - - fn sequence( - parent_mp: Box<MatcherPos<'tt>>, - seq: &'tt SequenceRepetition, - empty_matches: Lrc<NamedMatchVec>, - ) -> Self { - let seq_kind = box SequenceSubmatcher { - parent: Parent { tts: parent_mp.tts, idx: parent_mp.idx, kind: parent_mp.kind }, - seq, - }; - let mut mp = MatcherPos { - tts: &seq.tts, - idx: 0, - matches: parent_mp.matches, - seq_depth: parent_mp.seq_depth, - match_cur: parent_mp.match_cur, - kind: MatcherKind::Sequence(seq_kind), - }; - // Start with an empty vec for each metavar within the sequence. Note that `mp.seq_depth` - // must have the parent's depth at this point for these `push_match` calls to work. - for idx in mp.match_cur..mp.match_cur + seq.num_captures { - mp.push_match(idx, MatchedSeq(empty_matches.clone())); - } - mp.seq_depth += 1; - mp - } - - /// Adds `m` as a named match for the `idx`-th metavar. - fn push_match(&mut self, idx: usize, m: NamedMatch) { +impl MatcherPos { + /// Adds `m` as a named match for the `metavar_idx`-th metavar. There are only two call sites, + /// and both are hot enough to be always worth inlining. + #[inline(always)] + fn push_match(&mut self, metavar_idx: usize, seq_depth: usize, m: NamedMatch) { let matches = Lrc::make_mut(&mut self.matches); - match self.seq_depth { + match seq_depth { 0 => { // We are not within a sequence. Just append `m`. - assert_eq!(idx, matches.len()); + assert_eq!(metavar_idx, matches.len()); matches.push(m); } _ => { // We are within a sequence. Find the final `MatchedSeq` at the appropriate depth // and append `m` to its vector. - let mut curr = &mut matches[idx]; - for _ in 0..self.seq_depth - 1 { + let mut curr = &mut matches[metavar_idx]; + for _ in 0..seq_depth - 1 { match curr { MatchedSeq(seq) => { let seq = Lrc::make_mut(seq); @@ -255,9 +263,9 @@ fn push_match(&mut self, idx: usize, m: NamedMatch) { } } -enum EofMatcherPositions<'tt> { +enum EofMatcherPositions { None, - One(Box<MatcherPos<'tt>>), + One(MatcherPos), Multiple, } @@ -307,7 +315,7 @@ pub(super) fn count_metavar_decls(matcher: &[TokenTree]) -> usize { /// only on the nesting depth of repetitions in the originating token tree it /// was derived from. /// -/// In layman's terms: `NamedMatch` will form a tree representing nested matches of a particular +/// In layperson's terms: `NamedMatch` will form a tree representing nested matches of a particular /// meta variable. For example, if we are matching the following macro against the following /// invocation... /// @@ -349,63 +357,6 @@ pub(super) fn count_metavar_decls(matcher: &[TokenTree]) -> usize { MatchedNonterminal(Lrc<Nonterminal>), } -fn nameize<I: Iterator<Item = NamedMatch>>( - sess: &ParseSess, - matcher: &[TokenTree], - mut res: I, -) -> NamedParseResult { - // Recursively descend into each type of matcher (e.g., sequences, delimited, metavars) and make - // sure that each metavar has _exactly one_ binding. If a metavar does not have exactly one - // binding, then there is an error. If it does, then we insert the binding into the - // `NamedParseResult`. - fn n_rec<I: Iterator<Item = NamedMatch>>( - sess: &ParseSess, - tt: &TokenTree, - res: &mut I, - ret_val: &mut FxHashMap<MacroRulesNormalizedIdent, NamedMatch>, - ) -> Result<(), (rustc_span::Span, String)> { - match *tt { - TokenTree::Sequence(_, ref seq) => { - for next_m in &seq.tts { - n_rec(sess, next_m, res.by_ref(), ret_val)? - } - } - TokenTree::Delimited(_, ref delim) => { - for next_m in delim.inner_tts() { - n_rec(sess, next_m, res.by_ref(), ret_val)?; - } - } - TokenTree::MetaVarDecl(span, _, None) => { - if sess.missing_fragment_specifiers.borrow_mut().remove(&span).is_some() { - return Err((span, "missing fragment specifier".to_string())); - } - } - TokenTree::MetaVarDecl(sp, bind_name, _) => match ret_val - .entry(MacroRulesNormalizedIdent::new(bind_name)) - { - Vacant(spot) => { - spot.insert(res.next().unwrap()); - } - Occupied(..) => return Err((sp, format!("duplicated bind name: {}", bind_name))), - }, - TokenTree::Token(..) => (), - TokenTree::MetaVar(..) | TokenTree::MetaVarExpr(..) => unreachable!(), - } - - Ok(()) - } - - let mut ret_val = FxHashMap::default(); - for tt in matcher { - match n_rec(sess, tt, res.by_ref(), &mut ret_val) { - Ok(_) => {} - Err((sp, msg)) => return Error(sp, msg), - } - } - - Success(ret_val) -} - /// Performs a token equality check, ignoring syntax context (that is, an unhygienic comparison) fn token_name_eq(t1: &Token, t2: &Token) -> bool { if let (Some((ident1, is_raw1)), Some((ident2, is_raw2))) = (t1.ident(), t2.ident()) { @@ -417,29 +368,29 @@ fn token_name_eq(t1: &Token, t2: &Token) -> bool { } } -// Note: the position vectors could be created and dropped within `parse_tt`, but to avoid excess +// Note: the vectors could be created and dropped within `parse_tt`, but to avoid excess // allocations we have a single vector fo each kind that is cleared and reused repeatedly. -pub struct TtParser<'tt> { +pub struct TtParser { macro_name: Ident, /// The set of current mps to be processed. This should be empty by the end of a successful /// execution of `parse_tt_inner`. - cur_mps: Vec<Box<MatcherPos<'tt>>>, + cur_mps: Vec<MatcherPos>, /// The set of newly generated mps. These are used to replenish `cur_mps` in the function /// `parse_tt`. - next_mps: Vec<Box<MatcherPos<'tt>>>, + next_mps: Vec<MatcherPos>, /// The set of mps that are waiting for the black-box parser. - bb_mps: Vec<Box<MatcherPos<'tt>>>, + bb_mps: Vec<MatcherPos>, /// Pre-allocate an empty match array, so it can be cloned cheaply for macros with many rules /// that have no metavars. empty_matches: Lrc<NamedMatchVec>, } -impl<'tt> TtParser<'tt> { - pub(super) fn new(macro_name: Ident) -> TtParser<'tt> { +impl TtParser { + pub(super) fn new(macro_name: Ident) -> TtParser { TtParser { macro_name, cur_mps: vec![], @@ -459,7 +410,7 @@ pub(super) fn new(macro_name: Ident) -> TtParser<'tt> { fn parse_tt_inner( &mut self, sess: &ParseSess, - matcher: &[TokenTree], + matcher: &[MatcherLoc], token: &Token, ) -> Option<NamedParseResult> { // Matcher positions that would be valid if the macro invocation was over now. Only @@ -467,151 +418,121 @@ fn parse_tt_inner( let mut eof_mps = EofMatcherPositions::None; while let Some(mut mp) = self.cur_mps.pop() { - // Get the current position of the "dot" (`idx`) in `mp` and the number of token - // trees in the matcher (`len`). - let idx = mp.idx; - let len = mp.tts.len(); - - if idx < len { - // We are in the middle of a matcher. Compare the matcher's current tt against - // `token`. - match &mp.tts[idx] { - TokenTree::Sequence(_sp, seq) => { - let op = seq.kleene.op; - if op == mbe::KleeneOp::ZeroOrMore || op == mbe::KleeneOp::ZeroOrOne { - // Allow for the possibility of zero matches of this sequence. - self.cur_mps.push(box MatcherPos::empty_sequence( - &*mp, - &seq, - self.empty_matches.clone(), - )); - } - - // Allow for the possibility of one or more matches of this sequence. - self.cur_mps.push(box MatcherPos::sequence( - mp, - &seq, - self.empty_matches.clone(), - )); - } - - &TokenTree::MetaVarDecl(span, _, None) => { - // E.g. `$e` instead of `$e:expr`. - if sess.missing_fragment_specifiers.borrow_mut().remove(&span).is_some() { - return Some(Error(span, "missing fragment specifier".to_string())); - } - } - - &TokenTree::MetaVarDecl(_, _, Some(kind)) => { - // Built-in nonterminals never start with these tokens, so we can eliminate - // them from consideration. - // - // We use the span of the metavariable declaration to determine any - // edition-specific matching behavior for non-terminals. - if Parser::nonterminal_may_begin_with(kind, token) { - self.bb_mps.push(mp); - } - } - - TokenTree::Delimited(_, delimited) => { - // To descend into a delimited submatcher, we update `mp` appropriately, - // including enough information to re-ascend afterwards, and push it onto - // `cur_mps`. Later, when we reach the closing delimiter, we will recover - // the parent matcher position to ascend. Note that we use `all_tts` to - // include the open and close delimiter tokens. - let kind = MatcherKind::Delimited(box DelimitedSubmatcher { - parent: Parent { tts: mp.tts, idx: mp.idx, kind: mp.kind }, - }); - mp.tts = &delimited.all_tts; - mp.idx = 0; - mp.kind = kind; + match &matcher[mp.idx] { + MatcherLoc::Token { token: t } => { + // If it's a doc comment, we just ignore it and move on to the next tt in the + // matcher. This is a bug, but #95267 showed that existing programs rely on + // this behaviour, and changing it would require some care and a transition + // period. + // + // If the token matches, we can just advance the parser. + // + // Otherwise, this match has failed, there is nothing to do, and hopefully + // another mp in `cur_mps` will match. + if matches!(t, Token { kind: DocComment(..), .. }) { + mp.idx += 1; self.cur_mps.push(mp); - } - - TokenTree::Token(t) => { - // If it's a doc comment, we just ignore it and move on to the next tt in - // the matcher. This is a bug, but #95267 showed that existing programs - // rely on this behaviour, and changing it would require some care and a - // transition period. - // - // If the token matches, we can just advance the parser. - // - // Otherwise, this match has failed, there is nothing to do, and hopefully - // another mp in `cur_mps` will match. - if matches!(t, Token { kind: DocComment(..), .. }) { - mp.idx += 1; - self.cur_mps.push(mp); - } else if token_name_eq(&t, token) { - if let TokenKind::CloseDelim(_) = token.kind { - // Ascend out of the delimited submatcher. - debug_assert_eq!(idx, len - 1); - match mp.kind { - MatcherKind::Delimited(submatcher) => { - mp.tts = submatcher.parent.tts; - mp.idx = submatcher.parent.idx; - mp.kind = submatcher.parent.kind; - } - _ => unreachable!(), - } - } - mp.idx += 1; - self.next_mps.push(mp); - } - } - - // These cannot appear in a matcher. - TokenTree::MetaVar(..) | TokenTree::MetaVarExpr(..) => unreachable!(), - } - } else if let MatcherKind::Sequence(box SequenceSubmatcher { parent, seq }) = &mp.kind { - // We are past the end of a sequence. - // - If it has no separator, we must be only one past the end. - // - If it has a separator, we may be one past the end, in which case we must - // look for a separator. Or we may be two past the end, in which case we have - // already dealt with the separator. - debug_assert!(idx == len || idx == len + 1 && seq.separator.is_some()); - - if idx == len { - // Sequence matching may have finished: move the "dot" past the sequence in - // `parent`. This applies whether a separator is used or not. If sequence - // matching hasn't finished, this `new_mp` will fail quietly when it is - // processed next time around the loop. - let new_mp = box MatcherPos { - tts: parent.tts, - idx: parent.idx + 1, - matches: mp.matches.clone(), // a cheap clone - seq_depth: mp.seq_depth - 1, - match_cur: mp.match_cur, - kind: parent.kind.clone(), // an expensive clone - }; - self.cur_mps.push(new_mp); - } - - if seq.separator.is_some() && idx == len { - // Look for the separator. - if seq.separator.as_ref().map_or(false, |sep| token_name_eq(token, sep)) { - // The matcher has a separator, and it matches the current token. We can - // advance past the separator token. + } else if token_name_eq(&t, token) { mp.idx += 1; self.next_mps.push(mp); } - } else if seq.kleene.op != mbe::KleeneOp::ZeroOrOne { - // We don't need to look for a separator: either this sequence doesn't have - // one, or it does and we've already handled it. Also, we are allowed to have - // more than one repetition. Move the "dot" back to the beginning of the - // matcher and try to match again. - mp.match_cur -= seq.num_captures; - mp.idx = 0; + } + MatcherLoc::Delimited => { + // Entering the delimeter is trivial. + mp.idx += 1; self.cur_mps.push(mp); } - } else { - // We are past the end of the matcher, and not in a sequence. Look for end of - // input. - debug_assert_eq!(idx, len); - if *token == token::Eof { - eof_mps = match eof_mps { - EofMatcherPositions::None => EofMatcherPositions::One(mp), - EofMatcherPositions::One(_) | EofMatcherPositions::Multiple => { - EofMatcherPositions::Multiple + &MatcherLoc::Sequence { + op, + num_metavar_decls, + idx_first_after, + next_metavar, + seq_depth, + } => { + // Install an empty vec for each metavar within the sequence. + for metavar_idx in next_metavar..next_metavar + num_metavar_decls { + mp.push_match( + metavar_idx, + seq_depth, + MatchedSeq(self.empty_matches.clone()), + ); + } + + if op == KleeneOp::ZeroOrMore || op == KleeneOp::ZeroOrOne { + // Try zero matches of this sequence, by skipping over it. + self.cur_mps.push(MatcherPos { + idx: idx_first_after, + matches: mp.matches.clone(), // a cheap clone + }); + } + + // Try one or more matches of this sequence, by entering it. + mp.idx += 1; + self.cur_mps.push(mp); + } + &MatcherLoc::SequenceKleeneOpNoSep { op, idx_first } => { + // We are past the end of a sequence with no separator. Try ending the + // sequence. If that's not possible, `ending_mp` will fail quietly when it is + // processed next time around the loop. + let ending_mp = MatcherPos { + idx: mp.idx + 1, // +1 skips the Kleene op + matches: mp.matches.clone(), // a cheap clone + }; + self.cur_mps.push(ending_mp); + + if op != KleeneOp::ZeroOrOne { + // Try another repetition. + mp.idx = idx_first; + self.cur_mps.push(mp); + } + } + MatcherLoc::SequenceSep { separator } => { + // We are past the end of a sequence with a separator but we haven't seen the + // separator yet. Try ending the sequence. If that's not possible, `ending_mp` + // will fail quietly when it is processed next time around the loop. + let ending_mp = MatcherPos { + idx: mp.idx + 2, // +2 skips the separator and the Kleene op + matches: mp.matches.clone(), // a cheap clone + }; + self.cur_mps.push(ending_mp); + + if token_name_eq(token, separator) { + // The separator matches the current token. Advance past it. + mp.idx += 1; + self.next_mps.push(mp); + } + } + &MatcherLoc::SequenceKleeneOpAfterSep { idx_first } => { + // We are past the sequence separator. This can't be a `?` Kleene op, because + // they don't permit separators. Try another repetition. + mp.idx = idx_first; + self.cur_mps.push(mp); + } + &MatcherLoc::MetaVarDecl { span, kind, .. } => { + // Built-in nonterminals never start with these tokens, so we can eliminate + // them from consideration. We use the span of the metavariable declaration + // to determine any edition-specific matching behavior for non-terminals. + if let Some(kind) = kind { + if Parser::nonterminal_may_begin_with(kind, token) { + self.bb_mps.push(mp); + } + } else { + // Both this check and the one in `nameize` are necessary, surprisingly. + if sess.missing_fragment_specifiers.borrow_mut().remove(&span).is_some() { + // E.g. `$e` instead of `$e:expr`. + return Some(Error(span, "missing fragment specifier".to_string())); + } + } + } + MatcherLoc::Eof => { + // We are past the matcher's end, and not in a sequence. Try to end things. + debug_assert_eq!(mp.idx, matcher.len() - 1); + if *token == token::Eof { + eof_mps = match eof_mps { + EofMatcherPositions::None => EofMatcherPositions::One(mp), + EofMatcherPositions::One(_) | EofMatcherPositions::Multiple => { + EofMatcherPositions::Multiple + } } } } @@ -623,11 +544,10 @@ fn parse_tt_inner( if *token == token::Eof { Some(match eof_mps { EofMatcherPositions::One(mut eof_mp) => { - assert_eq!(eof_mp.matches.len(), count_metavar_decls(matcher)); // Need to take ownership of the matches from within the `Lrc`. Lrc::make_mut(&mut eof_mp.matches); let matches = Lrc::try_unwrap(eof_mp.matches).unwrap().into_iter(); - nameize(sess, matcher, matches) + self.nameize(sess, matcher, matches) } EofMatcherPositions::Multiple => { Error(token.span, "ambiguity: multiple successful parses".to_string()) @@ -649,7 +569,7 @@ fn parse_tt_inner( pub(super) fn parse_tt( &mut self, parser: &mut Cow<'_, Parser<'_>>, - matcher: &'tt [TokenTree], + matcher: &[MatcherLoc], ) -> NamedParseResult { // A queue of possible matcher positions. We initialize it with the matcher position in // which the "dot" is before the first token of the first token tree in `matcher`. @@ -657,7 +577,7 @@ pub(super) fn parse_tt( // possible next positions into `next_mps`. After some post-processing, the contents of // `next_mps` replenish `cur_mps` and we start over again. self.cur_mps.clear(); - self.cur_mps.push(box MatcherPos::top_level(matcher, self.empty_matches.clone())); + self.cur_mps.push(MatcherPos { idx: 0, matches: self.empty_matches.clone() }); loop { self.next_mps.clear(); @@ -665,8 +585,8 @@ pub(super) fn parse_tt( // Process `cur_mps` until either we have finished the input or we need to get some // parsing from the black-box parser done. - if let Some(result) = self.parse_tt_inner(parser.sess, matcher, &parser.token) { - return result; + if let Some(res) = self.parse_tt_inner(&parser.sess, matcher, &parser.token) { + return res; } // `parse_tt_inner` handled all of `cur_mps`, so it's empty. @@ -693,8 +613,15 @@ pub(super) fn parse_tt( (0, 1) => { // We need to call the black-box parser to get some nonterminal. let mut mp = self.bb_mps.pop().unwrap(); - if let TokenTree::MetaVarDecl(span, _, Some(kind)) = mp.tts[mp.idx] { - let match_cur = mp.match_cur; + let loc = &matcher[mp.idx]; + if let &MatcherLoc::MetaVarDecl { + span, + kind: Some(kind), + next_metavar, + seq_depth, + .. + } = loc + { // We use the span of the metavariable declaration to determine any // edition-specific matching behavior for non-terminals. let nt = match parser.to_mut().parse_nonterminal(kind) { @@ -714,9 +641,8 @@ pub(super) fn parse_tt( NtOrTt::Nt(nt) => MatchedNonterminal(Lrc::new(nt)), NtOrTt::Tt(tt) => MatchedTokenTree(tt), }; - mp.push_match(match_cur, m); + mp.push_match(next_metavar, seq_depth, m); mp.idx += 1; - mp.match_cur += 1; } else { unreachable!() } @@ -725,7 +651,7 @@ pub(super) fn parse_tt( (_, _) => { // Too many possibilities! - return self.ambiguity_error(parser.token.span); + return self.ambiguity_error(matcher, parser.token.span); } } @@ -733,15 +659,19 @@ pub(super) fn parse_tt( } } - fn ambiguity_error(&self, token_span: rustc_span::Span) -> NamedParseResult { + fn ambiguity_error( + &self, + matcher: &[MatcherLoc], + token_span: rustc_span::Span, + ) -> NamedParseResult { let nts = self .bb_mps .iter() - .map(|mp| match mp.tts[mp.idx] { - TokenTree::MetaVarDecl(_, bind, Some(kind)) => { + .map(|mp| match &matcher[mp.idx] { + MatcherLoc::MetaVarDecl { bind, kind: Some(kind), .. } => { format!("{} ('{}')", kind, bind) } - _ => panic!(), + _ => unreachable!(), }) .collect::<Vec<String>>() .join(" or "); @@ -759,4 +689,34 @@ fn ambiguity_error(&self, token_span: rustc_span::Span) -> NamedParseResult { ), ) } + + fn nameize<I: Iterator<Item = NamedMatch>>( + &self, + sess: &ParseSess, + matcher: &[MatcherLoc], + mut res: I, + ) -> NamedParseResult { + // Make that each metavar has _exactly one_ binding. If so, insert the binding into the + // `NamedParseResult`. Otherwise, it's an error. + let mut ret_val = FxHashMap::default(); + for loc in matcher { + if let &MatcherLoc::MetaVarDecl { span, bind, kind, .. } = loc { + if kind.is_some() { + match ret_val.entry(MacroRulesNormalizedIdent::new(bind)) { + Vacant(spot) => spot.insert(res.next().unwrap()), + Occupied(..) => { + return Error(span, format!("duplicated bind name: {}", bind)); + } + }; + } else { + // Both this check and the one in `parse_tt_inner` are necessary, surprisingly. + if sess.missing_fragment_specifiers.borrow_mut().remove(&span).is_some() { + // E.g. `$e` instead of `$e:expr`. + return Error(span, "missing fragment specifier".to_string()); + } + } + } + } + Success(ret_val) + } }
diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 10b2b9f..5dc086e 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs
@@ -4,7 +4,7 @@ use crate::mbe; use crate::mbe::macro_check; use crate::mbe::macro_parser::{Error, ErrorReported, Failure, Success, TtParser}; -use crate::mbe::macro_parser::{MatchedSeq, MatchedTokenTree}; +use crate::mbe::macro_parser::{MatchedSeq, MatchedTokenTree, MatcherLoc}; use crate::mbe::transcribe::transcribe; use rustc_ast as ast; @@ -68,17 +68,18 @@ fn emit_frag_parse_err( arm_span: Span, kind: AstFragmentKind, ) { - if parser.token == token::Eof && e.message().ends_with(", found `<eof>`") { + // FIXME(davidtwco): avoid depending on the error message text + if parser.token == token::Eof && e.message[0].0.expect_str().ends_with(", found `<eof>`") { if !e.span.is_dummy() { // early end of macro arm (#52866) e.replace_span_with(parser.sess.source_map().next_point(parser.token.span)); } let msg = &e.message[0]; e.message[0] = ( - format!( + rustc_errors::DiagnosticMessage::Str(format!( "macro expansion ends with an incomplete expression: {}", - msg.0.replace(", found `<eof>`", ""), - ), + msg.0.expect_str().replace(", found `<eof>`", ""), + )), msg.1, ); } @@ -159,7 +160,7 @@ struct MacroRulesMacroExpander { name: Ident, span: Span, transparency: Transparency, - lhses: Vec<mbe::TokenTree>, + lhses: Vec<Vec<MatcherLoc>>, rhses: Vec<mbe::TokenTree>, valid: bool, is_local: bool, @@ -210,7 +211,7 @@ fn generic_extension<'cx, 'tt>( name: Ident, transparency: Transparency, arg: TokenStream, - lhses: &'tt [mbe::TokenTree], + lhses: &'tt [Vec<MatcherLoc>], rhses: &'tt [mbe::TokenTree], is_local: bool, ) -> Box<dyn MacResult + 'cx> { @@ -245,14 +246,6 @@ fn generic_extension<'cx, 'tt>( // this situation.) let parser = parser_from_cx(sess, arg.clone()); - // A matcher is always delimited, but the delimiters are ignored. - let delimited_inner_tts = |tt: &'tt mbe::TokenTree| -> &'tt [mbe::TokenTree] { - match tt { - mbe::TokenTree::Delimited(_, delimited) => delimited.inner_tts(), - _ => cx.span_bug(sp, "malformed macro lhs"), - } - }; - // Try each arm's matchers. let mut tt_parser = TtParser::new(name); for (i, lhs) in lhses.iter().enumerate() { @@ -262,13 +255,19 @@ fn generic_extension<'cx, 'tt>( // are not recorded. On the first `Success(..)`ful matcher, the spans are merged. let mut gated_spans_snapshot = mem::take(&mut *sess.gated_spans.spans.borrow_mut()); - match tt_parser.parse_tt(&mut Cow::Borrowed(&parser), delimited_inner_tts(lhs)) { + match tt_parser.parse_tt(&mut Cow::Borrowed(&parser), lhs) { Success(named_matches) => { // The matcher was `Success(..)`ful. // Merge the gated spans from parsing the matcher with the pre-existing ones. sess.gated_spans.merge(gated_spans_snapshot); - let rhs = delimited_inner_tts(&rhses[i]).to_vec().clone(); + // Ignore the delimiters on the RHS. + let rhs = match &rhses[i] { + mbe::TokenTree::Delimited(_, delimited) => { + delimited.inner_tts().to_vec().clone() + } + _ => cx.span_bug(sp, "malformed macro rhs"), + }; let arm_span = rhses[i].span(); let rhs_spans = rhs.iter().map(|t| t.span()).collect::<Vec<_>>(); @@ -346,10 +345,8 @@ fn generic_extension<'cx, 'tt>( // Check whether there's a missing comma in this macro call, like `println!("{}" a);` if let Some((arg, comma_span)) = arg.add_comma() { for lhs in lhses { - if let Success(_) = tt_parser.parse_tt( - &mut Cow::Borrowed(&parser_from_cx(sess, arg.clone())), - delimited_inner_tts(lhs), - ) { + let parser = parser_from_cx(sess, arg.clone()); + if let Success(_) = tt_parser.parse_tt(&mut Cow::Borrowed(&parser), lhs) { if comma_span.is_dummy() { err.note("you might be missing a comma"); } else { @@ -440,6 +437,8 @@ pub fn compile_declarative_macro( }), ), ]; + // Convert it into `MatcherLoc` form. + let argument_gram = mbe::macro_parser::compute_locs(&sess.parse_sess, &argument_gram); let parser = Parser::new(&sess.parse_sess, body, true, rustc_parse::MACRO_ARGUMENTS); let mut tt_parser = TtParser::new(def.ident); @@ -536,6 +535,25 @@ pub fn compile_declarative_macro( None => {} } + // Convert the lhses into `MatcherLoc` form, which is better for doing the + // actual matching. Unless the matcher is invalid. + let lhses = if valid { + lhses + .iter() + .map(|lhs| { + // Ignore the delimiters around the matcher. + match lhs { + mbe::TokenTree::Delimited(_, delimited) => { + mbe::macro_parser::compute_locs(&sess.parse_sess, delimited.inner_tts()) + } + _ => sess.parse_sess.span_diagnostic.span_bug(def.span, "malformed macro lhs"), + } + }) + .collect() + } else { + vec![] + }; + mk_syn_ext(Box::new(MacroRulesMacroExpander { name: def.ident, span: def.span,
diff --git a/compiler/rustc_expand/src/mbe/metavar_expr.rs b/compiler/rustc_expand/src/mbe/metavar_expr.rs index 2949ca7..52a656e 100644 --- a/compiler/rustc_expand/src/mbe/metavar_expr.rs +++ b/compiler/rustc_expand/src/mbe/metavar_expr.rs
@@ -128,13 +128,15 @@ fn parse_ident<'sess>( sess: &'sess ParseSess, span: Span, ) -> PResult<'sess, Ident> { - let err_fn = |msg| sess.span_diagnostic.struct_span_err(span, msg); if let Some(tt) = iter.next() && let TokenTree::Token(token) = tt { if let Some((elem, false)) = token.ident() { return Ok(elem); } let token_str = pprust::token_to_string(&token); - let mut err = err_fn(&format!("expected identifier, found `{}`", &token_str)); + let mut err = sess.span_diagnostic.struct_span_err( + span, + &format!("expected identifier, found `{}`", &token_str) + ); err.span_suggestion( token.span, &format!("try removing `{}`", &token_str), @@ -143,7 +145,7 @@ fn parse_ident<'sess>( ); return Err(err); } - Err(err_fn("expected identifier")) + Err(sess.span_diagnostic.struct_span_err(span, "expected identifier")) } /// Tries to move the iterator forward returning `true` if there is a comma. If not, then the
diff --git a/compiler/rustc_expand/src/proc_macro.rs b/compiler/rustc_expand/src/proc_macro.rs index a5afb7a..aec401a 100644 --- a/compiler/rustc_expand/src/proc_macro.rs +++ b/compiler/rustc_expand/src/proc_macro.rs
@@ -24,6 +24,8 @@ fn expand<'cx>( span: Span, input: TokenStream, ) -> Result<TokenStream, ErrorGuaranteed> { + let _timer = + ecx.sess.prof.generic_activity_with_arg("expand_proc_macro", ecx.expansion_descr()); let proc_macro_backtrace = ecx.ecfg.proc_macro_backtrace; let server = proc_macro_server::Rustc::new(ecx); self.client.run(&EXEC_STRATEGY, server, input, proc_macro_backtrace).map_err(|e| { @@ -48,6 +50,8 @@ fn expand<'cx>( annotation: TokenStream, annotated: TokenStream, ) -> Result<TokenStream, ErrorGuaranteed> { + let _timer = + ecx.sess.prof.generic_activity_with_arg("expand_proc_macro", ecx.expansion_descr()); let proc_macro_backtrace = ecx.ecfg.proc_macro_backtrace; let server = proc_macro_server::Rustc::new(ecx); self.client @@ -86,7 +90,7 @@ fn expand( // A proc macro can't observe the fact that we're passing // them an `NtStmt` - it can only see the underlying tokens // of the wrapped item - token::NtStmt(stmt.into_inner()) + token::NtStmt(stmt) } _ => unreachable!(), }; @@ -97,17 +101,21 @@ fn expand( nt_to_tokenstream(&item, &ecx.sess.parse_sess, CanSynthesizeMissingTokens::No) }; - let proc_macro_backtrace = ecx.ecfg.proc_macro_backtrace; - let server = proc_macro_server::Rustc::new(ecx); - let stream = match self.client.run(&EXEC_STRATEGY, server, input, proc_macro_backtrace) { - Ok(stream) => stream, - Err(e) => { - let mut err = ecx.struct_span_err(span, "proc-macro derive panicked"); - if let Some(s) = e.as_str() { - err.help(&format!("message: {}", s)); + let stream = { + let _timer = + ecx.sess.prof.generic_activity_with_arg("expand_proc_macro", ecx.expansion_descr()); + let proc_macro_backtrace = ecx.ecfg.proc_macro_backtrace; + let server = proc_macro_server::Rustc::new(ecx); + match self.client.run(&EXEC_STRATEGY, server, input, proc_macro_backtrace) { + Ok(stream) => stream, + Err(e) => { + let mut err = ecx.struct_span_err(span, "proc-macro derive panicked"); + if let Some(s) = e.as_str() { + err.help(&format!("message: {}", s)); + } + err.emit(); + return ExpandResult::Ready(vec![]); } - err.emit(); - return ExpandResult::Ready(vec![]); } };
diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index bfdf997..bd6f0b7 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs
@@ -7,13 +7,13 @@ use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; -use rustc_errors::{Diagnostic, PResult}; +use rustc_errors::{Diagnostic, MultiSpan, PResult}; use rustc_parse::lexer::nfc_normalize; use rustc_parse::{nt_to_tokenstream, parse_stream_from_source_str}; use rustc_session::parse::ParseSess; use rustc_span::def_id::CrateNum; use rustc_span::symbol::{self, kw, sym, Symbol}; -use rustc_span::{BytePos, FileName, MultiSpan, Pos, SourceFile, Span}; +use rustc_span::{BytePos, FileName, Pos, SourceFile, Span}; use pm::bridge::{server, TokenTree}; use pm::{Delimiter, Level, LineColumn, Spacing}; @@ -658,16 +658,16 @@ fn f64(&mut self, n: &str) -> Self::Literal { self.lit(token::Float, Symbol::intern(n), Some(sym::f64)) } fn string(&mut self, string: &str) -> Self::Literal { - let mut escaped = String::new(); - for ch in string.chars() { - escaped.extend(ch.escape_debug()); - } - self.lit(token::Str, Symbol::intern(&escaped), None) + let quoted = format!("{:?}", string); + assert!(quoted.starts_with('"') && quoted.ends_with('"')); + let symbol = "ed[1..quoted.len() - 1]; + self.lit(token::Str, Symbol::intern(symbol), None) } fn character(&mut self, ch: char) -> Self::Literal { - let mut escaped = String::new(); - escaped.extend(ch.escape_unicode()); - self.lit(token::Char, Symbol::intern(&escaped), None) + let quoted = format!("{:?}", ch); + assert!(quoted.starts_with('\'') && quoted.ends_with('\'')); + let symbol = "ed[1..quoted.len() - 1]; + self.lit(token::Char, Symbol::intern(symbol), None) } fn byte_string(&mut self, bytes: &[u8]) -> Self::Literal { let string = bytes
diff --git a/compiler/rustc_expand/src/tests.rs b/compiler/rustc_expand/src/tests.rs index ed3aa1e..88f3cf9 100644 --- a/compiler/rustc_expand/src/tests.rs +++ b/compiler/rustc_expand/src/tests.rs
@@ -4,11 +4,11 @@ use rustc_session::parse::ParseSess; use rustc_span::create_default_session_if_not_set_then; use rustc_span::source_map::{FilePathMapping, SourceMap}; -use rustc_span::{BytePos, MultiSpan, Span}; +use rustc_span::{BytePos, Span}; use rustc_data_structures::sync::Lrc; use rustc_errors::emitter::EmitterWriter; -use rustc_errors::{Handler, PResult}; +use rustc_errors::{Handler, MultiSpan, PResult}; use std::io; use std::io::prelude::*; @@ -127,6 +127,8 @@ fn test_harness(file_text: &str, span_labels: Vec<SpanLabel>, expected_output: & create_default_session_if_not_set_then(|_| { let output = Arc::new(Mutex::new(Vec::new())); + let fallback_bundle = rustc_errors::fallback_fluent_bundle(false) + .expect("failed to load fallback fluent bundle"); let source_map = Lrc::new(SourceMap::new(FilePathMapping::empty())); source_map.new_source_file(Path::new("test.rs").to_owned().into(), file_text.to_owned()); @@ -142,6 +144,8 @@ fn test_harness(file_text: &str, span_labels: Vec<SpanLabel>, expected_output: & let emitter = EmitterWriter::new( Box::new(Shared { data: output.clone() }), Some(source_map.clone()), + None, + fallback_bundle, false, false, false,
diff --git a/compiler/rustc_hir/Cargo.toml b/compiler/rustc_hir/Cargo.toml index 41c6344..34d366f 100644 --- a/compiler/rustc_hir/Cargo.toml +++ b/compiler/rustc_hir/Cargo.toml
@@ -11,6 +11,7 @@ rustc_feature = { path = "../rustc_feature" } rustc_macros = { path = "../rustc_macros" } rustc_data_structures = { path = "../rustc_data_structures" } +rustc_error_messages = { path = "../rustc_error_messages" } rustc_index = { path = "../rustc_index" } rustc_span = { path = "../rustc_span" } rustc_serialize = { path = "../rustc_serialize" }
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 10871df..1511807 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs
@@ -13,12 +13,13 @@ use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sorted_map::SortedMap; +use rustc_error_messages::MultiSpan; use rustc_index::vec::IndexVec; use rustc_macros::HashStable_Generic; use rustc_span::hygiene::MacroKind; use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, sym, Ident, Symbol}; -use rustc_span::{def_id::LocalDefId, BytePos, MultiSpan, Span, DUMMY_SP}; +use rustc_span::{def_id::LocalDefId, BytePos, Span, DUMMY_SP}; use rustc_target::asm::InlineAsmRegOrRegClass; use rustc_target::spec::abi::Abi;
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index d915f9a..f25215f 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -59,7 +59,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{pluralize, struct_span_err, Diagnostic, ErrorGuaranteed}; -use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString}; +use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString, MultiSpan}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; @@ -72,7 +72,7 @@ subst::{GenericArgKind, Subst, SubstsRef}, Binder, List, Region, Ty, TyCtxt, TypeFoldable, }; -use rustc_span::{sym, BytePos, DesugaringKind, MultiSpan, Pos, Span}; +use rustc_span::{sym, BytePos, DesugaringKind, Pos, Span}; use rustc_target::spec::abi; use std::ops::ControlFlow; use std::{cmp, fmt, iter}; @@ -2075,7 +2075,7 @@ fn suggest_as_ref_where_appropriate( { diag.span_suggestion( span, - msg, + *msg, format!("{}.as_ref()", snippet), Applicability::MachineApplicable, );
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs index 61e3334..80500f3 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs
@@ -7,11 +7,10 @@ use crate::infer::{SubregionOrigin, TypeTrace}; use crate::traits::ObligationCauseCode; use rustc_data_structures::stable_set::FxHashSet; -use rustc_errors::{Applicability, ErrorGuaranteed}; +use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan}; use rustc_hir as hir; use rustc_hir::intravisit::Visitor; use rustc_middle::ty::TypeVisitor; -use rustc_span::MultiSpan; impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { pub(super) fn try_report_mismatched_static_lifetime(&self) -> Option<ErrorGuaranteed> { @@ -42,8 +41,7 @@ pub(super) fn try_report_mismatched_static_lifetime(&self) -> Option<ErrorGuaran let mut err = self.tcx().sess.struct_span_err(cause.span, "incompatible lifetime on type"); // FIXME: we should point at the lifetime let mut multi_span: MultiSpan = vec![binding_span].into(); - multi_span - .push_span_label(binding_span, "introduces a `'static` lifetime requirement".into()); + multi_span.push_span_label(binding_span, "introduces a `'static` lifetime requirement"); err.span_note(multi_span, "because this has an unmet lifetime requirement"); note_and_explain_region(self.tcx(), &mut err, "", sup, "...", Some(binding_span)); if let Some(impl_node) = self.tcx().hir().get_if_local(*impl_def_id) {
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs index c33c0c9..a4c46d5 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
@@ -5,7 +5,7 @@ use crate::infer::{SubregionOrigin, TypeTrace}; use crate::traits::{ObligationCauseCode, UnifyReceiverContext}; use rustc_data_structures::stable_set::FxHashSet; -use rustc_errors::{struct_span_err, Applicability, Diagnostic, ErrorGuaranteed}; +use rustc_errors::{struct_span_err, Applicability, Diagnostic, ErrorGuaranteed, MultiSpan}; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{walk_ty, Visitor}; use rustc_hir::{self as hir, GenericBound, Item, ItemKind, Lifetime, LifetimeName, Node, TyKind}; @@ -13,7 +13,7 @@ self, AssocItemContainer, StaticLifetimeVisitor, Ty, TyCtxt, TypeFoldable, TypeVisitor, }; use rustc_span::symbol::Ident; -use rustc_span::{MultiSpan, Span}; +use rustc_span::Span; use std::ops::ControlFlow;
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs index 6d23dc4..1788eb8 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs
@@ -4,7 +4,7 @@ use crate::infer::lexical_region_resolve::RegionResolutionError; use crate::infer::{SubregionOrigin, Subtype}; use crate::traits::ObligationCauseCode::CompareImplMethodObligation; -use rustc_errors::ErrorGuaranteed; +use rustc_errors::{ErrorGuaranteed, MultiSpan}; use rustc_hir as hir; use rustc_hir::def::Res; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -12,8 +12,7 @@ use rustc_middle::hir::nested_filter; use rustc_middle::ty::print::RegionHighlightMode; use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeVisitor}; - -use rustc_span::{MultiSpan, Span, Symbol}; +use rustc_span::{Span, Symbol}; use std::ops::ControlFlow;
diff --git a/compiler/rustc_infer/src/infer/error_reporting/note.rs b/compiler/rustc_infer/src/infer/error_reporting/note.rs index 5dcac7f..baea3e8 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note.rs
@@ -7,7 +7,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { pub(super) fn note_region_origin(&self, err: &mut Diagnostic, origin: &SubregionOrigin<'tcx>) { - let mut label_or_note = |span, msg| { + let mut label_or_note = |span, msg: &str| { let sub_count = err.children.iter().filter(|d| d.span.is_dummy()).count(); let expanded_sub_count = err.children.iter().filter(|d| !d.span.is_dummy()).count(); let span_is_primary = err.span.primary_spans().iter().all(|&sp| sp == span);
diff --git a/compiler/rustc_infer/src/traits/error_reporting/mod.rs b/compiler/rustc_infer/src/traits/error_reporting/mod.rs index 25b11e3..d297640 100644 --- a/compiler/rustc_infer/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/traits/error_reporting/mod.rs
@@ -2,11 +2,11 @@ use crate::infer::InferCtxt; use rustc_data_structures::fx::FxHashSet; -use rustc_errors::{struct_span_err, DiagnosticBuilder, ErrorGuaranteed}; +use rustc_errors::{struct_span_err, DiagnosticBuilder, ErrorGuaranteed, MultiSpan}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::ty::TyCtxt; -use rustc_span::{MultiSpan, Span}; +use rustc_span::Span; use std::fmt; use std::iter;
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index f2164bc..eac6a33 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs
@@ -10,7 +10,7 @@ use rustc_data_structures::parallel; use rustc_data_structures::sync::{Lrc, OnceCell, WorkerLocal}; use rustc_data_structures::temp_dir::MaybeTempDir; -use rustc_errors::{Applicability, ErrorGuaranteed, PResult}; +use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan, PResult}; use rustc_expand::base::{ExtCtxt, LintStoreExpand, ResolverExpand}; use rustc_hir::def_id::{StableCrateId, LOCAL_CRATE}; use rustc_hir::Crate; @@ -35,7 +35,7 @@ use rustc_session::search_paths::PathKind; use rustc_session::{Limit, Session}; use rustc_span::symbol::{sym, Symbol}; -use rustc_span::{FileName, MultiSpan}; +use rustc_span::FileName; use rustc_trait_selection::traits; use rustc_typeck as typeck; use tempfile::Builder as TempFileBuilder;
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index d43c661..e6f9246 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs
@@ -31,7 +31,7 @@ use rustc_ast_pretty::pprust::{self, expr_to_string}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::stack::ensure_sufficient_stack; -use rustc_errors::{Applicability, Diagnostic, DiagnosticStyledString}; +use rustc_errors::{Applicability, Diagnostic, DiagnosticStyledString, MultiSpan}; use rustc_feature::{deprecated_attributes, AttributeGate, BuiltinAttribute, GateIssue, Stability}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; @@ -49,7 +49,7 @@ use rustc_span::edition::Edition; use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, sym, Ident, Symbol}; -use rustc_span::{BytePos, InnerSpan, MultiSpan, Span}; +use rustc_span::{BytePos, InnerSpan, Span}; use rustc_target::abi::VariantIdx; use rustc_trait_selection::traits::{self, misc::can_type_implement_copy}; @@ -1571,7 +1571,7 @@ fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) { lint.build("bounds on generic parameters are not enforced in type aliases"); let msg = "the bound will not be checked when the type alias is used, \ and should be removed"; - err.multipart_suggestion(&msg, suggestion, Applicability::MachineApplicable); + err.multipart_suggestion(msg, suggestion, Applicability::MachineApplicable); if !suggested_changing_assoc_types { TypeAliasBounds::suggest_changing_assoc_types(ty, &mut err); suggested_changing_assoc_types = true;
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 882fa44..3600b6a 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs
@@ -21,7 +21,7 @@ use rustc_ast::util::unicode::TEXT_FLOW_CONTROL_CHARS; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync; -use rustc_errors::{struct_span_err, Applicability, SuggestionStyle}; +use rustc_errors::{struct_span_err, Applicability, MultiSpan, SuggestionStyle}; use rustc_hir as hir; use rustc_hir::def::Res; use rustc_hir::def_id::{CrateNum, DefId}; @@ -38,7 +38,7 @@ use rustc_session::Session; use rustc_span::lev_distance::find_best_match_for_name; use rustc_span::symbol::{sym, Ident, Symbol}; -use rustc_span::{BytePos, MultiSpan, Span, DUMMY_SP}; +use rustc_span::{BytePos, Span, DUMMY_SP}; use rustc_target::abi; use tracing::debug;
diff --git a/compiler/rustc_lint/src/expect.rs b/compiler/rustc_lint/src/expect.rs index 74fef0b..67f5aa0 100644 --- a/compiler/rustc_lint/src/expect.rs +++ b/compiler/rustc_lint/src/expect.rs
@@ -37,7 +37,7 @@ fn emit_unfulfilled_expectation_lint( |diag| { let mut diag = diag.build("this lint expectation is unfulfilled"); if let Some(rationale) = expectation.reason { - diag.note(&rationale.as_str()); + diag.note(rationale.as_str()); } if expectation.is_unfulfilled_lint_expectations {
diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index 99a5720..01f1d1e 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs
@@ -3,7 +3,7 @@ use rustc_ast as ast; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashMap; -use rustc_errors::{struct_span_err, Applicability, Diagnostic}; +use rustc_errors::{struct_span_err, Applicability, Diagnostic, MultiSpan}; use rustc_hir as hir; use rustc_hir::{intravisit, HirId}; use rustc_middle::hir::nested_filter; @@ -20,7 +20,7 @@ use rustc_session::parse::{add_feature_diagnostics, feature_err}; use rustc_session::Session; use rustc_span::symbol::{sym, Symbol}; -use rustc_span::{source_map::MultiSpan, Span, DUMMY_SP}; +use rustc_span::{Span, DUMMY_SP}; use tracing::debug; fn lint_levels(tcx: TyCtxt<'_>, (): ()) -> LintLevelMap {
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index c95905b..437104d 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs
@@ -12,7 +12,7 @@ use rustc_span::source_map; use rustc_span::symbol::sym; use rustc_span::{Span, Symbol, DUMMY_SP}; -use rustc_target::abi::Abi; +use rustc_target::abi::{Abi, WrappingRange}; use rustc_target::abi::{Integer, TagEncoding, Variants}; use rustc_target::spec::abi::Abi as SpecAbi; @@ -154,7 +154,7 @@ fn lint_overflowing_range_endpoint<'tcx>( let suggestion = format!("{}..={}{}", start, lit_val - 1, suffix); err.span_suggestion( parent_expr.span, - &"use an inclusive range instead", + "use an inclusive range instead", suggestion, Applicability::MachineApplicable, ); @@ -399,7 +399,7 @@ fn lint_uint_literal<'tcx>( lint.build("only `u8` can be cast into `char`") .span_suggestion( par_e.span, - &"use a `char` literal instead", + "use a `char` literal instead", format!("'\\u{{{:X}}}'", lit_val), Applicability::MachineApplicable, ) @@ -796,14 +796,18 @@ fn get_nullable_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'t // Return the nullable type this Option-like enum can be safely represented with. let field_ty_abi = &cx.layout_of(field_ty).unwrap().abi; if let Abi::Scalar(field_ty_scalar) = field_ty_abi { - match (field_ty_scalar.valid_range.start, field_ty_scalar.valid_range.end) { - (0, x) if x == field_ty_scalar.value.size(&cx.tcx).unsigned_int_max() - 1 => { + match field_ty_scalar.valid_range(cx) { + WrappingRange { start: 0, end } + if end == field_ty_scalar.size(&cx.tcx).unsigned_int_max() - 1 => + { return Some(get_nullable_type(cx, field_ty).unwrap()); } - (1, _) => { + WrappingRange { start: 1, .. } => { return Some(get_nullable_type(cx, field_ty).unwrap()); } - (start, end) => unreachable!("Unhandled start and end range: ({}, {})", start, end), + WrappingRange { start, end } => { + unreachable!("Unhandled start and end range: ({}, {})", start, end) + } }; } } @@ -1342,7 +1346,7 @@ fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) { return }; - let tag_size = tag.value.size(&cx.tcx).bytes(); + let tag_size = tag.size(&cx.tcx).bytes(); debug!( "enum `{}` is {} bytes large with layout:\n{:#?}",
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 91b72f1..494bdaa 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs
@@ -3,7 +3,7 @@ use rustc_ast as ast; use rustc_ast::util::{classify, parser}; use rustc_ast::{ExprKind, StmtKind}; -use rustc_errors::{pluralize, Applicability}; +use rustc_errors::{pluralize, Applicability, MultiSpan}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; @@ -11,7 +11,7 @@ use rustc_middle::ty::{self, Ty}; use rustc_span::symbol::Symbol; use rustc_span::symbol::{kw, sym}; -use rustc_span::{BytePos, MultiSpan, Span, DUMMY_SP}; +use rustc_span::{BytePos, Span, DUMMY_SP}; declare_lint! { /// The `unused_must_use` lint detects unused result of a type flagged as
diff --git a/compiler/rustc_lint_defs/Cargo.toml b/compiler/rustc_lint_defs/Cargo.toml index 8acf794..fcd8c37 100644 --- a/compiler/rustc_lint_defs/Cargo.toml +++ b/compiler/rustc_lint_defs/Cargo.toml
@@ -6,6 +6,7 @@ [dependencies] rustc_ast = { path = "../rustc_ast" } rustc_data_structures = { path = "../rustc_data_structures" } +rustc_error_messages = { path = "../rustc_error_messages" } rustc_span = { path = "../rustc_span" } rustc_serialize = { path = "../rustc_serialize" } rustc_macros = { path = "../rustc_macros" }
diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index f0eb27c..031b01a 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs
@@ -7,10 +7,11 @@ use rustc_ast::node_id::{NodeId, NodeMap}; use rustc_ast::{AttrId, Attribute}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey}; +use rustc_error_messages::MultiSpan; use rustc_hir::HirId; use rustc_serialize::json::Json; use rustc_span::edition::Edition; -use rustc_span::{sym, symbol::Ident, MultiSpan, Span, Symbol}; +use rustc_span::{sym, symbol::Ident, Span, Symbol}; use rustc_target::spec::abi::Abi; pub mod builtin;
diff --git a/compiler/rustc_llvm/src/lib.rs b/compiler/rustc_llvm/src/lib.rs index 0324ac3..b63f81b 100644 --- a/compiler/rustc_llvm/src/lib.rs +++ b/compiler/rustc_llvm/src/lib.rs
@@ -1,5 +1,4 @@ #![feature(nll)] -#![cfg_attr(bootstrap, feature(native_link_modifiers))] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] // NOTE: This crate only exists to allow linking on mingw targets.
diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs index 03e1397..3589860 100644 --- a/compiler/rustc_macros/src/lib.rs +++ b/compiler/rustc_macros/src/lib.rs
@@ -63,9 +63,14 @@ pub fn newtype_index(input: TokenStream) -> TokenStream { decl_derive!([Lift, attributes(lift)] => lift::lift_derive); decl_derive!( [SessionDiagnostic, attributes( - message, - lint, + // struct attributes + warning, error, + note, + help, + // field attributes + skip_arg, + primary_span, label, suggestion, suggestion_short,
diff --git a/compiler/rustc_macros/src/session_diagnostic.rs b/compiler/rustc_macros/src/session_diagnostic.rs index c9e4049..46f698f 100644 --- a/compiler/rustc_macros/src/session_diagnostic.rs +++ b/compiler/rustc_macros/src/session_diagnostic.rs
@@ -5,8 +5,9 @@ use std::collections::{BTreeSet, HashMap}; -/// Implements #[derive(SessionDiagnostic)], which allows for errors to be specified as a struct, independent -/// from the actual diagnostics emitting code. +/// Implements `#[derive(SessionDiagnostic)]`, which allows for errors to be specified as a struct, +/// independent from the actual diagnostics emitting code. +/// /// ```ignore (pseudo-rust) /// # extern crate rustc_errors; /// # use rustc_errors::Applicability; @@ -15,11 +16,11 @@ /// # extern crate rust_middle; /// # use rustc_middle::ty::Ty; /// #[derive(SessionDiagnostic)] -/// #[code = "E0505"] -/// #[error = "cannot move out of {name} because it is borrowed"] +/// #[error(code = "E0505", slug = "move-out-of-borrow-error")] /// pub struct MoveOutOfBorrowError<'tcx> { /// pub name: Ident, /// pub ty: Ty<'tcx>, +/// #[primary_span] /// #[label = "cannot move out of borrow"] /// pub span: Span, /// #[label = "`{ty}` first borrowed here"] @@ -28,6 +29,7 @@ /// pub opt_sugg: Option<(Span, Applicability)> /// } /// ``` +/// /// Then, later, to emit the error: /// /// ```ignore (pseudo-rust) @@ -47,10 +49,10 @@ pub fn session_diagnostic_derive(s: synstructure::Structure<'_>) -> proc_macro2: SessionDiagnosticDerive::new(diag, sess, s).into_tokens() } -// Checks whether the type name of `ty` matches `name`. -// -// Given some struct at a::b::c::Foo, this will return true for c::Foo, b::c::Foo, or -// a::b::c::Foo. This reasonably allows qualified names to be used in the macro. +/// Checks whether the type name of `ty` matches `name`. +/// +/// Given some struct at `a::b::c::Foo`, this will return true for `c::Foo`, `b::c::Foo`, or +/// `a::b::c::Foo`. This reasonably allows qualified names to be used in the macro. fn type_matches_path(ty: &syn::Type, name: &[&str]) -> bool { if let syn::Type::Path(ty) = ty { ty.path @@ -65,7 +67,7 @@ fn type_matches_path(ty: &syn::Type, name: &[&str]) -> bool { } } -/// The central struct for constructing the as_error method from an annotated struct. +/// The central struct for constructing the `as_error` method from an annotated struct. struct SessionDiagnosticDerive<'a> { structure: synstructure::Structure<'a>, builder: SessionDiagnosticDeriveBuilder<'a>, @@ -77,13 +79,6 @@ fn from(e: syn::Error) -> Self { } } -/// Equivalent to rustc:errors::diagnostic::DiagnosticId, except stores the quoted expression to -/// initialise the code with. -enum DiagnosticId { - Error(proc_macro2::TokenStream), - Lint(proc_macro2::TokenStream), -} - #[derive(Debug)] enum SessionDiagnosticDeriveError { SynError(syn::Error), @@ -98,7 +93,7 @@ fn to_compile_error(self) -> proc_macro2::TokenStream { // Return ! to avoid having to create a blank DiagnosticBuilder to return when an // error has already been emitted to the compiler. quote! { - unreachable!() + { unreachable!(); } } } } @@ -109,9 +104,10 @@ fn span_err(span: impl proc_macro::MultiSpan, msg: &str) -> proc_macro::Diagnost Diagnostic::spanned(span, proc_macro::Level::Error, msg) } -/// For methods that return a Result<_, SessionDiagnosticDeriveError>: emit a diagnostic on -/// span $span with msg $msg (and, optionally, perform additional decoration using the FnOnce -/// passed in `diag`). Then, return Err(ErrorHandled). +/// For methods that return a `Result<_, SessionDiagnosticDeriveError>`: +/// +/// Emit a diagnostic on span `$span` with msg `$msg` (optionally performing additional decoration +/// using the `FnOnce` passed in `diag`) and return `Err(ErrorHandled)`. macro_rules! throw_span_err { ($span:expr, $msg:expr) => {{ throw_span_err!($span, $msg, |diag| diag) }}; ($span:expr, $msg:expr, $f:expr) => {{ @@ -119,8 +115,8 @@ macro_rules! throw_span_err { }}; } -/// When possible, prefer using throw_span_err! over using this function directly. This only exists -/// as a function to constrain `f` to an impl FnOnce. +/// When possible, prefer using `throw_span_err!` over using this function directly. This only +/// exists as a function to constrain `f` to an `impl FnOnce`. fn _throw_span_err( span: impl proc_macro::MultiSpan, msg: &str, @@ -149,17 +145,25 @@ fn new(diag: syn::Ident, sess: syn::Ident, structure: synstructure::Structure<'a } Self { - builder: SessionDiagnosticDeriveBuilder { diag, sess, fields: fields_map, kind: None }, + builder: SessionDiagnosticDeriveBuilder { + diag, + sess, + fields: fields_map, + kind: None, + code: None, + slug: None, + }, structure, } } + fn into_tokens(self) -> proc_macro2::TokenStream { - let SessionDiagnosticDerive { structure, mut builder } = self; + let SessionDiagnosticDerive { mut structure, mut builder } = self; let ast = structure.ast(); let attrs = &ast.attrs; - let implementation = { + let (implementation, param_ty) = { if let syn::Data::Struct(..) = ast.data { let preamble = { let preamble = attrs.iter().map(|attr| { @@ -167,16 +171,23 @@ fn into_tokens(self) -> proc_macro2::TokenStream { .generate_structure_code(attr) .unwrap_or_else(|v| v.to_compile_error()) }); + quote! { #(#preamble)*; } }; - let body = structure.each(|field_binding| { + // Generates calls to `span_label` and similar functions based on the attributes + // on fields. Code for suggestions uses formatting machinery and the value of + // other fields - because any given field can be referenced multiple times, it + // should be accessed through a borrow. When passing fields to `set_arg` (which + // happens below) for Fluent, we want to move the data, so that has to happen + // in a separate pass over the fields. + let attrs = structure.each(|field_binding| { let field = field_binding.ast(); let result = field.attrs.iter().map(|attr| { builder - .generate_field_code( + .generate_field_attr_code( attr, FieldInfo { vis: &field.vis, @@ -187,52 +198,109 @@ fn into_tokens(self) -> proc_macro2::TokenStream { ) .unwrap_or_else(|v| v.to_compile_error()) }); - return quote! { - #(#result);* - }; + + quote! { #(#result);* } }); - // Finally, putting it altogether. - match builder.kind { - None => { - span_err(ast.span().unwrap(), "`code` not specified") - .help("use the [code = \"...\"] attribute to set this diagnostic's error code ") - .emit(); - SessionDiagnosticDeriveError::ErrorHandled.to_compile_error() - } - Some((kind, _)) => match kind { - DiagnosticId::Lint(_lint) => todo!(), - DiagnosticId::Error(code) => { - let (diag, sess) = (&builder.diag, &builder.sess); - quote! { - let mut #diag = #sess.struct_err_with_code("", rustc_errors::DiagnosticId::Error(#code)); - #preamble - match self { - #body - } - #diag - } + + // When generating `set_arg` calls, move data rather than borrow it to avoid + // requiring clones - this must therefore be the last use of each field (for + // example, any formatting machinery that might refer to a field should be + // generated already). + structure.bind_with(|_| synstructure::BindStyle::Move); + let args = structure.each(|field_binding| { + let field = field_binding.ast(); + // When a field has attributes like `#[label]` or `#[note]` then it doesn't + // need to be passed as an argument to the diagnostic. But when a field has no + // attributes then it must be passed as an argument to the diagnostic so that + // it can be referred to by Fluent messages. + if field.attrs.is_empty() { + let diag = &builder.diag; + let ident = field_binding.ast().ident.as_ref().unwrap(); + quote! { + #diag.set_arg( + stringify!(#ident), + #field_binding.into_diagnostic_arg() + ); } - }, - } + } else { + quote! {} + } + }); + + let span = ast.span().unwrap(); + let (diag, sess) = (&builder.diag, &builder.sess); + let init = match (builder.kind, builder.slug) { + (None, _) => { + span_err(span, "diagnostic kind not specified") + .help("use the `#[error(...)]` attribute to create an error") + .emit(); + return SessionDiagnosticDeriveError::ErrorHandled.to_compile_error(); + } + (Some((kind, _)), None) => { + span_err(span, "`slug` not specified") + .help(&format!("use the `#[{}(slug = \"...\")]` attribute to set this diagnostic's slug", kind.descr())) + .emit(); + return SessionDiagnosticDeriveError::ErrorHandled.to_compile_error(); + } + (Some((SessionDiagnosticKind::Error, _)), Some((slug, _))) => { + quote! { + let mut #diag = #sess.struct_err( + rustc_errors::DiagnosticMessage::fluent(#slug), + ); + } + } + (Some((SessionDiagnosticKind::Warn, _)), Some((slug, _))) => { + quote! { + let mut #diag = #sess.struct_warn( + rustc_errors::DiagnosticMessage::fluent(#slug), + ); + } + } + }; + + let implementation = quote! { + #init + #preamble + match self { + #attrs + } + match self { + #args + } + #diag + }; + let param_ty = match builder.kind { + Some((SessionDiagnosticKind::Error, _)) => { + quote! { rustc_errors::ErrorGuaranteed } + } + Some((SessionDiagnosticKind::Warn, _)) => quote! { () }, + _ => unreachable!(), + }; + + (implementation, param_ty) } else { span_err( ast.span().unwrap(), "`#[derive(SessionDiagnostic)]` can only be used on structs", ) .emit(); - SessionDiagnosticDeriveError::ErrorHandled.to_compile_error() + + let implementation = SessionDiagnosticDeriveError::ErrorHandled.to_compile_error(); + let param_ty = quote! { rustc_errors::ErrorGuaranteed }; + (implementation, param_ty) } }; let sess = &builder.sess; structure.gen_impl(quote! { - gen impl<'__session_diagnostic_sess> rustc_session::SessionDiagnostic<'__session_diagnostic_sess> + gen impl<'__session_diagnostic_sess> rustc_session::SessionDiagnostic<'__session_diagnostic_sess, #param_ty> for @Self { fn into_diagnostic( self, #sess: &'__session_diagnostic_sess rustc_session::Session - ) -> rustc_errors::DiagnosticBuilder<'__session_diagnostic_sess, rustc_errors::ErrorGuaranteed> { + ) -> rustc_errors::DiagnosticBuilder<'__session_diagnostic_sess, #param_ty> { + use rustc_errors::IntoDiagnosticArg; #implementation } } @@ -240,8 +308,8 @@ fn into_diagnostic( } } -/// Field information passed to the builder. Deliberately omits attrs to discourage the generate_* -/// methods from walking the attributes themselves. +/// Field information passed to the builder. Deliberately omits attrs to discourage the +/// `generate_*` methods from walking the attributes themselves. struct FieldInfo<'a> { vis: &'a syn::Visibility, binding: &'a synstructure::BindingInfo<'a>, @@ -249,108 +317,256 @@ struct FieldInfo<'a> { span: &'a proc_macro2::Span, } +/// What kind of session diagnostic is being derived - an error or a warning? +#[derive(Copy, Clone)] +enum SessionDiagnosticKind { + /// `#[error(..)]` + Error, + /// `#[warn(..)]` + Warn, +} + +impl SessionDiagnosticKind { + /// Returns human-readable string corresponding to the kind. + fn descr(&self) -> &'static str { + match self { + SessionDiagnosticKind::Error => "error", + SessionDiagnosticKind::Warn => "warning", + } + } +} + /// Tracks persistent information required for building up the individual calls to diagnostic -/// methods for the final generated method. This is a separate struct to SessionDerive only to be -/// able to destructure and split self.builder and the self.structure up to avoid a double mut -/// borrow later on. +/// methods for the final generated method. This is a separate struct to `SessionDiagnosticDerive` +/// only to be able to destructure and split `self.builder` and the `self.structure` up to avoid a +/// double mut borrow later on. struct SessionDiagnosticDeriveBuilder<'a> { - /// Name of the session parameter that's passed in to the as_error method. + /// Name of the session parameter that's passed in to the `as_error` method. sess: syn::Ident, + /// The identifier to use for the generated `DiagnosticBuilder` instance. + diag: syn::Ident, /// Store a map of field name to its corresponding field. This is built on construction of the /// derive builder. fields: HashMap<String, &'a syn::Field>, - /// The identifier to use for the generated DiagnosticBuilder instance. - diag: syn::Ident, - - /// Whether this is a lint or an error. This dictates how the diag will be initialised. Span - /// stores at what Span the kind was first set at (for error reporting purposes, if the kind - /// was multiply specified). - kind: Option<(DiagnosticId, proc_macro2::Span)>, + /// Kind of diagnostic requested via the struct attribute. + kind: Option<(SessionDiagnosticKind, proc_macro::Span)>, + /// Slug is a mandatory part of the struct attribute as corresponds to the Fluent message that + /// has the actual diagnostic message. + slug: Option<(String, proc_macro::Span)>, + /// Error codes are a optional part of the struct attribute - this is only set to detect + /// multiple specifications. + code: Option<proc_macro::Span>, } impl<'a> SessionDiagnosticDeriveBuilder<'a> { + /// Establishes state in the `SessionDiagnosticDeriveBuilder` resulting from the struct + /// attributes like `#[error(..)#`, such as the diagnostic kind and slug. Generates + /// diagnostic builder calls for setting error code and creating note/help messages. fn generate_structure_code( &mut self, attr: &syn::Attribute, ) -> Result<proc_macro2::TokenStream, SessionDiagnosticDeriveError> { - Ok(match attr.parse_meta()? { - syn::Meta::NameValue(syn::MetaNameValue { lit: syn::Lit::Str(s), .. }) => { - let formatted_str = self.build_format(&s.value(), attr.span()); - let name = attr.path.segments.last().unwrap().ident.to_string(); - let name = name.as_str(); - match name { - "message" => { - let diag = &self.diag; - quote! { - #diag.set_primary_message(#formatted_str); + let span = attr.span().unwrap(); + + let name = attr.path.segments.last().unwrap().ident.to_string(); + let name = name.as_str(); + let meta = attr.parse_meta()?; + + if matches!(name, "help" | "note") + && matches!(meta, syn::Meta::Path(_) | syn::Meta::NameValue(_)) + { + let diag = &self.diag; + let slug = match &self.slug { + Some((slug, _)) => slug.as_str(), + None => throw_span_err!( + span, + &format!( + "`#[{}{}]` must come after `#[error(..)]` or `#[warn(..)]`", + name, + match meta { + syn::Meta::Path(_) => "", + syn::Meta::NameValue(_) => " = ...", + _ => unreachable!(), + } + ) + ), + }; + let id = match meta { + syn::Meta::Path(..) => quote! { #name }, + syn::Meta::NameValue(syn::MetaNameValue { lit: syn::Lit::Str(s), .. }) => { + quote! { #s } + } + _ => unreachable!(), + }; + let fn_name = proc_macro2::Ident::new(name, attr.span()); + + return Ok(quote! { + #diag.#fn_name(rustc_errors::DiagnosticMessage::fluent_attr(#slug, #id)); + }); + } + + let nested = match meta { + syn::Meta::List(syn::MetaList { nested, .. }) => nested, + syn::Meta::Path(..) => throw_span_err!( + span, + &format!("`#[{}]` is not a valid `SessionDiagnostic` struct attribute", name) + ), + syn::Meta::NameValue(..) => throw_span_err!( + span, + &format!("`#[{} = ...]` is not a valid `SessionDiagnostic` struct attribute", name) + ), + }; + + let kind = match name { + "error" => SessionDiagnosticKind::Error, + "warning" => SessionDiagnosticKind::Warn, + other => throw_span_err!( + span, + &format!("`#[{}(...)]` is not a valid `SessionDiagnostic` struct attribute", other) + ), + }; + self.set_kind_once(kind, span)?; + + let mut tokens = Vec::new(); + for attr in nested { + let span = attr.span().unwrap(); + let meta = match attr { + syn::NestedMeta::Meta(meta) => meta, + syn::NestedMeta::Lit(_) => throw_span_err!( + span, + &format!( + "`#[{}(\"...\")]` is not a valid `SessionDiagnostic` struct attribute", + name + ) + ), + }; + + let path = meta.path(); + let nested_name = path.segments.last().unwrap().ident.to_string(); + match &meta { + // Struct attributes are only allowed to be applied once, and the diagnostic + // changes will be set in the initialisation code. + syn::Meta::NameValue(syn::MetaNameValue { lit: syn::Lit::Str(s), .. }) => { + match nested_name.as_str() { + "slug" => { + self.set_slug_once(s.value(), s.span().unwrap()); + } + "code" => { + tokens.push(self.set_code_once(s.value(), s.span().unwrap())); + } + other => { + let diag = span_err( + span, + &format!( + "`#[{}({} = ...)]` is not a valid `SessionDiagnostic` struct attribute", + name, other + ), + ); + diag.emit(); } } - attr @ "error" | attr @ "lint" => { - self.set_kind_once( - if attr == "error" { - DiagnosticId::Error(formatted_str) - } else if attr == "lint" { - DiagnosticId::Lint(formatted_str) - } else { - unreachable!() - }, - s.span(), - )?; - // This attribute is only allowed to be applied once, and the attribute - // will be set in the initialisation code. - quote! {} - } - other => throw_span_err!( - attr.span().unwrap(), + } + syn::Meta::NameValue(..) => { + span_err( + span, &format!( - "`#[{} = ...]` is not a valid SessionDiagnostic struct attribute", - other - ) - ), + "`#[{}({} = ...)]` is not a valid `SessionDiagnostic` struct attribute", + name, nested_name + ), + ) + .help("value must be a string") + .emit(); + } + syn::Meta::Path(..) => { + span_err( + span, + &format!( + "`#[{}({})]` is not a valid `SessionDiagnostic` struct attribute", + name, nested_name + ), + ) + .emit(); + } + syn::Meta::List(..) => { + span_err( + span, + &format!( + "`#[{}({}(...))]` is not a valid `SessionDiagnostic` struct attribute", + name, nested_name + ), + ) + .emit(); } } - _ => todo!("unhandled meta kind"), - }) + } + + Ok(tokens.drain(..).collect()) } #[must_use] fn set_kind_once( &mut self, - kind: DiagnosticId, - span: proc_macro2::Span, + kind: SessionDiagnosticKind, + span: proc_macro::Span, ) -> Result<(), SessionDiagnosticDeriveError> { - if self.kind.is_none() { - self.kind = Some((kind, span)); - Ok(()) - } else { - let kind_str = |kind: &DiagnosticId| match kind { - DiagnosticId::Lint(..) => "lint", - DiagnosticId::Error(..) => "error", - }; + match self.kind { + None => { + self.kind = Some((kind, span)); + Ok(()) + } + Some((prev_kind, prev_span)) => { + let existing = prev_kind.descr(); + let current = kind.descr(); - let existing_kind = kind_str(&self.kind.as_ref().unwrap().0); - let this_kind = kind_str(&kind); - - let msg = if this_kind == existing_kind { - format!("`{}` specified multiple times", existing_kind) - } else { - format!("`{}` specified when `{}` was already specified", this_kind, existing_kind) - }; - throw_span_err!(span.unwrap(), &msg); + let msg = if current == existing { + format!("`{}` specified multiple times", existing) + } else { + format!("`{}` specified when `{}` was already specified", current, existing) + }; + throw_span_err!(span, &msg, |diag| diag + .span_note(prev_span, "previously specified here")); + } } } - fn generate_field_code( + fn set_code_once(&mut self, code: String, span: proc_macro::Span) -> proc_macro2::TokenStream { + match self.code { + None => { + self.code = Some(span); + } + Some(prev_span) => { + span_err(span, "`code` specified multiple times") + .span_note(prev_span, "previously specified here") + .emit(); + } + } + + let diag = &self.diag; + quote! { #diag.code(rustc_errors::DiagnosticId::Error(#code.to_string())); } + } + + fn set_slug_once(&mut self, slug: String, span: proc_macro::Span) { + match self.slug { + None => { + self.slug = Some((slug, span)); + } + Some((_, prev_span)) => { + span_err(span, "`slug` specified multiple times") + .span_note(prev_span, "previously specified here") + .emit(); + } + } + } + + fn generate_field_attr_code( &mut self, attr: &syn::Attribute, info: FieldInfo<'_>, ) -> Result<proc_macro2::TokenStream, SessionDiagnosticDeriveError> { let field_binding = &info.binding.binding; - let option_ty = option_inner_ty(&info.ty); - let generated_code = self.generate_non_option_field_code( attr, FieldInfo { @@ -360,15 +576,16 @@ fn generate_field_code( span: info.span, }, )?; - Ok(if option_ty.is_none() { - quote! { #generated_code } + + if option_ty.is_none() { + Ok(quote! { #generated_code }) } else { - quote! { + Ok(quote! { if let Some(#field_binding) = #field_binding { #generated_code } - } - }) + }) + } } fn generate_non_option_field_code( @@ -377,190 +594,261 @@ fn generate_non_option_field_code( info: FieldInfo<'_>, ) -> Result<proc_macro2::TokenStream, SessionDiagnosticDeriveError> { let diag = &self.diag; + let span = attr.span().unwrap(); let field_binding = &info.binding.binding; + let name = attr.path.segments.last().unwrap().ident.to_string(); let name = name.as_str(); - // At this point, we need to dispatch based on the attribute key + the - // type. + let meta = attr.parse_meta()?; - Ok(match meta { - syn::Meta::NameValue(syn::MetaNameValue { lit: syn::Lit::Str(s), .. }) => { - let formatted_str = self.build_format(&s.value(), attr.span()); + match meta { + syn::Meta::Path(_) => match name { + "skip_arg" => { + // Don't need to do anything - by virtue of the attribute existing, the + // `set_arg` call will not be generated. + Ok(quote! {}) + } + "primary_span" => { + self.report_error_if_not_applied_to_span(attr, info)?; + Ok(quote! { + #diag.set_span(*#field_binding); + }) + } + "label" | "note" | "help" => { + self.report_error_if_not_applied_to_span(attr, info)?; + Ok(self.add_subdiagnostic(field_binding, name, name)) + } + other => throw_span_err!( + span, + &format!("`#[{}]` is not a valid `SessionDiagnostic` field attribute", other) + ), + }, + syn::Meta::NameValue(syn::MetaNameValue { lit: syn::Lit::Str(s), .. }) => match name { + "label" | "note" | "help" => { + self.report_error_if_not_applied_to_span(attr, info)?; + Ok(self.add_subdiagnostic(field_binding, name, &s.value())) + } + other => throw_span_err!( + span, + &format!( + "`#[{} = ...]` is not a valid `SessionDiagnostic` field attribute", + other + ) + ), + }, + syn::Meta::NameValue(_) => throw_span_err!( + span, + &format!("`#[{} = ...]` is not a valid `SessionDiagnostic` field attribute", name), + |diag| diag.help("value must be a string") + ), + syn::Meta::List(syn::MetaList { path, nested, .. }) => { + let name = path.segments.last().unwrap().ident.to_string(); + let name = name.as_ref(); + match name { - "message" => { - if type_matches_path(&info.ty, &["rustc_span", "Span"]) { - quote! { - #diag.set_span(*#field_binding); - #diag.set_primary_message(#formatted_str); - } - } else { - throw_span_err!( - attr.span().unwrap(), - "the `#[message = \"...\"]` attribute can only be applied to fields of type Span" - ); - } - } - "label" => { - if type_matches_path(&info.ty, &["rustc_span", "Span"]) { - quote! { - #diag.span_label(*#field_binding, #formatted_str); - } - } else { - throw_span_err!( - attr.span().unwrap(), - "The `#[label = ...]` attribute can only be applied to fields of type Span" - ); - } - } + "suggestion" | "suggestion_short" | "suggestion_hidden" + | "suggestion_verbose" => (), other => throw_span_err!( - attr.span().unwrap(), + span, &format!( - "`#[{} = ...]` is not a valid SessionDiagnostic field attribute", + "`#[{}(...)]` is not a valid `SessionDiagnostic` field attribute", other ) ), - } - } - syn::Meta::List(list) => { - match list.path.segments.iter().last().unwrap().ident.to_string().as_str() { - suggestion_kind @ "suggestion" - | suggestion_kind @ "suggestion_short" - | suggestion_kind @ "suggestion_hidden" - | suggestion_kind @ "suggestion_verbose" => { - // For suggest, we need to ensure we are running on a (Span, - // Applicability) pair. - let (span, applicability) = (|| match &info.ty { - ty @ syn::Type::Path(..) - if type_matches_path(ty, &["rustc_span", "Span"]) => - { - let binding = &info.binding.binding; - Ok(( - quote!(*#binding), - quote!(rustc_errors::Applicability::Unspecified), - )) - } - syn::Type::Tuple(tup) => { - let mut span_idx = None; - let mut applicability_idx = None; - for (idx, elem) in tup.elems.iter().enumerate() { - if type_matches_path(elem, &["rustc_span", "Span"]) { - if span_idx.is_none() { - span_idx = Some(syn::Index::from(idx)); - } else { - throw_span_err!( - info.span.unwrap(), - "type of field annotated with `#[suggestion(...)]` contains more than one Span" - ); - } - } else if type_matches_path( - elem, - &["rustc_errors", "Applicability"], - ) { - if applicability_idx.is_none() { - applicability_idx = Some(syn::Index::from(idx)); - } else { - throw_span_err!( - info.span.unwrap(), - "type of field annotated with `#[suggestion(...)]` contains more than one Applicability" - ); - } - } - } - if let Some(span_idx) = span_idx { - let binding = &info.binding.binding; - let span = quote!(#binding.#span_idx); - let applicability = applicability_idx - .map( - |applicability_idx| quote!(#binding.#applicability_idx), - ) - .unwrap_or_else(|| { - quote!(rustc_errors::Applicability::Unspecified) - }); - return Ok((span, applicability)); - } - throw_span_err!( - info.span.unwrap(), - "wrong types for suggestion", - |diag| { - diag.help("#[suggestion(...)] on a tuple field must be applied to fields of type (Span, Applicability)") - } - ); - } - _ => throw_span_err!( - info.span.unwrap(), - "wrong field type for suggestion", - |diag| { - diag.help("#[suggestion(...)] should be applied to fields of type Span or (Span, Applicability)") - } - ), - })()?; - // Now read the key-value pairs. - let mut msg = None; - let mut code = None; + }; - for arg in list.nested.iter() { - if let syn::NestedMeta::Meta(syn::Meta::NameValue(arg_name_value)) = arg - { - if let syn::MetaNameValue { lit: syn::Lit::Str(s), .. } = - arg_name_value - { - let name = arg_name_value - .path - .segments - .last() - .unwrap() - .ident - .to_string(); - let name = name.as_str(); - let formatted_str = self.build_format(&s.value(), arg.span()); - match name { - "message" => { - msg = Some(formatted_str); - } - "code" => { - code = Some(formatted_str); - } - other => throw_span_err!( - arg.span().unwrap(), - &format!( - "`{}` is not a valid key for `#[suggestion(...)]`", - other - ) - ), - } - } + let (span_, applicability) = self.span_and_applicability_of_ty(info)?; + + let mut msg = None; + let mut code = None; + + for attr in nested { + let meta = match attr { + syn::NestedMeta::Meta(meta) => meta, + syn::NestedMeta::Lit(_) => throw_span_err!( + span, + &format!( + "`#[{}(\"...\")]` is not a valid `SessionDiagnostic` field attribute", + name + ) + ), + }; + + let span = meta.span().unwrap(); + let nested_name = meta.path().segments.last().unwrap().ident.to_string(); + let nested_name = nested_name.as_str(); + + match meta { + syn::Meta::NameValue(syn::MetaNameValue { + lit: syn::Lit::Str(s), .. + }) => match nested_name { + "message" => { + msg = Some(s.value()); } - } - let msg = if let Some(msg) = msg { - quote!(#msg.as_str()) + "code" => { + let formatted_str = self.build_format(&s.value(), s.span()); + code = Some(formatted_str); + } + other => throw_span_err!( + span, + &format!( + "`#[{}({} = ...)]` is not a valid `SessionDiagnostic` field attribute", + name, other + ) + ), + }, + syn::Meta::NameValue(..) => throw_span_err!( + span, + &format!( + "`#[{}({} = ...)]` is not a valid `SessionDiagnostic` struct attribute", + name, nested_name + ), + |diag| diag.help("value must be a string") + ), + syn::Meta::Path(..) => throw_span_err!( + span, + &format!( + "`#[{}({})]` is not a valid `SessionDiagnostic` struct attribute", + name, nested_name + ) + ), + syn::Meta::List(..) => throw_span_err!( + span, + &format!( + "`#[{}({}(...))]` is not a valid `SessionDiagnostic` struct attribute", + name, nested_name + ) + ), + } + } + + let method = format_ident!("span_{}", name); + + let slug = self + .slug + .as_ref() + .map(|(slug, _)| slug.as_str()) + .unwrap_or_else(|| "missing-slug"); + let msg = msg.as_deref().unwrap_or("suggestion"); + let msg = quote! { rustc_errors::DiagnosticMessage::fluent_attr(#slug, #msg) }; + let code = code.unwrap_or_else(|| quote! { String::new() }); + + Ok(quote! { #diag.#method(#span_, #msg, #code, #applicability); }) + } + } + } + + /// Reports an error if the field's type is not `Span`. + fn report_error_if_not_applied_to_span( + &self, + attr: &syn::Attribute, + info: FieldInfo<'_>, + ) -> Result<(), SessionDiagnosticDeriveError> { + if !type_matches_path(&info.ty, &["rustc_span", "Span"]) { + let name = attr.path.segments.last().unwrap().ident.to_string(); + let name = name.as_str(); + let meta = attr.parse_meta()?; + + throw_span_err!( + attr.span().unwrap(), + &format!( + "the `#[{}{}]` attribute can only be applied to fields of type `Span`", + name, + match meta { + syn::Meta::Path(_) => "", + syn::Meta::NameValue(_) => " = ...", + syn::Meta::List(_) => "(...)", + } + ) + ); + } + + Ok(()) + } + + /// Adds a subdiagnostic by generating a `diag.span_$kind` call with the current slug and + /// `fluent_attr_identifier`. + fn add_subdiagnostic( + &self, + field_binding: &proc_macro2::Ident, + kind: &str, + fluent_attr_identifier: &str, + ) -> proc_macro2::TokenStream { + let diag = &self.diag; + + let slug = + self.slug.as_ref().map(|(slug, _)| slug.as_str()).unwrap_or_else(|| "missing-slug"); + let fn_name = format_ident!("span_{}", kind); + quote! { + #diag.#fn_name( + *#field_binding, + rustc_errors::DiagnosticMessage::fluent_attr(#slug, #fluent_attr_identifier) + ); + } + } + + fn span_and_applicability_of_ty( + &self, + info: FieldInfo<'_>, + ) -> Result<(proc_macro2::TokenStream, proc_macro2::TokenStream), SessionDiagnosticDeriveError> + { + match &info.ty { + // If `ty` is `Span` w/out applicability, then use `Applicability::Unspecified`. + ty @ syn::Type::Path(..) if type_matches_path(ty, &["rustc_span", "Span"]) => { + let binding = &info.binding.binding; + Ok((quote!(*#binding), quote!(rustc_errors::Applicability::Unspecified))) + } + // If `ty` is `(Span, Applicability)` then return tokens accessing those. + syn::Type::Tuple(tup) => { + let mut span_idx = None; + let mut applicability_idx = None; + + for (idx, elem) in tup.elems.iter().enumerate() { + if type_matches_path(elem, &["rustc_span", "Span"]) { + if span_idx.is_none() { + span_idx = Some(syn::Index::from(idx)); } else { throw_span_err!( - list.span().unwrap(), - "missing suggestion message", - |diag| { - diag.help("provide a suggestion message using #[suggestion(message = \"...\")]") - } + info.span.unwrap(), + "type of field annotated with `#[suggestion(...)]` contains more than one `Span`" ); - }; - let code = code.unwrap_or_else(|| quote! { String::new() }); - // Now build it out: - let suggestion_method = format_ident!("span_{}", suggestion_kind); - quote! { - #diag.#suggestion_method(#span, #msg, #code, #applicability); + } + } else if type_matches_path(elem, &["rustc_errors", "Applicability"]) { + if applicability_idx.is_none() { + applicability_idx = Some(syn::Index::from(idx)); + } else { + throw_span_err!( + info.span.unwrap(), + "type of field annotated with `#[suggestion(...)]` contains more than one Applicability" + ); } } - other => throw_span_err!( - list.span().unwrap(), - &format!("invalid annotation list `#[{}(...)]`", other) - ), } + + if let Some(span_idx) = span_idx { + let binding = &info.binding.binding; + let span = quote!(#binding.#span_idx); + let applicability = applicability_idx + .map(|applicability_idx| quote!(#binding.#applicability_idx)) + .unwrap_or_else(|| quote!(rustc_errors::Applicability::Unspecified)); + + return Ok((span, applicability)); + } + + throw_span_err!(info.span.unwrap(), "wrong types for suggestion", |diag| { + diag.help("`#[suggestion(...)]` on a tuple field must be applied to fields of type `(Span, Applicability)`") + }); } - _ => panic!("unhandled meta kind"), - }) + // If `ty` isn't a `Span` or `(Span, Applicability)` then emit an error. + _ => throw_span_err!(info.span.unwrap(), "wrong field type for suggestion", |diag| { + diag.help("`#[suggestion(...)]` should be applied to fields of type `Span` or `(Span, Applicability)`") + }), + } } /// In the strings in the attributes supplied to this macro, we want callers to be able to - /// reference fields in the format string. Take this, for example: + /// reference fields in the format string. For example: + /// /// ```ignore (not-usage-example) /// struct Point { /// #[error = "Expected a point greater than ({x}, {y})"] @@ -568,12 +856,15 @@ fn generate_non_option_field_code( /// y: i32, /// } /// ``` - /// We want to automatically pick up that {x} refers `self.x` and {y} refers to `self.y`, then - /// generate this call to format!: + /// + /// We want to automatically pick up that `{x}` refers `self.x` and `{y}` refers to `self.y`, + /// then generate this call to `format!`: + /// /// ```ignore (not-usage-example) /// format!("Expected a point greater than ({x}, {y})", x = self.x, y = self.y) /// ``` - /// This function builds the entire call to format!. + /// + /// This function builds the entire call to `format!`. fn build_format(&self, input: &str, span: proc_macro2::Span) -> proc_macro2::TokenStream { // This set is used later to generate the final format string. To keep builds reproducible, // the iteration order needs to be deterministic, hence why we use a BTreeSet here instead @@ -646,7 +937,7 @@ fn build_format(&self, input: &str, span: proc_macro2::Span) -> proc_macro2::Tok } } -/// If `ty` is an Option, returns Some(inner type). Else, returns None. +/// If `ty` is an Option, returns `Some(inner type)`, otherwise returns `None`. fn option_inner_ty(ty: &syn::Type) -> Option<&syn::Type> { if type_matches_path(ty, &["std", "option", "Option"]) { if let syn::Type::Path(ty_path) = ty {
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 046322a..3402acc 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -1169,14 +1169,18 @@ fn get_fn_has_self_parameter(self, id: DefIndex) -> bool { } } - fn get_associated_item_def_ids(self, tcx: TyCtxt<'tcx>, id: DefIndex) -> &'tcx [DefId] { - if let Some(children) = self.root.tables.children.get(self, id) { - tcx.arena.alloc_from_iter( - children.decode((self, tcx.sess)).map(|child_index| self.local_def_id(child_index)), - ) - } else { - &[] - } + fn get_associated_item_def_ids( + self, + id: DefIndex, + sess: &'a Session, + ) -> impl Iterator<Item = DefId> + 'a { + self.root + .tables + .children + .get(self, id) + .unwrap_or_else(Lazy::empty) + .decode((self, sess)) + .map(move |child_index| self.local_def_id(child_index)) } fn get_associated_item(self, id: DefIndex) -> ty::AssocItem {
diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index cd3a1d7..63bf929 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
@@ -160,7 +160,9 @@ fn into_args(self) -> (DefId, SimplifiedType) { let _ = cdata; tcx.calculate_dtor(def_id, |_,_| Ok(())) } - associated_item_def_ids => { cdata.get_associated_item_def_ids(tcx, def_id.index) } + associated_item_def_ids => { + tcx.arena.alloc_from_iter(cdata.get_associated_item_def_ids(def_id.index, tcx.sess)) + } associated_item => { cdata.get_associated_item(def_id.index) } inherent_impls => { cdata.get_inherent_implementations_for_type(tcx, def_id.index) } is_foreign_item => { cdata.is_foreign_item(def_id.index) }
diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index 002d25a..e55b045 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs
@@ -3,7 +3,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_errors::{ - Diagnostic, DiagnosticBuilder, DiagnosticId, EmissionGuarantee, ErrorGuaranteed, + Diagnostic, DiagnosticBuilder, DiagnosticId, EmissionGuarantee, ErrorGuaranteed, MultiSpan, }; use rustc_hir::HirId; use rustc_index::vec::IndexVec; @@ -14,7 +14,7 @@ }; use rustc_session::Session; use rustc_span::hygiene::MacroKind; -use rustc_span::source_map::{DesugaringKind, ExpnKind, MultiSpan}; +use rustc_span::source_map::{DesugaringKind, ExpnKind}; use rustc_span::{symbol, Span, Symbol, DUMMY_SP}; /// How a lint level was set.
diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index fed6a60..63f2bc5 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs
@@ -58,7 +58,7 @@ pub struct Allocation<Tag = AllocId, Extra = ()> { /// means that both the inner type (`Allocation`) and the outer type /// (`ConstAllocation`) are used quite a bit. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)] -#[cfg_attr(not(bootstrap), rustc_pass_by_value)] +#[rustc_pass_by_value] pub struct ConstAllocation<'tcx, Tag = AllocId, Extra = ()>( pub Interned<'tcx, Allocation<Tag, Extra>>, );
diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index cee510a..4d4eed1 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs
@@ -9,7 +9,6 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_index::bit_set::BitMatrix; use rustc_index::vec::IndexVec; -use rustc_middle::ty::OpaqueTypeKey; use rustc_span::Span; use rustc_target::abi::VariantIdx; use smallvec::SmallVec; @@ -242,7 +241,7 @@ pub struct BorrowCheckResult<'tcx> { /// All the opaque types that are restricted to concrete types /// by this function. Unlike the value in `TypeckResults`, this has /// unerased regions. - pub concrete_opaque_types: VecMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>, + pub concrete_opaque_types: VecMap<DefId, OpaqueHiddenType<'tcx>>, pub closure_requirements: Option<ClosureRegionRequirements<'tcx>>, pub used_mut_upvars: SmallVec<[Field; 8]>, pub tainted_by_errors: Option<ErrorGuaranteed>,
diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs index 5297825..ffa70cd 100644 --- a/compiler/rustc_middle/src/traits/select.rs +++ b/compiler/rustc_middle/src/traits/select.rs
@@ -13,12 +13,19 @@ use rustc_query_system::cache::Cache; pub type SelectionCache<'tcx> = Cache< - ty::ParamEnvAnd<'tcx, ty::TraitPredicate<'tcx>>, + // This cache does not use `ParamEnvAnd` in its keys because `ParamEnv::and` can replace + // caller bounds with an empty list if the `TraitPredicate` looks global, which may happen + // after erasing lifetimes from the predicate. + (ty::ParamEnv<'tcx>, ty::TraitPredicate<'tcx>), SelectionResult<'tcx, SelectionCandidate<'tcx>>, >; -pub type EvaluationCache<'tcx> = - Cache<ty::ParamEnvAnd<'tcx, ty::PolyTraitPredicate<'tcx>>, EvaluationResult>; +pub type EvaluationCache<'tcx> = Cache< + // See above: this cache does not use `ParamEnvAnd` in its keys due to sometimes incorrectly + // caching with the wrong `ParamEnv`. + (ty::ParamEnv<'tcx>, ty::PolyTraitPredicate<'tcx>), + EvaluationResult, +>; /// The selection process begins by considering all impls, where /// clauses, and so forth that might resolve an obligation. Sometimes
diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs index cb219c4..fc6710f 100644 --- a/compiler/rustc_middle/src/ty/adt.rs +++ b/compiler/rustc_middle/src/ty/adt.rs
@@ -161,7 +161,7 @@ fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHas } #[derive(Copy, Clone, PartialEq, Eq, Hash, Ord, PartialOrd, HashStable)] -#[cfg_attr(not(bootstrap), rustc_pass_by_value)] +#[rustc_pass_by_value] pub struct AdtDef<'tcx>(pub Interned<'tcx, AdtDefData>); impl<'tcx> AdtDef<'tcx> {
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index ac9f04e..6ca8f8b 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs
@@ -34,7 +34,7 @@ use rustc_data_structures::steal::Steal; use rustc_data_structures::sync::{self, Lock, Lrc, WorkerLocal}; use rustc_data_structures::vec_map::VecMap; -use rustc_errors::ErrorGuaranteed; +use rustc_errors::{ErrorGuaranteed, MultiSpan}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LOCAL_CRATE}; @@ -54,7 +54,7 @@ use rustc_session::Limit; use rustc_session::Session; use rustc_span::def_id::{DefPathHash, StableCrateId}; -use rustc_span::source_map::{MultiSpan, SourceMap}; +use rustc_span::source_map::SourceMap; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; use rustc_target::abi::{Layout, LayoutS, TargetDataLayout, VariantIdx};
diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index ee4ba49..49d0ce5 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs
@@ -8,12 +8,18 @@ }; use rustc_data_structures::fx::FxHashMap; -use rustc_errors::{Applicability, Diagnostic}; +use rustc_errors::{Applicability, Diagnostic, DiagnosticArgValue, IntoDiagnosticArg}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::{QPath, TyKind, WhereBoundPredicate, WherePredicate}; use rustc_span::Span; +impl<'tcx> IntoDiagnosticArg for Ty<'tcx> { + fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + format!("{}", self).into_diagnostic_arg() + } +} + impl<'tcx> Ty<'tcx> { /// Similar to `Ty::is_primitive`, but also considers inferred numeric values to be primitive. pub fn is_primitive_ty(self) -> bool {
diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index 3aad189..d93c9a7 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs
@@ -3,11 +3,11 @@ use crate::ty::print::{FmtPrinter, Printer}; use crate::ty::{self, BoundRegionKind, Region, Ty, TyCtxt}; use rustc_errors::Applicability::{MachineApplicable, MaybeIncorrect}; -use rustc_errors::{pluralize, Diagnostic}; +use rustc_errors::{pluralize, Diagnostic, MultiSpan}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_span::symbol::{sym, Symbol}; -use rustc_span::{BytePos, MultiSpan, Span}; +use rustc_span::{BytePos, Span}; use rustc_target::spec::abi; use std::borrow::Cow;
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 0c1ab67..e278efa 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -305,10 +305,10 @@ fn invert_mapping(map: &[u32]) -> Vec<u32> { impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { fn scalar_pair(&self, a: Scalar, b: Scalar) -> LayoutS<'tcx> { let dl = self.data_layout(); - let b_align = b.value.align(dl); - let align = a.value.align(dl).max(b_align).max(dl.aggregate_align); - let b_offset = a.value.size(dl).align_to(b_align.abi); - let size = (b_offset + b.value.size(dl)).align_to(align.abi); + let b_align = b.align(dl); + let align = a.align(dl).max(b_align).max(dl.aggregate_align); + let b_offset = a.size(dl).align_to(b_align.abi); + let size = (b_offset + b.size(dl)).align_to(align.abi); // HACK(nox): We iter on `b` and then `a` because `max_by_key` // returns the last maximum. @@ -567,7 +567,7 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<Layout<'tcx>, LayoutError<' let scalar_unit = |value: Primitive| { let size = value.size(dl); assert!(size.bits() <= 128); - Scalar { value, valid_range: WrappingRange { start: 0, end: size.unsigned_int_max() } } + Scalar::Initialized { value, valid_range: WrappingRange::full(size) } }; let scalar = |value: Primitive| tcx.intern_layout(LayoutS::scalar(self, scalar_unit(value))); @@ -581,11 +581,14 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<Layout<'tcx>, LayoutError<' // Basic scalars. ty::Bool => tcx.intern_layout(LayoutS::scalar( self, - Scalar { value: Int(I8, false), valid_range: WrappingRange { start: 0, end: 1 } }, + Scalar::Initialized { + value: Int(I8, false), + valid_range: WrappingRange { start: 0, end: 1 }, + }, )), ty::Char => tcx.intern_layout(LayoutS::scalar( self, - Scalar { + Scalar::Initialized { value: Int(I32, false), valid_range: WrappingRange { start: 0, end: 0x10FFFF }, }, @@ -598,7 +601,7 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<Layout<'tcx>, LayoutError<' }), ty::FnPtr(_) => { let mut ptr = scalar_unit(Pointer); - ptr.valid_range = ptr.valid_range.with_start(1); + ptr.valid_range_mut().start = 1; tcx.intern_layout(LayoutS::scalar(self, ptr)) } @@ -616,7 +619,7 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<Layout<'tcx>, LayoutError<' ty::Ref(_, pointee, _) | ty::RawPtr(ty::TypeAndMut { ty: pointee, .. }) => { let mut data_ptr = scalar_unit(Pointer); if !ty.is_unsafe_ptr() { - data_ptr.valid_range = data_ptr.valid_range.with_start(1); + data_ptr.valid_range_mut().start = 1; } let pointee = tcx.normalize_erasing_regions(param_env, pointee); @@ -632,7 +635,7 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<Layout<'tcx>, LayoutError<' ty::Slice(_) | ty::Str => scalar_unit(Int(dl.ptr_sized_integer(), false)), ty::Dynamic(..) => { let mut vtable = scalar_unit(Pointer); - vtable.valid_range = vtable.valid_range.with_start(1); + vtable.valid_range_mut().start = 1; vtable } _ => return Err(LayoutError::Unknown(unsized_part)), @@ -889,14 +892,14 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<Layout<'tcx>, LayoutError<' // If all non-ZST fields have the same ABI, forward this ABI if optimize && !field.is_zst() { - // Normalize scalar_unit to the maximal valid range + // Discard valid range information and allow undef let field_abi = match field.abi { - Abi::Scalar(x) => Abi::Scalar(scalar_unit(x.value)), + Abi::Scalar(x) => Abi::Scalar(x.to_union()), Abi::ScalarPair(x, y) => { - Abi::ScalarPair(scalar_unit(x.value), scalar_unit(y.value)) + Abi::ScalarPair(x.to_union(), y.to_union()) } Abi::Vector { element: x, count } => { - Abi::Vector { element: scalar_unit(x.value), count } + Abi::Vector { element: x.to_union(), count } } Abi::Uninhabited | Abi::Aggregate { .. } => { Abi::Aggregate { sized: true } @@ -1000,14 +1003,16 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<Layout<'tcx>, LayoutError<' if let Bound::Included(start) = start { // FIXME(eddyb) this might be incorrect - it doesn't // account for wrap-around (end < start) ranges. - assert!(scalar.valid_range.start <= start); - scalar.valid_range.start = start; + let valid_range = scalar.valid_range_mut(); + assert!(valid_range.start <= start); + valid_range.start = start; } if let Bound::Included(end) = end { // FIXME(eddyb) this might be incorrect - it doesn't // account for wrap-around (end < start) ranges. - assert!(scalar.valid_range.end >= end); - scalar.valid_range.end = end; + let valid_range = scalar.valid_range_mut(); + assert!(valid_range.end >= end); + valid_range.end = end; } // Update `largest_niche` if we have introduced a larger niche. @@ -1133,9 +1138,15 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<Layout<'tcx>, LayoutError<' // guaranteed to be initialised, not the // other primitive. if offset.bytes() == 0 { - Abi::ScalarPair(niche_scalar, scalar_unit(second.value)) + Abi::ScalarPair( + niche_scalar, + scalar_unit(second.primitive()), + ) } else { - Abi::ScalarPair(scalar_unit(first.value), niche_scalar) + Abi::ScalarPair( + scalar_unit(first.primitive()), + niche_scalar, + ) } } _ => Abi::Aggregate { sized: true }, @@ -1314,7 +1325,7 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<Layout<'tcx>, LayoutError<' } let tag_mask = ity.size().unsigned_int_max(); - let tag = Scalar { + let tag = Scalar::Initialized { value: Int(ity, signed), valid_range: WrappingRange { start: (min as u128 & tag_mask), @@ -1325,7 +1336,7 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<Layout<'tcx>, LayoutError<' // Without latter check aligned enums with custom discriminant values // Would result in ICE see the issue #92464 for more info - if tag.value.size(dl) == size || variants.iter().all(|layout| layout.is_empty()) { + if tag.size(dl) == size || variants.iter().all(|layout| layout.is_empty()) { abi = Abi::Scalar(tag); } else { // Try to use a ScalarPair for all tagged enums. @@ -1345,7 +1356,7 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<Layout<'tcx>, LayoutError<' } }; let prim = match field.abi { - Abi::Scalar(scalar) => scalar.value, + Abi::Scalar(scalar) => scalar.primitive(), _ => { common_prim = None; break; @@ -1599,7 +1610,7 @@ fn generator_layout( let max_discr = (info.variant_fields.len() - 1) as u128; let discr_int = Integer::fit_unsigned(max_discr); let discr_int_ty = discr_int.to_ty(tcx, false); - let tag = Scalar { + let tag = Scalar::Initialized { value: Primitive::Int(discr_int, false), valid_range: WrappingRange { start: 0, end: max_discr }, }; @@ -1898,7 +1909,7 @@ fn record_layout_for_printing_outlined(&self, layout: TyAndLayout<'tcx>) { adt_kind.into(), adt_packed, match tag_encoding { - TagEncoding::Direct => Some(tag.value.size(self)), + TagEncoding::Direct => Some(tag.size(self)), _ => None, }, variant_infos, @@ -2304,7 +2315,7 @@ fn field_ty_or_layout<'tcx>( let tag_layout = |tag: Scalar| -> TyAndLayout<'tcx> { TyAndLayout { layout: tcx.intern_layout(LayoutS::scalar(cx, tag)), - ty: tag.value.to_ty(tcx), + ty: tag.primitive().to_ty(tcx), } }; @@ -3079,11 +3090,9 @@ fn fn_abi_new_uncached( } // Only pointer types handled below. - if scalar.value != Pointer { - return; - } + let Scalar::Initialized { value: Pointer, valid_range} = scalar else { return }; - if !scalar.valid_range.contains(0) { + if !valid_range.contains(0) { attrs.set(ArgAttribute::NonNull); }
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 37425c9..6e3dc92 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -41,7 +41,7 @@ use rustc_macros::HashStable; use rustc_query_system::ich::StableHashingContext; use rustc_session::cstore::CrateStoreDyn; -use rustc_span::symbol::{kw, Ident, Symbol}; +use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::Span; use rustc_target::abi::Align; @@ -1112,6 +1112,26 @@ pub struct OpaqueHiddenType<'tcx> { pub ty: Ty<'tcx>, } +impl<'tcx> OpaqueHiddenType<'tcx> { + pub fn report_mismatch(&self, other: &Self, tcx: TyCtxt<'tcx>) { + // Found different concrete types for the opaque type. + let mut err = tcx.sess.struct_span_err( + other.span, + "concrete type differs from previous defining opaque type use", + ); + err.span_label(other.span, format!("expected `{}`, got `{}`", self.ty, other.ty)); + if self.span == other.span { + err.span_label( + self.span, + "this expression supplies two conflicting concrete types for the same opaque type", + ); + } else { + err.span_note(self.span, "previous use here"); + } + err.emit(); + } +} + rustc_index::newtype_index! { /// "Universes" are used during type- and trait-checking in the /// presence of `for<..>` binders to control what sets of names are @@ -2206,7 +2226,7 @@ pub fn trait_id_of_impl(self, def_id: DefId) -> Option<DefId> { self.impl_trait_ref(def_id).map(|tr| tr.def_id) } - /// If the given defid describes a method belonging to an impl, returns the + /// If the given `DefId` describes a method belonging to an impl, returns the /// `DefId` of the impl that the method belongs to; otherwise, returns `None`. pub fn impl_of_method(self, def_id: DefId) -> Option<DefId> { self.opt_associated_item(def_id).and_then(|trait_item| match trait_item.container { @@ -2215,6 +2235,11 @@ pub fn impl_of_method(self, def_id: DefId) -> Option<DefId> { }) } + /// If the given `DefId` belongs to a trait that was automatically derived, returns `true`. + pub fn is_builtin_derive(self, def_id: DefId) -> bool { + self.has_attr(def_id, sym::automatically_derived) + } + /// Looks up the span of `impl_did` if the impl is local; otherwise returns `Err` /// with the name of the crate containing the impl. pub fn span_of_impl(self, impl_did: DefId) -> Result<Span, Symbol> {
diff --git a/compiler/rustc_middle/src/util/bug.rs b/compiler/rustc_middle/src/util/bug.rs index 791d506..fd7045d 100644 --- a/compiler/rustc_middle/src/util/bug.rs +++ b/compiler/rustc_middle/src/util/bug.rs
@@ -1,7 +1,8 @@ // These functions are used by macro expansion for bug! and span_bug! use crate::ty::{tls, TyCtxt}; -use rustc_span::{MultiSpan, Span}; +use rustc_errors::MultiSpan; +use rustc_span::Span; use std::fmt; use std::panic::{panic_any, Location};
diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 8a3a46c..44caa2a 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -8,7 +8,7 @@ use rustc_ast::Mutability; use rustc_errors::{ error_code, pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, - ErrorGuaranteed, + ErrorGuaranteed, MultiSpan, }; use rustc_hir as hir; use rustc_hir::def::*; @@ -21,7 +21,7 @@ }; use rustc_session::Session; use rustc_span::source_map::Spanned; -use rustc_span::{BytePos, DesugaringKind, ExpnKind, MultiSpan, Span}; +use rustc_span::{BytePos, DesugaringKind, ExpnKind, Span}; crate fn check_match(tcx: TyCtxt<'_>, def_id: DefId) { let body_id = match def_id.as_local() {
diff --git a/compiler/rustc_mir_transform/src/check_packed_ref.rs b/compiler/rustc_mir_transform/src/check_packed_ref.rs index f036795..4bf66cd 100644 --- a/compiler/rustc_mir_transform/src/check_packed_ref.rs +++ b/compiler/rustc_mir_transform/src/check_packed_ref.rs
@@ -1,10 +1,9 @@ -use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::def_id::LocalDefId; use rustc_middle::mir::visit::{PlaceContext, Visitor}; use rustc_middle::mir::*; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, TyCtxt}; use rustc_session::lint::builtin::UNALIGNED_REFERENCES; -use rustc_span::symbol::sym; use crate::util; use crate::MirLint; @@ -50,22 +49,6 @@ fn unsafe_derive_on_repr_packed(tcx: TyCtxt<'_>, def_id: LocalDefId) { }); } -fn builtin_derive_def_id(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> { - debug!("builtin_derive_def_id({:?})", def_id); - if let Some(impl_def_id) = tcx.impl_of_method(def_id) { - if tcx.has_attr(impl_def_id, sym::automatically_derived) { - debug!("builtin_derive_def_id({:?}) - is {:?}", def_id, impl_def_id); - Some(impl_def_id) - } else { - debug!("builtin_derive_def_id({:?}) - not automatically derived", def_id); - None - } - } else { - debug!("builtin_derive_def_id({:?}) - not a method", def_id); - None - } -} - impl<'tcx> Visitor<'tcx> for PackedRefChecker<'_, 'tcx> { fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) { // Make sure we know where in the MIR we are. @@ -83,7 +66,11 @@ fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, _location: if context.is_borrow() { if util::is_disaligned(self.tcx, self.body, self.param_env, *place) { let def_id = self.body.source.instance.def_id(); - if let Some(impl_def_id) = builtin_derive_def_id(self.tcx, def_id) { + if let Some(impl_def_id) = self + .tcx + .impl_of_method(def_id) + .filter(|&def_id| self.tcx.is_builtin_derive(def_id)) + { // If a method is defined in the local crate, // the impl containing that method should also be. self.tcx.ensure().unsafe_derive_on_repr_packed(impl_def_id.expect_local());
diff --git a/compiler/rustc_mir_transform/src/const_goto.rs b/compiler/rustc_mir_transform/src/const_goto.rs index 905173b..5acf939 100644 --- a/compiler/rustc_mir_transform/src/const_goto.rs +++ b/compiler/rustc_mir_transform/src/const_goto.rs
@@ -39,7 +39,9 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { opt_finder.visit_body(body); let should_simplify = !opt_finder.optimizations.is_empty(); for opt in opt_finder.optimizations { - let terminator = body.basic_blocks_mut()[opt.bb_with_goto].terminator_mut(); + let block = &mut body.basic_blocks_mut()[opt.bb_with_goto]; + block.statements.extend(opt.stmts_move_up); + let terminator = block.terminator_mut(); let new_goto = TerminatorKind::Goto { target: opt.target_to_use_in_goto }; debug!("SUCCESS: replacing `{:?}` with `{:?}`", terminator.kind, new_goto); terminator.kind = new_goto; @@ -68,12 +70,15 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location // Now check that the target of this Goto switches on this place. let target_bb = &self.body.basic_blocks()[target]; - // FIXME(simonvandel): We are conservative here when we don't allow - // any statements in the target basic block. - // This could probably be relaxed to allow `StorageDead`s which could be - // copied to the predecessor of this block. - if !target_bb.statements.is_empty() { - None? + // The `StorageDead(..)` statement does not affect the functionality of mir. + // We can move this part of the statement up to the predecessor. + let mut stmts_move_up = Vec::new(); + for stmt in &target_bb.statements { + if let StatementKind::StorageDead(..) = stmt.kind { + stmts_move_up.push(stmt.clone()) + } else { + None?; + } } let target_bb_terminator = target_bb.terminator(); @@ -87,6 +92,7 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location self.optimizations.push(OptimizationToApply { bb_with_goto: location.block, target_to_use_in_goto, + stmts_move_up, }); } } @@ -97,14 +103,15 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location } } -struct OptimizationToApply { +struct OptimizationToApply<'tcx> { bb_with_goto: BasicBlock, target_to_use_in_goto: BasicBlock, + stmts_move_up: Vec<Statement<'tcx>>, } pub struct ConstGotoOptimizationFinder<'a, 'tcx> { tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, param_env: ParamEnv<'tcx>, - optimizations: Vec<OptimizationToApply>, + optimizations: Vec<OptimizationToApply<'tcx>>, }
diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs index e1dbf90..a342aee 100644 --- a/compiler/rustc_mir_transform/src/const_prop.rs +++ b/compiler/rustc_mir_transform/src/const_prop.rs
@@ -184,8 +184,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx> type MemoryKind = !; - type MemoryExtra = (); - fn load_mir( _ecx: &InterpCx<'mir, 'tcx, Self>, _instance: ty::InstanceDef<'tcx>, @@ -267,7 +265,8 @@ fn access_local_mut<'a>( } fn before_access_global( - _memory_extra: &(), + _tcx: TyCtxt<'tcx>, + _machine: &Self, _alloc_id: AllocId, alloc: ConstAllocation<'tcx, Self::PointerTag, Self::AllocExtra>, _static_def_id: Option<DefId>, @@ -377,7 +376,6 @@ fn new( span, param_env, ConstPropMachine::new(only_propagate_inside_block_locals, can_const_prop), - (), ); let ret = ecx
diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs index 5be745b..159503a 100644 --- a/compiler/rustc_mir_transform/src/const_prop_lint.rs +++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs
@@ -180,8 +180,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx> type MemoryKind = !; - type MemoryExtra = (); - fn load_mir( _ecx: &InterpCx<'mir, 'tcx, Self>, _instance: ty::InstanceDef<'tcx>, @@ -263,7 +261,8 @@ fn access_local_mut<'a>( } fn before_access_global( - _memory_extra: &(), + _tcx: TyCtxt<'tcx>, + _machine: &Self, _alloc_id: AllocId, alloc: ConstAllocation<'tcx, Self::PointerTag, Self::AllocExtra>, _static_def_id: Option<DefId>, @@ -374,7 +373,6 @@ fn new( span, param_env, ConstPropMachine::new(only_propagate_inside_block_locals, can_const_prop), - (), ); let ret = ecx
diff --git a/compiler/rustc_mir_transform/src/deref_separator.rs b/compiler/rustc_mir_transform/src/deref_separator.rs new file mode 100644 index 0000000..79aac16 --- /dev/null +++ b/compiler/rustc_mir_transform/src/deref_separator.rs
@@ -0,0 +1,72 @@ +use crate::MirPass; +use rustc_middle::mir::patch::MirPatch; +use rustc_middle::mir::*; +use rustc_middle::ty::TyCtxt; +pub struct Derefer; + +pub fn deref_finder<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + let mut patch = MirPatch::new(body); + let (basic_blocks, local_decl) = body.basic_blocks_and_local_decls_mut(); + for (block, data) in basic_blocks.iter_enumerated_mut() { + for (i, stmt) in data.statements.iter_mut().enumerate() { + match stmt.kind { + StatementKind::Assign(box (og_place, Rvalue::Ref(region, borrow_knd, place))) => { + for (idx, (p_ref, p_elem)) in place.iter_projections().enumerate() { + if p_elem == ProjectionElem::Deref && !p_ref.projection.is_empty() { + // The type that we are derefing. + let ty = p_ref.ty(local_decl, tcx).ty; + let temp = patch.new_temp(ty, stmt.source_info.span); + + // Because we are assigning this right before original statement + // we are using index i of statement. + let loc = Location { block: block, statement_index: i }; + patch.add_statement(loc, StatementKind::StorageLive(temp)); + + // We are adding current p_ref's projections to our + // temp value. + let deref_place = + Place::from(p_ref.local).project_deeper(p_ref.projection, tcx); + patch.add_assign( + loc, + Place::from(temp), + Rvalue::Use(Operand::Move(deref_place)), + ); + + // We are creating a place by using our temp value's location + // and copying derefed values which we need to create new statement. + let temp_place = + Place::from(temp).project_deeper(&place.projection[idx..], tcx); + let new_stmt = Statement { + source_info: stmt.source_info, + kind: StatementKind::Assign(Box::new(( + og_place, + Rvalue::Ref(region, borrow_knd, temp_place), + ))), + }; + + // Replace current statement with newly created one. + *stmt = new_stmt; + + // Since our job with the temp is done it should be gone + let loc = Location { block: block, statement_index: i + 1 }; + patch.add_statement(loc, StatementKind::StorageDead(temp)); + + // As all projections are off the base projection, if there are + // multiple derefs in the middle of projection, it might cause + // unsoundness, to not let that happen we break the loop. + break; + } + } + } + _ => (), + } + } + } + patch.apply(body); +} + +impl<'tcx> MirPass<'tcx> for Derefer { + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + deref_finder(tcx, body); + } +}
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 2fca498..059ee09 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -53,6 +53,7 @@ mod coverage; mod deaggregator; mod deduplicate_blocks; +mod deref_separator; mod dest_prop; pub mod dump_mir; mod early_otherwise_branch; @@ -431,6 +432,7 @@ fn run_post_borrowck_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tc // `Deaggregator` is conceptually part of MIR building, some backends rely on it happening // and it can help optimizations. &deaggregator::Deaggregator, + &deref_separator::Derefer, &Lint(const_prop_lint::ConstProp), ];
diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index 9865588..1724bab 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs
@@ -13,7 +13,7 @@ #[derive(Debug)] pub enum InnerAttrPolicy<'a> { Permitted, - Forbidden { reason: &'a str, saw_doc_comment: bool, prev_attr_sp: Option<Span> }, + Forbidden { reason: &'a str, saw_doc_comment: bool, prev_outer_attr_sp: Option<Span> }, } const DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG: &str = "an inner attribute is not \ @@ -22,7 +22,7 @@ pub enum InnerAttrPolicy<'a> { pub(super) const DEFAULT_INNER_ATTR_FORBIDDEN: InnerAttrPolicy<'_> = InnerAttrPolicy::Forbidden { reason: DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG, saw_doc_comment: false, - prev_attr_sp: None, + prev_outer_attr_sp: None, }; enum OuterAttributeType { @@ -34,14 +34,16 @@ enum OuterAttributeType { impl<'a> Parser<'a> { /// Parses attributes that appear before an item. pub(super) fn parse_outer_attributes(&mut self) -> PResult<'a, AttrWrapper> { - let mut attrs: Vec<ast::Attribute> = Vec::new(); + let mut outer_attrs: Vec<ast::Attribute> = Vec::new(); let mut just_parsed_doc_comment = false; let start_pos = self.token_cursor.num_next_calls; loop { let attr = if self.check(&token::Pound) { + let prev_outer_attr_sp = outer_attrs.last().map(|attr| attr.span); + let inner_error_reason = if just_parsed_doc_comment { "an inner attribute is not permitted following an outer doc comment" - } else if !attrs.is_empty() { + } else if prev_outer_attr_sp.is_some() { "an inner attribute is not permitted following an outer attribute" } else { DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG @@ -49,7 +51,7 @@ pub(super) fn parse_outer_attributes(&mut self) -> PResult<'a, AttrWrapper> { let inner_parse_policy = InnerAttrPolicy::Forbidden { reason: inner_error_reason, saw_doc_comment: just_parsed_doc_comment, - prev_attr_sp: attrs.last().map(|a| a.span), + prev_outer_attr_sp, }; just_parsed_doc_comment = false; Some(self.parse_attribute(inner_parse_policy)?) @@ -97,12 +99,14 @@ pub(super) fn parse_outer_attributes(&mut self) -> PResult<'a, AttrWrapper> { }; if let Some(attr) = attr { - attrs.push(attr); + if attr.style == ast::AttrStyle::Outer { + outer_attrs.push(attr); + } } else { break; } } - Ok(AttrWrapper::new(attrs.into(), start_pos)) + Ok(AttrWrapper::new(outer_attrs.into(), start_pos)) } /// Matches `attribute = # ! [ meta_item ]`. @@ -215,15 +219,15 @@ fn annotate_following_item_if_applicable( } pub(super) fn error_on_forbidden_inner_attr(&self, attr_sp: Span, policy: InnerAttrPolicy<'_>) { - if let InnerAttrPolicy::Forbidden { reason, saw_doc_comment, prev_attr_sp } = policy { - let prev_attr_note = + if let InnerAttrPolicy::Forbidden { reason, saw_doc_comment, prev_outer_attr_sp } = policy { + let prev_outer_attr_note = if saw_doc_comment { "previous doc comment" } else { "previous outer attribute" }; let mut diag = self.struct_span_err(attr_sp, reason); - if let Some(prev_attr_sp) = prev_attr_sp { + if let Some(prev_outer_attr_sp) = prev_outer_attr_sp { diag.span_label(attr_sp, "not permitted following an outer attribute") - .span_label(prev_attr_sp, prev_attr_note); + .span_label(prev_outer_attr_sp, prev_outer_attr_note); } diag.note(
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 3ac2261..ed26404 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -18,10 +18,12 @@ use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{pluralize, struct_span_err, Diagnostic, EmissionGuarantee, ErrorGuaranteed}; -use rustc_errors::{Applicability, DiagnosticBuilder, Handler, PResult}; +use rustc_errors::{ + Applicability, DiagnosticBuilder, DiagnosticMessage, Handler, MultiSpan, PResult, +}; use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, Ident}; -use rustc_span::{MultiSpan, Span, SpanSnippetError, DUMMY_SP}; +use rustc_span::{Span, SpanSnippetError, DUMMY_SP}; use std::ops::{Deref, DerefMut}; use std::mem::take; @@ -273,12 +275,12 @@ pub(super) fn span_err<S: Into<MultiSpan>>( pub fn struct_span_err<S: Into<MultiSpan>>( &self, sp: S, - m: &str, + m: impl Into<DiagnosticMessage>, ) -> DiagnosticBuilder<'a, ErrorGuaranteed> { self.sess.span_diagnostic.struct_span_err(sp, m) } - pub fn span_bug<S: Into<MultiSpan>>(&self, sp: S, m: &str) -> ! { + pub fn span_bug<S: Into<MultiSpan>>(&self, sp: S, m: impl Into<DiagnosticMessage>) -> ! { self.sess.span_diagnostic.span_bug(sp, m) } @@ -584,16 +586,22 @@ pub fn maybe_suggest_struct_literal( // field: value, // } } err.delay_as_bug(); - self.struct_span_err(expr.span, "struct literal body without path") - .multipart_suggestion( - "you might have forgotten to add the struct literal inside the block", - vec![ - (expr.span.shrink_to_lo(), "{ SomeStruct ".to_string()), - (expr.span.shrink_to_hi(), " }".to_string()), - ], - Applicability::MaybeIncorrect, - ) - .emit(); + self.struct_span_err( + expr.span, + DiagnosticMessage::fluent("parser-struct-literal-body-without-path"), + ) + .multipart_suggestion( + DiagnosticMessage::fluent_attr( + "parser-struct-literal-body-without-path", + "suggestion", + ), + vec![ + (expr.span.shrink_to_lo(), "{ SomeStruct ".to_string()), + (expr.span.shrink_to_hi(), " }".to_string()), + ], + Applicability::MaybeIncorrect, + ) + .emit(); self.restore_snapshot(snapshot); let mut tail = self.mk_block( vec![self.mk_stmt_err(expr.span)],
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 7c407cb..7efc0ca 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -41,7 +41,7 @@ macro_rules! maybe_whole_expr { return Ok(e); } token::NtPath(path) => { - let path = path.clone(); + let path = (**path).clone(); $p.bump(); return Ok($p.mk_expr( $p.prev_token.span, @@ -1703,7 +1703,7 @@ pub(super) fn parse_lit(&mut self) -> PResult<'a, Lit> { if matches!(expr.kind, ExprKind::Err) { let mut err = self .diagnostic() - .struct_span_err(self.token.span, &"invalid interpolated expression"); + .struct_span_err(self.token.span, "invalid interpolated expression"); err.downgrade_to_delayed_bug(); return err; } @@ -1820,7 +1820,7 @@ fn fix_base_capitalisation(s: &str) -> Option<String> { } else if let Some(fixed) = fix_base_capitalisation(suf) { let msg = "invalid base prefix for number literal"; - self.struct_span_err(span, &msg) + self.struct_span_err(span, msg) .note("base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase") .span_suggestion( span,
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index e55bdb0..5bf6f22 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs
@@ -1010,7 +1010,8 @@ fn parse_item_foreign_mod( let current_qual_sp = self.prev_token.span; let current_qual_sp = current_qual_sp.to(sp_start); if let Ok(current_qual) = self.span_to_snippet(current_qual_sp) { - if err.message() == "expected `{`, found keyword `unsafe`" { + // FIXME(davidtwco): avoid depending on the error message text + if err.message[0].0.expect_str() == "expected `{`, found keyword `unsafe`" { let invalid_qual_sp = self.token.uninterpolated_span(); let invalid_qual = self.span_to_snippet(invalid_qual_sp).unwrap();
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index b242c1e..f1956fb 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -33,10 +33,10 @@ use rustc_data_structures::sync::Lrc; use rustc_errors::PResult; use rustc_errors::{ - struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, FatalError, + struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, FatalError, MultiSpan, }; use rustc_session::parse::ParseSess; -use rustc_span::source_map::{MultiSpan, Span, DUMMY_SP}; +use rustc_span::source_map::{Span, DUMMY_SP}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use tracing::debug; @@ -1289,7 +1289,7 @@ fn is_crate_vis(&self) -> bool { /// so emit a proper diagnostic. // Public for rustfmt usage. pub fn parse_visibility(&mut self, fbt: FollowedByType) -> PResult<'a, Visibility> { - maybe_whole!(self, NtVis, |x| x); + maybe_whole!(self, NtVis, |x| x.into_inner()); self.expected_tokens.push(TokenType::Keyword(kw::Crate)); if self.is_crate_vis() {
diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index c105fbf..b45bca3 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs
@@ -118,7 +118,7 @@ pub fn parse_nonterminal(&mut self, kind: NonterminalKind) -> PResult<'a, NtOrTt token::NtBlock(self.collect_tokens_no_attrs(|this| this.parse_block())?) } NonterminalKind::Stmt => match self.parse_stmt(ForceCollect::Yes)? { - Some(s) => token::NtStmt(s), + Some(s) => token::NtStmt(P(s)), None => { return Err(self.struct_span_err(self.token.span, "expected a statement")); } @@ -161,11 +161,11 @@ pub fn parse_nonterminal(&mut self, kind: NonterminalKind) -> PResult<'a, NtOrTt return Err(self.struct_span_err(self.token.span, msg)); } NonterminalKind::Path => token::NtPath( - self.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type))?, + P(self.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type))?), ), NonterminalKind::Meta => token::NtMeta(P(self.parse_attr_item(true)?)), NonterminalKind::Vis => token::NtVis( - self.collect_tokens_no_attrs(|this| this.parse_visibility(FollowedByType::Yes))?, + P(self.collect_tokens_no_attrs(|this| this.parse_visibility(FollowedByType::Yes))?), ), NonterminalKind::Lifetime => { if self.check_lifetime() {
diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index 93663a3..207ecd0 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs
@@ -165,7 +165,7 @@ pub(super) fn parse_path_inner( maybe_whole!(self, NtPath, |path| { reject_generics_if_mod_style(self, &path); - path + path.into_inner() }); if let token::Interpolated(nt) = &self.token.kind {
diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index e3bcd945..5b7ae5f 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs
@@ -54,7 +54,7 @@ pub fn parse_stmt(&mut self, force_collect: ForceCollect) -> PResult<'a, Option< stmt.visit_attrs(|stmt_attrs| { attrs.prepend_to_nt_inner(stmt_attrs); }); - return Ok(Some(stmt)); + return Ok(Some(stmt.into_inner())); } Ok(Some(if self.token.is_keyword(kw::Let) { @@ -535,7 +535,7 @@ pub fn parse_full_stmt( recover: AttemptLocalParseRecovery, ) -> PResult<'a, Option<Stmt>> { // Skip looking for a trailing semicolon when we have an interpolated statement. - maybe_whole!(self, NtStmt, |x| Some(x)); + maybe_whole!(self, NtStmt, |x| Some(x.into_inner())); let Some(mut stmt) = self.parse_stmt_without_recovery(true, ForceCollect::No)? else { return Ok(None);
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 7ad8748..1f12f99 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs
@@ -6,7 +6,7 @@ use rustc_ast::{ast, AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem}; use rustc_data_structures::fx::FxHashMap; -use rustc_errors::{pluralize, struct_span_err, Applicability}; +use rustc_errors::{pluralize, struct_span_err, Applicability, MultiSpan}; use rustc_feature::{AttributeDuplicates, AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP}; use rustc_hir as hir; use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID}; @@ -21,7 +21,7 @@ }; use rustc_session::parse::feature_err; use rustc_span::symbol::{sym, Symbol}; -use rustc_span::{MultiSpan, Span, DUMMY_SP}; +use rustc_span::{Span, DUMMY_SP}; use std::collections::hash_map::Entry; pub(crate) fn target_from_impl_item<'tcx>(
diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index bd4e1dd..700290d 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs
@@ -620,8 +620,8 @@ fn incremental_verify_ich_cold(sess: &Session, dep_node: DebugArg<'_>, result: D } else { sess.struct_err(&format!("internal compiler error: encountered incremental compilation error with {:?}", dep_node)) .help(&format!("This is a known issue with the compiler. Run {} to allow your project to compile", run_cmd)) - .note(&"Please follow the instructions below to create a bug report with the provided information") - .note(&"See <https://github.com/rust-lang/rust/issues/84970> for more information") + .note("Please follow the instructions below to create a bug report with the provided information") + .note("See <https://github.com/rust-lang/rust/issues/84970> for more information") .emit(); panic!("Found unstable fingerprints for {:?}: {:?}", dep_node, result); }
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index b706547..07d261d 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -1248,7 +1248,7 @@ fn define_macro(&mut self, item: &ast::Item) -> MacroRulesScopeRef<'a> { }; let binding = (res, vis, span, expansion).to_name_binding(self.r.arenas); self.r.set_binding_parent_module(binding, parent_scope.module); - self.r.all_macros.insert(ident.name, res); + self.r.all_macro_rules.insert(ident.name, res); if is_macro_export { let module = self.r.graph_root; self.r.define(module, ident, MacroNS, (res, vis, span, expansion, IsMacroExport));
diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs index 601f2d9..6503b97 100644 --- a/compiler/rustc_resolve/src/check_unused.rs +++ b/compiler/rustc_resolve/src/check_unused.rs
@@ -32,10 +32,10 @@ use rustc_ast::visit::{self, Visitor}; use rustc_ast_lowering::ResolverAstLowering; use rustc_data_structures::fx::FxHashSet; -use rustc_errors::pluralize; +use rustc_errors::{pluralize, MultiSpan}; use rustc_session::lint::builtin::{MACRO_USE_EXTERN_CRATE, UNUSED_IMPORTS}; use rustc_session::lint::BuiltinLintDiagnostics; -use rustc_span::{MultiSpan, Span, DUMMY_SP}; +use rustc_span::{Span, DUMMY_SP}; struct UnusedImport<'a> { use_tree: &'a ast::UseTree,
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 6c7d4af..609dbd1f 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -4,7 +4,7 @@ use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{ - struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, + struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan, }; use rustc_feature::BUILTIN_ATTRIBUTES; use rustc_hir::def::Namespace::{self, *}; @@ -18,7 +18,7 @@ use rustc_span::lev_distance::find_best_match_for_name; use rustc_span::source_map::SourceMap; use rustc_span::symbol::{kw, sym, Ident, Symbol}; -use rustc_span::{BytePos, MultiSpan, Span}; +use rustc_span::{BytePos, Span}; use tracing::debug; use crate::imports::{Import, ImportKind, ImportResolver}; @@ -1341,7 +1341,7 @@ fn ctor_fields_span(&self, binding: &NameBinding<'_>) -> Option<Span> { let def_span = self.session.source_map().guess_head_span(binding.span); let mut note_span = MultiSpan::from_span(def_span); if !first && binding.vis.is_public() { - note_span.push_span_label(def_span, "consider importing it directly".into()); + note_span.push_span_label(def_span, "consider importing it directly"); } err.span_note(note_span, &msg); }
diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 253b604..02abdba 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs
@@ -12,7 +12,7 @@ use rustc_ast::NodeId; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::intern::Interned; -use rustc_errors::{pluralize, struct_span_err, Applicability}; +use rustc_errors::{pluralize, struct_span_err, Applicability, MultiSpan}; use rustc_hir::def::{self, PartialRes}; use rustc_hir::def_id::DefId; use rustc_middle::metadata::ModChild; @@ -23,7 +23,7 @@ use rustc_span::hygiene::LocalExpnId; use rustc_span::lev_distance::find_best_match_for_name; use rustc_span::symbol::{kw, Ident, Symbol}; -use rustc_span::{MultiSpan, Span}; +use rustc_span::Span; use tracing::*; @@ -739,7 +739,7 @@ fn throw_unresolved_import_error( if let Some((_, UnresolvedImportError { note, .. })) = errors.iter().last() { for message in note { - diag.note(&message); + diag.note(message); } }
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 400adf2..6fedabc 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs
@@ -2297,21 +2297,19 @@ fn resolve_block(&mut self, block: &'ast Block) { let prev = self.diagnostic_metadata.current_block_could_be_bare_struct_literal.take(); if let (true, [Stmt { kind: StmtKind::Expr(expr), .. }]) = (block.could_be_bare_literal, &block.stmts[..]) + && let ExprKind::Type(..) = expr.kind { - if let ExprKind::Type(..) = expr.kind { - self.diagnostic_metadata.current_block_could_be_bare_struct_literal = - Some(block.span); - } + self.diagnostic_metadata.current_block_could_be_bare_struct_literal = + Some(block.span); } // Descend into the block. for stmt in &block.stmts { - if let StmtKind::Item(ref item) = stmt.kind { - if let ItemKind::MacroDef(..) = item.kind { - num_macro_definition_ribs += 1; - let res = self.r.local_def_id(item.id).to_def_id(); - self.ribs[ValueNS].push(Rib::new(MacroDefinition(res))); - self.label_ribs.push(Rib::new(MacroDefinition(res))); - } + if let StmtKind::Item(ref item) = stmt.kind + && let ItemKind::MacroDef(..) = item.kind { + num_macro_definition_ribs += 1; + let res = self.r.local_def_id(item.id).to_def_id(); + self.ribs[ValueNS].push(Rib::new(MacroDefinition(res))); + self.label_ribs.push(Rib::new(MacroDefinition(res))); } self.visit_stmt(stmt);
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index b05ec65..1e943f0 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -14,6 +14,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_errors::{ pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, + MultiSpan, }; use rustc_hir as hir; use rustc_hir::def::Namespace::{self, *}; @@ -25,7 +26,7 @@ use rustc_span::hygiene::MacroKind; use rustc_span::lev_distance::find_best_match_for_name; use rustc_span::symbol::{kw, sym, Ident, Symbol}; -use rustc_span::{BytePos, MultiSpan, Span, DUMMY_SP}; +use rustc_span::{BytePos, Span, DUMMY_SP}; use std::iter; use std::ops::Deref; @@ -1106,7 +1107,7 @@ fn smart_resolve_context_dependent_help( .collect(); if non_visible_spans.len() > 0 { - let mut m: rustc_span::MultiSpan = non_visible_spans.clone().into(); + let mut m: MultiSpan = non_visible_spans.clone().into(); non_visible_spans .into_iter() .for_each(|s| m.push_span_label(s, "private field".to_string())); @@ -1139,7 +1140,7 @@ fn smart_resolve_context_dependent_help( } err.span_suggestion( span, - &"use this syntax instead", + "use this syntax instead", path_str.to_string(), Applicability::MaybeIncorrect, );
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 1f0a6e5..a09a225 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs
@@ -1003,7 +1003,8 @@ pub struct Resolver<'a> { registered_attrs: FxHashSet<Ident>, registered_tools: RegisteredTools, macro_use_prelude: FxHashMap<Symbol, &'a NameBinding<'a>>, - all_macros: FxHashMap<Symbol, Res>, + /// FIXME: The only user of this is a doc link resolution hack for rustdoc. + all_macro_rules: FxHashMap<Symbol, Res>, macro_map: FxHashMap<DefId, Lrc<SyntaxExtension>>, dummy_ext_bang: Lrc<SyntaxExtension>, dummy_ext_derive: Lrc<SyntaxExtension>, @@ -1385,7 +1386,7 @@ pub fn new( registered_attrs, registered_tools, macro_use_prelude: FxHashMap::default(), - all_macros: FxHashMap::default(), + all_macro_rules: Default::default(), macro_map: FxHashMap::default(), dummy_ext_bang: Lrc::new(SyntaxExtension::dummy_bang(session.edition())), dummy_ext_derive: Lrc::new(SyntaxExtension::dummy_derive(session.edition())), @@ -3270,12 +3271,21 @@ pub fn resolve_rustdoc_path( &mut self, path_str: &str, ns: Namespace, - module_id: DefId, + mut module_id: DefId, ) -> Option<Res> { let mut segments = Vec::from_iter(path_str.split("::").map(Ident::from_str).map(Segment::from_ident)); - if path_str.starts_with("::") { - segments[0].ident.name = kw::PathRoot; + if let Some(segment) = segments.first_mut() { + if segment.ident.name == kw::Crate { + // FIXME: `resolve_path` always resolves `crate` to the current crate root, but + // rustdoc wants it to resolve to the `module_id`'s crate root. This trick of + // replacing `crate` with `self` and changing the current module should achieve + // the same effect. + segment.ident.name = kw::SelfLower; + module_id = module_id.krate.as_def_id(); + } else if segment.ident.name == kw::Empty { + segment.ident.name = kw::PathRoot; + } } let module = self.expect_module(module_id); @@ -3289,7 +3299,9 @@ pub fn resolve_rustdoc_path( PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 => { Some(path_res.base_res()) } - PathResult::NonModule(..) | PathResult::Failed { .. } => None, + PathResult::Module(ModuleOrUniformRoot::ExternPrelude) + | PathResult::NonModule(..) + | PathResult::Failed { .. } => None, PathResult::Module(..) | PathResult::Indeterminate => unreachable!(), } } @@ -3300,8 +3312,8 @@ pub fn graph_root(&self) -> Module<'a> { } // For rustdoc. - pub fn all_macros(&self) -> &FxHashMap<Symbol, Res> { - &self.all_macros + pub fn take_all_macro_rules(&mut self) -> FxHashMap<Symbol, Res> { + mem::take(&mut self.all_macro_rules) } /// For rustdoc.
diff --git a/compiler/rustc_serialize/src/serialize.rs b/compiler/rustc_serialize/src/serialize.rs index 42bf6ff..d505303 100644 --- a/compiler/rustc_serialize/src/serialize.rs +++ b/compiler/rustc_serialize/src/serialize.rs
@@ -431,6 +431,20 @@ fn decode(d: &mut D) -> Cow<'static, [T]> { } } +impl<'a, S: Encoder> Encodable<S> for Cow<'a, str> { + fn encode(&self, s: &mut S) -> Result<(), S::Error> { + let val: &str = self; + val.encode(s) + } +} + +impl<'a, D: Decoder> Decodable<D> for Cow<'a, str> { + fn decode(d: &mut D) -> Cow<'static, str> { + let v: String = Decodable::decode(d); + Cow::Owned(v) + } +} + impl<S: Encoder, T: Encodable<S>> Encodable<S> for Option<T> { fn encode(&self, s: &mut S) -> Result<(), S::Error> { s.emit_option(|s| match *self {
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 4182a5d..5a447aa 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs
@@ -2856,6 +2856,7 @@ pub fn needs_analysis(&self) -> bool { use crate::lint; use crate::options::WasiExecModel; use crate::utils::{NativeLib, NativeLibKind}; + use rustc_errors::LanguageIdentifier; use rustc_feature::UnstableFeatures; use rustc_span::edition::Edition; use rustc_span::RealFileName; @@ -2948,6 +2949,7 @@ fn hash( LocationDetail, BranchProtection, OomStrategy, + LanguageIdentifier, ); impl<T1, T2> DepTrackingHash for (T1, T2)
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 463c5c9..4994f8e 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs
@@ -4,6 +4,7 @@ use crate::lint; use crate::search_paths::SearchPath; use crate::utils::NativeLib; +use rustc_errors::LanguageIdentifier; use rustc_target::spec::{CodeModel, LinkerFlavor, MergeFunctions, PanicStrategy, SanitizerSet}; use rustc_target::spec::{ RelocModel, RelroLevel, SplitDebuginfo, StackProtector, TargetTriple, TlsModel, @@ -365,6 +366,7 @@ mod desc { pub const parse_string: &str = "a string"; pub const parse_opt_string: &str = parse_string; pub const parse_string_push: &str = parse_string; + pub const parse_opt_langid: &str = "a language identifier"; pub const parse_opt_pathbuf: &str = "a path"; pub const parse_list: &str = "a space-separated list of strings"; pub const parse_opt_comma_list: &str = "a comma-separated list of strings"; @@ -487,6 +489,17 @@ mod parse { } } + /// Parse an optional language identifier, e.g. `en-US` or `zh-CN`. + crate fn parse_opt_langid(slot: &mut Option<LanguageIdentifier>, v: Option<&str>) -> bool { + match v { + Some(s) => { + *slot = rustc_errors::LanguageIdentifier::from_str(s).ok(); + true + } + None => false, + } + } + crate fn parse_opt_pathbuf(slot: &mut Option<PathBuf>, v: Option<&str>) -> bool { match v { Some(s) => { @@ -1462,6 +1475,15 @@ mod parse { "the directory the intermediate files are written to"), terminal_width: Option<usize> = (None, parse_opt_number, [UNTRACKED], "set the current terminal width"), + // Diagnostics are considered side-effects of a query (see `QuerySideEffects`) and are saved + // alongside query results and changes to translation options can affect diagnostics - so + // translation options should be tracked. + translate_lang: Option<LanguageIdentifier> = (None, parse_opt_langid, [TRACKED], + "language identifier for diagnostic output"), + translate_additional_ftl: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED], + "additional fluent translation to preferentially use (for testing translation)"), + translate_directionality_markers: bool = (false, parse_bool, [TRACKED], + "emit directionality isolation markers in translated diagnostics"), tune_cpu: Option<String> = (None, parse_opt_string, [TRACKED], "select processor to schedule for (`rustc --print target-cpus` for details)"), thinlto: Option<bool> = (None, parse_opt_bool, [TRACKED],
diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index 6f0c476..0b9c27c 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs
@@ -7,12 +7,15 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::{Lock, Lrc}; use rustc_errors::{emitter::SilentEmitter, ColorConfig, Handler}; -use rustc_errors::{error_code, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed}; +use rustc_errors::{ + error_code, fallback_fluent_bundle, Applicability, Diagnostic, DiagnosticBuilder, + ErrorGuaranteed, MultiSpan, +}; use rustc_feature::{find_feature_issue, GateIssue, UnstableFeatures}; use rustc_span::edition::Edition; use rustc_span::hygiene::ExpnId; use rustc_span::source_map::{FilePathMapping, SourceMap}; -use rustc_span::{MultiSpan, Span, Symbol}; +use rustc_span::{Span, Symbol}; use std::str; @@ -171,8 +174,17 @@ pub struct ParseSess { impl ParseSess { /// Used for testing. pub fn new(file_path_mapping: FilePathMapping) -> Self { + let fallback_bundle = + fallback_fluent_bundle(false).expect("failed to load fallback fluent bundle"); let sm = Lrc::new(SourceMap::new(file_path_mapping)); - let handler = Handler::with_tty_emitter(ColorConfig::Auto, true, None, Some(sm.clone())); + let handler = Handler::with_tty_emitter( + ColorConfig::Auto, + true, + None, + Some(sm.clone()), + None, + fallback_bundle, + ); ParseSess::with_span_handler(handler, sm) } @@ -201,8 +213,11 @@ pub fn with_span_handler(handler: Handler, source_map: Lrc<SourceMap>) -> Self { } pub fn with_silent_emitter(fatal_note: Option<String>) -> Self { + let fallback_bundle = + fallback_fluent_bundle(false).expect("failed to load fallback fluent bundle"); let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); - let fatal_handler = Handler::with_tty_emitter(ColorConfig::Auto, false, None, None); + let fatal_handler = + Handler::with_tty_emitter(ColorConfig::Auto, false, None, None, None, fallback_bundle); let handler = Handler::with_emitter( false, None,
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index eed0f1e..9881046 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs
@@ -19,11 +19,14 @@ use rustc_errors::emitter::{Emitter, EmitterWriter, HumanReadableErrorType}; use rustc_errors::json::JsonEmitter; use rustc_errors::registry::Registry; -use rustc_errors::{DiagnosticBuilder, DiagnosticId, ErrorGuaranteed}; +use rustc_errors::{ + fallback_fluent_bundle, fluent_bundle, DiagnosticBuilder, DiagnosticId, DiagnosticMessage, + EmissionGuarantee, ErrorGuaranteed, FluentBundle, MultiSpan, +}; use rustc_macros::HashStable_Generic; pub use rustc_span::def_id::StableCrateId; use rustc_span::edition::Edition; -use rustc_span::source_map::{FileLoader, MultiSpan, RealFileLoader, SourceMap, Span}; +use rustc_span::source_map::{FileLoader, RealFileLoader, SourceMap, Span}; use rustc_span::{sym, SourceFileHashAlgorithm, Symbol}; use rustc_target::asm::InlineAsmArch; use rustc_target::spec::{CodeModel, PanicStrategy, RelocModel, RelroLevel}; @@ -206,10 +209,10 @@ pub struct PerfStats { /// Trait implemented by error types. This should not be implemented manually. Instead, use /// `#[derive(SessionDiagnostic)]` -- see [rustc_macros::SessionDiagnostic]. -pub trait SessionDiagnostic<'a> { +pub trait SessionDiagnostic<'a, T: EmissionGuarantee = ErrorGuaranteed> { /// Write out as a diagnostic out of `sess`. #[must_use] - fn into_diagnostic(self, sess: &'a Session) -> DiagnosticBuilder<'a, ErrorGuaranteed>; + fn into_diagnostic(self, sess: &'a Session) -> DiagnosticBuilder<'a, T>; } impl Session { @@ -279,34 +282,34 @@ pub fn init_crate_types(&self, crate_types: Vec<CrateType>) { pub fn struct_span_warn<S: Into<MultiSpan>>( &self, sp: S, - msg: &str, + msg: impl Into<DiagnosticMessage>, ) -> DiagnosticBuilder<'_, ()> { self.diagnostic().struct_span_warn(sp, msg) } pub fn struct_span_warn_with_code<S: Into<MultiSpan>>( &self, sp: S, - msg: &str, + msg: impl Into<DiagnosticMessage>, code: DiagnosticId, ) -> DiagnosticBuilder<'_, ()> { self.diagnostic().struct_span_warn_with_code(sp, msg, code) } - pub fn struct_warn(&self, msg: &str) -> DiagnosticBuilder<'_, ()> { + pub fn struct_warn(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> { self.diagnostic().struct_warn(msg) } pub fn struct_span_allow<S: Into<MultiSpan>>( &self, sp: S, - msg: &str, + msg: impl Into<DiagnosticMessage>, ) -> DiagnosticBuilder<'_, ()> { self.diagnostic().struct_span_allow(sp, msg) } - pub fn struct_allow(&self, msg: &str) -> DiagnosticBuilder<'_, ()> { + pub fn struct_allow(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> { self.diagnostic().struct_allow(msg) } pub fn struct_expect( &self, - msg: &str, + msg: impl Into<DiagnosticMessage>, id: lint::LintExpectationId, ) -> DiagnosticBuilder<'_, ()> { self.diagnostic().struct_expect(msg, id) @@ -314,81 +317,108 @@ pub fn struct_expect( pub fn struct_span_err<S: Into<MultiSpan>>( &self, sp: S, - msg: &str, + msg: impl Into<DiagnosticMessage>, ) -> DiagnosticBuilder<'_, ErrorGuaranteed> { self.diagnostic().struct_span_err(sp, msg) } pub fn struct_span_err_with_code<S: Into<MultiSpan>>( &self, sp: S, - msg: &str, + msg: impl Into<DiagnosticMessage>, code: DiagnosticId, ) -> DiagnosticBuilder<'_, ErrorGuaranteed> { self.diagnostic().struct_span_err_with_code(sp, msg, code) } // FIXME: This method should be removed (every error should have an associated error code). - pub fn struct_err(&self, msg: &str) -> DiagnosticBuilder<'_, ErrorGuaranteed> { + pub fn struct_err( + &self, + msg: impl Into<DiagnosticMessage>, + ) -> DiagnosticBuilder<'_, ErrorGuaranteed> { self.diagnostic().struct_err(msg) } pub fn struct_err_with_code( &self, - msg: &str, + msg: impl Into<DiagnosticMessage>, code: DiagnosticId, ) -> DiagnosticBuilder<'_, ErrorGuaranteed> { self.diagnostic().struct_err_with_code(msg, code) } + pub fn struct_warn_with_code( + &self, + msg: impl Into<DiagnosticMessage>, + code: DiagnosticId, + ) -> DiagnosticBuilder<'_, ()> { + self.diagnostic().struct_warn_with_code(msg, code) + } pub fn struct_span_fatal<S: Into<MultiSpan>>( &self, sp: S, - msg: &str, + msg: impl Into<DiagnosticMessage>, ) -> DiagnosticBuilder<'_, !> { self.diagnostic().struct_span_fatal(sp, msg) } pub fn struct_span_fatal_with_code<S: Into<MultiSpan>>( &self, sp: S, - msg: &str, + msg: impl Into<DiagnosticMessage>, code: DiagnosticId, ) -> DiagnosticBuilder<'_, !> { self.diagnostic().struct_span_fatal_with_code(sp, msg, code) } - pub fn struct_fatal(&self, msg: &str) -> DiagnosticBuilder<'_, !> { + pub fn struct_fatal(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, !> { self.diagnostic().struct_fatal(msg) } - pub fn span_fatal<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> ! { + pub fn span_fatal<S: Into<MultiSpan>>(&self, sp: S, msg: impl Into<DiagnosticMessage>) -> ! { self.diagnostic().span_fatal(sp, msg) } pub fn span_fatal_with_code<S: Into<MultiSpan>>( &self, sp: S, - msg: &str, + msg: impl Into<DiagnosticMessage>, code: DiagnosticId, ) -> ! { self.diagnostic().span_fatal_with_code(sp, msg, code) } - pub fn fatal(&self, msg: &str) -> ! { + pub fn fatal(&self, msg: impl Into<DiagnosticMessage>) -> ! { self.diagnostic().fatal(msg).raise() } - pub fn span_err_or_warn<S: Into<MultiSpan>>(&self, is_warning: bool, sp: S, msg: &str) { + pub fn span_err_or_warn<S: Into<MultiSpan>>( + &self, + is_warning: bool, + sp: S, + msg: impl Into<DiagnosticMessage>, + ) { if is_warning { self.span_warn(sp, msg); } else { self.span_err(sp, msg); } } - pub fn span_err<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> ErrorGuaranteed { + pub fn span_err<S: Into<MultiSpan>>( + &self, + sp: S, + msg: impl Into<DiagnosticMessage>, + ) -> ErrorGuaranteed { self.diagnostic().span_err(sp, msg) } - pub fn span_err_with_code<S: Into<MultiSpan>>(&self, sp: S, msg: &str, code: DiagnosticId) { - self.diagnostic().span_err_with_code(sp, &msg, code) + pub fn span_err_with_code<S: Into<MultiSpan>>( + &self, + sp: S, + msg: impl Into<DiagnosticMessage>, + code: DiagnosticId, + ) { + self.diagnostic().span_err_with_code(sp, msg, code) } - pub fn err(&self, msg: &str) -> ErrorGuaranteed { + pub fn err(&self, msg: impl Into<DiagnosticMessage>) -> ErrorGuaranteed { self.diagnostic().err(msg) } pub fn emit_err<'a>(&'a self, err: impl SessionDiagnostic<'a>) -> ErrorGuaranteed { err.into_diagnostic(self).emit() } + pub fn emit_warning<'a>(&'a self, warning: impl SessionDiagnostic<'a, ()>) { + warning.into_diagnostic(self).emit() + } #[inline] pub fn err_count(&self) -> usize { self.diagnostic().err_count() @@ -423,25 +453,34 @@ pub fn track_errors<F, T>(&self, f: F) -> Result<T, ErrorGuaranteed> Err(ErrorGuaranteed::unchecked_claim_error_was_emitted()) } } - pub fn span_warn<S: Into<MultiSpan>>(&self, sp: S, msg: &str) { + pub fn span_warn<S: Into<MultiSpan>>(&self, sp: S, msg: impl Into<DiagnosticMessage>) { self.diagnostic().span_warn(sp, msg) } - pub fn span_warn_with_code<S: Into<MultiSpan>>(&self, sp: S, msg: &str, code: DiagnosticId) { + pub fn span_warn_with_code<S: Into<MultiSpan>>( + &self, + sp: S, + msg: impl Into<DiagnosticMessage>, + code: DiagnosticId, + ) { self.diagnostic().span_warn_with_code(sp, msg, code) } - pub fn warn(&self, msg: &str) { + pub fn warn(&self, msg: impl Into<DiagnosticMessage>) { self.diagnostic().warn(msg) } /// Delay a span_bug() call until abort_if_errors() #[track_caller] - pub fn delay_span_bug<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> ErrorGuaranteed { + pub fn delay_span_bug<S: Into<MultiSpan>>( + &self, + sp: S, + msg: impl Into<DiagnosticMessage>, + ) -> ErrorGuaranteed { self.diagnostic().delay_span_bug(sp, msg) } /// Used for code paths of expensive computations that should only take place when /// warnings or errors are emitted. If no messages are emitted ("good path"), then /// it's likely a bug. - pub fn delay_good_path_bug(&self, msg: &str) { + pub fn delay_good_path_bug(&self, msg: impl Into<DiagnosticMessage>) { if self.opts.debugging_opts.print_type_sizes || self.opts.debugging_opts.query_dep_graph || self.opts.debugging_opts.dump_mir.is_some() @@ -455,13 +494,20 @@ pub fn delay_good_path_bug(&self, msg: &str) { self.diagnostic().delay_good_path_bug(msg) } - pub fn note_without_error(&self, msg: &str) { + pub fn note_without_error(&self, msg: impl Into<DiagnosticMessage>) { self.diagnostic().note_without_error(msg) } - pub fn span_note_without_error<S: Into<MultiSpan>>(&self, sp: S, msg: &str) { + pub fn span_note_without_error<S: Into<MultiSpan>>( + &self, + sp: S, + msg: impl Into<DiagnosticMessage>, + ) { self.diagnostic().span_note_without_error(sp, msg) } - pub fn struct_note_without_error(&self, msg: &str) -> DiagnosticBuilder<'_, ()> { + pub fn struct_note_without_error( + &self, + msg: impl Into<DiagnosticMessage>, + ) -> DiagnosticBuilder<'_, ()> { self.diagnostic().struct_note_without_error(msg) } @@ -1033,6 +1079,8 @@ fn default_emitter( sopts: &config::Options, registry: rustc_errors::registry::Registry, source_map: Lrc<SourceMap>, + bundle: Option<Lrc<FluentBundle>>, + fallback_bundle: Lrc<FluentBundle>, emitter_dest: Option<Box<dyn Write + Send>>, ) -> Box<dyn Emitter + sync::Send> { let macro_backtrace = sopts.debugging_opts.macro_backtrace; @@ -1041,14 +1089,21 @@ fn default_emitter( let (short, color_config) = kind.unzip(); if let HumanReadableErrorType::AnnotateSnippet(_) = kind { - let emitter = - AnnotateSnippetEmitterWriter::new(Some(source_map), short, macro_backtrace); + let emitter = AnnotateSnippetEmitterWriter::new( + Some(source_map), + bundle, + fallback_bundle, + short, + macro_backtrace, + ); Box::new(emitter.ui_testing(sopts.debugging_opts.ui_testing)) } else { let emitter = match dst { None => EmitterWriter::stderr( color_config, Some(source_map), + bundle, + fallback_bundle, short, sopts.debugging_opts.teach, sopts.debugging_opts.terminal_width, @@ -1057,6 +1112,8 @@ fn default_emitter( Some(dst) => EmitterWriter::new( dst, Some(source_map), + bundle, + fallback_bundle, short, false, // no teach messages when writing to a buffer false, // no colors when writing to a buffer @@ -1071,6 +1128,8 @@ fn default_emitter( JsonEmitter::stderr( Some(registry), source_map, + bundle, + fallback_bundle, pretty, json_rendered, sopts.debugging_opts.terminal_width, @@ -1083,6 +1142,8 @@ fn default_emitter( dst, Some(registry), source_map, + bundle, + fallback_bundle, pretty, json_rendered, sopts.debugging_opts.terminal_width, @@ -1152,7 +1213,19 @@ pub fn build_session( sopts.file_path_mapping(), hash_kind, )); - let emitter = default_emitter(&sopts, registry, source_map.clone(), write_dest); + + let bundle = fluent_bundle( + &sysroot, + sopts.debugging_opts.translate_lang.clone(), + sopts.debugging_opts.translate_additional_ftl.as_deref(), + sopts.debugging_opts.translate_directionality_markers, + ) + .expect("failed to load fluent bundle"); + let fallback_bundle = + fallback_fluent_bundle(sopts.debugging_opts.translate_directionality_markers) + .expect("failed to load fallback fluent bundle"); + let emitter = + default_emitter(&sopts, registry, source_map.clone(), bundle, fallback_bundle, write_dest); let span_diagnostic = rustc_errors::Handler::with_emitter_and_flags( emitter, @@ -1385,13 +1458,24 @@ pub enum IncrCompSession { } fn early_error_handler(output: config::ErrorOutputType) -> rustc_errors::Handler { + let fallback_bundle = + fallback_fluent_bundle(false).expect("failed to load fallback fluent bundle"); let emitter: Box<dyn Emitter + sync::Send> = match output { config::ErrorOutputType::HumanReadable(kind) => { let (short, color_config) = kind.unzip(); - Box::new(EmitterWriter::stderr(color_config, None, short, false, None, false)) + Box::new(EmitterWriter::stderr( + color_config, + None, + None, + fallback_bundle, + short, + false, + None, + false, + )) } config::ErrorOutputType::Json { pretty, json_rendered } => { - Box::new(JsonEmitter::basic(pretty, json_rendered, None, false)) + Box::new(JsonEmitter::basic(pretty, json_rendered, None, fallback_bundle, None, false)) } }; rustc_errors::Handler::with_emitter(true, None, emitter)
diff --git a/compiler/rustc_span/src/lev_distance.rs b/compiler/rustc_span/src/lev_distance.rs index 93cf965..61e4b98 100644 --- a/compiler/rustc_span/src/lev_distance.rs +++ b/compiler/rustc_span/src/lev_distance.rs
@@ -46,6 +46,62 @@ pub fn lev_distance(a: &str, b: &str, limit: usize) -> Option<usize> { (dcol[m] <= limit).then_some(dcol[m]) } +/// Provides a word similarity score between two words that accounts for substrings being more +/// meaningful than a typical Levenshtein distance. The lower the score, the closer the match. +/// 0 is an identical match. +/// +/// Uses the Levenshtein distance between the two strings and removes the cost of the length +/// difference. If this is 0 then it is either a substring match or a full word match, in the +/// substring match case we detect this and return `1`. To prevent finding meaningless substrings, +/// eg. "in" in "shrink", we only perform this subtraction of length difference if one of the words +/// is not greater than twice the length of the other. For cases where the words are close in size +/// but not an exact substring then the cost of the length difference is discounted by half. +/// +/// Returns `None` if the distance exceeds the limit. +pub fn lev_distance_with_substrings(a: &str, b: &str, limit: usize) -> Option<usize> { + let n = a.chars().count(); + let m = b.chars().count(); + + // Check one isn't less than half the length of the other. If this is true then there is a + // big difference in length. + let big_len_diff = (n * 2) < m || (m * 2) < n; + let len_diff = if n < m { m - n } else { n - m }; + let lev = lev_distance(a, b, limit + len_diff)?; + + // This is the crux, subtracting length difference means exact substring matches will now be 0 + let score = lev - len_diff; + + // If the score is 0 but the words have different lengths then it's a substring match not a full + // word match + let score = if score == 0 && len_diff > 0 && !big_len_diff { + 1 // Exact substring match, but not a total word match so return non-zero + } else if !big_len_diff { + // Not a big difference in length, discount cost of length difference + score + (len_diff + 1) / 2 + } else { + // A big difference in length, add back the difference in length to the score + score + len_diff + }; + + (score <= limit).then_some(score) +} + +/// Finds the best match for given word in the given iterator where substrings are meaningful. +/// +/// A version of [`find_best_match_for_name`] that uses [`lev_distance_with_substrings`] as the score +/// for word similarity. This takes an optional distance limit which defaults to one-third of the +/// given word. +/// +/// Besides the modified Levenshtein, we use case insensitive comparison to improve accuracy +/// on an edge case with a lower(upper)case letters mismatch. +pub fn find_best_match_for_name_with_substrings( + candidates: &[Symbol], + lookup: Symbol, + dist: Option<usize>, +) -> Option<Symbol> { + find_best_match_for_name_impl(true, candidates, lookup, dist) +} + /// Finds the best match for a given word in the given iterator. /// /// As a loose rule to avoid the obviously incorrect suggestions, it takes @@ -54,12 +110,21 @@ pub fn lev_distance(a: &str, b: &str, limit: usize) -> Option<usize> { /// /// Besides Levenshtein, we use case insensitive comparison to improve accuracy /// on an edge case with a lower(upper)case letters mismatch. -#[cold] pub fn find_best_match_for_name( candidates: &[Symbol], lookup: Symbol, dist: Option<usize>, ) -> Option<Symbol> { + find_best_match_for_name_impl(false, candidates, lookup, dist) +} + +#[cold] +fn find_best_match_for_name_impl( + use_substring_score: bool, + candidates: &[Symbol], + lookup: Symbol, + dist: Option<usize>, +) -> Option<Symbol> { let lookup = lookup.as_str(); let lookup_uppercase = lookup.to_uppercase(); @@ -74,7 +139,11 @@ pub fn find_best_match_for_name( let mut dist = dist.unwrap_or_else(|| cmp::max(lookup.len(), 3) / 3); let mut best = None; for c in candidates { - match lev_distance(lookup, c.as_str(), dist) { + match if use_substring_score { + lev_distance_with_substrings(lookup, c.as_str(), dist) + } else { + lev_distance(lookup, c.as_str(), dist) + } { Some(0) => return Some(*c), Some(d) => { dist = d - 1;
diff --git a/compiler/rustc_span/src/lev_distance/tests.rs b/compiler/rustc_span/src/lev_distance/tests.rs index 4e34219..b17d658 100644 --- a/compiler/rustc_span/src/lev_distance/tests.rs +++ b/compiler/rustc_span/src/lev_distance/tests.rs
@@ -28,6 +28,17 @@ fn test_lev_distance_limit() { } #[test] +fn test_method_name_similarity_score() { + assert_eq!(lev_distance_with_substrings("empty", "is_empty", 1), Some(1)); + assert_eq!(lev_distance_with_substrings("shrunk", "rchunks", 2), None); + assert_eq!(lev_distance_with_substrings("abc", "abcd", 1), Some(1)); + assert_eq!(lev_distance_with_substrings("a", "abcd", 1), None); + assert_eq!(lev_distance_with_substrings("edf", "eq", 1), None); + assert_eq!(lev_distance_with_substrings("abc", "xyz", 3), Some(3)); + assert_eq!(lev_distance_with_substrings("abcdef", "abcdef", 2), Some(0)); +} + +#[test] fn test_find_best_match_for_name() { use crate::create_default_session_globals_then; create_default_session_globals_then(|| {
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 6d73779..5232c8d 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs
@@ -520,20 +520,6 @@ fn cmp(&self, rhs: &Self) -> Ordering { } } -/// A collection of `Span`s. -/// -/// Spans have two orthogonal attributes: -/// -/// - They can be *primary spans*. In this case they are the locus of -/// the error, and would be rendered with `^^^`. -/// - They can have a *label*. In this case, the label is written next -/// to the mark in the snippet when we render. -#[derive(Clone, Debug, Hash, PartialEq, Eq, Encodable, Decodable)] -pub struct MultiSpan { - primary_spans: Vec<Span>, - span_labels: Vec<(Span, String)>, -} - impl Span { #[inline] pub fn lo(self) -> BytePos { @@ -949,20 +935,6 @@ pub fn normalize_to_macro_rules(self) -> Span { } } -/// A span together with some additional data. -#[derive(Clone, Debug)] -pub struct SpanLabel { - /// The span we are going to include in the final snippet. - pub span: Span, - - /// Is this a primary span? This is the "locus" of the message, - /// and is indicated with a `^^^^` underline, versus `----`. - pub is_primary: bool, - - /// What label should we attach to this span (if any)? - pub label: Option<String>, -} - impl Default for Span { fn default() -> Self { DUMMY_SP @@ -1035,115 +1007,6 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { } } -impl MultiSpan { - #[inline] - pub fn new() -> MultiSpan { - MultiSpan { primary_spans: vec![], span_labels: vec![] } - } - - pub fn from_span(primary_span: Span) -> MultiSpan { - MultiSpan { primary_spans: vec![primary_span], span_labels: vec![] } - } - - pub fn from_spans(mut vec: Vec<Span>) -> MultiSpan { - vec.sort(); - MultiSpan { primary_spans: vec, span_labels: vec![] } - } - - pub fn push_span_label(&mut self, span: Span, label: String) { - self.span_labels.push((span, label)); - } - - /// Selects the first primary span (if any). - pub fn primary_span(&self) -> Option<Span> { - self.primary_spans.first().cloned() - } - - /// Returns all primary spans. - pub fn primary_spans(&self) -> &[Span] { - &self.primary_spans - } - - /// Returns `true` if any of the primary spans are displayable. - pub fn has_primary_spans(&self) -> bool { - self.primary_spans.iter().any(|sp| !sp.is_dummy()) - } - - /// Returns `true` if this contains only a dummy primary span with any hygienic context. - pub fn is_dummy(&self) -> bool { - let mut is_dummy = true; - for span in &self.primary_spans { - if !span.is_dummy() { - is_dummy = false; - } - } - is_dummy - } - - /// Replaces all occurrences of one Span with another. Used to move `Span`s in areas that don't - /// display well (like std macros). Returns whether replacements occurred. - pub fn replace(&mut self, before: Span, after: Span) -> bool { - let mut replacements_occurred = false; - for primary_span in &mut self.primary_spans { - if *primary_span == before { - *primary_span = after; - replacements_occurred = true; - } - } - for span_label in &mut self.span_labels { - if span_label.0 == before { - span_label.0 = after; - replacements_occurred = true; - } - } - replacements_occurred - } - - /// Returns the strings to highlight. We always ensure that there - /// is an entry for each of the primary spans -- for each primary - /// span `P`, if there is at least one label with span `P`, we return - /// those labels (marked as primary). But otherwise we return - /// `SpanLabel` instances with empty labels. - pub fn span_labels(&self) -> Vec<SpanLabel> { - let is_primary = |span| self.primary_spans.contains(&span); - - let mut span_labels = self - .span_labels - .iter() - .map(|&(span, ref label)| SpanLabel { - span, - is_primary: is_primary(span), - label: Some(label.clone()), - }) - .collect::<Vec<_>>(); - - for &span in &self.primary_spans { - if !span_labels.iter().any(|sl| sl.span == span) { - span_labels.push(SpanLabel { span, is_primary: true, label: None }); - } - } - - span_labels - } - - /// Returns `true` if any of the span labels is displayable. - pub fn has_span_labels(&self) -> bool { - self.span_labels.iter().any(|(sp, _)| !sp.is_dummy()) - } -} - -impl From<Span> for MultiSpan { - fn from(span: Span) -> MultiSpan { - MultiSpan::from_span(span) - } -} - -impl From<Vec<Span>> for MultiSpan { - fn from(spans: Vec<Span>) -> MultiSpan { - MultiSpan::from_spans(spans) - } -} - /// Identifies an offset of a multi-byte character in a `SourceFile`. #[derive(Copy, Clone, Encodable, Decodable, Eq, PartialEq, Debug)] pub struct MultiByteChar {
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 2737c26..f5803aa 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs
@@ -180,6 +180,9 @@ Error, File, FileType, + Fn, + FnMut, + FnOnce, FormatSpec, Formatter, From, @@ -248,6 +251,7 @@ RustcEncodable, Send, SeqCst, + SliceIndex, Some, String, StructuralEq,
diff --git a/compiler/rustc_target/src/abi/call/mips64.rs b/compiler/rustc_target/src/abi/call/mips64.rs index 1ac454b..cd54167 100644 --- a/compiler/rustc_target/src/abi/call/mips64.rs +++ b/compiler/rustc_target/src/abi/call/mips64.rs
@@ -6,7 +6,7 @@ fn extend_integer_width_mips<Ty>(arg: &mut ArgAbi<'_, Ty>, bits: u64) { // Always sign extend u32 values on 64-bit mips if let abi::Abi::Scalar(scalar) = arg.layout.abi { - if let abi::Int(i, signed) = scalar.value { + if let abi::Int(i, signed) = scalar.primitive() { if !signed && i.size().bits() == 32 { if let PassMode::Direct(ref mut attrs) = arg.mode { attrs.ext(ArgExtension::Sext); @@ -25,7 +25,7 @@ fn float_reg<'a, Ty, C>(cx: &C, ret: &ArgAbi<'a, Ty>, i: usize) -> Option<Reg> C: HasDataLayout, { match ret.layout.field(cx, i).abi { - abi::Abi::Scalar(scalar) => match scalar.value { + abi::Abi::Scalar(scalar) => match scalar.primitive() { abi::F32 => Some(Reg::f32()), abi::F64 => Some(Reg::f64()), _ => None, @@ -110,7 +110,7 @@ fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) // We only care about aligned doubles if let abi::Abi::Scalar(scalar) = field.abi { - if let abi::F64 = scalar.value { + if let abi::F64 = scalar.primitive() { if offset.is_aligned(dl.f64_align.abi) { // Insert enough integers to cover [last_offset, offset) assert!(last_offset.is_aligned(dl.f64_align.abi));
diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs index 34324a5..ce564d1 100644 --- a/compiler/rustc_target/src/abi/call/mod.rs +++ b/compiler/rustc_target/src/abi/call/mod.rs
@@ -348,7 +348,7 @@ pub fn homogeneous_aggregate<C>(&self, cx: &C) -> Result<HomogeneousAggregate, H // The primitive for this algorithm. Abi::Scalar(scalar) => { - let kind = match scalar.value { + let kind = match scalar.primitive() { abi::Int(..) | abi::Pointer => RegKind::Integer, abi::F32 | abi::F64 => RegKind::Float, }; @@ -482,7 +482,7 @@ pub fn new( Abi::Scalar(scalar) => PassMode::Direct(scalar_attrs(&layout, scalar, Size::ZERO)), Abi::ScalarPair(a, b) => PassMode::Pair( scalar_attrs(&layout, a, Size::ZERO), - scalar_attrs(&layout, b, a.value.size(cx).align_to(b.value.align(cx).abi)), + scalar_attrs(&layout, b, a.size(cx).align_to(b.align(cx).abi)), ), Abi::Vector { .. } => PassMode::Direct(ArgAttributes::new()), Abi::Aggregate { .. } => PassMode::Direct(ArgAttributes::new()), @@ -534,7 +534,7 @@ pub fn make_indirect_byval(&mut self) { pub fn extend_integer_width_to(&mut self, bits: u64) { // Only integers have signedness if let Abi::Scalar(scalar) = self.layout.abi { - if let abi::Int(i, signed) = scalar.value { + if let abi::Int(i, signed) = scalar.primitive() { if i.size().bits() < bits { if let PassMode::Direct(ref mut attrs) = self.mode { if signed {
diff --git a/compiler/rustc_target/src/abi/call/riscv.rs b/compiler/rustc_target/src/abi/call/riscv.rs index bbefc73..752b44f 100644 --- a/compiler/rustc_target/src/abi/call/riscv.rs +++ b/compiler/rustc_target/src/abi/call/riscv.rs
@@ -44,7 +44,7 @@ fn should_use_fp_conv_helper<'a, Ty, C>( Ty: TyAbiInterface<'a, C> + Copy, { match arg_layout.abi { - Abi::Scalar(scalar) => match scalar.value { + Abi::Scalar(scalar) => match scalar.primitive() { abi::Int(..) | abi::Pointer => { if arg_layout.size.bits() > xlen { return Err(CannotUseFpConv); @@ -298,7 +298,7 @@ fn classify_arg<'a, Ty, C>( fn extend_integer_width<'a, Ty>(arg: &mut ArgAbi<'a, Ty>, xlen: u64) { if let Abi::Scalar(scalar) = arg.layout.abi { - if let abi::Int(i, _) = scalar.value { + if let abi::Int(i, _) = scalar.primitive() { // 32-bit integers are always sign-extended if i.size().bits() == 32 && xlen > 32 { if let PassMode::Direct(ref mut attrs) = arg.mode {
diff --git a/compiler/rustc_target/src/abi/call/sparc64.rs b/compiler/rustc_target/src/abi/call/sparc64.rs index 72709d3..5a92ebd 100644 --- a/compiler/rustc_target/src/abi/call/sparc64.rs +++ b/compiler/rustc_target/src/abi/call/sparc64.rs
@@ -20,7 +20,7 @@ fn arg_scalar<C>(cx: &C, scalar: &Scalar, offset: Size, mut data: Sdata) -> Sdat { let dl = cx.data_layout(); - if scalar.value != abi::F32 && scalar.value != abi::F64 { + if !scalar.primitive().is_float() { return data; } @@ -56,7 +56,7 @@ fn arg_scalar<C>(cx: &C, scalar: &Scalar, offset: Size, mut data: Sdata) -> Sdat return data; } - if scalar.value == abi::F32 { + if scalar.primitive() == abi::F32 { data.arg_attribute = ArgAttribute::InReg; data.prefix[data.prefix_index] = Some(Reg::f32()); data.last_offset = offset + Reg::f32().size; @@ -79,17 +79,15 @@ fn arg_scalar_pair<C>( C: HasDataLayout, { data = arg_scalar(cx, &scalar1, offset, data); - if scalar1.value == abi::F32 { - offset += Reg::f32().size; - } else if scalar2.value == abi::F64 { - offset += Reg::f64().size; - } else if let abi::Int(i, _signed) = scalar1.value { - offset += i.size(); - } else if scalar1.value == abi::Pointer { - offset = offset + Reg::i64().size; + match (scalar1.primitive(), scalar2.primitive()) { + (abi::F32, _) => offset += Reg::f32().size, + (_, abi::F64) => offset += Reg::f64().size, + (abi::Int(i, _signed), _) => offset += i.size(), + (abi::Pointer, _) => offset += Reg::i64().size, + _ => {} } - if (offset.raw % 4) != 0 && (scalar2.value == abi::F32 || scalar2.value == abi::F64) { + if (offset.raw % 4) != 0 && scalar2.primitive().is_float() { offset.raw += 4 - (offset.raw % 4); } data = arg_scalar(cx, &scalar2, offset, data);
diff --git a/compiler/rustc_target/src/abi/call/x86_64.rs b/compiler/rustc_target/src/abi/call/x86_64.rs index fae3c3a..a52e01a 100644 --- a/compiler/rustc_target/src/abi/call/x86_64.rs +++ b/compiler/rustc_target/src/abi/call/x86_64.rs
@@ -49,7 +49,7 @@ fn classify<'a, Ty, C>( let mut c = match layout.abi { Abi::Uninhabited => return Ok(()), - Abi::Scalar(scalar) => match scalar.value { + Abi::Scalar(scalar) => match scalar.primitive() { abi::Int(..) | abi::Pointer => Class::Int, abi::F32 | abi::F64 => Class::Sse, },
diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs index 52fce7c..169167f 100644 --- a/compiler/rustc_target/src/abi/mod.rs +++ b/compiler/rustc_target/src/abi/mod.rs
@@ -752,6 +752,10 @@ pub struct WrappingRange { } impl WrappingRange { + pub fn full(size: Size) -> Self { + Self { start: 0, end: size.unsigned_int_max() } + } + /// Returns `true` if `v` is contained in the range. #[inline(always)] pub fn contains(&self, v: u128) -> bool { @@ -799,13 +803,23 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { /// Information about one scalar component of a Rust type. #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] #[derive(HashStable_Generic)] -pub struct Scalar { - pub value: Primitive, +pub enum Scalar { + Initialized { + value: Primitive, - // FIXME(eddyb) always use the shortest range, e.g., by finding - // the largest space between two consecutive valid values and - // taking everything else as the (shortest) valid range. - pub valid_range: WrappingRange, + // FIXME(eddyb) always use the shortest range, e.g., by finding + // the largest space between two consecutive valid values and + // taking everything else as the (shortest) valid range. + valid_range: WrappingRange, + }, + Union { + /// Even for unions, we need to use the correct registers for the kind of + /// values inside the union, so we keep the `Primitive` type around. We + /// also use it to compute the size of the scalar. + /// However, unions never have niches and even allow undef, + /// so there is no `valid_range`. + value: Primitive, + }, } impl Scalar { @@ -813,14 +827,58 @@ impl Scalar { pub fn is_bool(&self) -> bool { matches!( self, - Scalar { value: Int(I8, false), valid_range: WrappingRange { start: 0, end: 1 } } + Scalar::Initialized { + value: Int(I8, false), + valid_range: WrappingRange { start: 0, end: 1 } + } ) } + /// Get the primitive representation of this type, ignoring the valid range and whether the + /// value is allowed to be undefined (due to being a union). + pub fn primitive(&self) -> Primitive { + match *self { + Scalar::Initialized { value, .. } | Scalar::Union { value } => value, + } + } + + pub fn align(self, cx: &impl HasDataLayout) -> AbiAndPrefAlign { + self.primitive().align(cx) + } + + pub fn size(self, cx: &impl HasDataLayout) -> Size { + self.primitive().size(cx) + } + + #[inline] + pub fn to_union(&self) -> Self { + Self::Union { value: self.primitive() } + } + + #[inline] + pub fn valid_range(&self, cx: &impl HasDataLayout) -> WrappingRange { + match *self { + Scalar::Initialized { valid_range, .. } => valid_range, + Scalar::Union { value } => WrappingRange::full(value.size(cx)), + } + } + + #[inline] + /// Allows the caller to mutate the valid range. This operation will panic if attempted on a union. + pub fn valid_range_mut(&mut self) -> &mut WrappingRange { + match self { + Scalar::Initialized { valid_range, .. } => valid_range, + Scalar::Union { .. } => panic!("cannot change the valid range of a union"), + } + } + /// Returns `true` if all possible numbers are valid, i.e `valid_range` covers the whole layout #[inline] pub fn is_always_valid<C: HasDataLayout>(&self, cx: &C) -> bool { - self.valid_range.is_full_for(self.value.size(cx)) + match *self { + Scalar::Initialized { valid_range, .. } => valid_range.is_full_for(self.size(cx)), + Scalar::Union { .. } => true, + } } } @@ -988,7 +1046,7 @@ pub fn is_unsized(&self) -> bool { #[inline] pub fn is_signed(&self) -> bool { match self { - Abi::Scalar(scal) => match scal.value { + Abi::Scalar(scal) => match scal.primitive() { Primitive::Int(_, signed) => signed, _ => false, }, @@ -1060,17 +1118,19 @@ pub enum TagEncoding { #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable_Generic)] pub struct Niche { pub offset: Size, - pub scalar: Scalar, + pub value: Primitive, + pub valid_range: WrappingRange, } impl Niche { pub fn from_scalar<C: HasDataLayout>(cx: &C, offset: Size, scalar: Scalar) -> Option<Self> { - let niche = Niche { offset, scalar }; + let Scalar::Initialized { value, valid_range } = scalar else { return None }; + let niche = Niche { offset, value, valid_range }; if niche.available(cx) > 0 { Some(niche) } else { None } } pub fn available<C: HasDataLayout>(&self, cx: &C) -> u128 { - let Scalar { value, valid_range: v } = self.scalar; + let Self { value, valid_range: v, .. } = *self; let size = value.size(cx); assert!(size.bits() <= 128); let max_value = size.unsigned_int_max(); @@ -1083,7 +1143,7 @@ pub fn available<C: HasDataLayout>(&self, cx: &C) -> u128 { pub fn reserve<C: HasDataLayout>(&self, cx: &C, count: u128) -> Option<(u128, Scalar)> { assert!(count > 0); - let Scalar { value, valid_range: v } = self.scalar; + let Self { value, valid_range: v, .. } = *self; let size = value.size(cx); assert!(size.bits() <= 128); let max_value = size.unsigned_int_max(); @@ -1107,12 +1167,12 @@ pub fn reserve<C: HasDataLayout>(&self, cx: &C, count: u128) -> Option<(u128, Sc // If niche zero is already reserved, the selection of bounds are of little interest. let move_start = |v: WrappingRange| { let start = v.start.wrapping_sub(count) & max_value; - Some((start, Scalar { value, valid_range: v.with_start(start) })) + Some((start, Scalar::Initialized { value, valid_range: v.with_start(start) })) }; let move_end = |v: WrappingRange| { let start = v.end.wrapping_add(1) & max_value; let end = v.end.wrapping_add(count) & max_value; - Some((start, Scalar { value, valid_range: v.with_end(end) })) + Some((start, Scalar::Initialized { value, valid_range: v.with_end(end) })) }; let distance_end_zero = max_value - v.end; if v.start > v.end { @@ -1172,8 +1232,8 @@ pub struct LayoutS<'a> { impl<'a> LayoutS<'a> { pub fn scalar<C: HasDataLayout>(cx: &C, scalar: Scalar) -> Self { let largest_niche = Niche::from_scalar(cx, Size::ZERO, scalar); - let size = scalar.value.size(cx); - let align = scalar.value.align(cx); + let size = scalar.size(cx); + let align = scalar.align(cx); LayoutS { variants: Variants::Single { index: VariantIdx::new(0) }, fields: FieldsShape::Primitive, @@ -1202,7 +1262,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { } #[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable_Generic)] -#[cfg_attr(not(bootstrap), rustc_pass_by_value)] +#[rustc_pass_by_value] pub struct Layout<'a>(pub Interned<'a, LayoutS<'a>>); impl<'a> fmt::Debug for Layout<'a> { @@ -1325,7 +1385,7 @@ pub fn is_single_fp_element<C>(self, cx: &C) -> bool C: HasDataLayout, { match self.abi { - Abi::Scalar(scalar) => scalar.value.is_float(), + Abi::Scalar(scalar) => scalar.primitive().is_float(), Abi::Aggregate { .. } => { if self.fields.count() == 1 && self.fields.offset(0).bytes() == 0 { self.field(cx, 0).is_single_fp_element(cx) @@ -1371,7 +1431,7 @@ pub fn might_permit_raw_init<C>(self, cx: &C, zero: bool) -> bool let scalar_allows_raw_init = move |s: Scalar| -> bool { if zero { // The range must contain 0. - s.valid_range.contains(0) + s.valid_range(cx).contains(0) } else { // The range must include all values. s.is_always_valid(cx)
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 216aa89..9998c5b 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -2,10 +2,11 @@ pub mod suggestions; use super::{ - EvaluationResult, FulfillmentContext, FulfillmentError, FulfillmentErrorCode, - MismatchedProjectionTypes, Obligation, ObligationCause, ObligationCauseCode, - OnUnimplementedDirective, OnUnimplementedNote, OutputTypeParameterMismatch, Overflow, - PredicateObligation, SelectionContext, SelectionError, TraitNotObjectSafe, + DerivedObligationCause, EvaluationResult, FulfillmentContext, FulfillmentError, + FulfillmentErrorCode, ImplDerivedObligationCause, MismatchedProjectionTypes, Obligation, + ObligationCause, ObligationCauseCode, OnUnimplementedDirective, OnUnimplementedNote, + OutputTypeParameterMismatch, Overflow, PredicateObligation, SelectionContext, SelectionError, + TraitNotObjectSafe, }; use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCode}; @@ -14,6 +15,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_errors::{ pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, + MultiSpan, Style, }; use rustc_hir as hir; use rustc_hir::def_id::DefId; @@ -28,10 +30,10 @@ use rustc_middle::ty::error::ExpectedFound; use rustc_middle::ty::fold::TypeFolder; use rustc_middle::ty::{ - self, SubtypePredicate, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, + self, SubtypePredicate, ToPolyTraitRef, ToPredicate, TraitRef, Ty, TyCtxt, TypeFoldable, }; use rustc_span::symbol::{kw, sym}; -use rustc_span::{ExpnKind, MultiSpan, Span, DUMMY_SP}; +use rustc_span::{ExpnKind, Span, DUMMY_SP}; use std::fmt; use std::iter; @@ -354,7 +356,7 @@ fn report_selection_error( let have_alt_message = message.is_some() || label.is_some(); let is_try_conversion = self.is_try_conversion(span, trait_ref.def_id()); let is_unsize = - { Some(trait_ref.def_id()) == self.tcx.lang_items().unsize_trait() }; + Some(trait_ref.def_id()) == self.tcx.lang_items().unsize_trait(); let (message, note, append_const_msg) = if is_try_conversion { ( Some(format!( @@ -363,7 +365,7 @@ fn report_selection_error( )), Some( "the question mark operation (`?`) implicitly performs a \ - conversion on the error value using the `From` trait" + conversion on the error value using the `From` trait" .to_owned(), ), Some(None), @@ -474,6 +476,12 @@ fn report_selection_error( err.span_label(span, explanation); } + if let ObligationCauseCode::ObjectCastObligation(obj_ty) = obligation.cause.code().peel_derives() && + let Some(self_ty) = trait_predicate.self_ty().no_bound_vars() && + Some(trait_ref.def_id()) == self.tcx.lang_items().sized_trait() { + self.suggest_borrowing_for_object_cast(&mut err, &obligation, self_ty, *obj_ty); + } + if trait_predicate.is_const_if_const() && obligation.param_env.is_const() { let non_const_predicate = trait_ref.without_const(); let non_const_obligation = Obligation { @@ -519,10 +527,12 @@ fn report_selection_error( } self.suggest_floating_point_literal(&obligation, &mut err, &trait_ref); - self.suggest_dereferences(&obligation, &mut err, trait_predicate); - self.suggest_fn_call(&obligation, &mut err, trait_predicate); - self.suggest_remove_reference(&obligation, &mut err, trait_predicate); - self.suggest_semicolon_removal( + let mut suggested = + self.suggest_dereferences(&obligation, &mut err, trait_predicate); + suggested |= self.suggest_fn_call(&obligation, &mut err, trait_predicate); + suggested |= + self.suggest_remove_reference(&obligation, &mut err, trait_predicate); + suggested |= self.suggest_semicolon_removal( &obligation, &mut err, span, @@ -530,6 +540,7 @@ fn report_selection_error( ); self.note_version_mismatch(&mut err, &trait_ref); self.suggest_remove_await(&obligation, &mut err); + self.suggest_derive(&obligation, &mut err, trait_predicate); if Some(trait_ref.def_id()) == tcx.lang_items().try_trait() { self.suggest_await_before_try( @@ -648,10 +659,80 @@ fn report_selection_error( trait_predicate, obligation.cause.body_id, ); - } else if !have_alt_message { + } else if !suggested { // Can't show anything else useful, try to find similar impls. let impl_candidates = self.find_similar_impl_candidates(trait_ref); - self.report_similar_impl_candidates(impl_candidates, &mut err); + if !self.report_similar_impl_candidates( + impl_candidates, + trait_ref, + &mut err, + ) { + // This is *almost* equivalent to + // `obligation.cause.code().peel_derives()`, but it gives us the + // trait predicate for that corresponding root obligation. This + // lets us get a derived obligation from a type parameter, like + // when calling `string.strip_suffix(p)` where `p` is *not* an + // implementer of `Pattern<'_>`. + let mut code = obligation.cause.code(); + let mut trait_pred = trait_predicate; + let mut peeled = false; + loop { + match &*code { + ObligationCauseCode::FunctionArgumentObligation { + parent_code, + .. + } => { + code = &parent_code; + } + ObligationCauseCode::ImplDerivedObligation( + box ImplDerivedObligationCause { + derived: + DerivedObligationCause { + parent_code, + parent_trait_pred, + }, + .. + }, + ) + | ObligationCauseCode::BuiltinDerivedObligation( + DerivedObligationCause { + parent_code, + parent_trait_pred, + }, + ) + | ObligationCauseCode::DerivedObligation( + DerivedObligationCause { + parent_code, + parent_trait_pred, + }, + ) => { + peeled = true; + code = &parent_code; + trait_pred = *parent_trait_pred; + } + _ => break, + }; + } + let def_id = trait_pred.def_id(); + // Mention *all* the `impl`s for the *top most* obligation, the + // user might have meant to use one of them, if any found. We skip + // auto-traits or fundamental traits that might not be exactly what + // the user might expect to be presented with. Instead this is + // useful for less general traits. + if peeled + && !self.tcx.trait_is_auto(def_id) + && !self.tcx.lang_items().items().contains(&Some(def_id)) + { + let trait_ref = trait_pred.to_poly_trait_ref(); + let impl_candidates = + self.find_similar_impl_candidates(trait_ref); + self.report_similar_impl_candidates( + impl_candidates, + trait_ref, + &mut err, + ); + } + } } // Changing mutability doesn't make a difference to whether we have @@ -676,7 +757,6 @@ fn report_selection_error( }); let unit_obligation = obligation.with(predicate.to_predicate(tcx)); if self.predicate_may_hold(&unit_obligation) { - err.note("this trait is implemented for `()`"); err.note( "this error might have been caused by changes to \ Rust's type-inference algorithm (see issue #48950 \ @@ -1301,8 +1381,9 @@ fn find_similar_impl_candidates( fn report_similar_impl_candidates( &self, impl_candidates: Vec<ImplCandidate<'tcx>>, + trait_ref: ty::PolyTraitRef<'tcx>, err: &mut Diagnostic, - ); + ) -> bool; /// Gets the parent trait chain start fn get_parent_trait_ref( @@ -1313,7 +1394,11 @@ fn get_parent_trait_ref( /// If the `Self` type of the unsatisfied trait `trait_ref` implements a trait /// with the same path as `trait_ref`, a help message about /// a probable version mismatch is added to `err` - fn note_version_mismatch(&self, err: &mut Diagnostic, trait_ref: &ty::PolyTraitRef<'tcx>); + fn note_version_mismatch( + &self, + err: &mut Diagnostic, + trait_ref: &ty::PolyTraitRef<'tcx>, + ) -> bool; /// Creates a `PredicateObligation` with `new_self_ty` replacing the existing type in the /// `trait_ref`. @@ -1675,14 +1760,82 @@ fn find_similar_impl_candidates( fn report_similar_impl_candidates( &self, impl_candidates: Vec<ImplCandidate<'tcx>>, + trait_ref: ty::PolyTraitRef<'tcx>, err: &mut Diagnostic, - ) { - if impl_candidates.is_empty() { - return; - } + ) -> bool { + let report = |mut candidates: Vec<TraitRef<'tcx>>, err: &mut Diagnostic| { + candidates.sort(); + candidates.dedup(); + let len = candidates.len(); + if candidates.len() == 0 { + return false; + } + if candidates.len() == 1 { + err.highlighted_help(vec![ + ( + format!("the trait `{}` ", candidates[0].print_only_trait_path()), + Style::NoStyle, + ), + ("is".to_string(), Style::Highlight), + (" implemented for `".to_string(), Style::NoStyle), + (candidates[0].self_ty().to_string(), Style::Highlight), + ("`".to_string(), Style::NoStyle), + ]); + return true; + } + let trait_ref = TraitRef::identity(self.tcx, candidates[0].def_id); + // Check if the trait is the same in all cases. If so, we'll only show the type. + let mut traits: Vec<_> = + candidates.iter().map(|c| c.print_only_trait_path().to_string()).collect(); + traits.sort(); + traits.dedup(); - let len = impl_candidates.len(); - let end = if impl_candidates.len() <= 5 { impl_candidates.len() } else { 4 }; + let mut candidates: Vec<String> = candidates + .into_iter() + .map(|c| { + if traits.len() == 1 { + format!("\n {}", c.self_ty()) + } else { + format!("\n {}", c) + } + }) + .collect(); + + candidates.sort(); + candidates.dedup(); + let end = if candidates.len() <= 9 { candidates.len() } else { 8 }; + err.help(&format!( + "the following other types implement trait `{}`:{}{}", + trait_ref.print_only_trait_path(), + candidates[..end].join(""), + if len > 9 { format!("\nand {} others", len - 8) } else { String::new() } + )); + true + }; + + let def_id = trait_ref.def_id(); + if impl_candidates.is_empty() { + if self.tcx.trait_is_auto(def_id) + || self.tcx.lang_items().items().contains(&Some(def_id)) + || self.tcx.get_diagnostic_name(def_id).is_some() + { + // Mentioning implementers of `Copy`, `Debug` and friends is not useful. + return false; + } + let normalized_impl_candidates: Vec<_> = self + .tcx + .all_impls(def_id) + // Ignore automatically derived impls and `!Trait` impls. + .filter(|&def_id| { + self.tcx.impl_polarity(def_id) != ty::ImplPolarity::Negative + || self.tcx.is_builtin_derive(def_id) + }) + .filter_map(|def_id| self.tcx.impl_trait_ref(def_id)) + // Avoid mentioning type parameters. + .filter(|trait_ref| !matches!(trait_ref.self_ty().kind(), ty::Param(_))) + .collect(); + return report(normalized_impl_candidates, err); + } let normalize = |candidate| { self.tcx.infer_ctxt().enter(|ref infcx| { @@ -1691,8 +1844,8 @@ fn report_similar_impl_candidates( .normalize(candidate) .ok(); match normalized { - Some(normalized) => format!("\n {}", normalized.value), - None => format!("\n {}", candidate), + Some(normalized) => normalized.value, + None => candidate, } }) }; @@ -1711,17 +1864,14 @@ fn report_similar_impl_candidates( }) .collect::<Vec<_>>(); normalized_impl_candidates_and_similarities.sort(); + normalized_impl_candidates_and_similarities.dedup(); let normalized_impl_candidates = normalized_impl_candidates_and_similarities .into_iter() .map(|(_, normalized)| normalized) .collect::<Vec<_>>(); - err.help(&format!( - "the following implementations were found:{}{}", - normalized_impl_candidates[..end].join(""), - if len > 5 { format!("\nand {} others", len - 4) } else { String::new() } - )); + report(normalized_impl_candidates, err) } /// Gets the parent trait chain start @@ -1752,7 +1902,11 @@ fn get_parent_trait_ref( /// If the `Self` type of the unsatisfied trait `trait_ref` implements a trait /// with the same path as `trait_ref`, a help message about /// a probable version mismatch is added to `err` - fn note_version_mismatch(&self, err: &mut Diagnostic, trait_ref: &ty::PolyTraitRef<'tcx>) { + fn note_version_mismatch( + &self, + err: &mut Diagnostic, + trait_ref: &ty::PolyTraitRef<'tcx>, + ) -> bool { let get_trait_impl = |trait_def_id| { self.tcx.find_map_relevant_impl(trait_def_id, trait_ref.skip_binder().self_ty(), Some) }; @@ -1763,6 +1917,7 @@ fn note_version_mismatch(&self, err: &mut Diagnostic, trait_ref: &ty::PolyTraitR .filter(|trait_def_id| *trait_def_id != trait_ref.def_id()) .filter(|trait_def_id| self.tcx.def_path_str(*trait_def_id) == required_trait_path) .collect(); + let mut suggested = false; for trait_with_same_path in traits_with_same_path { if let Some(impl_def_id) = get_trait_impl(trait_with_same_path) { let impl_span = self.tcx.def_span(impl_def_id); @@ -1773,8 +1928,10 @@ fn note_version_mismatch(&self, err: &mut Diagnostic, trait_ref: &ty::PolyTraitR trait_crate ); err.note(&crate_msg); + suggested = true; } } + suggested } fn mk_trait_obligation_with_new_self_ty(
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs index d2b1fe2..31b92d5 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
@@ -208,6 +208,15 @@ fn on_unimplemented_note( flags.push((sym::_Self, Some("&[]".to_owned()))); } + if self_ty.is_fn() { + let fn_sig = self_ty.fn_sig(self.tcx); + let shortname = match fn_sig.unsafety() { + hir::Unsafety::Normal => "fn", + hir::Unsafety::Unsafe => "unsafe fn", + }; + flags.push((sym::_Self, Some(shortname.to_owned()))); + } + if let ty::Array(aty, len) = self_ty.kind() { flags.push((sym::_Self, Some("[]".to_owned()))); flags.push((sym::_Self, Some(format!("[{}]", aty))));
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index b49a5f6..7c3f306 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -1,6 +1,6 @@ use super::{ - EvaluationResult, Obligation, ObligationCause, ObligationCauseCode, PredicateObligation, - SelectionContext, + DerivedObligationCause, EvaluationResult, ImplDerivedObligationCause, Obligation, + ObligationCause, ObligationCauseCode, PredicateObligation, SelectionContext, }; use crate::autoderef::Autoderef; @@ -11,7 +11,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{ error_code, pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, - ErrorGuaranteed, Style, + ErrorGuaranteed, MultiSpan, Style, }; use rustc_hir as hir; use rustc_hir::def::DefKind; @@ -27,7 +27,7 @@ use rustc_session::Limit; use rustc_span::def_id::LOCAL_CRATE; use rustc_span::symbol::{kw, sym, Ident, Symbol}; -use rustc_span::{BytePos, DesugaringKind, ExpnKind, MultiSpan, Span, DUMMY_SP}; +use rustc_span::{BytePos, DesugaringKind, ExpnKind, Span, DUMMY_SP}; use rustc_target::spec::abi; use std::fmt; @@ -58,7 +58,7 @@ fn suggest_dereferences( obligation: &PredicateObligation<'tcx>, err: &mut Diagnostic, trait_pred: ty::PolyTraitPredicate<'tcx>, - ); + ) -> bool; fn get_closure_name(&self, def_id: DefId, err: &mut Diagnostic, msg: &str) -> Option<String>; @@ -67,7 +67,7 @@ fn suggest_fn_call( obligation: &PredicateObligation<'tcx>, err: &mut Diagnostic, trait_pred: ty::PolyTraitPredicate<'tcx>, - ); + ) -> bool; fn suggest_add_reference_to_arg( &self, @@ -77,12 +77,20 @@ fn suggest_add_reference_to_arg( has_custom_message: bool, ) -> bool; + fn suggest_borrowing_for_object_cast( + &self, + err: &mut Diagnostic, + obligation: &PredicateObligation<'tcx>, + self_ty: Ty<'tcx>, + object_ty: Ty<'tcx>, + ); + fn suggest_remove_reference( &self, obligation: &PredicateObligation<'tcx>, err: &mut Diagnostic, trait_pred: ty::PolyTraitPredicate<'tcx>, - ); + ) -> bool; fn suggest_remove_await(&self, obligation: &PredicateObligation<'tcx>, err: &mut Diagnostic); @@ -99,7 +107,7 @@ fn suggest_semicolon_removal( err: &mut Diagnostic, span: Span, trait_pred: ty::PolyTraitPredicate<'tcx>, - ); + ) -> bool; fn return_type_span(&self, obligation: &PredicateObligation<'tcx>) -> Option<Span>; @@ -181,6 +189,13 @@ fn suggest_floating_point_literal( err: &mut Diagnostic, trait_ref: &ty::PolyTraitRef<'tcx>, ); + + fn suggest_derive( + &self, + obligation: &PredicateObligation<'tcx>, + err: &mut Diagnostic, + trait_pred: ty::PolyTraitPredicate<'tcx>, + ); } fn predicate_constraint(generics: &hir::Generics<'_>, pred: String) -> (Span, String) { @@ -494,54 +509,87 @@ fn suggest_dereferences( obligation: &PredicateObligation<'tcx>, err: &mut Diagnostic, trait_pred: ty::PolyTraitPredicate<'tcx>, - ) { + ) -> bool { // It only make sense when suggesting dereferences for arguments - let code = if let ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } = - obligation.cause.code() - { - parent_code.clone() - } else { - return; + let ObligationCauseCode::FunctionArgumentObligation { .. } = obligation.cause.code() else { + return false; }; let param_env = obligation.param_env; let body_id = obligation.cause.body_id; let span = obligation.cause.span; - let real_trait_pred = match &*code { - ObligationCauseCode::ImplDerivedObligation(cause) => cause.derived.parent_trait_pred, - ObligationCauseCode::DerivedObligation(cause) - | ObligationCauseCode::BuiltinDerivedObligation(cause) => cause.parent_trait_pred, - _ => trait_pred, - }; - let Some(real_ty) = real_trait_pred.self_ty().no_bound_vars() else { - return; - }; + let mut real_trait_pred = trait_pred; + let mut code = obligation.cause.code(); + loop { + match &code { + ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } => { + code = &parent_code; + } + ObligationCauseCode::ImplDerivedObligation(box ImplDerivedObligationCause { + derived: DerivedObligationCause { parent_code, parent_trait_pred }, + .. + }) + | ObligationCauseCode::BuiltinDerivedObligation(DerivedObligationCause { + parent_code, + parent_trait_pred, + }) + | ObligationCauseCode::DerivedObligation(DerivedObligationCause { + parent_code, + parent_trait_pred, + }) => { + code = &parent_code; + real_trait_pred = *parent_trait_pred; + } + _ => break, + }; + let Some(real_ty) = real_trait_pred.self_ty().no_bound_vars() else { + continue; + }; - if let ty::Ref(region, base_ty, mutbl) = *real_ty.kind() { - let mut autoderef = Autoderef::new(self, param_env, body_id, span, base_ty, span); - if let Some(steps) = autoderef.find_map(|(ty, steps)| { - // Re-add the `&` - let ty = self.tcx.mk_ref(region, TypeAndMut { ty, mutbl }); - let obligation = - self.mk_trait_obligation_with_new_self_ty(param_env, real_trait_pred, ty); - Some(steps).filter(|_| self.predicate_may_hold(&obligation)) - }) { - if steps > 0 { - if let Ok(src) = self.tcx.sess.source_map().span_to_snippet(span) { - // Don't care about `&mut` because `DerefMut` is used less - // often and user will not expect autoderef happens. - if src.starts_with('&') && !src.starts_with("&mut ") { - let derefs = "*".repeat(steps); - err.span_suggestion( - span, - "consider adding dereference here", - format!("&{}{}", derefs, &src[1..]), - Applicability::MachineApplicable, - ); + if let ty::Ref(region, base_ty, mutbl) = *real_ty.kind() { + let mut autoderef = Autoderef::new(self, param_env, body_id, span, base_ty, span); + if let Some(steps) = autoderef.find_map(|(ty, steps)| { + // Re-add the `&` + let ty = self.tcx.mk_ref(region, TypeAndMut { ty, mutbl }); + let obligation = + self.mk_trait_obligation_with_new_self_ty(param_env, real_trait_pred, ty); + Some(steps).filter(|_| self.predicate_may_hold(&obligation)) + }) { + if steps > 0 { + if let Ok(src) = self.tcx.sess.source_map().span_to_snippet(span) { + // Don't care about `&mut` because `DerefMut` is used less + // often and user will not expect autoderef happens. + if src.starts_with('&') && !src.starts_with("&mut ") { + let derefs = "*".repeat(steps); + err.span_suggestion( + span, + "consider dereferencing here", + format!("&{}{}", derefs, &src[1..]), + Applicability::MachineApplicable, + ); + return true; + } } } + } else if real_trait_pred != trait_pred { + // This branch addresses #87437. + let obligation = self.mk_trait_obligation_with_new_self_ty( + param_env, + real_trait_pred, + base_ty, + ); + if self.predicate_may_hold(&obligation) { + err.span_suggestion_verbose( + span.shrink_to_lo(), + "consider dereferencing here", + "*".to_string(), + Applicability::MachineApplicable, + ); + return true; + } } } } + false } /// Given a closure's `DefId`, return the given name of the closure. @@ -556,7 +604,7 @@ fn get_closure_name(&self, def_id: DefId, err: &mut Diagnostic, msg: &str) -> Op Some(format!("{}", name)) } _ => { - err.note(&msg); + err.note(msg); None } } @@ -584,22 +632,22 @@ fn suggest_fn_call( obligation: &PredicateObligation<'tcx>, err: &mut Diagnostic, trait_pred: ty::PolyTraitPredicate<'tcx>, - ) { + ) -> bool { let Some(self_ty) = trait_pred.self_ty().no_bound_vars() else { - return; + return false; }; let (def_id, output_ty, callable) = match *self_ty.kind() { ty::Closure(def_id, substs) => (def_id, substs.as_closure().sig().output(), "closure"), ty::FnDef(def_id, _) => (def_id, self_ty.fn_sig(self.tcx).output(), "function"), - _ => return, + _ => return false, }; let msg = format!("use parentheses to call the {}", callable); // `mk_trait_obligation_with_new_self_ty` only works for types with no escaping bound // variables, so bail out if we have any. let Some(output_ty) = output_ty.no_bound_vars() else { - return; + return false; }; let new_obligation = @@ -611,7 +659,7 @@ fn suggest_fn_call( | EvaluationResult::EvaluatedToOkModuloRegions | EvaluationResult::EvaluatedToAmbig, ) => {} - _ => return, + _ => return false, } let hir = self.tcx.hir(); // Get the name of the callable and the arguments to be used in the suggestion. @@ -622,7 +670,7 @@ fn suggest_fn_call( })) => { err.span_label(*span, "consider calling this closure"); let Some(name) = self.get_closure_name(def_id, err, &msg) else { - return; + return false; }; let args = decl.inputs.iter().map(|_| "_").collect::<Vec<_>>().join(", "); let sugg = format!("({})", args); @@ -650,7 +698,7 @@ fn suggest_fn_call( let sugg = format!("({})", args); (format!("{}{}", ident, sugg), sugg) } - _ => return, + _ => return false, }; if matches!(obligation.cause.code(), ObligationCauseCode::FunctionArgumentObligation { .. }) { @@ -667,6 +715,7 @@ fn suggest_fn_call( } else { err.help(&format!("{}: `{}`", msg, snippet)); } + true } fn suggest_add_reference_to_arg( @@ -738,7 +787,8 @@ fn suggest_add_reference_to_arg( if has_custom_message { err.note(&msg); } else { - err.message = vec![(msg, Style::NoStyle)]; + err.message = + vec![(rustc_errors::DiagnosticMessage::Str(msg), Style::NoStyle)]; } if snippet.starts_with('&') { // This is already a literal borrow and the obligation is failing @@ -801,6 +851,35 @@ fn suggest_add_reference_to_arg( } } + // Suggest borrowing the type + fn suggest_borrowing_for_object_cast( + &self, + err: &mut Diagnostic, + obligation: &PredicateObligation<'tcx>, + self_ty: Ty<'tcx>, + object_ty: Ty<'tcx>, + ) { + let ty::Dynamic(predicates, _) = object_ty.kind() else { return; }; + let self_ref_ty = self.tcx.mk_imm_ref(self.tcx.lifetimes.re_erased, self_ty); + + for predicate in predicates.iter() { + if !self.predicate_must_hold_modulo_regions( + &obligation.with(predicate.with_self_ty(self.tcx, self_ref_ty)), + ) { + return; + } + } + + err.span_suggestion( + obligation.cause.span.shrink_to_lo(), + &format!( + "consider borrowing the value, since `&{self_ty}` can be coerced into `{object_ty}`" + ), + "&".to_string(), + Applicability::MaybeIncorrect, + ); + } + /// Whenever references are used by mistake, like `for (i, e) in &vec.iter().enumerate()`, /// suggest removing these references until we reach a type that implements the trait. fn suggest_remove_reference( @@ -808,19 +887,20 @@ fn suggest_remove_reference( obligation: &PredicateObligation<'tcx>, err: &mut Diagnostic, trait_pred: ty::PolyTraitPredicate<'tcx>, - ) { + ) -> bool { let span = obligation.cause.span; + let mut suggested = false; if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { let refs_number = snippet.chars().filter(|c| !c.is_whitespace()).take_while(|c| *c == '&').count(); if let Some('\'') = snippet.chars().filter(|c| !c.is_whitespace()).nth(refs_number) { // Do not suggest removal of borrow from type arguments. - return; + return false; } let Some(mut suggested_ty) = trait_pred.self_ty().no_bound_vars() else { - return; + return false; }; for refs_remaining in 0..refs_number { @@ -856,10 +936,12 @@ fn suggest_remove_reference( String::new(), Applicability::MachineApplicable, ); + suggested = true; break; } } } + suggested } fn suggest_remove_await(&self, obligation: &PredicateObligation<'tcx>, err: &mut Diagnostic) { @@ -996,7 +1078,7 @@ fn suggest_semicolon_removal( err: &mut Diagnostic, span: Span, trait_pred: ty::PolyTraitPredicate<'tcx>, - ) { + ) -> bool { let hir = self.tcx.hir(); let parent_node = hir.get_parent_node(obligation.cause.body_id); let node = hir.find(parent_node); @@ -1015,7 +1097,9 @@ fn suggest_semicolon_removal( { let sp = self.tcx.sess.source_map().end_point(stmt.span); err.span_label(sp, "consider removing this semicolon"); + return true; } + false } fn return_type_span(&self, obligation: &PredicateObligation<'tcx>) -> Option<Span> { @@ -1045,8 +1129,8 @@ fn suggest_impl_trait( } let hir = self.tcx.hir(); - let parent_node = hir.get_parent_node(obligation.cause.body_id); - let node = hir.find(parent_node); + let fn_hir_id = hir.get_parent_node(obligation.cause.body_id); + let node = hir.find(fn_hir_id); let Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, _, body_id), .. @@ -1084,16 +1168,17 @@ fn suggest_impl_trait( visitor.visit_body(&body); let typeck_results = self.in_progress_typeck_results.map(|t| t.borrow()).unwrap(); + let Some(liberated_sig) = typeck_results.liberated_fn_sigs().get(fn_hir_id) else { return false; }; - let mut ret_types = visitor + let ret_types = visitor .returns .iter() - .filter_map(|expr| typeck_results.node_type_opt(expr.hir_id)) - .map(|ty| self.resolve_vars_if_possible(ty)); + .filter_map(|expr| Some((expr.span, typeck_results.node_type_opt(expr.hir_id)?))) + .map(|(expr_span, ty)| (expr_span, self.resolve_vars_if_possible(ty))); let (last_ty, all_returns_have_same_type, only_never_return) = ret_types.clone().fold( (None, true, true), |(last_ty, mut same, only_never_return): (std::option::Option<Ty<'_>>, bool, bool), - ty| { + (_, ty)| { let ty = self.resolve_vars_if_possible(ty); same &= !matches!(ty.kind(), ty::Error(_)) @@ -1114,39 +1199,60 @@ fn suggest_impl_trait( (Some(ty), same, only_never_return && matches!(ty.kind(), ty::Never)) }, ); - let all_returns_conform_to_trait = - if let Some(ty_ret_ty) = typeck_results.node_type_opt(ret_ty.hir_id) { - match ty_ret_ty.kind() { - ty::Dynamic(predicates, _) => { - let cause = ObligationCause::misc(ret_ty.span, ret_ty.hir_id); - let param_env = ty::ParamEnv::empty(); - only_never_return - || ret_types.all(|returned_ty| { - predicates.iter().all(|predicate| { - let pred = predicate.with_self_ty(self.tcx, returned_ty); - let obl = Obligation::new(cause.clone(), param_env, pred); - self.predicate_may_hold(&obl) - }) + let mut spans_and_needs_box = vec![]; + + match liberated_sig.output().kind() { + ty::Dynamic(predicates, _) => { + let cause = ObligationCause::misc(ret_ty.span, fn_hir_id); + let param_env = ty::ParamEnv::empty(); + + if !only_never_return { + for (expr_span, return_ty) in ret_types { + let self_ty_satisfies_dyn_predicates = |self_ty| { + predicates.iter().all(|predicate| { + let pred = predicate.with_self_ty(self.tcx, self_ty); + let obl = Obligation::new(cause.clone(), param_env, pred); + self.predicate_may_hold(&obl) }) + }; + + if let ty::Adt(def, substs) = return_ty.kind() + && def.is_box() + && self_ty_satisfies_dyn_predicates(substs.type_at(0)) + { + spans_and_needs_box.push((expr_span, false)); + } else if self_ty_satisfies_dyn_predicates(return_ty) { + spans_and_needs_box.push((expr_span, true)); + } else { + return false; + } } - _ => false, } - } else { - true - }; + } + _ => return false, + }; let sm = self.tcx.sess.source_map(); - let (true, hir::TyKind::TraitObject(..), Ok(snippet), true) = ( - // Verify that we're dealing with a return `dyn Trait` - ret_ty.span.overlaps(span), - &ret_ty.kind, - sm.span_to_snippet(ret_ty.span), - // If any of the return types does not conform to the trait, then we can't - // suggest `impl Trait` nor trait objects: it is a type mismatch error. - all_returns_conform_to_trait, - ) else { + if !ret_ty.span.overlaps(span) { return false; + } + let snippet = if let hir::TyKind::TraitObject(..) = ret_ty.kind { + if let Ok(snippet) = sm.span_to_snippet(ret_ty.span) { + snippet + } else { + return false; + } + } else { + // Substitute the type, so we can print a fixup given `type Alias = dyn Trait` + let name = liberated_sig.output().to_string(); + let name = + name.strip_prefix('(').and_then(|name| name.strip_suffix(')')).unwrap_or(&name); + if !name.starts_with("dyn ") { + return false; + } + name.to_owned() }; + err.code(error_code!(E0746)); err.set_primary_message("return type cannot have an unboxed trait object"); err.children.clear(); @@ -1156,6 +1262,7 @@ fn suggest_impl_trait( let trait_obj_msg = "for information on trait objects, see \ <https://doc.rust-lang.org/book/ch17-02-trait-objects.html\ #using-trait-objects-that-allow-for-values-of-different-types>"; + let has_dyn = snippet.split_whitespace().next().map_or(false, |s| s == "dyn"); let trait_obj = if has_dyn { &snippet[4..] } else { &snippet }; if only_never_return { @@ -1183,26 +1290,25 @@ fn suggest_impl_trait( } else { if is_object_safe { // Suggest `-> Box<dyn Trait>` and `Box::new(returned_value)`. - // Get all the return values and collect their span and suggestion. - let mut suggestions: Vec<_> = visitor - .returns - .iter() - .flat_map(|expr| { - [ - (expr.span.shrink_to_lo(), "Box::new(".to_string()), - (expr.span.shrink_to_hi(), ")".to_string()), - ] - .into_iter() - }) - .collect(); - if !suggestions.is_empty() { - // Add the suggestion for the return type. - suggestions.push((ret_ty.span, format!("Box<dyn {}>", trait_obj))); - err.multipart_suggestion( - "return a boxed trait object instead", - suggestions, - Applicability::MaybeIncorrect, - ); + err.multipart_suggestion( + "return a boxed trait object instead", + vec![ + (ret_ty.span.shrink_to_lo(), "Box<".to_string()), + (span.shrink_to_hi(), ">".to_string()), + ], + Applicability::MaybeIncorrect, + ); + for (span, needs_box) in spans_and_needs_box { + if needs_box { + err.multipart_suggestion( + "... and box this value", + vec![ + (span.shrink_to_lo(), "Box::new(".to_string()), + (span.shrink_to_hi(), ")".to_string()), + ], + Applicability::MaybeIncorrect, + ); + } } } else { // This is currently not possible to trigger because E0038 takes precedence, but @@ -2382,7 +2488,7 @@ fn note_obligation_cause_code<T>( .opt_associated_item(trait_item_def_id) .and_then(|i| self.tcx.opt_item_name(i.container.id())) { - assoc_span.push_span_label(ident.span, "in this trait".into()); + assoc_span.push_span_label(ident.span, "in this trait"); } err.span_note(assoc_span, &msg); } @@ -2407,7 +2513,7 @@ fn note_obligation_cause_code<T>( .opt_associated_item(trait_item_def_id) .and_then(|i| self.tcx.opt_item_name(i.container.id())) { - assoc_span.push_span_label(ident.span, "in this trait".into()); + assoc_span.push_span_label(ident.span, "in this trait"); } err.span_note(assoc_span, &msg); } @@ -2552,6 +2658,68 @@ fn suggest_floating_point_literal( _ => {} } } + + fn suggest_derive( + &self, + obligation: &PredicateObligation<'tcx>, + err: &mut Diagnostic, + trait_pred: ty::PolyTraitPredicate<'tcx>, + ) { + let Some(diagnostic_name) = self.tcx.get_diagnostic_name(trait_pred.def_id()) else { + return; + }; + let (adt, substs) = match trait_pred.skip_binder().self_ty().kind() { + ty::Adt(adt, substs) if adt.did().is_local() => (adt, substs), + _ => return, + }; + let can_derive = { + let is_derivable_trait = match diagnostic_name { + sym::Default => !adt.is_enum(), + sym::PartialEq | sym::PartialOrd => { + let rhs_ty = trait_pred.skip_binder().trait_ref.substs.type_at(1); + trait_pred.skip_binder().self_ty() == rhs_ty + } + sym::Eq | sym::Ord | sym::Clone | sym::Copy | sym::Hash | sym::Debug => true, + _ => false, + }; + is_derivable_trait && + // Ensure all fields impl the trait. + adt.all_fields().all(|field| { + let field_ty = field.ty(self.tcx, substs); + let trait_substs = match diagnostic_name { + sym::PartialEq | sym::PartialOrd => { + self.tcx.mk_substs_trait(field_ty, &[field_ty.into()]) + } + _ => self.tcx.mk_substs_trait(field_ty, &[]), + }; + let trait_pred = trait_pred.map_bound_ref(|tr| ty::TraitPredicate { + trait_ref: ty::TraitRef { + substs: trait_substs, + ..trait_pred.skip_binder().trait_ref + }, + ..*tr + }); + let field_obl = Obligation::new( + obligation.cause.clone(), + obligation.param_env, + trait_pred.to_predicate(self.tcx), + ); + self.predicate_must_hold_modulo_regions(&field_obl) + }) + }; + if can_derive { + err.span_suggestion_verbose( + self.tcx.def_span(adt.did()).shrink_to_lo(), + &format!( + "consider annotating `{}` with `#[derive({})]`", + trait_pred.skip_binder().self_ty(), + diagnostic_name.to_string(), + ), + format!("#[derive({})]\n", diagnostic_name.to_string()), + Applicability::MaybeIncorrect, + ); + } + } } /// Collect all the returned expressions within the input expression. @@ -2677,13 +2845,15 @@ fn suggest_trait_object_return_type_alternatives( Applicability::MaybeIncorrect, ); if is_object_safe { - err.span_suggestion( - ret_ty, + err.multipart_suggestion( &format!( "use a boxed trait object if all return paths implement trait `{}`", trait_obj, ), - format!("Box<dyn {}>", trait_obj), + vec![ + (ret_ty.shrink_to_lo(), "Box<".to_string()), + (ret_ty.shrink_to_hi(), ">".to_string()), + ], Applicability::MaybeIncorrect, ); }
diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index 54f7c68..8495813 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs
@@ -14,7 +14,7 @@ use crate::traits::const_evaluatable::{self, AbstractConst}; use crate::traits::query::evaluate_obligation::InferCtxtExt; use crate::traits::{self, Obligation, ObligationCause}; -use rustc_errors::FatalError; +use rustc_errors::{FatalError, MultiSpan}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_middle::ty::subst::{GenericArg, InternalSubsts, Subst}; @@ -22,7 +22,7 @@ use rustc_middle::ty::{Predicate, ToPredicate}; use rustc_session::lint::builtin::WHERE_CLAUSES_OBJECT_SAFETY; use rustc_span::symbol::Symbol; -use rustc_span::{MultiSpan, Span}; +use rustc_span::Span; use smallvec::SmallVec; use std::iter; @@ -169,10 +169,7 @@ fn lint_object_unsafe_trait( let node = tcx.hir().get_if_local(trait_def_id); let mut spans = MultiSpan::from_span(span); if let Some(hir::Node::Item(item)) = node { - spans.push_span_label( - item.ident.span, - "this trait cannot be made into an object...".into(), - ); + spans.push_span_label(item.ident.span, "this trait cannot be made into an object..."); spans.push_span_label(span, format!("...because {}", violation.error_msg())); } else { spans.push_span_label(
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index cf47281..06f5824 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -307,17 +307,6 @@ pub(super) fn assemble_candidates<'o>( self.assemble_builtin_bound_candidates(sized_conditions, &mut candidates); } else if lang_items.unsize_trait() == Some(def_id) { self.assemble_candidates_for_unsizing(obligation, &mut candidates); - } else if lang_items.drop_trait() == Some(def_id) - && obligation.predicate.is_const_if_const() - { - // holds to make it easier to transition - // FIXME(fee1-dead): add a note for selection error of `~const Drop` - // when beta is bumped - // FIXME: remove this when beta is bumped - #[cfg(bootstrap)] - {} - - candidates.vec.push(SelectionCandidate::ConstDestructCandidate(None)) } else if lang_items.destruct_trait() == Some(def_id) { self.assemble_const_destruct_candidates(obligation, &mut candidates); } else {
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 18a3775..b97ab39 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -1106,13 +1106,6 @@ fn confirm_const_destruct_candidate( } let drop_trait = self.tcx().require_lang_item(LangItem::Drop, None); - // FIXME: remove if statement below when beta is bumped - #[cfg(bootstrap)] - {} - - if obligation.predicate.skip_binder().def_id() == drop_trait { - return Ok(ImplSourceConstDestructData { nested: vec![] }); - } let tcx = self.tcx(); let self_ty = self.infcx.shallow_resolve(obligation.self_ty());
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 5d316c6..e69bf6e 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -1025,11 +1025,11 @@ fn check_evaluation_cache( let tcx = self.tcx(); if self.can_use_global_caches(param_env) { - if let Some(res) = tcx.evaluation_cache.get(¶m_env.and(trait_pred), tcx) { + if let Some(res) = tcx.evaluation_cache.get(&(param_env, trait_pred), tcx) { return Some(res); } } - self.infcx.evaluation_cache.get(¶m_env.and(trait_pred), tcx) + self.infcx.evaluation_cache.get(&(param_env, trait_pred), tcx) } fn insert_evaluation_cache( @@ -1060,13 +1060,13 @@ fn insert_evaluation_cache( // FIXME: Due to #50507 this overwrites the different values // This should be changed to use HashMapExt::insert_same // when that is fixed - self.tcx().evaluation_cache.insert(param_env.and(trait_pred), dep_node, result); + self.tcx().evaluation_cache.insert((param_env, trait_pred), dep_node, result); return; } } debug!(?trait_pred, ?result, "insert_evaluation_cache"); - self.infcx.evaluation_cache.insert(param_env.and(trait_pred), dep_node, result); + self.infcx.evaluation_cache.insert((param_env, trait_pred), dep_node, result); } /// For various reasons, it's possible for a subobligation @@ -1275,11 +1275,11 @@ fn check_candidate_cache( pred.remap_constness(tcx, &mut param_env); if self.can_use_global_caches(param_env) { - if let Some(res) = tcx.selection_cache.get(¶m_env.and(pred), tcx) { + if let Some(res) = tcx.selection_cache.get(&(param_env, pred), tcx) { return Some(res); } } - self.infcx.selection_cache.get(¶m_env.and(pred), tcx) + self.infcx.selection_cache.get(&(param_env, pred), tcx) } /// Determines whether can we safely cache the result @@ -1340,14 +1340,14 @@ fn insert_candidate_cache( if !candidate.needs_infer() { debug!(?pred, ?candidate, "insert_candidate_cache global"); // This may overwrite the cache with the same value. - tcx.selection_cache.insert(param_env.and(pred), dep_node, candidate); + tcx.selection_cache.insert((param_env, pred), dep_node, candidate); return; } } } debug!(?pred, ?candidate, "insert_candidate_cache local"); - self.infcx.selection_cache.insert(param_env.and(pred), dep_node, candidate); + self.infcx.selection_cache.insert((param_env, pred), dep_node, candidate); } /// Matches a predicate against the bounds of its self type.
diff --git a/compiler/rustc_typeck/src/astconv/generics.rs b/compiler/rustc_typeck/src/astconv/generics.rs index a07700a..a50301d 100644 --- a/compiler/rustc_typeck/src/astconv/generics.rs +++ b/compiler/rustc_typeck/src/astconv/generics.rs
@@ -6,7 +6,7 @@ use crate::errors::AssocTypeBindingNotAllowed; use crate::structured_errors::{GenericArgsInfo, StructuredDiagnostic, WrongNumberOfGenericArgs}; use rustc_ast::ast::ParamKindOrd; -use rustc_errors::{struct_span_err, Applicability, Diagnostic}; +use rustc_errors::{struct_span_err, Applicability, Diagnostic, MultiSpan}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; @@ -16,7 +16,7 @@ self, subst, subst::SubstsRef, GenericParamDef, GenericParamDefKind, Ty, TyCtxt, }; use rustc_session::lint::builtin::LATE_BOUND_LIFETIME_ARGUMENTS; -use rustc_span::{symbol::kw, MultiSpan, Span}; +use rustc_span::{symbol::kw, Span}; use smallvec::SmallVec; impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
diff --git a/compiler/rustc_typeck/src/check/_match.rs b/compiler/rustc_typeck/src/check/_match.rs index 79be8bd..26f7c26 100644 --- a/compiler/rustc_typeck/src/check/_match.rs +++ b/compiler/rustc_typeck/src/check/_match.rs
@@ -1,11 +1,11 @@ use crate::check::coercion::{AsCoercionSite, CoerceMany}; use crate::check::{Diverges, Expectation, FnCtxt, Needs}; -use rustc_errors::{Applicability, Diagnostic}; +use rustc_errors::{Applicability, Diagnostic, MultiSpan}; use rustc_hir::{self as hir, ExprKind}; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::traits::Obligation; use rustc_middle::ty::{self, ToPredicate, Ty, TypeFoldable}; -use rustc_span::{MultiSpan, Span}; +use rustc_span::Span; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; use rustc_trait_selection::traits::{ IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode,
diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index 7cb478d..9ebafc2 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs
@@ -4,7 +4,7 @@ use super::*; use rustc_attr as attr; -use rustc_errors::{Applicability, ErrorGuaranteed}; +use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::Visitor; @@ -20,7 +20,7 @@ use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt}; use rustc_session::lint::builtin::{UNINHABITED_STATIC, UNSUPPORTED_CALLING_CONVENTIONS}; use rustc_span::symbol::sym; -use rustc_span::{self, MultiSpan, Span}; +use rustc_span::{self, Span}; use rustc_target::spec::abi::Abi; use rustc_trait_selection::traits; use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs index 00bc164..83e535b 100644 --- a/compiler/rustc_typeck/src/check/demand.rs +++ b/compiler/rustc_typeck/src/check/demand.rs
@@ -40,6 +40,7 @@ pub fn emit_coerce_suggestions( self.suggest_boxing_when_appropriate(err, expr, expected, expr_ty); self.suggest_missing_parentheses(err, expr); self.suggest_block_to_brackets_peeling_refs(err, expr, expr_ty, expected); + self.note_type_is_not_clone(err, expected, expr_ty, expr); self.note_need_for_fn_pointer(err, expected, expr_ty); self.note_internal_mutation_in_method(err, expr, expected, expr_ty); self.report_closure_inferred_return_type(err, expected); @@ -630,7 +631,6 @@ pub fn check_ref( Applicability::MachineApplicable, true, )); - } } _ => {}
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index bb3bfbb..d403d6e 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
@@ -8,7 +8,7 @@ use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxHashSet; -use rustc_errors::{Applicability, Diagnostic, ErrorGuaranteed}; +use rustc_errors::{Applicability, Diagnostic, ErrorGuaranteed, MultiSpan}; use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::DefId; @@ -30,7 +30,7 @@ use rustc_span::hygiene::DesugaringKind; use rustc_span::source_map::{original_sp, DUMMY_SP}; use rustc_span::symbol::{kw, sym, Ident}; -use rustc_span::{self, BytePos, MultiSpan, Span}; +use rustc_span::{self, BytePos, Span}; use rustc_trait_selection::infer::InferCtxtExt as _; use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _; use rustc_trait_selection::traits::{
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs index 2a1b7a5..1cc1460 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
@@ -11,7 +11,7 @@ use rustc_ast as ast; use rustc_data_structures::sync::Lrc; -use rustc_errors::{Applicability, Diagnostic, DiagnosticId}; +use rustc_errors::{Applicability, Diagnostic, DiagnosticId, MultiSpan}; use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::DefId; @@ -21,7 +21,7 @@ use rustc_middle::ty::{self, Ty}; use rustc_session::Session; use rustc_span::symbol::Ident; -use rustc_span::{self, MultiSpan, Span}; +use rustc_span::{self, Span}; use rustc_trait_selection::traits::{self, ObligationCauseCode, StatementAsExpression}; use crate::structured_errors::StructuredDiagnostic;
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs index 68d555b..93a0900 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
@@ -2,9 +2,7 @@ use crate::astconv::AstConv; use rustc_ast::util::parser::ExprPrecedence; -use rustc_span::{self, MultiSpan, Span}; - -use rustc_errors::{Applicability, Diagnostic}; +use rustc_errors::{Applicability, Diagnostic, MultiSpan}; use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind}; use rustc_hir::lang_items::LangItem; @@ -13,12 +11,14 @@ WherePredicate, }; use rustc_infer::infer::{self, TyCtxtInferExt}; - +use rustc_infer::traits; use rustc_middle::lint::in_external_macro; -use rustc_middle::ty::{self, Binder, Ty}; -use rustc_span::symbol::{kw, sym}; - use rustc_middle::ty::subst::GenericArgKind; +use rustc_middle::ty::{self, Binder, ToPredicate, Ty}; +use rustc_span::symbol::{kw, sym}; +use rustc_span::Span; +use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; + use std::iter; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { @@ -846,4 +846,53 @@ fn is_local_statement(&self, id: hir::HirId) -> bool { let node = self.tcx.hir().get(id); matches!(node, Node::Stmt(Stmt { kind: StmtKind::Local(..), .. })) } + + /// Suggest that `&T` was cloned instead of `T` because `T` does not implement `Clone`, + /// which is a side-effect of autoref. + pub(crate) fn note_type_is_not_clone( + &self, + diag: &mut Diagnostic, + expected_ty: Ty<'tcx>, + found_ty: Ty<'tcx>, + expr: &hir::Expr<'_>, + ) { + let hir::ExprKind::MethodCall(segment, &[ref callee_expr], _) = expr.kind else { return; }; + let Some(clone_trait_did) = self.tcx.lang_items().clone_trait() else { return; }; + let ty::Ref(_, pointee_ty, _) = found_ty.kind() else { return }; + let results = self.typeck_results.borrow(); + // First, look for a `Clone::clone` call + if segment.ident.name == sym::clone + && results.type_dependent_def_id(expr.hir_id).map_or( + false, + |did| { + self.tcx.associated_item(did).container + == ty::AssocItemContainer::TraitContainer(clone_trait_did) + }, + ) + // If that clone call hasn't already dereferenced the self type (i.e. don't give this + // diagnostic in cases where we have `(&&T).clone()` and we expect `T`). + && !results.expr_adjustments(callee_expr).iter().any(|adj| matches!(adj.kind, ty::adjustment::Adjust::Deref(..))) + // Check that we're in fact trying to clone into the expected type + && self.can_coerce(*pointee_ty, expected_ty) + // And the expected type doesn't implement `Clone` + && !self.predicate_must_hold_considering_regions(&traits::Obligation { + cause: traits::ObligationCause::dummy(), + param_env: self.param_env, + recursion_depth: 0, + predicate: ty::Binder::dummy(ty::TraitRef { + def_id: clone_trait_did, + substs: self.tcx.mk_substs([expected_ty.into()].iter()), + }) + .without_const() + .to_predicate(self.tcx), + }) + { + diag.span_note( + callee_expr.span, + &format!( + "`{expected_ty}` does not implement `Clone`, so `{found_ty}` was cloned instead" + ), + ); + } + } }
diff --git a/compiler/rustc_typeck/src/check/intrinsic.rs b/compiler/rustc_typeck/src/check/intrinsic.rs index 74f6f50..cd6b111 100644 --- a/compiler/rustc_typeck/src/check/intrinsic.rs +++ b/compiler/rustc_typeck/src/check/intrinsic.rs
@@ -7,7 +7,7 @@ }; use crate::require_same_types; -use rustc_errors::{pluralize, struct_span_err}; +use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_middle::traits::{ObligationCause, ObligationCauseCode}; use rustc_middle::ty::subst::Subst; @@ -43,7 +43,6 @@ fn equate_intrinsic_type<'tcx>( span, found, expected, - expected_pluralize: pluralize!(expected), descr, }); false
diff --git a/compiler/rustc_typeck/src/check/method/mod.rs b/compiler/rustc_typeck/src/check/method/mod.rs index adc2847..8137d70 100644 --- a/compiler/rustc_typeck/src/check/method/mod.rs +++ b/compiler/rustc_typeck/src/check/method/mod.rs
@@ -8,7 +8,6 @@ mod suggest; pub use self::suggest::SelfSource; -pub use self::CandidateSource::*; pub use self::MethodError::*; use crate::check::FnCtxt; @@ -82,8 +81,8 @@ pub struct NoMatchData<'tcx> { // candidate can arise. Used for error reporting only. #[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] pub enum CandidateSource { - ImplSource(DefId), - TraitSource(DefId /* trait id */), + Impl(DefId), + Trait(DefId /* trait id */), } impl<'a, 'tcx> FnCtxt<'a, 'tcx> { @@ -237,8 +236,8 @@ pub fn lookup_method( match *source { // Note: this cannot come from an inherent impl, // because the first probing succeeded. - ImplSource(def) => self.tcx.trait_id_of_impl(def), - TraitSource(_) => None, + CandidateSource::Impl(def) => self.tcx.trait_id_of_impl(def), + CandidateSource::Trait(_) => None, } }) .collect(),
diff --git a/compiler/rustc_typeck/src/check/method/probe.rs b/compiler/rustc_typeck/src/check/method/probe.rs index 6edcc12..83474bd 100644 --- a/compiler/rustc_typeck/src/check/method/probe.rs +++ b/compiler/rustc_typeck/src/check/method/probe.rs
@@ -1,7 +1,7 @@ use super::suggest; +use super::CandidateSource; use super::MethodError; use super::NoMatchData; -use super::{CandidateSource, ImplSource, TraitSource}; use crate::check::FnCtxt; use crate::errors::MethodCallOnUnknownType; @@ -24,7 +24,9 @@ use rustc_middle::ty::{self, ParamEnvAnd, ToPredicate, Ty, TyCtxt, TypeFoldable}; use rustc_session::lint; use rustc_span::def_id::LocalDefId; -use rustc_span::lev_distance::{find_best_match_for_name, lev_distance}; +use rustc_span::lev_distance::{ + find_best_match_for_name_with_substrings, lev_distance_with_substrings, +}; use rustc_span::{symbol::Ident, Span, Symbol, DUMMY_SP}; use rustc_trait_selection::autoderef::{self, Autoderef}; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; @@ -692,7 +694,7 @@ fn assemble_inherent_impl_probe(&mut self, impl_def_id: DefId) { for item in self.impl_or_trait_item(impl_def_id) { if !self.has_applicable_self(&item) { // No receiver declared. Not a candidate. - self.record_static_candidate(ImplSource(impl_def_id)); + self.record_static_candidate(CandidateSource::Impl(impl_def_id)); continue; } @@ -846,7 +848,7 @@ fn elaborate_bounds<F>( debug!("elaborate_bounds(bound_trait_ref={:?})", bound_trait_ref); for item in self.impl_or_trait_item(bound_trait_ref.def_id()) { if !self.has_applicable_self(&item) { - self.record_static_candidate(TraitSource(bound_trait_ref.def_id())); + self.record_static_candidate(CandidateSource::Trait(bound_trait_ref.def_id())); } else { mk_cand(self, bound_trait_ref, item); } @@ -944,7 +946,7 @@ fn assemble_extension_candidates_for_trait( // Check whether `trait_def_id` defines a method with suitable name. if !self.has_applicable_self(&item) { debug!("method has inapplicable self"); - self.record_static_candidate(TraitSource(trait_def_id)); + self.record_static_candidate(CandidateSource::Trait(trait_def_id)); continue; } @@ -1016,8 +1018,8 @@ fn pick(mut self) -> PickResult<'tcx> { Some(Err(MethodError::Ambiguity(v))) => v .into_iter() .map(|source| match source { - TraitSource(id) => id, - ImplSource(impl_id) => match tcx.trait_id_of_impl(impl_id) { + CandidateSource::Trait(id) => id, + CandidateSource::Impl(impl_id) => match tcx.trait_id_of_impl(impl_id) { Some(id) => id, None => span_bug!(span, "found inherent method when looking at traits"), }, @@ -1415,8 +1417,10 @@ fn select_trait_candidate( fn candidate_source(&self, candidate: &Candidate<'tcx>, self_ty: Ty<'tcx>) -> CandidateSource { match candidate.kind { - InherentImplCandidate(..) => ImplSource(candidate.item.container.id()), - ObjectCandidate | WhereClauseCandidate(_) => TraitSource(candidate.item.container.id()), + InherentImplCandidate(..) => CandidateSource::Impl(candidate.item.container.id()), + ObjectCandidate | WhereClauseCandidate(_) => { + CandidateSource::Trait(candidate.item.container.id()) + } TraitCandidate(trait_ref) => self.probe(|_| { let _ = self .at(&ObligationCause::dummy(), self.param_env) @@ -1426,9 +1430,9 @@ fn candidate_source(&self, candidate: &Candidate<'tcx>, self_ty: Ty<'tcx>) -> Ca Ok(Some(traits::ImplSource::UserDefined(ref impl_data))) => { // If only a single impl matches, make the error message point // to that impl. - ImplSource(impl_data.impl_def_id) + CandidateSource::Impl(impl_data.impl_def_id) } - _ => TraitSource(candidate.item.container.id()), + _ => CandidateSource::Trait(candidate.item.container.id()), } }), } @@ -1699,7 +1703,11 @@ fn probe_for_lev_candidate(&mut self) -> Result<Option<ty::AssocItem>, MethodErr .iter() .map(|cand| cand.name) .collect::<Vec<Symbol>>(); - find_best_match_for_name(&names, self.method_name.unwrap().name, None) + find_best_match_for_name_with_substrings( + &names, + self.method_name.unwrap().name, + None, + ) } .unwrap(); Ok(applicable_close_candidates.into_iter().find(|method| method.name == best_name)) @@ -1856,7 +1864,8 @@ fn erase_late_bound_regions<T>(&self, value: ty::Binder<'tcx, T>) -> T if x.kind.namespace() != Namespace::ValueNS { return false; } - match lev_distance(name.as_str(), x.name.as_str(), max_dist) { + match lev_distance_with_substrings(name.as_str(), x.name.as_str(), max_dist) + { Some(d) => d > 0, None => false, }
diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index b05f0e4..ecc2996 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs
@@ -5,6 +5,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{ pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, + MultiSpan, }; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -17,7 +18,7 @@ use rustc_middle::ty::ToPolyTraitRef; use rustc_middle::ty::{self, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable}; use rustc_span::symbol::{kw, sym, Ident}; -use rustc_span::{lev_distance, source_map, ExpnKind, FileName, MacroKind, MultiSpan, Span}; +use rustc_span::{lev_distance, source_map, ExpnKind, FileName, MacroKind, Span}; use rustc_trait_selection::traits::error_reporting::on_unimplemented::InferCtxtExt as _; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _; use rustc_trait_selection::traits::{ @@ -110,7 +111,7 @@ pub fn report_method_error( for (idx, source) in sources.iter().take(limit).enumerate() { match *source { - CandidateSource::ImplSource(impl_did) => { + CandidateSource::Impl(impl_did) => { // Provide the best span we can. Use the item, if local to crate, else // the impl, if local to crate (item may be defaulted), else nothing. let Some(item) = self.associated_value(impl_did, item_name).or_else(|| { @@ -193,7 +194,7 @@ pub fn report_method_error( ); } } - CandidateSource::TraitSource(trait_did) => { + CandidateSource::Trait(trait_did) => { let Some(item) = self.associated_value(trait_did, item_name) else { continue }; let item_span = self .tcx @@ -515,23 +516,22 @@ fn report_function<T: std::fmt::Display>(err: &mut Diagnostic, name: T) { custom_span_label = true; } if static_sources.len() == 1 { - let ty_str = if let Some(CandidateSource::ImplSource(impl_did)) = - static_sources.get(0) - { - // When the "method" is resolved through dereferencing, we really want the - // original type that has the associated function for accurate suggestions. - // (#61411) - let ty = tcx.at(span).type_of(*impl_did); - match (&ty.peel_refs().kind(), &actual.peel_refs().kind()) { - (ty::Adt(def, _), ty::Adt(def_actual, _)) if def == def_actual => { - // Use `actual` as it will have more `substs` filled in. - self.ty_to_value_string(actual.peel_refs()) + let ty_str = + if let Some(CandidateSource::Impl(impl_did)) = static_sources.get(0) { + // When the "method" is resolved through dereferencing, we really want the + // original type that has the associated function for accurate suggestions. + // (#61411) + let ty = tcx.at(span).type_of(*impl_did); + match (&ty.peel_refs().kind(), &actual.peel_refs().kind()) { + (ty::Adt(def, _), ty::Adt(def_actual, _)) if def == def_actual => { + // Use `actual` as it will have more `substs` filled in. + self.ty_to_value_string(actual.peel_refs()) + } + _ => self.ty_to_value_string(ty.peel_refs()), } - _ => self.ty_to_value_string(ty.peel_refs()), - } - } else { - self.ty_to_value_string(actual.peel_refs()) - }; + } else { + self.ty_to_value_string(actual.peel_refs()) + }; if let SelfSource::MethodCall(expr) = source { err.span_suggestion( expr.span.to(span),
diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs index bf0bf2e..19d52f4 100644 --- a/compiler/rustc_typeck/src/check/mod.rs +++ b/compiler/rustc_typeck/src/check/mod.rs
@@ -103,7 +103,7 @@ use crate::astconv::AstConv; use crate::check::gather_locals::GatherLocalsVisitor; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_errors::{pluralize, struct_span_err, Applicability}; +use rustc_errors::{pluralize, struct_span_err, Applicability, MultiSpan}; use rustc_hir as hir; use rustc_hir::def::Res; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -121,7 +121,7 @@ use rustc_session::Session; use rustc_span::source_map::DUMMY_SP; use rustc_span::symbol::{kw, Ident}; -use rustc_span::{self, BytePos, MultiSpan, Span}; +use rustc_span::{self, BytePos, Span}; use rustc_target::abi::VariantIdx; use rustc_target::spec::abi::Abi; use rustc_trait_selection::traits;
diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index 464a2cd..0baca90 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs
@@ -4,6 +4,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_errors::{ pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, + MultiSpan, }; use rustc_hir as hir; use rustc_hir::def::{CtorKind, DefKind, Res}; @@ -18,7 +19,7 @@ use rustc_span::lev_distance::find_best_match_for_name; use rustc_span::source_map::{Span, Spanned}; use rustc_span::symbol::{kw, sym, Ident}; -use rustc_span::{BytePos, MultiSpan, DUMMY_SP}; +use rustc_span::{BytePos, DUMMY_SP}; use rustc_trait_selection::autoderef::Autoderef; use rustc_trait_selection::traits::{ObligationCause, Pattern}; use ty::VariantDef;
diff --git a/compiler/rustc_typeck/src/check/upvar.rs b/compiler/rustc_typeck/src/check/upvar.rs index 0b343a5f..1118e96 100644 --- a/compiler/rustc_typeck/src/check/upvar.rs +++ b/compiler/rustc_typeck/src/check/upvar.rs
@@ -33,7 +33,7 @@ use super::FnCtxt; use crate::expr_use_visitor as euv; -use rustc_errors::Applicability; +use rustc_errors::{Applicability, MultiSpan}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::def_id::LocalDefId; @@ -46,7 +46,7 @@ }; use rustc_session::lint; use rustc_span::sym; -use rustc_span::{BytePos, MultiSpan, Pos, Span, Symbol}; +use rustc_span::{BytePos, Pos, Span, Symbol}; use rustc_trait_selection::infer::InferCtxtExt; use rustc_data_structures::stable_map::FxHashMap;
diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index 9b1767c..b2be70e 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs
@@ -1657,7 +1657,7 @@ fn receiver_is_valid<'fcx, 'tcx>( } } else { debug!("receiver_is_valid: type `{:?}` does not deref to `{:?}`", receiver_ty, self_ty); - // If he receiver already has errors reported due to it, consider it valid to avoid + // If the receiver already has errors reported due to it, consider it valid to avoid // unnecessary errors (#58712). return receiver_ty.references_error(); }
diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 90b880a..ec783a1 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs
@@ -2700,7 +2700,7 @@ fn linkage_by_name(tcx: TyCtxt<'_>, def_id: DefId, name: &str) -> Linkage { // Use the names from src/llvm/docs/LangRef.rst here. Most types are only // applicable to variable declarations and may not really make sense for // Rust code in the first place but allow them anyway and trust that the - // user knows what s/he's doing. Who knows, unanticipated use cases may pop + // user knows what they're doing. Who knows, unanticipated use cases may pop // up in the future. // // ghost, dllimport, dllexport and linkonce_odr_autohide are not supported
diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index cb32e88..785538a 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs
@@ -356,7 +356,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { let concrete_ty = tcx .mir_borrowck(owner) .concrete_opaque_types - .get_value_matching(|(key, _)| key.def_id == def_id.to_def_id()) + .get(&def_id.to_def_id()) .copied() .map(|concrete| concrete.ty) .unwrap_or_else(|| { @@ -591,31 +591,17 @@ fn check(&mut self, def_id: LocalDefId) { // Use borrowck to get the type with unerased regions. let concrete_opaque_types = &self.tcx.mir_borrowck(def_id).concrete_opaque_types; debug!(?concrete_opaque_types); - for &(opaque_type_key, concrete_type) in concrete_opaque_types { - if opaque_type_key.def_id != self.def_id { + for &(def_id, concrete_type) in concrete_opaque_types { + if def_id != self.def_id { // Ignore constraints for other opaque types. continue; } - debug!(?concrete_type, ?opaque_type_key.substs, "found constraint"); + debug!(?concrete_type, "found constraint"); if let Some(prev) = self.found { if concrete_type.ty != prev.ty && !(concrete_type, prev).references_error() { - // Found different concrete types for the opaque type. - let mut err = self.tcx.sess.struct_span_err( - concrete_type.span, - "concrete type differs from previous defining opaque type use", - ); - err.span_label( - concrete_type.span, - format!("expected `{}`, got `{}`", prev.ty, concrete_type.ty), - ); - if prev.span == concrete_type.span { - err.span_label(prev.span, "this expression supplies two conflicting concrete types for the same opaque type"); - } else { - err.span_note(prev.span, "previous use here"); - } - err.emit(); + prev.report_mismatch(&concrete_type, self.tcx); } } else { self.found = Some(concrete_type);
diff --git a/compiler/rustc_typeck/src/errors.rs b/compiler/rustc_typeck/src/errors.rs index 4707777..0b78aea 100644 --- a/compiler/rustc_typeck/src/errors.rs +++ b/compiler/rustc_typeck/src/errors.rs
@@ -3,188 +3,185 @@ use rustc_span::{symbol::Ident, Span, Symbol}; #[derive(SessionDiagnostic)] -#[error = "E0062"] +#[error(code = "E0062", slug = "typeck-field-multiply-specified-in-initializer")] pub struct FieldMultiplySpecifiedInInitializer { - #[message = "field `{ident}` specified more than once"] - #[label = "used more than once"] + #[primary_span] + #[label] pub span: Span, - #[label = "first use of `{ident}`"] + #[label = "previous-use-label"] pub prev_span: Span, pub ident: Ident, } #[derive(SessionDiagnostic)] -#[error = "E0092"] +#[error(code = "E0092", slug = "typeck-unrecognized-atomic-operation")] pub struct UnrecognizedAtomicOperation<'a> { - #[message = "unrecognized atomic operation function: `{op}`"] - #[label = "unrecognized atomic operation"] + #[primary_span] + #[label] pub span: Span, pub op: &'a str, } #[derive(SessionDiagnostic)] -#[error = "E0094"] +#[error(code = "E0094", slug = "typeck-wrong-number-of-generic-arguments-to-intrinsic")] pub struct WrongNumberOfGenericArgumentsToIntrinsic<'a> { - #[message = "intrinsic has wrong number of {descr} \ - parameters: found {found}, expected {expected}"] - #[label = "expected {expected} {descr} parameter{expected_pluralize}"] + #[primary_span] + #[label] pub span: Span, pub found: usize, pub expected: usize, - pub expected_pluralize: &'a str, pub descr: &'a str, } #[derive(SessionDiagnostic)] -#[error = "E0093"] +#[error(code = "E0093", slug = "typeck-unrecognized-intrinsic-function")] pub struct UnrecognizedIntrinsicFunction { - #[message = "unrecognized intrinsic function: `{name}`"] - #[label = "unrecognized intrinsic"] + #[primary_span] + #[label] pub span: Span, pub name: Symbol, } #[derive(SessionDiagnostic)] -#[error = "E0195"] +#[error(code = "E0195", slug = "typeck-lifetimes-or-bounds-mismatch-on-trait")] pub struct LifetimesOrBoundsMismatchOnTrait { - #[message = "lifetime parameters or bounds on {item_kind} `{ident}` do not match the trait declaration"] - #[label = "lifetimes do not match {item_kind} in trait"] + #[primary_span] + #[label] pub span: Span, - #[label = "lifetimes in impl do not match this {item_kind} in trait"] + #[label = "generics-label"] pub generics_span: Option<Span>, pub item_kind: &'static str, pub ident: Ident, } #[derive(SessionDiagnostic)] -#[error = "E0120"] +#[error(code = "E0120", slug = "typeck-drop-impl-on-wrong-item")] pub struct DropImplOnWrongItem { - #[message = "the `Drop` trait may only be implemented for structs, enums, and unions"] - #[label = "must be a struct, enum, or union"] + #[primary_span] + #[label] pub span: Span, } #[derive(SessionDiagnostic)] -#[error = "E0124"] +#[error(code = "E0124", slug = "typeck-field-already-declared")] pub struct FieldAlreadyDeclared { pub field_name: Ident, - #[message = "field `{field_name}` is already declared"] - #[label = "field already declared"] + #[primary_span] + #[label] pub span: Span, - #[label = "`{field_name}` first declared here"] + #[label = "previous-decl-label"] pub prev_span: Span, } #[derive(SessionDiagnostic)] -#[error = "E0184"] +#[error(code = "E0184", slug = "typeck-copy-impl-on-type-with-dtor")] pub struct CopyImplOnTypeWithDtor { - #[message = "the trait `Copy` may not be implemented for this type; the \ - type has a destructor"] - #[label = "Copy not allowed on types with destructors"] + #[primary_span] + #[label] pub span: Span, } #[derive(SessionDiagnostic)] -#[error = "E0203"] +#[error(code = "E0203", slug = "typeck-multiple-relaxed-default-bounds")] pub struct MultipleRelaxedDefaultBounds { - #[message = "type parameter has more than one relaxed default bound, only one is supported"] + #[primary_span] pub span: Span, } #[derive(SessionDiagnostic)] -#[error = "E0206"] +#[error(code = "E0206", slug = "typeck-copy-impl-on-non-adt")] pub struct CopyImplOnNonAdt { - #[message = "the trait `Copy` may not be implemented for this type"] - #[label = "type is not a structure or enumeration"] + #[primary_span] + #[label] pub span: Span, } #[derive(SessionDiagnostic)] -#[error = "E0224"] +#[error(code = "E0224", slug = "typeck-trait-object-declared-with-no-traits")] pub struct TraitObjectDeclaredWithNoTraits { - #[message = "at least one trait is required for an object type"] + #[primary_span] pub span: Span, } #[derive(SessionDiagnostic)] -#[error = "E0227"] +#[error(code = "E0227", slug = "typeck-ambiguous-lifetime-bound")] pub struct AmbiguousLifetimeBound { - #[message = "ambiguous lifetime bound, explicit lifetime bound required"] + #[primary_span] pub span: Span, } #[derive(SessionDiagnostic)] -#[error = "E0229"] +#[error(code = "E0229", slug = "typeck-assoc-type-binding-not-allowed")] pub struct AssocTypeBindingNotAllowed { - #[message = "associated type bindings are not allowed here"] - #[label = "associated type not allowed here"] + #[primary_span] + #[label] pub span: Span, } #[derive(SessionDiagnostic)] -#[error = "E0436"] +#[error(code = "E0436", slug = "typeck-functional-record-update-on-non-struct")] pub struct FunctionalRecordUpdateOnNonStruct { - #[message = "functional record update syntax requires a struct"] + #[primary_span] pub span: Span, } #[derive(SessionDiagnostic)] -#[error = "E0516"] +#[error(code = "E0516", slug = "typeck-typeof-reserved-keyword-used")] pub struct TypeofReservedKeywordUsed { - #[message = "`typeof` is a reserved keyword but unimplemented"] - #[label = "reserved keyword"] + #[primary_span] + #[label] pub span: Span, } #[derive(SessionDiagnostic)] -#[error = "E0572"] +#[error(code = "E0572", slug = "typeck-return-stmt-outside-of-fn-body")] pub struct ReturnStmtOutsideOfFnBody { - #[message = "return statement outside of function body"] + #[primary_span] pub span: Span, - #[label = "the return is part of this body..."] + #[label = "encl-body-label"] pub encl_body_span: Option<Span>, - #[label = "...not the enclosing function body"] + #[label = "encl-fn-label"] pub encl_fn_span: Option<Span>, } #[derive(SessionDiagnostic)] -#[error = "E0627"] +#[error(code = "E0627", slug = "typeck-yield-expr-outside-of-generator")] pub struct YieldExprOutsideOfGenerator { - #[message = "yield expression outside of generator literal"] + #[primary_span] pub span: Span, } #[derive(SessionDiagnostic)] -#[error = "E0639"] +#[error(code = "E0639", slug = "typeck-struct-expr-non-exhaustive")] pub struct StructExprNonExhaustive { - #[message = "cannot create non-exhaustive {what} using struct expression"] + #[primary_span] pub span: Span, pub what: &'static str, } #[derive(SessionDiagnostic)] -#[error = "E0699"] +#[error(code = "E0699", slug = "typeck-method-call-on-unknown-type")] pub struct MethodCallOnUnknownType { - #[message = "the type of this value must be known to call a method on a raw pointer on it"] + #[primary_span] pub span: Span, } #[derive(SessionDiagnostic)] -#[error = "E0719"] +#[error(code = "E0719", slug = "typeck-value-of-associated-struct-already-specified")] pub struct ValueOfAssociatedStructAlreadySpecified { - #[message = "the value of the associated type `{item_name}` (from trait `{def_path}`) is already specified"] - #[label = "re-bound here"] + #[primary_span] + #[label] pub span: Span, - #[label = "`{item_name}` bound here first"] + #[label = "previous-bound-label"] pub prev_span: Span, pub item_name: Ident, pub def_path: String, } #[derive(SessionDiagnostic)] -#[error = "E0745"] +#[error(code = "E0745", slug = "typeck-address-of-temporary-taken")] pub struct AddressOfTemporaryTaken { - #[message = "cannot take address of a temporary"] - #[label = "temporary value"] + #[primary_span] + #[label] pub span: Span, }
diff --git a/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs b/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs index a117ed6..24b6639 100644 --- a/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs +++ b/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs
@@ -1,13 +1,14 @@ use crate::structured_errors::StructuredDiagnostic; use rustc_errors::{ pluralize, Applicability, Diagnostic, DiagnosticBuilder, DiagnosticId, ErrorGuaranteed, + MultiSpan, }; use rustc_hir as hir; use rustc_middle::hir::map::fn_sig; use rustc_middle::middle::resolve_lifetime::LifetimeScopeForPath; use rustc_middle::ty::{self as ty, TyCtxt}; use rustc_session::Session; -use rustc_span::{def_id::DefId, MultiSpan}; +use rustc_span::def_id::DefId; use GenericArgsInfo::*;
diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index 44389ee..39f8f1d 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs
@@ -326,16 +326,12 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 { #[cfg_attr(not(test), lang = "box_free")] #[inline] #[rustc_const_unstable(feature = "const_box", issue = "92521")] -#[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping // This signature has to be the same as `Box`, otherwise an ICE will happen. // When an additional parameter to `Box` is added (like `A: Allocator`), this has to be added here as // well. // For example if `Box` is changed to `struct Box<T: ?Sized, A: Allocator>(Unique<T>, A)`, // this function has to be changed to `fn box_free<T: ?Sized, A: Allocator>(Unique<T>, A)` as well. -pub(crate) const unsafe fn box_free< - T: ?Sized, - A: ~const Allocator + ~const Drop + ~const Destruct, ->( +pub(crate) const unsafe fn box_free<T: ?Sized, A: ~const Allocator + ~const Destruct>( ptr: Unique<T>, alloc: A, ) {
diff --git a/library/alloc/src/borrow.rs b/library/alloc/src/borrow.rs index 27e5af4..8b13e36 100644 --- a/library/alloc/src/borrow.rs +++ b/library/alloc/src/borrow.rs
@@ -331,7 +331,6 @@ pub fn into_owned(self) -> <B as ToOwned>::Owned { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_deref", issue = "88955")] -#[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping impl<B: ?Sized + ToOwned> const Deref for Cow<'_, B> where B::Owned: ~const Borrow<B>,
diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index b5f4c9a..a56d4de 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs
@@ -349,10 +349,9 @@ impl<T, A: Allocator> Box<T, A> { #[rustc_const_unstable(feature = "const_box", issue = "92521")] #[must_use] #[inline] - #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn new_in(x: T, alloc: A) -> Self where - A: ~const Allocator + ~const Drop + ~const Destruct, + A: ~const Allocator + ~const Destruct, { let mut boxed = Self::new_uninit_in(alloc); unsafe { @@ -379,11 +378,10 @@ pub const fn new_in(x: T, alloc: A) -> Self #[unstable(feature = "allocator_api", issue = "32838")] #[rustc_const_unstable(feature = "const_box", issue = "92521")] #[inline] - #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn try_new_in(x: T, alloc: A) -> Result<Self, AllocError> where - T: ~const Drop + ~const Destruct, - A: ~const Allocator + ~const Drop + ~const Destruct, + T: ~const Destruct, + A: ~const Allocator + ~const Destruct, { let mut boxed = Self::try_new_uninit_in(alloc)?; unsafe { @@ -417,10 +415,9 @@ pub const fn try_new_in(x: T, alloc: A) -> Result<Self, AllocError> #[cfg(not(no_global_oom_handling))] #[must_use] // #[unstable(feature = "new_uninit", issue = "63291")] - #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn new_uninit_in(alloc: A) -> Box<mem::MaybeUninit<T>, A> where - A: ~const Allocator + ~const Drop + ~const Destruct, + A: ~const Allocator + ~const Destruct, { let layout = Layout::new::<mem::MaybeUninit<T>>(); // NOTE: Prefer match over unwrap_or_else since closure sometimes not inlineable. @@ -456,10 +453,9 @@ pub const fn new_uninit_in(alloc: A) -> Box<mem::MaybeUninit<T>, A> #[unstable(feature = "allocator_api", issue = "32838")] // #[unstable(feature = "new_uninit", issue = "63291")] #[rustc_const_unstable(feature = "const_box", issue = "92521")] - #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn try_new_uninit_in(alloc: A) -> Result<Box<mem::MaybeUninit<T>, A>, AllocError> where - A: ~const Allocator + ~const Drop + ~const Destruct, + A: ~const Allocator + ~const Destruct, { let layout = Layout::new::<mem::MaybeUninit<T>>(); let ptr = alloc.allocate(layout)?.cast(); @@ -491,10 +487,9 @@ pub const fn try_new_uninit_in(alloc: A) -> Result<Box<mem::MaybeUninit<T>, A>, #[cfg(not(no_global_oom_handling))] // #[unstable(feature = "new_uninit", issue = "63291")] #[must_use] - #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn new_zeroed_in(alloc: A) -> Box<mem::MaybeUninit<T>, A> where - A: ~const Allocator + ~const Drop + ~const Destruct, + A: ~const Allocator + ~const Destruct, { let layout = Layout::new::<mem::MaybeUninit<T>>(); // NOTE: Prefer match over unwrap_or_else since closure sometimes not inlineable. @@ -530,10 +525,9 @@ pub const fn new_zeroed_in(alloc: A) -> Box<mem::MaybeUninit<T>, A> #[unstable(feature = "allocator_api", issue = "32838")] // #[unstable(feature = "new_uninit", issue = "63291")] #[rustc_const_unstable(feature = "const_box", issue = "92521")] - #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn try_new_zeroed_in(alloc: A) -> Result<Box<mem::MaybeUninit<T>, A>, AllocError> where - A: ~const Allocator + ~const Drop + ~const Destruct, + A: ~const Allocator + ~const Destruct, { let layout = Layout::new::<mem::MaybeUninit<T>>(); let ptr = alloc.allocate_zeroed(layout)?.cast(); @@ -547,10 +541,9 @@ pub const fn try_new_zeroed_in(alloc: A) -> Result<Box<mem::MaybeUninit<T>, A>, #[rustc_const_unstable(feature = "const_box", issue = "92521")] #[must_use] #[inline(always)] - #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn pin_in(x: T, alloc: A) -> Pin<Self> where - A: 'static + ~const Allocator + ~const Drop + ~const Destruct, + A: 'static + ~const Allocator + ~const Destruct, { Self::into_pin(Self::new_in(x, alloc)) } @@ -579,10 +572,9 @@ pub const fn into_boxed_slice(boxed: Self) -> Box<[T], A> { #[unstable(feature = "box_into_inner", issue = "80437")] #[rustc_const_unstable(feature = "const_box", issue = "92521")] #[inline] - #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn into_inner(boxed: Self) -> T where - Self: ~const Drop + ~const Destruct, + Self: ~const Destruct, { *boxed }
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 065d071..2ddb5f2 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs
@@ -131,6 +131,7 @@ #![feature(trusted_len)] #![feature(trusted_random_access)] #![feature(try_trait_v2)] +#![feature(unchecked_math)] #![feature(unicode_internals)] #![feature(unsize)] // @@ -141,7 +142,6 @@ #![feature(box_syntax)] #![feature(cfg_sanitize)] #![feature(const_deref)] -#![cfg_attr(bootstrap, feature(const_fn_trait_bound))] #![feature(const_mut_refs)] #![feature(const_ptr_write)] #![feature(const_precise_live_drops)]
diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs index 0ce2beb..9dbac3c 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs
@@ -168,7 +168,8 @@ pub unsafe fn into_box(self, len: usize) -> Box<[MaybeUninit<T>], A> { #[cfg(not(no_global_oom_handling))] fn allocate_in(capacity: usize, init: AllocInit, alloc: A) -> Self { - if mem::size_of::<T>() == 0 { + // Don't allocate here because `Drop` will not deallocate when `capacity` is 0. + if mem::size_of::<T>() == 0 || capacity == 0 { Self::new_in(alloc) } else { // We avoid `unwrap_or_else` here because it bloats the amount of
diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs index 89d8514..31edbe0 100644 --- a/library/alloc/src/slice.rs +++ b/library/alloc/src/slice.rs
@@ -237,7 +237,6 @@ fn to_vec<A: Allocator>(s: &[Self], alloc: A) -> Vec<Self, A> { } } -#[cfg_attr(bootstrap, lang = "slice_alloc")] #[cfg(not(test))] impl<T> [T] { /// Sorts the slice. @@ -267,7 +266,7 @@ impl<T> [T] { /// assert!(v == [-5, -3, 1, 2, 4]); /// ``` #[cfg(not(no_global_oom_handling))] - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn sort(&mut self) @@ -323,7 +322,7 @@ pub fn sort(&mut self) /// assert!(v == [5, 4, 3, 2, 1]); /// ``` #[cfg(not(no_global_oom_handling))] - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn sort_by<F>(&mut self, mut compare: F) @@ -365,7 +364,7 @@ pub fn sort_by<F>(&mut self, mut compare: F) /// assert!(v == [1, 2, -3, 4, -5]); /// ``` #[cfg(not(no_global_oom_handling))] - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[stable(feature = "slice_sort_by_key", since = "1.7.0")] #[inline] pub fn sort_by_key<K, F>(&mut self, mut f: F) @@ -412,7 +411,7 @@ pub fn sort_by_key<K, F>(&mut self, mut f: F) /// /// [pdqsort]: https://github.com/orlp/pdqsort #[cfg(not(no_global_oom_handling))] - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[stable(feature = "slice_sort_by_cached_key", since = "1.34.0")] #[inline] pub fn sort_by_cached_key<K, F>(&mut self, f: F) @@ -471,7 +470,7 @@ macro_rules! sort_by_key { /// // Here, `s` and `x` can be modified independently. /// ``` #[cfg(not(no_global_oom_handling))] - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[rustc_conversion_suggestion] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -496,7 +495,7 @@ pub fn to_vec(&self) -> Vec<T> /// // Here, `s` and `x` can be modified independently. /// ``` #[cfg(not(no_global_oom_handling))] - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[inline] #[unstable(feature = "allocator_api", issue = "32838")] pub fn to_vec_in<A: Allocator>(&self, alloc: A) -> Vec<T, A> @@ -521,7 +520,7 @@ pub fn to_vec_in<A: Allocator>(&self, alloc: A) -> Vec<T, A> /// /// assert_eq!(x, vec![10, 40, 30]); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn into_vec<A: Allocator>(self: Box<Self, A>) -> Vec<T, A> { @@ -549,7 +548,7 @@ pub fn into_vec<A: Allocator>(self: Box<Self, A>) -> Vec<T, A> { /// // this will panic at runtime /// b"0123456789abcdef".repeat(usize::MAX); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[cfg(not(no_global_oom_handling))] #[stable(feature = "repeat_generic_slice", since = "1.40.0")] pub fn repeat(&self, n: usize) -> Vec<T> @@ -618,7 +617,7 @@ pub fn repeat(&self, n: usize) -> Vec<T> /// assert_eq!(["hello", "world"].concat(), "helloworld"); /// assert_eq!([[1, 2], [3, 4]].concat(), [1, 2, 3, 4]); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[stable(feature = "rust1", since = "1.0.0")] pub fn concat<Item: ?Sized>(&self) -> <Self as Concat<Item>>::Output where @@ -637,7 +636,7 @@ pub fn concat<Item: ?Sized>(&self) -> <Self as Concat<Item>>::Output /// assert_eq!([[1, 2], [3, 4]].join(&0), [1, 2, 0, 3, 4]); /// assert_eq!([[1, 2], [3, 4]].join(&[0, 0][..]), [1, 2, 0, 0, 3, 4]); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[stable(feature = "rename_connect_to_join", since = "1.3.0")] pub fn join<Separator>(&self, sep: Separator) -> <Self as Join<Separator>>::Output where @@ -656,7 +655,7 @@ pub fn join<Separator>(&self, sep: Separator) -> <Self as Join<Separator>>::Outp /// assert_eq!(["hello", "world"].connect(" "), "hello world"); /// assert_eq!([[1, 2], [3, 4]].connect(&0), [1, 2, 0, 3, 4]); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_deprecated(since = "1.3.0", reason = "renamed to join")] pub fn connect<Separator>(&self, sep: Separator) -> <Self as Join<Separator>>::Output @@ -667,7 +666,6 @@ pub fn connect<Separator>(&self, sep: Separator) -> <Self as Join<Separator>>::O } } -#[cfg_attr(bootstrap, lang = "slice_u8_alloc")] #[cfg(not(test))] impl [u8] { /// Returns a vector containing a copy of this slice where each byte @@ -680,7 +678,7 @@ impl [u8] { /// /// [`make_ascii_uppercase`]: slice::make_ascii_uppercase #[cfg(not(no_global_oom_handling))] - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "this returns the uppercase bytes as a new Vec, \ without modifying the original"] #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] @@ -701,7 +699,7 @@ pub fn to_ascii_uppercase(&self) -> Vec<u8> { /// /// [`make_ascii_lowercase`]: slice::make_ascii_lowercase #[cfg(not(no_global_oom_handling))] - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "this returns the lowercase bytes as a new Vec, \ without modifying the original"] #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
diff --git a/library/alloc/src/str.rs b/library/alloc/src/str.rs index a3c1761..0eaa263 100644 --- a/library/alloc/src/str.rs +++ b/library/alloc/src/str.rs
@@ -235,7 +235,6 @@ fn clone_into(&self, target: &mut String) { } /// Methods for string slices. -#[cfg_attr(bootstrap, lang = "str_alloc")] #[cfg(not(test))] impl str { /// Converts a `Box<str>` into a `Box<[u8]>` without copying or allocating. @@ -250,7 +249,7 @@ impl str { /// let boxed_bytes = boxed_str.into_boxed_bytes(); /// assert_eq!(*boxed_bytes, *s.as_bytes()); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[stable(feature = "str_box_extras", since = "1.20.0")] #[must_use = "`self` will be dropped if the result is not used"] #[inline] @@ -281,7 +280,7 @@ pub fn into_boxed_bytes(self: Box<str>) -> Box<[u8]> { /// assert_eq!(s, s.replace("cookie monster", "little lamb")); /// ``` #[cfg(not(no_global_oom_handling))] - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "this returns the replaced string as a new allocation, \ without modifying the original"] #[stable(feature = "rust1", since = "1.0.0")] @@ -322,7 +321,7 @@ pub fn replace<'a, P: Pattern<'a>>(&'a self, from: P, to: &str) -> String { /// assert_eq!(s, s.replacen("cookie monster", "little lamb", 10)); /// ``` #[cfg(not(no_global_oom_handling))] - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "this returns the replaced string as a new allocation, \ without modifying the original"] #[stable(feature = "str_replacen", since = "1.16.0")] @@ -379,7 +378,7 @@ pub fn replacen<'a, P: Pattern<'a>>(&'a self, pat: P, to: &str, count: usize) -> /// assert_eq!(new_year, new_year.to_lowercase()); /// ``` #[cfg(not(no_global_oom_handling))] - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "this returns the lowercase string as a new String, \ without modifying the original"] #[stable(feature = "unicode_case_mapping", since = "1.2.0")] @@ -462,7 +461,7 @@ fn case_ignoreable_then_cased<I: Iterator<Item = char>>(iter: I) -> bool { /// assert_eq!("TSCHÜSS", s.to_uppercase()); /// ``` #[cfg(not(no_global_oom_handling))] - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "this returns the uppercase string as a new String, \ without modifying the original"] #[stable(feature = "unicode_case_mapping", since = "1.2.0")] @@ -498,7 +497,7 @@ pub fn to_uppercase(&self) -> String { /// assert_eq!(boxed_str.into_string(), string); /// ``` #[stable(feature = "box_str", since = "1.4.0")] - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "`self` will be dropped if the result is not used"] #[inline] pub fn into_string(self: Box<str>) -> String { @@ -527,7 +526,7 @@ pub fn into_string(self: Box<str>) -> String { /// let huge = "0123456789abcdef".repeat(usize::MAX); /// ``` #[cfg(not(no_global_oom_handling))] - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use] #[stable(feature = "repeat_str", since = "1.16.0")] pub fn repeat(&self, n: usize) -> String { @@ -556,7 +555,7 @@ pub fn repeat(&self, n: usize) -> String { /// [`make_ascii_uppercase`]: str::make_ascii_uppercase /// [`to_uppercase`]: #method.to_uppercase #[cfg(not(no_global_oom_handling))] - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "to uppercase the value in-place, use `make_ascii_uppercase()`"] #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[inline] @@ -589,7 +588,7 @@ pub fn to_ascii_uppercase(&self) -> String { /// [`make_ascii_lowercase`]: str::make_ascii_lowercase /// [`to_lowercase`]: #method.to_lowercase #[cfg(not(no_global_oom_handling))] - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "to lowercase the value in-place, use `make_ascii_lowercase()`"] #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[inline]
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 0b62622..74bcac2 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs
@@ -2274,6 +2274,51 @@ pub fn extend_from_within<R>(&mut self, src: R) } } +impl<T, A: Allocator, const N: usize> Vec<[T; N], A> { + /// Takes a `Vec<[T; N]>` and flattens it into a `Vec<T>`. + /// + /// # Panics + /// + /// Panics if the length of the resulting vector would overflow a `usize`. + /// + /// This is only possible when flattening a vector of arrays of zero-sized + /// types, and thus tends to be irrelevant in practice. If + /// `size_of::<T>() > 0`, this will never panic. + /// + /// # Examples + /// + /// ``` + /// #![feature(slice_flatten)] + /// + /// let mut vec = vec![[1, 2, 3], [4, 5, 6], [7, 8, 9]]; + /// assert_eq!(vec.pop(), Some([7, 8, 9])); + /// + /// let mut flattened = vec.into_flattened(); + /// assert_eq!(flattened.pop(), Some(6)); + /// ``` + #[unstable(feature = "slice_flatten", issue = "95629")] + pub fn into_flattened(self) -> Vec<T, A> { + let (ptr, len, cap, alloc) = self.into_raw_parts_with_alloc(); + let (new_len, new_cap) = if mem::size_of::<T>() == 0 { + (len.checked_mul(N).expect("vec len overflow"), usize::MAX) + } else { + // SAFETY: + // - `cap * N` cannot overflow because the allocation is already in + // the address space. + // - Each `[T; N]` has `N` valid elements, so there are `len * N` + // valid elements in the allocation. + unsafe { (len.unchecked_mul(N), cap.unchecked_mul(N)) } + }; + // SAFETY: + // - `ptr` was allocated by `self` + // - `ptr` is well-aligned because `[T; N]` has the same alignment as `T`. + // - `new_cap` refers to the same sized allocation as `cap` because + // `new_cap * size_of::<T>()` == `cap * size_of::<[T; N]>()` + // - `len` <= `cap`, so `len * N` <= `cap * N`. + unsafe { Vec::<T, A>::from_raw_parts_in(ptr.cast(), new_len, new_cap, alloc) } + } +} + // This code generalizes `extend_with_{element,default}`. trait ExtendWith<T> { fn next(&mut self) -> T;
diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index abce47e..16ceb8e 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs
@@ -38,6 +38,7 @@ #![feature(const_str_from_utf8)] #![feature(nonnull_slice_from_raw_parts)] #![feature(panic_update_hook)] +#![feature(slice_flatten)] use std::collections::hash_map::DefaultHasher; use std::hash::{Hash, Hasher};
diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs index 19e39eb..bc13971 100644 --- a/library/alloc/tests/vec.rs +++ b/library/alloc/tests/vec.rs
@@ -2408,3 +2408,10 @@ fn drop(&mut self) { assert_eq!(count.load(Ordering::SeqCst), 4); } + +#[test] +#[should_panic = "vec len overflow"] +fn test_into_flattened_size_overflow() { + let v = vec![[(); usize::MAX]; 2]; + let _ = v.into_flattened(); +}
diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 9e42ab5..af661e4 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs
@@ -395,7 +395,6 @@ macro_rules! array_impl_default { array_impl_default! {32, T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T} -#[cfg_attr(bootstrap, lang = "array")] impl<T, const N: usize> [T; N] { /// Returns an array of the same size as `self`, with function `f` applied to each element /// in order.
diff --git a/library/core/src/bool.rs b/library/core/src/bool.rs index 06aee3c..36000f8 100644 --- a/library/core/src/bool.rs +++ b/library/core/src/bool.rs
@@ -2,7 +2,6 @@ use crate::marker::Destruct; -#[cfg_attr(bootstrap, lang = "bool")] impl bool { /// Returns `Some(t)` if the `bool` is [`true`](../std/keyword.true.html), /// or `None` otherwise. @@ -18,10 +17,9 @@ impl bool { #[unstable(feature = "bool_to_option", issue = "80967")] #[rustc_const_unstable(feature = "const_bool_to_option", issue = "91917")] #[inline] - #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn then_some<T>(self, t: T) -> Option<T> where - T: ~const Drop + ~const Destruct, + T: ~const Destruct, { if self { Some(t) } else { None } } @@ -38,11 +36,10 @@ pub const fn then_some<T>(self, t: T) -> Option<T> #[stable(feature = "lazy_bool_to_option", since = "1.50.0")] #[rustc_const_unstable(feature = "const_bool_to_option", issue = "91917")] #[inline] - #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn then<T, F>(self, f: F) -> Option<T> where F: ~const FnOnce() -> T, - F: ~const Drop + ~const Destruct, + F: ~const Destruct, { if self { Some(f()) } else { None } }
diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index 9dbb5ee..2a49017 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs
@@ -1990,9 +1990,106 @@ fn from(t: T) -> UnsafeCell<T> { #[unstable(feature = "coerce_unsized", issue = "27732")] impl<T: CoerceUnsized<U>, U> CoerceUnsized<UnsafeCell<U>> for UnsafeCell<T> {} +/// [`UnsafeCell`], but [`Sync`]. +/// +/// This is just an `UnsafeCell`, except it implements `Sync` +/// if `T` implements `Sync`. +/// +/// `UnsafeCell` doesn't implement `Sync`, to prevent accidental mis-use. +/// You can use `SyncUnsafeCell` instead of `UnsafeCell` to allow it to be +/// shared between threads, if that's intentional. +/// Providing proper synchronization is still the task of the user, +/// making this type just as unsafe to use. +/// +/// See [`UnsafeCell`] for details. +#[unstable(feature = "sync_unsafe_cell", issue = "95439")] +#[repr(transparent)] +pub struct SyncUnsafeCell<T: ?Sized> { + value: UnsafeCell<T>, +} + +#[unstable(feature = "sync_unsafe_cell", issue = "95439")] +unsafe impl<T: ?Sized + Sync> Sync for SyncUnsafeCell<T> {} + +#[unstable(feature = "sync_unsafe_cell", issue = "95439")] +impl<T> SyncUnsafeCell<T> { + /// Constructs a new instance of `SyncUnsafeCell` which will wrap the specified value. + #[inline] + pub const fn new(value: T) -> Self { + Self { value: UnsafeCell { value } } + } + + /// Unwraps the value. + #[inline] + pub const fn into_inner(self) -> T { + self.value.into_inner() + } +} + +#[unstable(feature = "sync_unsafe_cell", issue = "95439")] +impl<T: ?Sized> SyncUnsafeCell<T> { + /// Gets a mutable pointer to the wrapped value. + /// + /// This can be cast to a pointer of any kind. + /// Ensure that the access is unique (no active references, mutable or not) + /// when casting to `&mut T`, and ensure that there are no mutations + /// or mutable aliases going on when casting to `&T` + #[inline] + pub const fn get(&self) -> *mut T { + self.value.get() + } + + /// Returns a mutable reference to the underlying data. + /// + /// This call borrows the `SyncUnsafeCell` mutably (at compile-time) which + /// guarantees that we possess the only reference. + #[inline] + pub const fn get_mut(&mut self) -> &mut T { + self.value.get_mut() + } + + /// Gets a mutable pointer to the wrapped value. + /// + /// See [`UnsafeCell::get`] for details. + #[inline] + pub const fn raw_get(this: *const Self) -> *mut T { + // We can just cast the pointer from `SyncUnsafeCell<T>` to `T` because + // of #[repr(transparent)] on both SyncUnsafeCell and UnsafeCell. + // See UnsafeCell::raw_get. + this as *const T as *mut T + } +} + +#[unstable(feature = "sync_unsafe_cell", issue = "95439")] +impl<T: Default> Default for SyncUnsafeCell<T> { + /// Creates an `SyncUnsafeCell`, with the `Default` value for T. + fn default() -> SyncUnsafeCell<T> { + SyncUnsafeCell::new(Default::default()) + } +} + +#[unstable(feature = "sync_unsafe_cell", issue = "95439")] +#[rustc_const_unstable(feature = "const_convert", issue = "88674")] +impl<T> const From<T> for SyncUnsafeCell<T> { + /// Creates a new `SyncUnsafeCell<T>` containing the given value. + fn from(t: T) -> SyncUnsafeCell<T> { + SyncUnsafeCell::new(t) + } +} + +#[unstable(feature = "coerce_unsized", issue = "27732")] +//#[unstable(feature = "sync_unsafe_cell", issue = "95439")] +impl<T: CoerceUnsized<U>, U> CoerceUnsized<SyncUnsafeCell<U>> for SyncUnsafeCell<T> {} + #[allow(unused)] -fn assert_coerce_unsized(a: UnsafeCell<&i32>, b: Cell<&i32>, c: RefCell<&i32>) { +fn assert_coerce_unsized( + a: UnsafeCell<&i32>, + b: SyncUnsafeCell<&i32>, + c: Cell<&i32>, + d: RefCell<&i32>, +) { let _: UnsafeCell<&dyn Send> = a; - let _: Cell<&dyn Send> = b; - let _: RefCell<&dyn Send> = c; + let _: SyncUnsafeCell<&dyn Send> = b; + let _: Cell<&dyn Send> = c; + let _: RefCell<&dyn Send> = d; }
diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index 3195205..5809ed1 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs
@@ -7,7 +7,6 @@ use super::*; -#[cfg_attr(bootstrap, lang = "char")] impl char { /// The highest valid code point a `char` can have, `'\u{10FFFF}'`. /// @@ -804,6 +803,9 @@ pub fn is_uppercase(self) -> bool { /// ``` /// assert!(' '.is_whitespace()); /// + /// // line break + /// assert!('\n'.is_whitespace()); + /// /// // a non-breaking space /// assert!('\u{A0}'.is_whitespace()); ///
diff --git a/library/core/src/clone.rs b/library/core/src/clone.rs index cfdc51c..0444a95 100644 --- a/library/core/src/clone.rs +++ b/library/core/src/clone.rs
@@ -130,10 +130,9 @@ pub trait Clone: Sized { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[default_method_body_is_const] - #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping fn clone_from(&mut self, source: &Self) where - Self: ~const Drop + ~const Destruct, + Self: ~const Destruct, { *self = source.clone() }
diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index 6c1d20f..fac959a 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs
@@ -2,7 +2,7 @@ #![stable(feature = "rust1", since = "1.0.0")] -use crate::cell::{Cell, Ref, RefCell, RefMut, UnsafeCell}; +use crate::cell::{Cell, Ref, RefCell, RefMut, SyncUnsafeCell, UnsafeCell}; use crate::char::EscapeDebugExtArgs; use crate::marker::PhantomData; use crate::mem; @@ -2400,6 +2400,13 @@ fn fmt(&self, f: &mut Formatter<'_>) -> Result { } } +#[unstable(feature = "sync_unsafe_cell", issue = "95439")] +impl<T: ?Sized> Debug for SyncUnsafeCell<T> { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + f.debug_struct("SyncUnsafeCell").finish_non_exhaustive() + } +} + // If you expected tests to be here, look instead at the core/tests/fmt.rs file, // it's a lot easier than creating all of the rt::Piece structures here. // There are also tests in the alloc crate, for those that need allocations.
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 0744e9c..8e02ca8 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs
@@ -991,6 +991,16 @@ pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) { /// let ptr_num_cast = ptr as *const i32 as usize; /// ``` /// + /// Note that using `transmute` to turn a pointer to a `usize` is (as noted above) [undefined + /// behavior][ub] in `const` contexts. Also outside of consts, this operation might not behave + /// as expected -- this is touching on many unspecified aspects of the Rust memory model. + /// Depending on what the code is doing, the following alternatives are preferrable to + /// pointer-to-integer transmutation: + /// - If the code just wants to store data of arbitrary type in some buffer and needs to pick a + /// type for that buffer, it can use [`MaybeUninit`][mem::MaybeUninit]. + /// - If the code actually wants to work on the address the pointer points to, it can use `as` + /// casts or [`ptr.addr()`][pointer::addr]. + /// /// Turning a `*mut T` into an `&mut T`: /// /// ``` @@ -2348,7 +2358,6 @@ pub(crate) fn is_nonoverlapping<T>(src: *const T, dst: *const T, count: usize) - #[rustc_const_unstable(feature = "const_eval_select", issue = "none")] #[lang = "const_eval_select"] #[rustc_do_not_const_check] -#[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const unsafe fn const_eval_select<ARG, F, G, RET>( arg: ARG, _called_in_const: F, @@ -2356,7 +2365,7 @@ pub(crate) fn is_nonoverlapping<T>(src: *const T, dst: *const T, count: usize) - ) -> RET where F: ~const FnOnce<ARG, Output = RET>, - G: FnOnce<ARG, Output = RET> + ~const Drop + ~const Destruct, + G: FnOnce<ARG, Output = RET> + ~const Destruct, { called_at_rt.call_once(arg) } @@ -2368,7 +2377,6 @@ pub(crate) fn is_nonoverlapping<T>(src: *const T, dst: *const T, count: usize) - )] #[rustc_const_unstable(feature = "const_eval_select", issue = "none")] #[lang = "const_eval_select_ct"] -#[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const unsafe fn const_eval_select_ct<ARG, F, G, RET>( arg: ARG, called_in_const: F, @@ -2376,7 +2384,7 @@ pub(crate) fn is_nonoverlapping<T>(src: *const T, dst: *const T, count: usize) - ) -> RET where F: ~const FnOnce<ARG, Output = RET>, - G: FnOnce<ARG, Output = RET> + ~const Drop + ~const Destruct, + G: FnOnce<ARG, Output = RET> + ~const Destruct, { called_in_const.call_once(arg) }
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 7dfcc36..660f6d9 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs
@@ -84,7 +84,7 @@ target_has_atomic_load_store = "ptr", ))] #![no_core] -#![cfg_attr(not(bootstrap), rustc_coherence_is_core)] +#![rustc_coherence_is_core] // // Lints: #![deny(rust_2021_incompatible_or_patterns)] @@ -139,6 +139,7 @@ #![feature(const_type_id)] #![feature(const_type_name)] #![feature(const_default_impls)] +#![feature(const_unsafecell_get_mut)] #![feature(core_panic)] #![feature(duration_consts_float)] #![feature(maybe_uninit_uninit_array)] @@ -162,15 +163,12 @@ #![feature(cfg_target_has_atomic)] #![feature(cfg_target_has_atomic_equal_alignment)] #![feature(const_fn_floating_point_arithmetic)] -#![cfg_attr(bootstrap, feature(const_fn_fn_ptr_basics))] -#![cfg_attr(bootstrap, feature(const_fn_trait_bound))] -#![cfg_attr(bootstrap, feature(const_impl_trait))] #![feature(const_mut_refs)] #![feature(const_precise_live_drops)] #![feature(const_refs_to_cell)] #![feature(decl_macro)] #![feature(derive_default_enum)] -#![cfg_attr(not(bootstrap), feature(deprecated_suggestion))] +#![feature(deprecated_suggestion)] #![feature(doc_cfg)] #![feature(doc_notable_trait)] #![feature(rustdoc_internals)] @@ -207,7 +205,6 @@ #![feature(asm_const)] // // Target features: -#![cfg_attr(bootstrap, feature(aarch64_target_feature))] #![feature(arm_target_feature)] #![feature(avx512_target_feature)] #![feature(cmpxchg16b_target_feature)] @@ -219,7 +216,6 @@ #![feature(sse4a_target_feature)] #![feature(tbm_target_feature)] #![feature(wasm_target_feature)] -#![cfg_attr(bootstrap, feature(adx_target_feature))] // allow using `core::` in intra-doc links #[allow(unused_extern_crates)]
diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 74c9468..83f33ca 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs
@@ -909,7 +909,10 @@ macro_rules! format_args_nl { /// Inspects an environment variable at compile time. /// /// This macro will expand to the value of the named environment variable at - /// compile time, yielding an expression of type `&'static str`. + /// compile time, yielding an expression of type `&'static str`. Use + /// [`std::env::var`] instead if you want to read the value at runtime. + /// + /// [`std::env::var`]: ../std/env/fn.var.html /// /// If the environment variable is not defined, then a compilation error /// will be emitted. To not emit a compile error, use the [`option_env!`] @@ -950,7 +953,10 @@ macro_rules! env { /// expand into an expression of type `Option<&'static str>` whose value is /// `Some` of the value of the environment variable. If the environment /// variable is not present, then this will expand to `None`. See - /// [`Option<T>`][Option] for more information on this type. + /// [`Option<T>`][Option] for more information on this type. Use + /// [`std::env::var`] instead if you want to read the value at runtime. + /// + /// [`std::env::var`]: ../std/env/fn.var.html /// /// A compile time error is never emitted when using this macro regardless /// of whether the environment variable is present or not.
diff --git a/library/core/src/macros/panic.md b/library/core/src/macros/panic.md index 5127a16..d8206e7 100644 --- a/library/core/src/macros/panic.md +++ b/library/core/src/macros/panic.md
@@ -1,8 +1,7 @@ Panics the current thread. This allows a program to terminate immediately and provide feedback -to the caller of the program. `panic!` should be used when a program reaches -an unrecoverable state. +to the caller of the program. This macro is the perfect way to assert conditions in example code and in tests. `panic!` is closely tied with the `unwrap` method of both @@ -21,13 +20,25 @@ which contains either a `&str` or `String` for regular `panic!()` invocations. To panic with a value of another other type, [`panic_any`] can be used. -[`Result`] enum is often a better solution for recovering from errors than -using the `panic!` macro. This macro should be used to avoid proceeding using -incorrect values, such as from external sources. Detailed information about -error handling is found in the [book]. - See also the macro [`compile_error!`], for raising errors during compilation. +# When to use `panic!` vs `Result` + +The Rust model of error handling groups errors into two major categories: +recoverable and unrecoverable errors. For a recoverable error, such as a file +not found error, it’s reasonable to report the problem to the user and retry +the operation. Unrecoverable errors are always symptoms of bugs, like trying to +access a location beyond the end of an array. + +The Rust language and standard library provides `Result` and `panic!` as parts +of two complementary systems for representing, reporting, propagating, reacting +to, and discarding errors for in these two categories. + +The `panic!` macro is provided to represent unrecoverable errors, whereas the +`Result` enum is provided to represent recoverable errors. For more detailed +information about error handling check out the [book] or the [`std::result`] +module docs. + [ounwrap]: Option::unwrap [runwrap]: Result::unwrap [`std::panic::set_hook()`]: ../std/panic/fn.set_hook.html @@ -36,6 +47,7 @@ [`Any`]: crate::any::Any [`format!`]: ../std/macro.format.html [book]: ../book/ch09-00-error-handling.html +[`std::result`]: ../std/result/index.html # Current implementation
diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 6b9d625..4a90ef9 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs
@@ -797,17 +797,10 @@ impl<T: ?Sized> Unpin for *mut T {} /// This should be used for `~const` bounds, /// as non-const bounds will always hold for every type. #[unstable(feature = "const_trait_impl", issue = "67792")] -#[cfg_attr(not(bootstrap), lang = "destruct")] -#[cfg_attr( - not(bootstrap), - rustc_on_unimplemented(message = "can't drop `{Self}`", append_const_msg,) -)] +#[lang = "destruct"] +#[rustc_on_unimplemented(message = "can't drop `{Self}`", append_const_msg)] pub trait Destruct {} -#[cfg(bootstrap)] -#[unstable(feature = "const_trait_impl", issue = "67792")] -impl<T: ?Sized> const Destruct for T {} - /// Implementations of `Copy` for primitive types. /// /// Implementations that cannot be described in Rust
diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index 17ca854..a983d08 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs
@@ -370,7 +370,6 @@ pub mod consts { pub const LN_10: f32 = 2.30258509299404568401799145468436421_f32; } -#[cfg_attr(bootstrap, lang = "f32")] #[cfg(not(test))] impl f32 { /// The radix or base of the internal representation of `f32`. @@ -1040,7 +1039,6 @@ pub const fn from_bits(v: u32) -> Self { /// # Example /// /// ``` - /// #![feature(total_cmp)] /// struct GoodBoy { /// name: String, /// weight: f32, @@ -1060,7 +1058,7 @@ pub const fn from_bits(v: u32) -> Self { /// # .zip([-5.0, 0.1, 10.0, 99.0, f32::INFINITY, f32::NAN].iter()) /// # .all(|(a, b)| a.to_bits() == b.to_bits())) /// ``` - #[unstable(feature = "total_cmp", issue = "72599")] + #[stable(feature = "total_cmp", since = "1.62.0")] #[must_use] #[inline] pub fn total_cmp(&self, other: &Self) -> crate::cmp::Ordering {
diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index 350d852..05598e5 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs
@@ -370,7 +370,6 @@ pub mod consts { pub const LN_10: f64 = 2.30258509299404568401799145468436421_f64; } -#[cfg_attr(bootstrap, lang = "f64")] #[cfg(not(test))] impl f64 { /// The radix or base of the internal representation of `f64`. @@ -1056,7 +1055,6 @@ pub const fn from_bits(v: u64) -> Self { /// # Example /// /// ``` - /// #![feature(total_cmp)] /// struct GoodBoy { /// name: String, /// weight: f64, @@ -1076,7 +1074,7 @@ pub const fn from_bits(v: u64) -> Self { /// # .zip([-5.0, 0.1, 10.0, 99.0, f64::INFINITY, f64::NAN].iter()) /// # .all(|(a, b)| a.to_bits() == b.to_bits())) /// ``` - #[unstable(feature = "total_cmp", issue = "72599")] + #[stable(feature = "total_cmp", since = "1.62.0")] #[must_use] #[inline] pub fn total_cmp(&self, other: &Self) -> crate::cmp::Ordering {
diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index 8cbece0..a30d2ff 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs
@@ -193,26 +193,22 @@ pub const fn carrying_mul(self, rhs: Self, carry: Self) -> (Self, Self) { }; } -#[cfg_attr(bootstrap, lang = "i8")] impl i8 { int_impl! { i8, i8, u8, 8, 7, -128, 127, 2, "-0x7e", "0xa", "0x12", "0x12", "0x48", "[0x12]", "[0x12]", "", "" } } -#[cfg_attr(bootstrap, lang = "i16")] impl i16 { int_impl! { i16, i16, u16, 16, 15, -32768, 32767, 4, "-0x5ffd", "0x3a", "0x1234", "0x3412", "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]", "", "" } } -#[cfg_attr(bootstrap, lang = "i32")] impl i32 { int_impl! { i32, i32, u32, 32, 31, -2147483648, 2147483647, 8, "0x10000b3", "0xb301", "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]", "", "" } } -#[cfg_attr(bootstrap, lang = "i64")] impl i64 { int_impl! { i64, i64, u64, 64, 63, -9223372036854775808, 9223372036854775807, 12, "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412", @@ -220,7 +216,6 @@ impl i64 { "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", "", "" } } -#[cfg_attr(bootstrap, lang = "i128")] impl i128 { int_impl! { i128, i128, u128, 128, 127, -170141183460469231731687303715884105728, 170141183460469231731687303715884105727, 16, @@ -233,7 +228,6 @@ impl i128 { } #[cfg(target_pointer_width = "16")] -#[cfg_attr(bootstrap, lang = "isize")] impl isize { int_impl! { isize, i16, usize, 16, 15, -32768, 32767, 4, "-0x5ffd", "0x3a", "0x1234", "0x3412", "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]", @@ -241,7 +235,6 @@ impl isize { } #[cfg(target_pointer_width = "32")] -#[cfg_attr(bootstrap, lang = "isize")] impl isize { int_impl! { isize, i32, usize, 32, 31, -2147483648, 2147483647, 8, "0x10000b3", "0xb301", "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", @@ -250,7 +243,6 @@ impl isize { } #[cfg(target_pointer_width = "64")] -#[cfg_attr(bootstrap, lang = "isize")] impl isize { int_impl! { isize, i64, usize, 64, 63, -9223372036854775808, 9223372036854775807, 12, "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412", @@ -262,7 +254,6 @@ impl isize { /// If 6th bit set ascii is upper case. const ASCII_CASE_MASK: u8 = 0b0010_0000; -#[cfg_attr(bootstrap, lang = "u8")] impl u8 { uint_impl! { u8, u8, i8, NonZeroU8, 8, 255, 2, "0x82", "0xa", "0x12", "0x12", "0x48", "[0x12]", "[0x12]", "", "" } @@ -816,7 +807,6 @@ pub(crate) const fn is_utf8_char_boundary(self) -> bool { } } -#[cfg_attr(bootstrap, lang = "u16")] impl u16 { uint_impl! { u16, u16, i16, NonZeroU16, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]", "", "" } @@ -848,14 +838,12 @@ pub const fn is_utf16_surrogate(self) -> bool { } } -#[cfg_attr(bootstrap, lang = "u32")] impl u32 { uint_impl! { u32, u32, i32, NonZeroU32, 32, 4294967295, 8, "0x10000b3", "0xb301", "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]", "", "" } widening_impl! { u32, u64, 32, unsigned } } -#[cfg_attr(bootstrap, lang = "u64")] impl u64 { uint_impl! { u64, u64, i64, NonZeroU64, 64, 18446744073709551615, 12, "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48", @@ -865,7 +853,6 @@ impl u64 { widening_impl! { u64, u128, 64, unsigned } } -#[cfg_attr(bootstrap, lang = "u128")] impl u128 { uint_impl! { u128, u128, i128, NonZeroU128, 128, 340282366920938463463374607431768211455, 16, "0x13f40000000000000000000000004f76", "0x4f7613f4", "0x12345678901234567890123456789012", @@ -878,7 +865,6 @@ impl u128 { } #[cfg(target_pointer_width = "16")] -#[cfg_attr(bootstrap, lang = "usize")] impl usize { uint_impl! { usize, u16, isize, NonZeroUsize, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]", @@ -886,7 +872,6 @@ impl usize { widening_impl! { usize, u32, 16, unsigned } } #[cfg(target_pointer_width = "32")] -#[cfg_attr(bootstrap, lang = "usize")] impl usize { uint_impl! { usize, u32, isize, NonZeroUsize, 32, 4294967295, 8, "0x10000b3", "0xb301", "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]", @@ -895,7 +880,6 @@ impl usize { } #[cfg(target_pointer_width = "64")] -#[cfg_attr(bootstrap, lang = "usize")] impl usize { uint_impl! { usize, u64, isize, NonZeroUsize, 64, 18446744073709551615, 12, "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48",
diff --git a/library/core/src/ops/function.rs b/library/core/src/ops/function.rs index e5c4798..c5a194b 100644 --- a/library/core/src/ops/function.rs +++ b/library/core/src/ops/function.rs
@@ -53,12 +53,19 @@ /// ``` #[lang = "fn"] #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_diagnostic_item = "Fn"] #[rustc_paren_sugar] #[rustc_on_unimplemented( on( Args = "()", note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}`" ), + on( + _Self = "unsafe fn", + note = "unsafe function cannot be called generically without an unsafe block", + // SAFETY: tidy is not smart enough to tell that the below unsafe block is a string + label = "call the function in a closure: `|| unsafe {{ /* code */ }}`" + ), message = "expected a `{Fn}<{Args}>` closure, found `{Self}`", label = "expected an `Fn<{Args}>` closure, found `{Self}`" )] @@ -133,12 +140,19 @@ pub trait Fn<Args>: FnMut<Args> { /// ``` #[lang = "fn_mut"] #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_diagnostic_item = "FnMut"] #[rustc_paren_sugar] #[rustc_on_unimplemented( on( Args = "()", note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}`" ), + on( + _Self = "unsafe fn", + note = "unsafe function cannot be called generically without an unsafe block", + // SAFETY: tidy is not smart enough to tell that the below unsafe block is a string + label = "call the function in a closure: `|| unsafe {{ /* code */ }}`" + ), message = "expected a `{FnMut}<{Args}>` closure, found `{Self}`", label = "expected an `FnMut<{Args}>` closure, found `{Self}`" )] @@ -205,12 +219,19 @@ pub trait FnMut<Args>: FnOnce<Args> { /// ``` #[lang = "fn_once"] #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_diagnostic_item = "FnOnce"] #[rustc_paren_sugar] #[rustc_on_unimplemented( on( Args = "()", note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}`" ), + on( + _Self = "unsafe fn", + note = "unsafe function cannot be called generically without an unsafe block", + // SAFETY: tidy is not smart enough to tell that the below unsafe block is a string + label = "call the function in a closure: `|| unsafe {{ /* code */ }}`" + ), message = "expected a `{FnOnce}<{Args}>` closure, found `{Self}`", label = "expected an `FnOnce<{Args}>` closure, found `{Self}`" )]
diff --git a/library/core/src/option.rs b/library/core/src/option.rs index b5ca9e3..91e4708 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs
@@ -773,10 +773,9 @@ pub const fn unwrap(self) -> T { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn unwrap_or(self, default: T) -> T where - T: ~const Drop + ~const Destruct, + T: ~const Destruct, { match self { Some(x) => x, @@ -796,11 +795,10 @@ pub const fn unwrap_or(self, default: T) -> T #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn unwrap_or_else<F>(self, f: F) -> T where F: ~const FnOnce() -> T, - F: ~const Drop + ~const Destruct, + F: ~const Destruct, { match self { Some(x) => x, @@ -902,11 +900,10 @@ pub const fn unwrap_or_default(self) -> T #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn map<U, F>(self, f: F) -> Option<U> where F: ~const FnOnce(T) -> U, - F: ~const Drop + ~const Destruct, + F: ~const Destruct, { match self { Some(x) => Some(f(x)), @@ -932,11 +929,10 @@ pub const fn map<U, F>(self, f: F) -> Option<U> #[inline] #[unstable(feature = "result_option_inspect", issue = "91345")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn inspect<F>(self, f: F) -> Self where F: ~const FnOnce(&T), - F: ~const Drop + ~const Destruct, + F: ~const Destruct, { if let Some(ref x) = self { f(x); @@ -966,12 +962,11 @@ pub const fn inspect<F>(self, f: F) -> Self #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn map_or<U, F>(self, default: U, f: F) -> U where F: ~const FnOnce(T) -> U, - F: ~const Drop + ~const Destruct, - U: ~const Drop + ~const Destruct, + F: ~const Destruct, + U: ~const Destruct, { match self { Some(t) => f(t), @@ -996,13 +991,12 @@ pub const fn map_or<U, F>(self, default: U, f: F) -> U #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn map_or_else<U, D, F>(self, default: D, f: F) -> U where D: ~const FnOnce() -> U, - D: ~const Drop + ~const Destruct, + D: ~const Destruct, F: ~const FnOnce(T) -> U, - F: ~const Drop + ~const Destruct, + F: ~const Destruct, { match self { Some(t) => f(t), @@ -1034,10 +1028,9 @@ pub const fn map_or_else<U, D, F>(self, default: D, f: F) -> U #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn ok_or<E>(self, err: E) -> Result<T, E> where - E: ~const Drop + ~const Destruct, + E: ~const Destruct, { match self { Some(v) => Ok(v), @@ -1064,11 +1057,10 @@ pub const fn ok_or<E>(self, err: E) -> Result<T, E> #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn ok_or_else<E, F>(self, err: F) -> Result<T, E> where F: ~const FnOnce() -> E, - F: ~const Drop + ~const Destruct, + F: ~const Destruct, { match self { Some(v) => Ok(v), @@ -1199,11 +1191,10 @@ pub fn iter_mut(&mut self) -> IterMut<'_, T> { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn and<U>(self, optb: Option<U>) -> Option<U> where - T: ~const Drop + ~const Destruct, - U: ~const Drop + ~const Destruct, + T: ~const Destruct, + U: ~const Destruct, { match self { Some(_) => optb, @@ -1242,11 +1233,10 @@ pub const fn and<U>(self, optb: Option<U>) -> Option<U> #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn and_then<U, F>(self, f: F) -> Option<U> where F: ~const FnOnce(T) -> Option<U>, - F: ~const Drop + ~const Destruct, + F: ~const Destruct, { match self { Some(x) => f(x), @@ -1281,12 +1271,11 @@ pub const fn and_then<U, F>(self, f: F) -> Option<U> #[inline] #[stable(feature = "option_filter", since = "1.27.0")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn filter<P>(self, predicate: P) -> Self where - T: ~const Drop + ~const Destruct, + T: ~const Destruct, P: ~const FnOnce(&T) -> bool, - P: ~const Drop + ~const Destruct, + P: ~const Destruct, { if let Some(x) = self { if predicate(&x) { @@ -1326,10 +1315,9 @@ pub const fn filter<P>(self, predicate: P) -> Self #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn or(self, optb: Option<T>) -> Option<T> where - T: ~const Drop + ~const Destruct, + T: ~const Destruct, { match self { Some(x) => Some(x), @@ -1353,11 +1341,10 @@ pub const fn or(self, optb: Option<T>) -> Option<T> #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn or_else<F>(self, f: F) -> Option<T> where F: ~const FnOnce() -> Option<T>, - F: ~const Drop + ~const Destruct, + F: ~const Destruct, { match self { Some(x) => Some(x), @@ -1389,10 +1376,9 @@ pub const fn or_else<F>(self, f: F) -> Option<T> #[inline] #[stable(feature = "option_xor", since = "1.37.0")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn xor(self, optb: Option<T>) -> Option<T> where - T: ~const Drop + ~const Destruct, + T: ~const Destruct, { match (self, optb) { (Some(a), None) => Some(a), @@ -1428,10 +1414,9 @@ pub const fn xor(self, optb: Option<T>) -> Option<T> #[inline] #[stable(feature = "option_insert", since = "1.53.0")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn insert(&mut self, value: T) -> &mut T where - T: ~const Drop + ~const Destruct, + T: ~const Destruct, { *self = Some(value); @@ -1462,10 +1447,9 @@ pub const fn insert(&mut self, value: T) -> &mut T #[inline] #[stable(feature = "option_entry", since = "1.20.0")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn get_or_insert(&mut self, value: T) -> &mut T where - T: ~const Drop + ~const Destruct, + T: ~const Destruct, { if let None = *self { *self = Some(value); @@ -1530,11 +1514,10 @@ const fn default<T: ~const Default>() -> T { #[inline] #[stable(feature = "option_entry", since = "1.20.0")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn get_or_insert_with<F>(&mut self, f: F) -> &mut T where F: ~const FnOnce() -> T, - F: ~const Drop + ~const Destruct, + F: ~const Destruct, { if let None = *self { // the compiler isn't smart enough to know that we are not dropping a `T` @@ -1645,11 +1628,10 @@ pub const fn contains<U>(&self, x: &U) -> bool /// ``` #[stable(feature = "option_zip_option", since = "1.46.0")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn zip<U>(self, other: Option<U>) -> Option<(T, U)> where - T: ~const Drop + ~const Destruct, - U: ~const Drop + ~const Destruct, + T: ~const Destruct, + U: ~const Destruct, { match (self, other) { (Some(a), Some(b)) => Some((a, b)), @@ -1687,13 +1669,12 @@ pub const fn zip<U>(self, other: Option<U>) -> Option<(T, U)> /// ``` #[unstable(feature = "option_zip", issue = "70086")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn zip_with<U, F, R>(self, other: Option<U>, f: F) -> Option<R> where F: ~const FnOnce(T, U) -> R, - F: ~const Drop + ~const Destruct, - T: ~const Drop + ~const Destruct, - U: ~const Drop + ~const Destruct, + F: ~const Destruct, + T: ~const Destruct, + U: ~const Destruct, { match (self, other) { (Some(a), Some(b)) => Some(f(a, b)), @@ -1880,10 +1861,9 @@ const fn expect_failed(msg: &str) -> ! { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_clone", issue = "91805")] -#[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping impl<T> const Clone for Option<T> where - T: ~const Clone + ~const Drop + ~const Destruct, + T: ~const Clone + ~const Destruct, { #[inline] fn clone(&self) -> Self {
diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs index a908b1f..7a575a8 100644 --- a/library/core/src/panicking.rs +++ b/library/core/src/panicking.rs
@@ -88,7 +88,6 @@ fn panic_bounds_check(index: usize, len: usize) -> ! { // any extra arguments (including those synthesized by track_caller). #[cold] #[inline(never)] -#[cfg_attr(bootstrap, track_caller)] #[lang = "panic_no_unwind"] // needed by codegen for panic in nounwind function fn panic_no_unwind() -> ! { if cfg!(feature = "panic_immediate_abort") {
diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 209ea5c..68f39dc 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs
@@ -4,7 +4,6 @@ use crate::mem; use crate::slice::{self, SliceIndex}; -#[cfg_attr(bootstrap, lang = "const_ptr")] impl<T: ?Sized> *const T { /// Returns `true` if the pointer is null. /// @@ -152,9 +151,17 @@ pub fn from_bits(bits: usize) -> Self /// Gets the "address" portion of the pointer. /// - /// This is equivalent to `self as usize`, which semantically discards - /// *provenance* and *address-space* information. To properly restore that information, - /// use [`with_addr`][pointer::with_addr] or [`map_addr`][pointer::map_addr]. + /// This is similar to `self as usize`, which semantically discards *provenance* and + /// *address-space* information. However, unlike `self as usize`, casting the returned address + /// back to a pointer yields [`invalid`][], which is undefined behavior to dereference. To + /// properly restore the lost information and obtain a dereferencable pointer, use + /// [`with_addr`][pointer::with_addr] or [`map_addr`][pointer::map_addr]. + /// + /// If using those APIs is not possible because there is no way to preserve a pointer with the + /// required provenance, use [`expose_addr`][pointer::expose_addr] and + /// [`from_exposed_addr`][from_exposed_addr] instead. However, note that this makes + /// your code less portable and less amenable to tools that check for compliance with the Rust + /// memory model. /// /// On most platforms this will produce a value with the same bytes as the original /// pointer, because all the bytes are dedicated to describing the address. @@ -162,8 +169,9 @@ pub fn from_bits(bits: usize) -> Self /// perform a change of representation to produce a value containing only the address /// portion of the pointer. What that means is up to the platform to define. /// - /// This API and its claimed semantics are part of the Strict Provenance experiment, - /// see the [module documentation][crate::ptr] for details. + /// This API and its claimed semantics are part of the Strict Provenance experiment, and as such + /// might change in the future (including possibly weakening this so it becomes wholly + /// equivalent to `self as usize`). See the [module documentation][crate::ptr] for details. #[must_use] #[inline] #[unstable(feature = "strict_provenance", issue = "95228")] @@ -175,6 +183,41 @@ pub fn addr(self) -> usize self as usize } + /// Gets the "address" portion of the pointer, and 'exposes' the "provenance" part for future + /// use in [`from_exposed_addr`][]. + /// + /// This is equivalent to `self as usize`, which semantically discards *provenance* and + /// *address-space* information. Furthermore, this (like the `as` cast) has the implicit + /// side-effect of marking the provenance as 'exposed', so on platforms that support it you can + /// later call [`from_exposed_addr`][] to reconstitute the original pointer including its + /// provenance. (Reconstructing address space information, if required, is your responsibility.) + /// + /// Using this method means that code is *not* following Strict Provenance rules. Supporting + /// [`from_exposed_addr`][] complicates specification and reasoning and may not be supported by + /// tools that help you to stay conformant with the Rust memory model, so it is recommended to + /// use [`addr`][pointer::addr] wherever possible. + /// + /// On most platforms this will produce a value with the same bytes as the original pointer, + /// because all the bytes are dedicated to describing the address. Platforms which need to store + /// additional information in the pointer may not support this operation, since the 'expose' + /// side-effect which is required for [`from_exposed_addr`][] to work is typically not + /// available. + /// + /// This API and its claimed semantics are part of the Strict Provenance experiment, see the + /// [module documentation][crate::ptr] for details. + /// + /// [`from_exposed_addr`]: from_exposed_addr + #[must_use] + #[inline] + #[unstable(feature = "strict_provenance", issue = "95228")] + pub fn expose_addr(self) -> usize + where + T: Sized, + { + // FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic. + self as usize + } + /// Creates a new pointer with the given address. /// /// This performs the same operation as an `addr as ptr` cast, but copies @@ -1042,7 +1085,6 @@ const fn ctfe_impl<T>(_: *const T, _: usize) -> usize { } } -#[cfg_attr(bootstrap, lang = "const_slice_ptr")] impl<T> *const [T] { /// Returns the length of a raw slice. ///
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index b93c2ea..ba8b067 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs
@@ -70,7 +70,7 @@ //! interpretation of provenance. It's ok if your code doesn't strictly conform to it.** //! //! [Strict Provenance][] is an experimental set of APIs that help tools that try -//! to validate the memory-safety of your program's execution. Notably this includes [miri][] +//! to validate the memory-safety of your program's execution. Notably this includes [Miri][] //! and [CHERI][], which can detect when you access out of bounds memory or otherwise violate //! Rust's memory model. //! @@ -136,7 +136,7 @@ //! //! The strict provenance experiment is mostly only interested in exploring stricter *spatial* //! provenance. In this sense it can be thought of as a subset of the more ambitious and -//! formal [Stacked Borrows][] research project, which is what tools like [miri][] are based on. +//! formal [Stacked Borrows][] research project, which is what tools like [Miri][] are based on. //! In particular, Stacked Borrows is necessary to properly describe what borrows are allowed //! to do and when they become invalidated. This necessarily involves much more complex //! *temporal* reasoning than simply identifying allocations. Adjusting APIs and code @@ -170,7 +170,8 @@ //! Under Strict Provenance, a usize *cannot* accurately represent a pointer, and converting from //! a pointer to a usize is generally an operation which *only* extracts the address. It is //! therefore *impossible* to construct a valid pointer from a usize because there is no way -//! to restore the address-space and provenance. +//! to restore the address-space and provenance. In other words, pointer-integer-pointer +//! roundtrips are not possible (in the sense that the resulting pointer is not dereferencable). //! //! The key insight to making this model *at all* viable is the [`with_addr`][] method: //! @@ -194,10 +195,10 @@ //! and then immediately converting back to a pointer. To make this use case more ergonomic, //! we provide the [`map_addr`][] method. //! -//! To help make it clear that code is "following" Strict Provenance semantics, we also -//! provide an [`addr`][] method which is currently equivalent to `ptr as usize`. In the -//! future we may provide a lint for pointer<->integer casts to help you audit if your -//! code conforms to strict provenance. +//! To help make it clear that code is "following" Strict Provenance semantics, we also provide an +//! [`addr`][] method which promises that the returned address is not part of a +//! pointer-usize-pointer roundtrip. In the future we may provide a lint for pointer<->integer +//! casts to help you audit if your code conforms to strict provenance. //! //! //! ## Using Strict Provenance @@ -310,6 +311,41 @@ //! For instance, ARM explicitly supports high-bit tagging, and so CHERI on ARM inherits //! that and should support it. //! +//! ## Pointer-usize-pointer roundtrips and 'exposed' provenance +//! +//! **This section is *non-normative* and is part of the [Strict Provenance] experiment.** +//! +//! As discussed above, pointer-usize-pointer roundtrips are not possible under [Strict Provenance]. +//! However, there exists legacy Rust code that is full of such roundtrips, and legacy platform APIs +//! regularly assume that `usize` can capture all the information that makes up a pointer. There +//! also might be code that cannot be ported to Strict Provenance (which is something we would [like +//! to hear about][Strict Provenance]). +//! +//! For situations like this, there is a fallback plan, a way to 'opt out' of Strict Provenance. +//! However, note that this makes your code a lot harder to specify, and the code will not work +//! (well) with tools like [Miri] and [CHERI]. +//! +//! This fallback plan is provided by the [`expose_addr`] and [`from_exposed_addr`] methods (which +//! are equivalent to `as` casts between pointers and integers). [`expose_addr`] is a lot like +//! [`addr`], but additionally adds the provenance of the pointer to a global list of 'exposed' +//! provenances. (This list is purely conceptual, it exists for the purpose of specifying Rust but +//! is not materialized in actual executions, except in tools like [Miri].) [`from_exposed_addr`] +//! can be used to construct a pointer with one of these previously 'exposed' provenances. +//! [`from_exposed_addr`] takes only `addr: usize` as arguments, so unlike in [`with_addr`] there is +//! no indication of what the correct provenance for the returned pointer is -- and that is exactly +//! what makes pointer-usize-pointer roundtrips so tricky to rigorously specify! There is no +//! algorithm that decides which provenance will be used. You can think of this as "guessing" the +//! right provenance, and the guess will be "maximally in your favor", in the sense that if there is +//! any way to avoid undefined behavior, then that is the guess that will be taken. However, if +//! there is *no* previously 'exposed' provenance that justifies the way the returned pointer will +//! be used, the program has undefined behavior. +//! +//! Using [`expose_addr`] or [`from_exposed_addr`] (or the equivalent `as` casts) means that code is +//! *not* following Strict Provenance rules. The goal of the Strict Provenance experiment is to +//! determine whether it is possible to use Rust without [`expose_addr`] and [`from_exposed_addr`]. +//! If this is successful, it would be a major win for avoiding specification complexity and to +//! facilitate adoption of tools like [CHERI] and [Miri] that can be a big help in increasing the +//! confidence in (unsafe) Rust code. //! //! [aliasing]: ../../nomicon/aliasing.html //! [book]: ../../book/ch19-01-unsafe-rust.html#dereferencing-a-raw-pointer @@ -322,7 +358,9 @@ //! [`map_addr`]: pointer::map_addr //! [`addr`]: pointer::addr //! [`ptr::invalid`]: core::ptr::invalid -//! [miri]: https://github.com/rust-lang/miri +//! [`expose_addr`]: pointer::expose_addr +//! [`from_exposed_addr`]: from_exposed_addr +//! [Miri]: https://github.com/rust-lang/miri //! [CHERI]: https://www.cl.cam.ac.uk/research/security/ctsrd/cheri/ //! [Strict Provenance]: https://github.com/rust-lang/rust/issues/95228 //! [Stacked Borrows]: https://plv.mpi-sws.org/rustbelt/stacked-borrows/ @@ -547,6 +585,78 @@ pub const fn invalid_mut<T>(addr: usize) -> *mut T { addr as *mut T } +/// Convert an address back to a pointer, picking up a previously 'exposed' provenance. +/// +/// This is equivalent to `addr as *const T`. The provenance of the returned pointer is that of *any* +/// pointer that was previously passed to [`expose_addr`][pointer::expose_addr] or a `ptr as usize` +/// cast. If there is no previously 'exposed' provenance that justifies the way this pointer will be +/// used, the program has undefined behavior. Note that there is no algorithm that decides which +/// provenance will be used. You can think of this as "guessing" the right provenance, and the guess +/// will be "maximally in your favor", in the sense that if there is any way to avoid undefined +/// behavior, then that is the guess that will be taken. +/// +/// On platforms with multiple address spaces, it is your responsibility to ensure that the +/// address makes sense in the address space that this pointer will be used with. +/// +/// Using this method means that code is *not* following strict provenance rules. "Guessing" a +/// suitable provenance complicates specification and reasoning and may not be supported by +/// tools that help you to stay conformant with the Rust memory model, so it is recommended to +/// use [`with_addr`][pointer::with_addr] wherever possible. +/// +/// On most platforms this will produce a value with the same bytes as the address. Platforms +/// which need to store additional information in a pointer may not support this operation, +/// since it is generally not possible to actually *compute* which provenance the returned +/// pointer has to pick up. +/// +/// This API and its claimed semantics are part of the Strict Provenance experiment, see the +/// [module documentation][crate::ptr] for details. +#[must_use] +#[inline] +#[unstable(feature = "strict_provenance", issue = "95228")] +pub fn from_exposed_addr<T>(addr: usize) -> *const T +where + T: Sized, +{ + // FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic. + addr as *const T +} + +/// Convert an address back to a mutable pointer, picking up a previously 'exposed' provenance. +/// +/// This is equivalent to `addr as *mut T`. The provenance of the returned pointer is that of *any* +/// pointer that was previously passed to [`expose_addr`][pointer::expose_addr] or a `ptr as usize` +/// cast. If there is no previously 'exposed' provenance that justifies the way this pointer will be +/// used, the program has undefined behavior. Note that there is no algorithm that decides which +/// provenance will be used. You can think of this as "guessing" the right provenance, and the guess +/// will be "maximally in your favor", in the sense that if there is any way to avoid undefined +/// behavior, then that is the guess that will be taken. +/// +/// On platforms with multiple address spaces, it is your responsibility to ensure that the +/// address makes sense in the address space that this pointer will be used with. +/// +/// Using this method means that code is *not* following strict provenance rules. "Guessing" a +/// suitable provenance complicates specification and reasoning and may not be supported by +/// tools that help you to stay conformant with the Rust memory model, so it is recommended to +/// use [`with_addr`][pointer::with_addr] wherever possible. +/// +/// On most platforms this will produce a value with the same bytes as the address. Platforms +/// which need to store additional information in a pointer may not support this operation, +/// since it is generally not possible to actually *compute* which provenance the returned +/// pointer has to pick up. +/// +/// This API and its claimed semantics are part of the Strict Provenance experiment, see the +/// [module documentation][crate::ptr] for details. +#[must_use] +#[inline] +#[unstable(feature = "strict_provenance", issue = "95228")] +pub fn from_exposed_addr_mut<T>(addr: usize) -> *mut T +where + T: Sized, +{ + // FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic. + addr as *mut T +} + /// Forms a raw slice from a pointer and a length. /// /// The `len` argument is the number of **elements**, not the number of bytes. @@ -763,7 +873,7 @@ macro_rules! attempt_swap_as_chunks { ); } - // NOTE(scottmcm) MIRI is disabled here as reading in smaller units is a + // NOTE(scottmcm) Miri is disabled here as reading in smaller units is a // pessimization for it. Also, if the type contains any unaligned pointers, // copying those over multiple reads is difficult to support. #[cfg(not(miri))]
diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index bfc8962..4c9b0f7 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs
@@ -3,7 +3,6 @@ use crate::intrinsics; use crate::slice::{self, SliceIndex}; -#[cfg_attr(bootstrap, lang = "mut_ptr")] impl<T: ?Sized> *mut T { /// Returns `true` if the pointer is null. /// @@ -156,9 +155,17 @@ pub fn from_bits(bits: usize) -> Self /// Gets the "address" portion of the pointer. /// - /// This is equivalent to `self as usize`, which semantically discards - /// *provenance* and *address-space* information. To properly restore that information, - /// use [`with_addr`][pointer::with_addr] or [`map_addr`][pointer::map_addr]. + /// This is similar to `self as usize`, which semantically discards *provenance* and + /// *address-space* information. However, unlike `self as usize`, casting the returned address + /// back to a pointer yields [`invalid`][], which is undefined behavior to dereference. To + /// properly restore the lost information and obtain a dereferencable pointer, use + /// [`with_addr`][pointer::with_addr] or [`map_addr`][pointer::map_addr]. + /// + /// If using those APIs is not possible because there is no way to preserve a pointer with the + /// required provenance, use [`expose_addr`][pointer::expose_addr] and + /// [`from_exposed_addr_mut`][from_exposed_addr_mut] instead. However, note that this makes + /// your code less portable and less amenable to tools that check for compliance with the Rust + /// memory model. /// /// On most platforms this will produce a value with the same bytes as the original /// pointer, because all the bytes are dedicated to describing the address. @@ -166,8 +173,9 @@ pub fn from_bits(bits: usize) -> Self /// perform a change of representation to produce a value containing only the address /// portion of the pointer. What that means is up to the platform to define. /// - /// This API and its claimed semantics are part of the Strict Provenance experiment, - /// see the [module documentation][crate::ptr] for details. + /// This API and its claimed semantics are part of the Strict Provenance experiment, and as such + /// might change in the future (including possibly weakening this so it becomes wholly + /// equivalent to `self as usize`). See the [module documentation][crate::ptr] for details. #[must_use] #[inline] #[unstable(feature = "strict_provenance", issue = "95228")] @@ -179,6 +187,41 @@ pub fn addr(self) -> usize self as usize } + /// Gets the "address" portion of the pointer, and 'exposes' the "provenance" part for future + /// use in [`from_exposed_addr`][]. + /// + /// This is equivalent to `self as usize`, which semantically discards *provenance* and + /// *address-space* information. Furthermore, this (like the `as` cast) has the implicit + /// side-effect of marking the provenance as 'exposed', so on platforms that support it you can + /// later call [`from_exposed_addr_mut`][] to reconstitute the original pointer including its + /// provenance. (Reconstructing address space information, if required, is your responsibility.) + /// + /// Using this method means that code is *not* following Strict Provenance rules. Supporting + /// [`from_exposed_addr_mut`][] complicates specification and reasoning and may not be supported + /// by tools that help you to stay conformant with the Rust memory model, so it is recommended + /// to use [`addr`][pointer::addr] wherever possible. + /// + /// On most platforms this will produce a value with the same bytes as the original pointer, + /// because all the bytes are dedicated to describing the address. Platforms which need to store + /// additional information in the pointer may not support this operation, since the 'expose' + /// side-effect which is required for [`from_exposed_addr_mut`][] to work is typically not + /// available. + /// + /// This API and its claimed semantics are part of the Strict Provenance experiment, see the + /// [module documentation][crate::ptr] for details. + /// + /// [`from_exposed_addr_mut`]: from_exposed_addr_mut + #[must_use] + #[inline] + #[unstable(feature = "strict_provenance", issue = "95228")] + pub fn expose_addr(self) -> usize + where + T: Sized, + { + // FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic. + self as usize + } + /// Creates a new pointer with the given address. /// /// This performs the same operation as an `addr as ptr` cast, but copies @@ -1313,7 +1356,6 @@ const fn ctfe_impl<T>(_: *mut T, _: usize) -> usize { } } -#[cfg_attr(bootstrap, lang = "mut_slice_ptr")] impl<T> *mut [T] { /// Returns the length of a raw slice. ///
diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index 7516d4b..6f40292 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs
@@ -256,8 +256,10 @@ pub const fn to_raw_parts(self) -> (NonNull<()>, <T as super::Pointee>::Metadata /// Gets the "address" portion of the pointer. /// + /// For more details see the equivalent method on a raw pointer, [`pointer::addr`]. + /// /// This API and its claimed semantics are part of the Strict Provenance experiment, - /// see the [module documentation][crate::ptr] for details. + /// see the [`ptr` module documentation][crate::ptr]. #[must_use] #[inline] #[unstable(feature = "strict_provenance", issue = "95228")] @@ -272,8 +274,10 @@ pub fn addr(self) -> NonZeroUsize /// Creates a new pointer with the given address. /// + /// For more details see the equivalent method on a raw pointer, [`pointer::with_addr`]. + /// /// This API and its claimed semantics are part of the Strict Provenance experiment, - /// see the [module documentation][crate::ptr] for details. + /// see the [`ptr` module documentation][crate::ptr]. #[must_use] #[inline] #[unstable(feature = "strict_provenance", issue = "95228")] @@ -287,10 +291,10 @@ pub fn with_addr(self, addr: NonZeroUsize) -> Self /// Creates a new pointer by mapping `self`'s address to a new one. /// - /// This is a convenience for [`with_addr`][Self::with_addr], see that method for details. + /// For more details see the equivalent method on a raw pointer, [`pointer::map_addr`]. /// /// This API and its claimed semantics are part of the Strict Provenance experiment, - /// see the [module documentation][crate::ptr] for details. + /// see the [`ptr` module documentation][crate::ptr]. #[must_use] #[inline] #[unstable(feature = "strict_provenance", issue = "95228")]
diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 641749b..b2b1323 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs
@@ -636,7 +636,7 @@ pub fn is_err_and(&self, f: impl FnOnce(&E) -> bool) -> bool { #[rustc_const_unstable(feature = "const_result_drop", issue = "92384")] pub const fn ok(self) -> Option<T> where - E: ~const Drop + ~const Destruct, + E: ~const Destruct, { match self { Ok(x) => Some(x), @@ -667,7 +667,7 @@ pub const fn ok(self) -> Option<T> #[rustc_const_unstable(feature = "const_result_drop", issue = "92384")] pub const fn err(self) -> Option<E> where - T: ~const Drop + ~const Destruct, + T: ~const Destruct, { match self { // FIXME: ~const Drop doesn't quite work right yet @@ -1283,9 +1283,9 @@ pub fn into_err(self) -> E #[stable(feature = "rust1", since = "1.0.0")] pub const fn and<U>(self, res: Result<U, E>) -> Result<U, E> where - T: ~const Drop + ~const Destruct, - U: ~const Drop + ~const Destruct, - E: ~const Drop + ~const Destruct, + T: ~const Destruct, + U: ~const Destruct, + E: ~const Destruct, { match self { // FIXME: ~const Drop doesn't quite work right yet @@ -1368,9 +1368,9 @@ pub fn and_then<U, F: FnOnce(T) -> Result<U, E>>(self, op: F) -> Result<U, E> { #[stable(feature = "rust1", since = "1.0.0")] pub const fn or<F>(self, res: Result<T, F>) -> Result<T, F> where - T: ~const Drop + ~const Destruct, - E: ~const Drop + ~const Destruct, - F: ~const Drop + ~const Destruct, + T: ~const Destruct, + E: ~const Destruct, + F: ~const Destruct, { match self { Ok(v) => Ok(v), @@ -1432,8 +1432,8 @@ pub fn or_else<F, O: FnOnce(E) -> Result<T, F>>(self, op: O) -> Result<T, F> { #[stable(feature = "rust1", since = "1.0.0")] pub const fn unwrap_or(self, default: T) -> T where - T: ~const Drop + ~const Destruct, - E: ~const Drop + ~const Destruct, + T: ~const Destruct, + E: ~const Destruct, { match self { Ok(t) => t, @@ -1803,11 +1803,10 @@ fn unwrap_failed<T>(_msg: &str, _error: &T) -> ! { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_clone", issue = "91805")] -#[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping impl<T, E> const Clone for Result<T, E> where - T: ~const Clone + ~const Drop + ~const Destruct, - E: ~const Clone + ~const Drop + ~const Destruct, + T: ~const Clone + ~const Destruct, + E: ~const Clone + ~const Destruct, { #[inline] fn clone(&self) -> Self {
diff --git a/library/core/src/slice/ascii.rs b/library/core/src/slice/ascii.rs index 7c00213..9aa5c88 100644 --- a/library/core/src/slice/ascii.rs +++ b/library/core/src/slice/ascii.rs
@@ -6,7 +6,6 @@ use crate::mem; use crate::ops; -#[cfg_attr(bootstrap, lang = "slice_u8")] #[cfg(not(test))] impl [u8] { /// Checks if all bytes in this slice are within the ASCII range.
diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs index 880d0f8..68de4e4 100644 --- a/library/core/src/slice/index.rs +++ b/library/core/src/slice/index.rs
@@ -140,6 +140,7 @@ impl Sealed for (ops::Bound<usize>, ops::Bound<usize>) {} /// Implementations of this trait have to promise that if the argument /// to `get_(mut_)unchecked` is a safe reference, then so is the result. #[stable(feature = "slice_get_slice", since = "1.28.0")] +#[rustc_diagnostic_item = "SliceIndex"] #[rustc_on_unimplemented( on(T = "str", label = "string indices are ranges of `usize`",), on(
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 17f6373..2240c29 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs
@@ -110,7 +110,6 @@ enum Direction { Back, } -#[cfg_attr(bootstrap, lang = "slice")] #[cfg(not(test))] impl<T> [T] { /// Returns the number of elements in the slice. @@ -814,7 +813,7 @@ pub fn windows(&self, size: usize) -> Windows<'_, T> { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn chunks(&self, chunk_size: usize) -> Chunks<'_, T> { - assert_ne!(chunk_size, 0); + assert_ne!(chunk_size, 0, "chunks cannot have a size of zero"); Chunks::new(self, chunk_size) } @@ -852,7 +851,7 @@ pub fn chunks(&self, chunk_size: usize) -> Chunks<'_, T> { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn chunks_mut(&mut self, chunk_size: usize) -> ChunksMut<'_, T> { - assert_ne!(chunk_size, 0); + assert_ne!(chunk_size, 0, "chunks cannot have a size of zero"); ChunksMut::new(self, chunk_size) } @@ -3993,6 +3992,88 @@ pub fn take_last_mut<'a>(self: &mut &'a mut Self) -> Option<&'a mut T> { } } +#[cfg(not(bootstrap))] +impl<T, const N: usize> [[T; N]] { + /// Takes a `&[[T; N]]`, and flattens it to a `&[T]`. + /// + /// # Panics + /// + /// This panics if the length of the resulting slice would overflow a `usize`. + /// + /// This is only possible when flattening a slice of arrays of zero-sized + /// types, and thus tends to be irrelevant in practice. If + /// `size_of::<T>() > 0`, this will never panic. + /// + /// # Examples + /// + /// ``` + /// #![feature(slice_flatten)] + /// + /// assert_eq!([[1, 2, 3], [4, 5, 6]].flatten(), &[1, 2, 3, 4, 5, 6]); + /// + /// assert_eq!( + /// [[1, 2, 3], [4, 5, 6]].flatten(), + /// [[1, 2], [3, 4], [5, 6]].flatten(), + /// ); + /// + /// let slice_of_empty_arrays: &[[i32; 0]] = &[[], [], [], [], []]; + /// assert!(slice_of_empty_arrays.flatten().is_empty()); + /// + /// let empty_slice_of_arrays: &[[u32; 10]] = &[]; + /// assert!(empty_slice_of_arrays.flatten().is_empty()); + /// ``` + #[unstable(feature = "slice_flatten", issue = "95629")] + pub fn flatten(&self) -> &[T] { + let len = if crate::mem::size_of::<T>() == 0 { + self.len().checked_mul(N).expect("slice len overflow") + } else { + // SAFETY: `self.len() * N` cannot overflow because `self` is + // already in the address space. + unsafe { self.len().unchecked_mul(N) } + }; + // SAFETY: `[T]` is layout-identical to `[T; N]` + unsafe { from_raw_parts(self.as_ptr().cast(), len) } + } + + /// Takes a `&mut [[T; N]]`, and flattens it to a `&mut [T]`. + /// + /// # Panics + /// + /// This panics if the length of the resulting slice would overflow a `usize`. + /// + /// This is only possible when flattening a slice of arrays of zero-sized + /// types, and thus tends to be irrelevant in practice. If + /// `size_of::<T>() > 0`, this will never panic. + /// + /// # Examples + /// + /// ``` + /// #![feature(slice_flatten)] + /// + /// fn add_5_to_all(slice: &mut [i32]) { + /// for i in slice { + /// *i += 5; + /// } + /// } + /// + /// let mut array = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]; + /// add_5_to_all(array.flatten_mut()); + /// assert_eq!(array, [[6, 7, 8], [9, 10, 11], [12, 13, 14]]); + /// ``` + #[unstable(feature = "slice_flatten", issue = "95629")] + pub fn flatten_mut(&mut self) -> &mut [T] { + let len = if crate::mem::size_of::<T>() == 0 { + self.len().checked_mul(N).expect("slice len overflow") + } else { + // SAFETY: `self.len() * N` cannot overflow because `self` is + // already in the address space. + unsafe { self.len().unchecked_mul(N) } + }; + // SAFETY: `[T]` is layout-identical to `[T; N]` + unsafe { from_raw_parts_mut(self.as_mut_ptr().cast(), len) } + } +} + trait CloneFromSpec<T> { fn spec_clone_from(&mut self, src: &[T]); }
diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 6bfa6a5..86e1afa 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs
@@ -130,7 +130,6 @@ fn slice_error_fail_rt(s: &str, begin: usize, end: usize) -> ! { ); } -#[cfg_attr(bootstrap, lang = "str")] #[cfg(not(test))] impl str { /// Returns the length of `self`. @@ -1832,14 +1831,14 @@ pub fn rmatch_indices<'a, P>(&'a self, pat: P) -> RMatchIndices<'a, P> /// Returns a string slice with leading and trailing whitespace removed. /// /// 'Whitespace' is defined according to the terms of the Unicode Derived - /// Core Property `White_Space`. + /// Core Property `White_Space`, which includes newlines. /// /// # Examples /// /// Basic usage: /// /// ``` - /// let s = " Hello\tworld\t"; + /// let s = "\n Hello\tworld\t\n"; /// /// assert_eq!("Hello\tworld", s.trim()); /// ``` @@ -1855,7 +1854,7 @@ pub fn trim(&self) -> &str { /// Returns a string slice with leading whitespace removed. /// /// 'Whitespace' is defined according to the terms of the Unicode Derived - /// Core Property `White_Space`. + /// Core Property `White_Space`, which includes newlines. /// /// # Text directionality /// @@ -1869,8 +1868,8 @@ pub fn trim(&self) -> &str { /// Basic usage: /// /// ``` - /// let s = " Hello\tworld\t"; - /// assert_eq!("Hello\tworld\t", s.trim_start()); + /// let s = "\n Hello\tworld\t\n"; + /// assert_eq!("Hello\tworld\t\n", s.trim_start()); /// ``` /// /// Directionality: @@ -1894,7 +1893,7 @@ pub fn trim_start(&self) -> &str { /// Returns a string slice with trailing whitespace removed. /// /// 'Whitespace' is defined according to the terms of the Unicode Derived - /// Core Property `White_Space`. + /// Core Property `White_Space`, which includes newlines. /// /// # Text directionality /// @@ -1908,8 +1907,8 @@ pub fn trim_start(&self) -> &str { /// Basic usage: /// /// ``` - /// let s = " Hello\tworld\t"; - /// assert_eq!(" Hello\tworld", s.trim_end()); + /// let s = "\n Hello\tworld\t\n"; + /// assert_eq!("\n Hello\tworld", s.trim_end()); /// ``` /// /// Directionality: @@ -2407,7 +2406,7 @@ pub fn eq_ignore_ascii_case(&self, other: &str) -> bool { #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[inline] pub fn make_ascii_uppercase(&mut self) { - // SAFETY: safe because we transmute two types with the same layout. + // SAFETY: changing ASCII letters only does not invalidate UTF-8. let me = unsafe { self.as_bytes_mut() }; me.make_ascii_uppercase() } @@ -2434,7 +2433,7 @@ pub fn make_ascii_uppercase(&mut self) { #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[inline] pub fn make_ascii_lowercase(&mut self) { - // SAFETY: safe because we transmute two types with the same layout. + // SAFETY: changing ASCII letters only does not invalidate UTF-8. let me = unsafe { self.as_bytes_mut() }; me.make_ascii_lowercase() }
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 3af277a..09e2e04 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs
@@ -93,6 +93,7 @@ #![feature(const_array_from_ref)] #![feature(const_slice_from_ref)] #![feature(waker_getters)] +#![feature(slice_flatten)] #![deny(unsafe_op_in_unsafe_fn)] extern crate test;
diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs index 798fcc3..ada4791 100644 --- a/library/core/tests/slice.rs +++ b/library/core/tests/slice.rs
@@ -2504,3 +2504,19 @@ fn test_slice_from_ptr_range() { assert_eq!(slice::from_ptr_range(range), &arr); } } + +#[test] +#[cfg(not(bootstrap))] +#[should_panic = "slice len overflow"] +fn test_flatten_size_overflow() { + let x = &[[(); usize::MAX]; 2][..]; + let _ = x.flatten(); +} + +#[test] +#[cfg(not(bootstrap))] +#[should_panic = "slice len overflow"] +fn test_flatten_mut_size_overflow() { + let x = &mut [[(); usize::MAX]; 2][..]; + let _ = x.flatten_mut(); +}
diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index 5338cd0..4a020e5 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs
@@ -20,8 +20,6 @@ #![feature(rustc_allow_const_fn_unstable)] #![feature(nll)] #![feature(staged_api)] -#![cfg_attr(bootstrap, feature(const_fn_trait_bound))] -#![cfg_attr(bootstrap, feature(const_fn_fn_ptr_basics))] #![feature(allow_internal_unstable)] #![feature(decl_macro)] #![feature(extern_types)]
diff --git a/library/std/src/alloc.rs b/library/std/src/alloc.rs index ae11964..49b6cd4 100644 --- a/library/std/src/alloc.rs +++ b/library/std/src/alloc.rs
@@ -315,14 +315,11 @@ pub fn take_alloc_error_hook() -> fn(Layout) { } fn default_alloc_error_hook(layout: Layout) { - #[cfg(not(bootstrap))] extern "Rust" { // This symbol is emitted by rustc next to __rust_alloc_error_handler. // Its value depends on the -Zoom={panic,abort} compiler option. static __rust_alloc_error_handler_should_panic: u8; } - #[cfg(bootstrap)] - let __rust_alloc_error_handler_should_panic = 0; #[allow(unused_unsafe)] if unsafe { __rust_alloc_error_handler_should_panic != 0 } {
diff --git a/library/std/src/f32.rs b/library/std/src/f32.rs index 70b5941..ac288c5 100644 --- a/library/std/src/f32.rs +++ b/library/std/src/f32.rs
@@ -28,7 +28,6 @@ }; #[cfg(not(test))] -#[cfg_attr(bootstrap, lang = "f32_runtime")] impl f32 { /// Returns the largest integer less than or equal to a number. /// @@ -43,7 +42,7 @@ impl f32 { /// assert_eq!(g.floor(), 3.0); /// assert_eq!(h.floor(), -4.0); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -62,7 +61,7 @@ pub fn floor(self) -> f32 { /// assert_eq!(f.ceil(), 4.0); /// assert_eq!(g.ceil(), 4.0); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -82,7 +81,7 @@ pub fn ceil(self) -> f32 { /// assert_eq!(f.round(), 3.0); /// assert_eq!(g.round(), -3.0); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -103,7 +102,7 @@ pub fn round(self) -> f32 { /// assert_eq!(g.trunc(), 3.0); /// assert_eq!(h.trunc(), -3.0); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -124,7 +123,7 @@ pub fn trunc(self) -> f32 { /// assert!(abs_difference_x <= f32::EPSILON); /// assert!(abs_difference_y <= f32::EPSILON); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -149,7 +148,7 @@ pub fn fract(self) -> f32 { /// /// assert!(f32::NAN.abs().is_nan()); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -173,7 +172,7 @@ pub fn abs(self) -> f32 { /// /// assert!(f32::NAN.signum().is_nan()); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -200,7 +199,7 @@ pub fn signum(self) -> f32 { /// /// assert!(f32::NAN.copysign(1.0).is_nan()); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[inline] #[stable(feature = "copysign", since = "1.35.0")] @@ -228,7 +227,7 @@ pub fn copysign(self, sign: f32) -> f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -253,7 +252,7 @@ pub fn mul_add(self, a: f32, b: f32) -> f32 { /// assert_eq!(a.div_euclid(-b), -1.0); // 7.0 >= -4.0 * -1.0 /// assert_eq!((-a).div_euclid(-b), 2.0); // -7.0 >= -4.0 * 2.0 /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[inline] #[stable(feature = "euclidean_division", since = "1.38.0")] @@ -288,7 +287,7 @@ pub fn div_euclid(self, rhs: f32) -> f32 { /// // limitation due to round-off error /// assert!((-f32::EPSILON).rem_euclid(3.0) != 0.0); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[inline] #[stable(feature = "euclidean_division", since = "1.38.0")] @@ -309,7 +308,7 @@ pub fn rem_euclid(self, rhs: f32) -> f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -327,7 +326,7 @@ pub fn powi(self, n: i32) -> f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -352,7 +351,7 @@ pub fn powf(self, n: f32) -> f32 { /// assert!(negative.sqrt().is_nan()); /// assert!(negative_zero.sqrt() == negative_zero); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -374,7 +373,7 @@ pub fn sqrt(self) -> f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -394,7 +393,7 @@ pub fn exp(self) -> f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -416,7 +415,7 @@ pub fn exp2(self) -> f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -440,7 +439,7 @@ pub fn ln(self) -> f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -460,7 +459,7 @@ pub fn log(self, base: f32) -> f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -483,7 +482,7 @@ pub fn log2(self) -> f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -508,7 +507,7 @@ pub fn log10(self) -> f32 { /// assert!(abs_difference_x <= f32::EPSILON); /// assert!(abs_difference_y <= f32::EPSILON); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -538,7 +537,7 @@ pub fn abs_sub(self, other: f32) -> f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -560,7 +559,7 @@ pub fn cbrt(self) -> f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -579,7 +578,7 @@ pub fn hypot(self, other: f32) -> f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -598,7 +597,7 @@ pub fn sin(self) -> f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -616,7 +615,7 @@ pub fn cos(self) -> f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -638,7 +637,7 @@ pub fn tan(self) -> f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -660,7 +659,7 @@ pub fn asin(self) -> f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -681,7 +680,7 @@ pub fn acos(self) -> f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -715,7 +714,7 @@ pub fn atan(self) -> f32 { /// assert!(abs_difference_1 <= f32::EPSILON); /// assert!(abs_difference_2 <= f32::EPSILON); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -738,7 +737,7 @@ pub fn atan2(self, other: f32) -> f32 { /// assert!(abs_difference_0 <= f32::EPSILON); /// assert!(abs_difference_1 <= f32::EPSILON); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn sin_cos(self) -> (f32, f32) { @@ -759,7 +758,7 @@ pub fn sin_cos(self) -> (f32, f32) { /// /// assert!(abs_difference < 1e-10); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -781,7 +780,7 @@ pub fn exp_m1(self) -> f32 { /// /// assert!(abs_difference < 1e-10); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -804,7 +803,7 @@ pub fn ln_1p(self) -> f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -827,7 +826,7 @@ pub fn sinh(self) -> f32 { /// // Same result /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -850,7 +849,7 @@ pub fn cosh(self) -> f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -870,7 +869,7 @@ pub fn tanh(self) -> f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -890,7 +889,7 @@ pub fn asinh(self) -> f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -910,7 +909,7 @@ pub fn acosh(self) -> f32 { /// /// assert!(abs_difference <= 1e-5); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline]
diff --git a/library/std/src/f64.rs b/library/std/src/f64.rs index b90d068..01279f01 100644 --- a/library/std/src/f64.rs +++ b/library/std/src/f64.rs
@@ -28,7 +28,6 @@ }; #[cfg(not(test))] -#[cfg_attr(bootstrap, lang = "f64_runtime")] impl f64 { /// Returns the largest integer less than or equal to a number. /// @@ -43,7 +42,7 @@ impl f64 { /// assert_eq!(g.floor(), 3.0); /// assert_eq!(h.floor(), -4.0); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -62,7 +61,7 @@ pub fn floor(self) -> f64 { /// assert_eq!(f.ceil(), 4.0); /// assert_eq!(g.ceil(), 4.0); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -82,7 +81,7 @@ pub fn ceil(self) -> f64 { /// assert_eq!(f.round(), 3.0); /// assert_eq!(g.round(), -3.0); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -103,7 +102,7 @@ pub fn round(self) -> f64 { /// assert_eq!(g.trunc(), 3.0); /// assert_eq!(h.trunc(), -3.0); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -124,7 +123,7 @@ pub fn trunc(self) -> f64 { /// assert!(abs_difference_x < 1e-10); /// assert!(abs_difference_y < 1e-10); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -149,7 +148,7 @@ pub fn fract(self) -> f64 { /// /// assert!(f64::NAN.abs().is_nan()); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -173,7 +172,7 @@ pub fn abs(self) -> f64 { /// /// assert!(f64::NAN.signum().is_nan()); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -200,7 +199,7 @@ pub fn signum(self) -> f64 { /// /// assert!(f64::NAN.copysign(1.0).is_nan()); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "copysign", since = "1.35.0")] #[inline] @@ -228,7 +227,7 @@ pub fn copysign(self, sign: f64) -> f64 { /// /// assert!(abs_difference < 1e-10); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -253,7 +252,7 @@ pub fn mul_add(self, a: f64, b: f64) -> f64 { /// assert_eq!(a.div_euclid(-b), -1.0); // 7.0 >= -4.0 * -1.0 /// assert_eq!((-a).div_euclid(-b), 2.0); // -7.0 >= -4.0 * 2.0 /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[inline] #[stable(feature = "euclidean_division", since = "1.38.0")] @@ -288,7 +287,7 @@ pub fn div_euclid(self, rhs: f64) -> f64 { /// // limitation due to round-off error /// assert!((-f64::EPSILON).rem_euclid(3.0) != 0.0); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[inline] #[stable(feature = "euclidean_division", since = "1.38.0")] @@ -309,7 +308,7 @@ pub fn rem_euclid(self, rhs: f64) -> f64 { /// /// assert!(abs_difference < 1e-10); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -327,7 +326,7 @@ pub fn powi(self, n: i32) -> f64 { /// /// assert!(abs_difference < 1e-10); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -352,7 +351,7 @@ pub fn powf(self, n: f64) -> f64 { /// assert!(negative.sqrt().is_nan()); /// assert!(negative_zero.sqrt() == negative_zero); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -374,7 +373,7 @@ pub fn sqrt(self) -> f64 { /// /// assert!(abs_difference < 1e-10); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -394,7 +393,7 @@ pub fn exp(self) -> f64 { /// /// assert!(abs_difference < 1e-10); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -416,7 +415,7 @@ pub fn exp2(self) -> f64 { /// /// assert!(abs_difference < 1e-10); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -440,7 +439,7 @@ pub fn ln(self) -> f64 { /// /// assert!(abs_difference < 1e-10); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -460,7 +459,7 @@ pub fn log(self, base: f64) -> f64 { /// /// assert!(abs_difference < 1e-10); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -485,7 +484,7 @@ pub fn log2(self) -> f64 { /// /// assert!(abs_difference < 1e-10); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -510,7 +509,7 @@ pub fn log10(self) -> f64 { /// assert!(abs_difference_x < 1e-10); /// assert!(abs_difference_y < 1e-10); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -540,7 +539,7 @@ pub fn abs_sub(self, other: f64) -> f64 { /// /// assert!(abs_difference < 1e-10); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -562,7 +561,7 @@ pub fn cbrt(self) -> f64 { /// /// assert!(abs_difference < 1e-10); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -581,7 +580,7 @@ pub fn hypot(self, other: f64) -> f64 { /// /// assert!(abs_difference < 1e-10); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -600,7 +599,7 @@ pub fn sin(self) -> f64 { /// /// assert!(abs_difference < 1e-10); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -618,7 +617,7 @@ pub fn cos(self) -> f64 { /// /// assert!(abs_difference < 1e-14); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -640,7 +639,7 @@ pub fn tan(self) -> f64 { /// /// assert!(abs_difference < 1e-10); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -662,7 +661,7 @@ pub fn asin(self) -> f64 { /// /// assert!(abs_difference < 1e-10); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -683,7 +682,7 @@ pub fn acos(self) -> f64 { /// /// assert!(abs_difference < 1e-10); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -717,7 +716,7 @@ pub fn atan(self) -> f64 { /// assert!(abs_difference_1 < 1e-10); /// assert!(abs_difference_2 < 1e-10); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -740,7 +739,7 @@ pub fn atan2(self, other: f64) -> f64 { /// assert!(abs_difference_0 < 1e-10); /// assert!(abs_difference_1 < 1e-10); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn sin_cos(self) -> (f64, f64) { @@ -761,7 +760,7 @@ pub fn sin_cos(self) -> (f64, f64) { /// /// assert!(abs_difference < 1e-20); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -783,7 +782,7 @@ pub fn exp_m1(self) -> f64 { /// /// assert!(abs_difference < 1e-20); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -806,7 +805,7 @@ pub fn ln_1p(self) -> f64 { /// /// assert!(abs_difference < 1e-10); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -829,7 +828,7 @@ pub fn sinh(self) -> f64 { /// // Same result /// assert!(abs_difference < 1.0e-10); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -852,7 +851,7 @@ pub fn cosh(self) -> f64 { /// /// assert!(abs_difference < 1.0e-10); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -872,7 +871,7 @@ pub fn tanh(self) -> f64 { /// /// assert!(abs_difference < 1.0e-10); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -892,7 +891,7 @@ pub fn asinh(self) -> f64 { /// /// assert!(abs_difference < 1.0e-10); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -912,7 +911,7 @@ pub fn acosh(self) -> f64 { /// /// assert!(abs_difference < 1.0e-10); /// ``` - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -923,7 +922,7 @@ pub fn atanh(self) -> f64 { // Solaris/Illumos requires a wrapper around log, log2, and log10 functions // because of their non-standard behavior (e.g., log(-n) returns -Inf instead // of expected NaN). - #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] + #[rustc_allow_incoherent_impl] fn log_wrapper<F: Fn(f64) -> f64>(self, log_fn: F) -> f64 { if !cfg!(any(target_os = "solaris", target_os = "illumos")) { log_fn(self)
diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 46acd0e..10c4242 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs
@@ -85,6 +85,12 @@ /// by different processes. Avoid assuming that holding a `&File` means that the /// file will not change. /// +/// # Platform-specific behavior +/// +/// On Windows, the implementation of [`Read`] and [`Write`] traits for `File` +/// perform synchronous I/O operations. Therefore the underlying file must not +/// have been opened for asynchronous I/O (e.g. by using `FILE_FLAG_OVERLAPPED`). +/// /// [`BufReader<R>`]: io::BufReader /// [`sync_all`]: File::sync_all #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs index 3fa731c..e8d0132 100644 --- a/library/std/src/fs/tests.rs +++ b/library/std/src/fs/tests.rs
@@ -644,9 +644,9 @@ fn recursive_rmdir_toctou() { // Test for time-of-check to time-of-use issues. // // Scenario: - // The attacker wants to get directory contents deleted, to which he does not have access. - // He has a way to get a privileged Rust binary call `std::fs::remove_dir_all()` on a - // directory he controls, e.g. in his home directory. + // The attacker wants to get directory contents deleted, to which they do not have access. + // They have a way to get a privileged Rust binary call `std::fs::remove_dir_all()` on a + // directory they control, e.g. in their home directory. // // The POC sets up the `attack_dest/attack_file` which the attacker wants to have deleted. // The attacker repeatedly creates a directory and replaces it with a symlink from
diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs index ac6d41e..ae16015 100644 --- a/library/std/src/io/stdio.rs +++ b/library/std/src/io/stdio.rs
@@ -394,7 +394,6 @@ pub fn read_line(&self, buf: &mut String) -> io::Result<usize> { /// # Examples /// /// ```no_run - /// #![feature(stdin_forwarders)] /// use std::io; /// /// let lines = io::stdin().lines(); @@ -403,7 +402,7 @@ pub fn read_line(&self, buf: &mut String) -> io::Result<usize> { /// } /// ``` #[must_use = "`self` will be dropped if the result is not used"] - #[unstable(feature = "stdin_forwarders", issue = "87096")] + #[stable(feature = "stdin_forwarders", since = "1.62.0")] pub fn lines(self) -> Lines<StdinLock<'static>> { self.lock().lines() }
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index e1c1800..5ade65a 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs
@@ -228,12 +228,10 @@ #![feature(c_unwind)] #![feature(cfg_target_thread_local)] #![feature(concat_idents)] -#![cfg_attr(bootstrap, feature(const_fn_fn_ptr_basics))] -#![cfg_attr(bootstrap, feature(const_fn_trait_bound))] #![feature(const_mut_refs)] #![feature(const_trait_impl)] #![feature(decl_macro)] -#![cfg_attr(not(bootstrap), feature(deprecated_suggestion))] +#![feature(deprecated_suggestion)] #![feature(doc_cfg)] #![feature(doc_cfg_hide)] #![feature(doc_masked)] @@ -285,7 +283,6 @@ #![feature(std_internals)] #![feature(str_internals)] #![feature(strict_provenance)] -#![feature(total_cmp)] // // Library features (alloc): #![feature(alloc_layout_extra)]
diff --git a/library/std/src/os/unix/net/ancillary.rs b/library/std/src/os/unix/net/ancillary.rs index fb1ff4b..658c798 100644 --- a/library/std/src/os/unix/net/ancillary.rs +++ b/library/std/src/os/unix/net/ancillary.rs
@@ -10,7 +10,7 @@ use crate::sys::net::Socket; // FIXME(#43348): Make libc adapt #[doc(cfg(...))] so we don't need these fake definitions here? -#[cfg(all(doc, not(target_os = "linux"), not(target_os = "android")))] +#[cfg(all(doc, not(target_os = "linux"), not(target_os = "android"), not(target_os = "netbsd")))] #[allow(non_camel_case_types)] mod libc { pub use libc::c_int; @@ -177,13 +177,24 @@ fn next(&mut self) -> Option<T> { } } +#[cfg(all(doc, not(target_os = "android"), not(target_os = "linux"), not(target_os = "netbsd")))] +#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] +#[derive(Clone)] +pub struct SocketCred(()); + /// Unix credential. -#[cfg(any(doc, target_os = "android", target_os = "linux",))] +#[cfg(any(target_os = "android", target_os = "linux",))] #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] #[derive(Clone)] pub struct SocketCred(libc::ucred); -#[cfg(any(doc, target_os = "android", target_os = "linux",))] +#[cfg(target_os = "netbsd")] +#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] +#[derive(Clone)] +pub struct SocketCred(libc::sockcred); + +#[doc(cfg(any(target_os = "android", target_os = "linux")))] +#[cfg(any(target_os = "android", target_os = "linux"))] impl SocketCred { /// Create a Unix credential struct. /// @@ -234,6 +245,61 @@ pub fn get_gid(&self) -> libc::gid_t { } } +#[cfg(target_os = "netbsd")] +impl SocketCred { + /// Create a Unix credential struct. + /// + /// PID, UID and GID is set to 0. + #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] + pub fn new() -> SocketCred { + SocketCred(libc::sockcred { + sc_pid: 0, + sc_uid: 0, + sc_euid: 0, + sc_gid: 0, + sc_egid: 0, + sc_ngroups: 0, + sc_groups: [0u32; 1], + }) + } + + /// Set the PID. + #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] + pub fn set_pid(&mut self, pid: libc::pid_t) { + self.0.sc_pid = pid; + } + + /// Get the current PID. + #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] + pub fn get_pid(&self) -> libc::pid_t { + self.0.sc_pid + } + + /// Set the UID. + #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] + pub fn set_uid(&mut self, uid: libc::uid_t) { + self.0.sc_uid = uid; + } + + /// Get the current UID. + #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] + pub fn get_uid(&self) -> libc::uid_t { + self.0.sc_uid + } + + /// Set the GID. + #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] + pub fn set_gid(&mut self, gid: libc::gid_t) { + self.0.sc_gid = gid; + } + + /// Get the current GID. + #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] + pub fn get_gid(&self) -> libc::gid_t { + self.0.sc_gid + } +} + /// This control message contains file descriptors. /// /// The level is equal to `SOL_SOCKET` and the type is equal to `SCM_RIGHTS`. @@ -249,14 +315,22 @@ fn next(&mut self) -> Option<RawFd> { } } +#[cfg(all(doc, not(target_os = "android"), not(target_os = "linux"), not(target_os = "netbsd")))] +#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] +pub struct ScmCredentials<'a>(AncillaryDataIter<'a, ()>); + /// This control message contains unix credentials. /// /// The level is equal to `SOL_SOCKET` and the type is equal to `SCM_CREDENTIALS` or `SCM_CREDS`. -#[cfg(any(doc, target_os = "android", target_os = "linux",))] +#[cfg(any(target_os = "android", target_os = "linux",))] #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] pub struct ScmCredentials<'a>(AncillaryDataIter<'a, libc::ucred>); -#[cfg(any(doc, target_os = "android", target_os = "linux",))] +#[cfg(target_os = "netbsd")] +#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] +pub struct ScmCredentials<'a>(AncillaryDataIter<'a, libc::sockcred>); + +#[cfg(any(doc, target_os = "android", target_os = "linux", target_os = "netbsd",))] #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] impl<'a> Iterator for ScmCredentials<'a> { type Item = SocketCred; @@ -278,7 +352,7 @@ pub enum AncillaryError { #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] pub enum AncillaryData<'a> { ScmRights(ScmRights<'a>), - #[cfg(any(doc, target_os = "android", target_os = "linux",))] + #[cfg(any(doc, target_os = "android", target_os = "linux", target_os = "netbsd",))] ScmCredentials(ScmCredentials<'a>), } @@ -300,8 +374,8 @@ unsafe fn as_rights(data: &'a [u8]) -> Self { /// # Safety /// /// `data` must contain a valid control message and the control message must be type of - /// `SOL_SOCKET` and level of `SCM_CREDENTIALS` or `SCM_CREDENTIALS`. - #[cfg(any(doc, target_os = "android", target_os = "linux",))] + /// `SOL_SOCKET` and level of `SCM_CREDENTIALS` or `SCM_CREDS`. + #[cfg(any(doc, target_os = "android", target_os = "linux", target_os = "netbsd",))] unsafe fn as_credentials(data: &'a [u8]) -> Self { let ancillary_data_iter = AncillaryDataIter::new(data); let scm_credentials = ScmCredentials(ancillary_data_iter); @@ -320,6 +394,8 @@ fn try_from_cmsghdr(cmsg: &'a libc::cmsghdr) -> Result<Self, AncillaryError> { libc::SCM_RIGHTS => Ok(AncillaryData::as_rights(data)), #[cfg(any(target_os = "android", target_os = "linux",))] libc::SCM_CREDENTIALS => Ok(AncillaryData::as_credentials(data)), + #[cfg(target_os = "netbsd")] + libc::SCM_CREDS => Ok(AncillaryData::as_credentials(data)), cmsg_type => { Err(AncillaryError::Unknown { cmsg_level: libc::SOL_SOCKET, cmsg_type }) } @@ -531,7 +607,7 @@ pub fn add_fds(&mut self, fds: &[RawFd]) -> bool { /// Technically, that means this operation adds a control message with the level `SOL_SOCKET` /// and type `SCM_CREDENTIALS` or `SCM_CREDS`. /// - #[cfg(any(doc, target_os = "android", target_os = "linux",))] + #[cfg(any(doc, target_os = "android", target_os = "linux", target_os = "netbsd",))] #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] pub fn add_creds(&mut self, creds: &[SocketCred]) -> bool { self.truncated = false; @@ -540,7 +616,10 @@ pub fn add_creds(&mut self, creds: &[SocketCred]) -> bool { &mut self.length, creds, libc::SOL_SOCKET, + #[cfg(not(target_os = "netbsd"))] libc::SCM_CREDENTIALS, + #[cfg(target_os = "netbsd")] + libc::SCM_CREDS, ) }
diff --git a/library/std/src/os/unix/net/datagram.rs b/library/std/src/os/unix/net/datagram.rs index 59c91e9..872058b 100644 --- a/library/std/src/os/unix/net/datagram.rs +++ b/library/std/src/os/unix/net/datagram.rs
@@ -865,7 +865,7 @@ pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { /// Ok(()) /// } /// ``` - #[cfg(any(doc, target_os = "android", target_os = "linux",))] + #[cfg(any(doc, target_os = "android", target_os = "linux", target_os = "netbsd",))] #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] pub fn set_passcred(&self, passcred: bool) -> io::Result<()> { self.0.set_passcred(passcred) @@ -877,7 +877,7 @@ pub fn set_passcred(&self, passcred: bool) -> io::Result<()> { /// Get the socket option `SO_PASSCRED`. /// /// [`set_passcred`]: UnixDatagram::set_passcred - #[cfg(any(doc, target_os = "android", target_os = "linux",))] + #[cfg(any(doc, target_os = "android", target_os = "linux", target_os = "netbsd",))] #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] pub fn passcred(&self) -> io::Result<bool> { self.0.passcred()
diff --git a/library/std/src/os/unix/net/stream.rs b/library/std/src/os/unix/net/stream.rs index 3943b4f..cd1aa01 100644 --- a/library/std/src/os/unix/net/stream.rs +++ b/library/std/src/os/unix/net/stream.rs
@@ -415,7 +415,7 @@ pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { /// Ok(()) /// } /// ``` - #[cfg(any(doc, target_os = "android", target_os = "linux",))] + #[cfg(any(doc, target_os = "android", target_os = "linux", target_os = "netbsd",))] #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] pub fn set_passcred(&self, passcred: bool) -> io::Result<()> { self.0.set_passcred(passcred) @@ -427,7 +427,7 @@ pub fn set_passcred(&self, passcred: bool) -> io::Result<()> { /// Get the socket option `SO_PASSCRED`. /// /// [`set_passcred`]: UnixStream::set_passcred - #[cfg(any(doc, target_os = "android", target_os = "linux",))] + #[cfg(any(doc, target_os = "android", target_os = "linux", target_os = "netbsd",))] #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] pub fn passcred(&self) -> io::Result<bool> { self.0.passcred()
diff --git a/library/std/src/os/windows/process.rs b/library/std/src/os/windows/process.rs index 9510d10..e189630 100644 --- a/library/std/src/os/windows/process.rs +++ b/library/std/src/os/windows/process.rs
@@ -159,7 +159,7 @@ pub trait CommandExt: Sealed { /// /// This is useful for passing arguments to `cmd.exe /c`, which doesn't follow /// `CommandLineToArgvW` escaping rules. - #[unstable(feature = "windows_process_extensions_raw_arg", issue = "29494")] + #[stable(feature = "windows_process_extensions_raw_arg", since = "1.62.0")] fn raw_arg<S: AsRef<OsStr>>(&mut self, text_to_append_as_is: S) -> &mut process::Command; }
diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs index 03de7ee..f1baf07 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs
@@ -20,7 +20,7 @@ use crate::sync::atomic::{AtomicBool, Ordering}; use crate::sys::stdio::panic_output; use crate::sys_common::backtrace; -use crate::sys_common::rwlock::StaticRWLock; +use crate::sys_common::rwlock::StaticRwLock; use crate::sys_common::thread_info; use crate::thread; @@ -83,7 +83,7 @@ fn custom(f: impl Fn(&PanicInfo<'_>) + 'static + Sync + Send) -> Self { } } -static HOOK_LOCK: StaticRWLock = StaticRWLock::new(); +static HOOK_LOCK: StaticRwLock = StaticRwLock::new(); static mut HOOK: Hook = Hook::Default; /// Registers a custom panic hook, replacing any that was previously registered.
diff --git a/library/std/src/sync/condvar/tests.rs b/library/std/src/sync/condvar/tests.rs index 6757707..f7a0067 100644 --- a/library/std/src/sync/condvar/tests.rs +++ b/library/std/src/sync/condvar/tests.rs
@@ -191,7 +191,7 @@ fn wait_timeout_wake() { #[test] #[should_panic] -#[cfg_attr(not(unix), ignore)] +#[cfg(all(unix, not(target_os = "linux"), not(target_os = "android")))] fn two_mutexes() { let m = Arc::new(Mutex::new(())); let m2 = m.clone();
diff --git a/library/std/src/sync/rwlock.rs b/library/std/src/sync/rwlock.rs index 2e72a9e..ed62fa9 100644 --- a/library/std/src/sync/rwlock.rs +++ b/library/std/src/sync/rwlock.rs
@@ -76,7 +76,7 @@ /// [`Mutex`]: super::Mutex #[stable(feature = "rust1", since = "1.0.0")] pub struct RwLock<T: ?Sized> { - inner: sys::MovableRWLock, + inner: sys::MovableRwLock, poison: poison::Flag, data: UnsafeCell<T>, } @@ -146,7 +146,7 @@ impl<T> RwLock<T> { #[stable(feature = "rust1", since = "1.0.0")] pub fn new(t: T) -> RwLock<T> { RwLock { - inner: sys::MovableRWLock::new(), + inner: sys::MovableRwLock::new(), poison: poison::Flag::new(), data: UnsafeCell::new(t), }
diff --git a/library/std/src/sys/hermit/rwlock.rs b/library/std/src/sys/hermit/rwlock.rs index 1cca809..690bb15 100644 --- a/library/std/src/sys/hermit/rwlock.rs +++ b/library/std/src/sys/hermit/rwlock.rs
@@ -1,13 +1,13 @@ use crate::cell::UnsafeCell; use crate::sys::locks::{Condvar, Mutex}; -pub struct RWLock { +pub struct RwLock { lock: Mutex, cond: Condvar, state: UnsafeCell<State>, } -pub type MovableRWLock = RWLock; +pub type MovableRwLock = RwLock; enum State { Unlocked, @@ -15,8 +15,8 @@ enum State { Writing, } -unsafe impl Send for RWLock {} -unsafe impl Sync for RWLock {} +unsafe impl Send for RwLock {} +unsafe impl Sync for RwLock {} // This rwlock implementation is a relatively simple implementation which has a // condition variable for readers/writers as well as a mutex protecting the @@ -26,9 +26,9 @@ unsafe impl Sync for RWLock {} // hopefully correct this implementation is very likely to want to be changed in // the future. -impl RWLock { - pub const fn new() -> RWLock { - RWLock { lock: Mutex::new(), cond: Condvar::new(), state: UnsafeCell::new(State::Unlocked) } +impl RwLock { + pub const fn new() -> RwLock { + RwLock { lock: Mutex::new(), cond: Condvar::new(), state: UnsafeCell::new(State::Unlocked) } } #[inline]
diff --git a/library/std/src/sys/sgx/rwlock.rs b/library/std/src/sys/sgx/rwlock.rs index 2d038b5..47be4c0 100644 --- a/library/std/src/sys/sgx/rwlock.rs +++ b/library/std/src/sys/sgx/rwlock.rs
@@ -8,25 +8,25 @@ }; use crate::mem; -pub struct RWLock { +pub struct RwLock { readers: SpinMutex<WaitVariable<Option<NonZeroUsize>>>, writer: SpinMutex<WaitVariable<bool>>, } -pub type MovableRWLock = Box<RWLock>; +pub type MovableRwLock = Box<RwLock>; -// Check at compile time that RWLock size matches C definition (see test_c_rwlock_initializer below) +// Check at compile time that RwLock size matches C definition (see test_c_rwlock_initializer below) // // # Safety // Never called, as it is a compile time check. #[allow(dead_code)] -unsafe fn rw_lock_size_assert(r: RWLock) { - unsafe { mem::transmute::<RWLock, [u8; 144]>(r) }; +unsafe fn rw_lock_size_assert(r: RwLock) { + unsafe { mem::transmute::<RwLock, [u8; 144]>(r) }; } -impl RWLock { - pub const fn new() -> RWLock { - RWLock { +impl RwLock { + pub const fn new() -> RwLock { + RwLock { readers: SpinMutex::new(WaitVariable::new(None)), writer: SpinMutex::new(WaitVariable::new(false)), } @@ -180,7 +180,7 @@ pub unsafe fn destroy(&self) {} #[cfg(not(test))] #[no_mangle] -pub unsafe extern "C" fn __rust_rwlock_rdlock(p: *mut RWLock) -> i32 { +pub unsafe extern "C" fn __rust_rwlock_rdlock(p: *mut RwLock) -> i32 { if p.is_null() { return EINVAL; } @@ -190,7 +190,7 @@ pub unsafe fn destroy(&self) {} #[cfg(not(test))] #[no_mangle] -pub unsafe extern "C" fn __rust_rwlock_wrlock(p: *mut RWLock) -> i32 { +pub unsafe extern "C" fn __rust_rwlock_wrlock(p: *mut RwLock) -> i32 { if p.is_null() { return EINVAL; } @@ -199,7 +199,7 @@ pub unsafe fn destroy(&self) {} } #[cfg(not(test))] #[no_mangle] -pub unsafe extern "C" fn __rust_rwlock_unlock(p: *mut RWLock) -> i32 { +pub unsafe extern "C" fn __rust_rwlock_unlock(p: *mut RwLock) -> i32 { if p.is_null() { return EINVAL; }
diff --git a/library/std/src/sys/sgx/rwlock/tests.rs b/library/std/src/sys/sgx/rwlock/tests.rs index 17c9e72..4799961 100644 --- a/library/std/src/sys/sgx/rwlock/tests.rs +++ b/library/std/src/sys/sgx/rwlock/tests.rs
@@ -1,7 +1,7 @@ use super::*; -// Verify that the byte pattern libunwind uses to initialize an RWLock is -// equivalent to the value of RWLock::new(). If the value changes, +// Verify that the byte pattern libunwind uses to initialize an RwLock is +// equivalent to the value of RwLock::new(). If the value changes, // `src/UnwindRustSgx.h` in libunwind needs to be changed too. #[test] fn test_c_rwlock_initializer() { @@ -18,9 +18,9 @@ fn test_c_rwlock_initializer() { /* 0x80 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ]; - // For the test to work, we need the padding/unused bytes in RWLock to be + // For the test to work, we need the padding/unused bytes in RwLock to be // initialized as 0. In practice, this is the case with statics. - static RUST_RWLOCK_INIT: RWLock = RWLock::new(); + static RUST_RWLOCK_INIT: RwLock = RwLock::new(); unsafe { // If the assertion fails, that not necessarily an issue with the value
diff --git a/library/std/src/sys/solid/os.rs b/library/std/src/sys/solid/os.rs index 127cca3..719d95b 100644 --- a/library/std/src/sys/solid/os.rs +++ b/library/std/src/sys/solid/os.rs
@@ -8,7 +8,7 @@ solid::ffi::{OsStrExt, OsStringExt}, }; use crate::path::{self, PathBuf}; -use crate::sys_common::rwlock::StaticRWLock; +use crate::sys_common::rwlock::StaticRwLock; use crate::vec; use super::{abi, error, itron, memchr}; @@ -78,7 +78,7 @@ pub fn current_exe() -> io::Result<PathBuf> { unsupported() } -static ENV_LOCK: StaticRWLock = StaticRWLock::new(); +static ENV_LOCK: StaticRwLock = StaticRwLock::new(); pub struct Env { iter: vec::IntoIter<(OsString, OsString)>,
diff --git a/library/std/src/sys/solid/rwlock.rs b/library/std/src/sys/solid/rwlock.rs index 4e39ac2..df16cc6 100644 --- a/library/std/src/sys/solid/rwlock.rs +++ b/library/std/src/sys/solid/rwlock.rs
@@ -7,24 +7,24 @@ }, }; -pub struct RWLock { +pub struct RwLock { /// The ID of the underlying mutex object rwl: SpinIdOnceCell<()>, } -pub type MovableRWLock = RWLock; +pub type MovableRwLock = RwLock; // Safety: `num_readers` is protected by `mtx_num_readers` -unsafe impl Send for RWLock {} -unsafe impl Sync for RWLock {} +unsafe impl Send for RwLock {} +unsafe impl Sync for RwLock {} fn new_rwl() -> Result<abi::ID, ItronError> { ItronError::err_if_negative(unsafe { abi::rwl_acre_rwl() }) } -impl RWLock { - pub const fn new() -> RWLock { - RWLock { rwl: SpinIdOnceCell::new() } +impl RwLock { + pub const fn new() -> RwLock { + RwLock { rwl: SpinIdOnceCell::new() } } /// Get the inner mutex's ID, which is lazily created.
diff --git a/library/std/src/sys/unix/futex.rs b/library/std/src/sys/unix/futex.rs index 42ddc1d..c61d948 100644 --- a/library/std/src/sys/unix/futex.rs +++ b/library/std/src/sys/unix/futex.rs
@@ -4,31 +4,46 @@ all(target_os = "emscripten", target_feature = "atomics") ))] -#[cfg(any(target_os = "linux", target_os = "android"))] -use crate::convert::TryInto; -#[cfg(any(target_os = "linux", target_os = "android"))] -use crate::ptr::null; use crate::sync::atomic::AtomicI32; use crate::time::Duration; #[cfg(any(target_os = "linux", target_os = "android"))] -pub fn futex_wait(futex: &AtomicI32, expected: i32, timeout: Option<Duration>) { - let timespec = timeout.and_then(|d| { - Some(libc::timespec { - // Sleep forever if the timeout is longer than fits in a timespec. - tv_sec: d.as_secs().try_into().ok()?, - // This conversion never truncates, as subsec_nanos is always <1e9. - tv_nsec: d.subsec_nanos() as _, - }) - }); - unsafe { - libc::syscall( - libc::SYS_futex, - futex as *const AtomicI32, - libc::FUTEX_WAIT | libc::FUTEX_PRIVATE_FLAG, - expected, - timespec.as_ref().map_or(null(), |d| d as *const libc::timespec), - ); +pub fn futex_wait(futex: &AtomicI32, expected: i32, timeout: Option<Duration>) -> bool { + use super::time::Timespec; + use crate::ptr::null; + use crate::sync::atomic::Ordering::Relaxed; + + // Calculate the timeout as an absolute timespec. + // + // Overflows are rounded up to an infinite timeout (None). + let timespec = + timeout.and_then(|d| Some(Timespec::now(libc::CLOCK_MONOTONIC).checked_add_duration(&d)?)); + + loop { + // No need to wait if the value already changed. + if futex.load(Relaxed) != expected { + return true; + } + + // Use FUTEX_WAIT_BITSET rather than FUTEX_WAIT to be able to give an + // absolute time rather than a relative time. + let r = unsafe { + libc::syscall( + libc::SYS_futex, + futex as *const AtomicI32, + libc::FUTEX_WAIT_BITSET | libc::FUTEX_PRIVATE_FLAG, + expected, + timespec.as_ref().map_or(null(), |t| &t.t as *const libc::timespec), + null::<u32>(), // This argument is unused for FUTEX_WAIT_BITSET. + !0u32, // A full bitmask, to make it behave like a regular FUTEX_WAIT. + ) + }; + + match (r < 0).then(super::os::errno) { + Some(libc::ETIMEDOUT) => return false, + Some(libc::EINTR) => continue, + _ => return true, + } } } @@ -65,6 +80,18 @@ pub fn futex_wake(futex: &AtomicI32) { } } +#[cfg(any(target_os = "linux", target_os = "android"))] +pub fn futex_wake_all(futex: &AtomicI32) { + unsafe { + libc::syscall( + libc::SYS_futex, + futex as *const AtomicI32, + libc::FUTEX_WAKE | libc::FUTEX_PRIVATE_FLAG, + i32::MAX, + ); + } +} + #[cfg(target_os = "emscripten")] pub fn futex_wake(futex: &AtomicI32) { extern "C" {
diff --git a/library/std/src/sys/unix/locks/futex.rs b/library/std/src/sys/unix/locks/futex.rs new file mode 100644 index 0000000..630351d --- /dev/null +++ b/library/std/src/sys/unix/locks/futex.rs
@@ -0,0 +1,164 @@ +use crate::sync::atomic::{ + AtomicI32, + Ordering::{Acquire, Relaxed, Release}, +}; +use crate::sys::futex::{futex_wait, futex_wake, futex_wake_all}; +use crate::time::Duration; + +pub type MovableMutex = Mutex; +pub type MovableCondvar = Condvar; + +pub struct Mutex { + /// 0: unlocked + /// 1: locked, no other threads waiting + /// 2: locked, and other threads waiting (contended) + futex: AtomicI32, +} + +impl Mutex { + #[inline] + pub const fn new() -> Self { + Self { futex: AtomicI32::new(0) } + } + + #[inline] + pub unsafe fn init(&mut self) {} + + #[inline] + pub unsafe fn destroy(&self) {} + + #[inline] + pub unsafe fn try_lock(&self) -> bool { + self.futex.compare_exchange(0, 1, Acquire, Relaxed).is_ok() + } + + #[inline] + pub unsafe fn lock(&self) { + if self.futex.compare_exchange(0, 1, Acquire, Relaxed).is_err() { + self.lock_contended(); + } + } + + #[cold] + fn lock_contended(&self) { + // Spin first to speed things up if the lock is released quickly. + let mut state = self.spin(); + + // If it's unlocked now, attempt to take the lock + // without marking it as contended. + if state == 0 { + match self.futex.compare_exchange(0, 1, Acquire, Relaxed) { + Ok(_) => return, // Locked! + Err(s) => state = s, + } + } + + loop { + // Put the lock in contended state. + // We avoid an unnecessary write if it as already set to 2, + // to be friendlier for the caches. + if state != 2 && self.futex.swap(2, Acquire) == 0 { + // We changed it from 0 to 2, so we just succesfully locked it. + return; + } + + // Wait for the futex to change state, assuming it is still 2. + futex_wait(&self.futex, 2, None); + + // Spin again after waking up. + state = self.spin(); + } + } + + fn spin(&self) -> i32 { + let mut spin = 100; + loop { + // We only use `load` (and not `swap` or `compare_exchange`) + // while spinning, to be easier on the caches. + let state = self.futex.load(Relaxed); + + // We stop spinning when the mutex is unlocked (0), + // but also when it's contended (2). + if state != 1 || spin == 0 { + return state; + } + + crate::hint::spin_loop(); + spin -= 1; + } + } + + #[inline] + pub unsafe fn unlock(&self) { + if self.futex.swap(0, Release) == 2 { + // We only wake up one thread. When that thread locks the mutex, it + // will mark the mutex as contended (2) (see lock_contended above), + // which makes sure that any other waiting threads will also be + // woken up eventually. + self.wake(); + } + } + + #[cold] + fn wake(&self) { + futex_wake(&self.futex); + } +} + +pub struct Condvar { + // The value of this atomic is simply incremented on every notification. + // This is used by `.wait()` to not miss any notifications after + // unlocking the mutex and before waiting for notifications. + futex: AtomicI32, +} + +impl Condvar { + #[inline] + pub const fn new() -> Self { + Self { futex: AtomicI32::new(0) } + } + + #[inline] + pub unsafe fn init(&mut self) {} + + #[inline] + pub unsafe fn destroy(&self) {} + + // All the memory orderings here are `Relaxed`, + // because synchronization is done by unlocking and locking the mutex. + + pub unsafe fn notify_one(&self) { + self.futex.fetch_add(1, Relaxed); + futex_wake(&self.futex); + } + + pub unsafe fn notify_all(&self) { + self.futex.fetch_add(1, Relaxed); + futex_wake_all(&self.futex); + } + + pub unsafe fn wait(&self, mutex: &Mutex) { + self.wait_optional_timeout(mutex, None); + } + + pub unsafe fn wait_timeout(&self, mutex: &Mutex, timeout: Duration) -> bool { + self.wait_optional_timeout(mutex, Some(timeout)) + } + + unsafe fn wait_optional_timeout(&self, mutex: &Mutex, timeout: Option<Duration>) -> bool { + // Examine the notification counter _before_ we unlock the mutex. + let futex_value = self.futex.load(Relaxed); + + // Unlock the mutex before going to sleep. + mutex.unlock(); + + // Wait, but only if there hasn't been any + // notification since we unlocked the mutex. + let r = futex_wait(&self.futex, futex_value, timeout); + + // Lock the mutex again. + mutex.lock(); + + r + } +}
diff --git a/library/std/src/sys/unix/locks/mod.rs b/library/std/src/sys/unix/locks/mod.rs index f07a9f9..2b8dd16 100644 --- a/library/std/src/sys/unix/locks/mod.rs +++ b/library/std/src/sys/unix/locks/mod.rs
@@ -1,8 +1,24 @@ -mod pthread_condvar; -mod pthread_mutex; -mod pthread_remutex; -mod pthread_rwlock; -pub use pthread_condvar::{Condvar, MovableCondvar}; -pub use pthread_mutex::{MovableMutex, Mutex}; -pub use pthread_remutex::ReentrantMutex; -pub use pthread_rwlock::{MovableRWLock, RWLock}; +cfg_if::cfg_if! { + if #[cfg(any( + target_os = "linux", + target_os = "android", + ))] { + mod futex; + #[allow(dead_code)] + mod pthread_mutex; // Only used for PthreadMutexAttr, needed by pthread_remutex. + mod pthread_remutex; // FIXME: Implement this using a futex + mod pthread_rwlock; // FIXME: Implement this using a futex + pub use futex::{Mutex, MovableMutex, Condvar, MovableCondvar}; + pub use pthread_remutex::ReentrantMutex; + pub use pthread_rwlock::{RwLock, MovableRwLock}; + } else { + mod pthread_mutex; + mod pthread_remutex; + mod pthread_rwlock; + mod pthread_condvar; + pub use pthread_mutex::{Mutex, MovableMutex}; + pub use pthread_remutex::ReentrantMutex; + pub use pthread_rwlock::{RwLock, MovableRwLock}; + pub use pthread_condvar::{Condvar, MovableCondvar}; + } +}
diff --git a/library/std/src/sys/unix/locks/pthread_rwlock.rs b/library/std/src/sys/unix/locks/pthread_rwlock.rs index 1318c5b..11a0c04 100644 --- a/library/std/src/sys/unix/locks/pthread_rwlock.rs +++ b/library/std/src/sys/unix/locks/pthread_rwlock.rs
@@ -1,20 +1,20 @@ use crate::cell::UnsafeCell; use crate::sync::atomic::{AtomicUsize, Ordering}; -pub struct RWLock { +pub struct RwLock { inner: UnsafeCell<libc::pthread_rwlock_t>, write_locked: UnsafeCell<bool>, // guarded by the `inner` RwLock num_readers: AtomicUsize, } -pub type MovableRWLock = Box<RWLock>; +pub type MovableRwLock = Box<RwLock>; -unsafe impl Send for RWLock {} -unsafe impl Sync for RWLock {} +unsafe impl Send for RwLock {} +unsafe impl Sync for RwLock {} -impl RWLock { - pub const fn new() -> RWLock { - RWLock { +impl RwLock { + pub const fn new() -> RwLock { + RwLock { inner: UnsafeCell::new(libc::PTHREAD_RWLOCK_INITIALIZER), write_locked: UnsafeCell::new(false), num_readers: AtomicUsize::new(0),
diff --git a/library/std/src/sys/unix/net.rs b/library/std/src/sys/unix/net.rs index e6fd9a0..9bf9607 100644 --- a/library/std/src/sys/unix/net.rs +++ b/library/std/src/sys/unix/net.rs
@@ -419,6 +419,17 @@ pub fn passcred(&self) -> io::Result<bool> { Ok(passcred != 0) } + #[cfg(target_os = "netbsd")] + pub fn set_passcred(&self, passcred: bool) -> io::Result<()> { + setsockopt(self, 0 as libc::c_int, libc::LOCAL_CREDS, passcred as libc::c_int) + } + + #[cfg(target_os = "netbsd")] + pub fn passcred(&self) -> io::Result<bool> { + let passcred: libc::c_int = getsockopt(self, 0 as libc::c_int, libc::LOCAL_CREDS)?; + Ok(passcred != 0) + } + #[cfg(not(any(target_os = "solaris", target_os = "illumos")))] pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { let mut nonblocking = nonblocking as libc::c_int;
diff --git a/library/std/src/sys/unix/os.rs b/library/std/src/sys/unix/os.rs index 0b6cdb9..1be733b 100644 --- a/library/std/src/sys/unix/os.rs +++ b/library/std/src/sys/unix/os.rs
@@ -20,7 +20,7 @@ use crate::sys::cvt; use crate::sys::fd; use crate::sys::memchr; -use crate::sys_common::rwlock::{StaticRWLock, StaticRWLockReadGuard}; +use crate::sys_common::rwlock::{StaticRwLock, StaticRwLockReadGuard}; use crate::vec; #[cfg(all(target_env = "gnu", not(target_os = "vxworks")))] @@ -481,9 +481,9 @@ pub unsafe fn environ() -> *mut *const *const c_char { ptr::addr_of_mut!(environ) } -static ENV_LOCK: StaticRWLock = StaticRWLock::new(); +static ENV_LOCK: StaticRwLock = StaticRwLock::new(); -pub fn env_read_lock() -> StaticRWLockReadGuard { +pub fn env_read_lock() -> StaticRwLockReadGuard { ENV_LOCK.read() }
diff --git a/library/std/src/sys/unix/stack_overflow.rs b/library/std/src/sys/unix/stack_overflow.rs index 1e8d113..75a5c0f 100644 --- a/library/std/src/sys/unix/stack_overflow.rs +++ b/library/std/src/sys/unix/stack_overflow.rs
@@ -54,22 +54,6 @@ mod imp { use crate::sys::unix::os::page_size; use crate::sys_common::thread_info; - #[cfg(any(target_os = "linux", target_os = "android"))] - unsafe fn siginfo_si_addr(info: *mut libc::siginfo_t) -> usize { - #[repr(C)] - struct siginfo_t { - a: [libc::c_int; 3], // si_signo, si_errno, si_code - si_addr: *mut libc::c_void, - } - - (*(info as *const siginfo_t)).si_addr as usize - } - - #[cfg(not(any(target_os = "linux", target_os = "android")))] - unsafe fn siginfo_si_addr(info: *mut libc::siginfo_t) -> usize { - (*info).si_addr as usize - } - // Signal handler for the SIGSEGV and SIGBUS handlers. We've got guard pages // (unmapped pages) at the end of every thread's stack, so if a thread ends // up running into the guard page it'll trigger this handler. We want to @@ -97,7 +81,7 @@ unsafe fn siginfo_si_addr(info: *mut libc::siginfo_t) -> usize { _data: *mut libc::c_void, ) { let guard = thread_info::stack_guard().unwrap_or(0..0); - let addr = siginfo_si_addr(info); + let addr = (*info).si_addr() as usize; // If the faulting address is within the guard page, then we print a // message saying so and abort.
diff --git a/library/std/src/sys/unix/thread.rs b/library/std/src/sys/unix/thread.rs index bb4e4ee..d191e1f 100644 --- a/library/std/src/sys/unix/thread.rs +++ b/library/std/src/sys/unix/thread.rs
@@ -122,7 +122,13 @@ pub fn set_name(name: &CStr) { // pthread wrapper only appeared in glibc 2.12, so we use syscall // directly. unsafe { - libc::prctl(PR_SET_NAME, name.as_ptr() as libc::c_ulong, 0, 0, 0); + libc::prctl( + PR_SET_NAME, + name.as_ptr(), + 0 as libc::c_ulong, + 0 as libc::c_ulong, + 0 as libc::c_ulong, + ); } }
diff --git a/library/std/src/sys/unix/time.rs b/library/std/src/sys/unix/time.rs index 59ddd1a..498c94d 100644 --- a/library/std/src/sys/unix/time.rs +++ b/library/std/src/sys/unix/time.rs
@@ -9,8 +9,8 @@ const NSEC_PER_SEC: u64 = 1_000_000_000; #[derive(Copy, Clone)] -struct Timespec { - t: libc::timespec, +pub(in crate::sys::unix) struct Timespec { + pub t: libc::timespec, } impl Timespec { @@ -18,7 +18,7 @@ const fn zero() -> Timespec { Timespec { t: libc::timespec { tv_sec: 0, tv_nsec: 0 } } } - fn sub_timespec(&self, other: &Timespec) -> Result<Duration, Duration> { + pub fn sub_timespec(&self, other: &Timespec) -> Result<Duration, Duration> { if self >= other { // NOTE(eddyb) two aspects of this `if`-`else` are required for LLVM // to optimize it into a branchless form (see also #75545): @@ -51,7 +51,7 @@ fn sub_timespec(&self, other: &Timespec) -> Result<Duration, Duration> { } } - fn checked_add_duration(&self, other: &Duration) -> Option<Timespec> { + pub fn checked_add_duration(&self, other: &Duration) -> Option<Timespec> { let mut secs = other .as_secs() .try_into() // <- target type would be `libc::time_t` @@ -68,7 +68,7 @@ fn checked_add_duration(&self, other: &Duration) -> Option<Timespec> { Some(Timespec { t: libc::timespec { tv_sec: secs, tv_nsec: nsec as _ } }) } - fn checked_sub_duration(&self, other: &Duration) -> Option<Timespec> { + pub fn checked_sub_duration(&self, other: &Duration) -> Option<Timespec> { let mut secs = other .as_secs() .try_into() // <- target type would be `libc::time_t` @@ -266,6 +266,7 @@ fn info_from_bits(bits: u64) -> mach_timebase_info { #[cfg(not(any(target_os = "macos", target_os = "ios")))] mod inner { use crate::fmt; + use crate::mem::MaybeUninit; use crate::sys::cvt; use crate::time::Duration; @@ -285,7 +286,7 @@ pub struct SystemTime { impl Instant { pub fn now() -> Instant { - Instant { t: now(libc::CLOCK_MONOTONIC) } + Instant { t: Timespec::now(libc::CLOCK_MONOTONIC) } } pub fn checked_sub_instant(&self, other: &Instant) -> Option<Duration> { @@ -312,7 +313,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { impl SystemTime { pub fn now() -> SystemTime { - SystemTime { t: now(libc::CLOCK_REALTIME) } + SystemTime { t: Timespec::now(libc::CLOCK_REALTIME) } } pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> { @@ -348,9 +349,11 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { #[cfg(any(target_os = "dragonfly", target_os = "espidf"))] pub type clock_t = libc::c_ulong; - fn now(clock: clock_t) -> Timespec { - let mut t = Timespec { t: libc::timespec { tv_sec: 0, tv_nsec: 0 } }; - cvt(unsafe { libc::clock_gettime(clock, &mut t.t) }).unwrap(); - t + impl Timespec { + pub fn now(clock: clock_t) -> Timespec { + let mut t = MaybeUninit::uninit(); + cvt(unsafe { libc::clock_gettime(clock, t.as_mut_ptr()) }).unwrap(); + Timespec { t: unsafe { t.assume_init() } } + } } }
diff --git a/library/std/src/sys/unsupported/locks/mod.rs b/library/std/src/sys/unsupported/locks/mod.rs index 5634f10..35bd591 100644 --- a/library/std/src/sys/unsupported/locks/mod.rs +++ b/library/std/src/sys/unsupported/locks/mod.rs
@@ -3,4 +3,4 @@ mod rwlock; pub use condvar::{Condvar, MovableCondvar}; pub use mutex::{MovableMutex, Mutex, ReentrantMutex}; -pub use rwlock::{MovableRWLock, RWLock}; +pub use rwlock::{MovableRwLock, RwLock};
diff --git a/library/std/src/sys/unsupported/locks/rwlock.rs b/library/std/src/sys/unsupported/locks/rwlock.rs index 8438ade..14fd351 100644 --- a/library/std/src/sys/unsupported/locks/rwlock.rs +++ b/library/std/src/sys/unsupported/locks/rwlock.rs
@@ -1,18 +1,18 @@ use crate::cell::Cell; -pub struct RWLock { +pub struct RwLock { // This platform has no threads, so we can use a Cell here. mode: Cell<isize>, } -pub type MovableRWLock = RWLock; +pub type MovableRwLock = RwLock; -unsafe impl Send for RWLock {} -unsafe impl Sync for RWLock {} // no threads on this platform +unsafe impl Send for RwLock {} +unsafe impl Sync for RwLock {} // no threads on this platform -impl RWLock { - pub const fn new() -> RWLock { - RWLock { mode: Cell::new(0) } +impl RwLock { + pub const fn new() -> RwLock { + RwLock { mode: Cell::new(0) } } #[inline]
diff --git a/library/std/src/sys/wasm/atomics/rwlock.rs b/library/std/src/sys/wasm/atomics/rwlock.rs index 1cca809..690bb15 100644 --- a/library/std/src/sys/wasm/atomics/rwlock.rs +++ b/library/std/src/sys/wasm/atomics/rwlock.rs
@@ -1,13 +1,13 @@ use crate::cell::UnsafeCell; use crate::sys::locks::{Condvar, Mutex}; -pub struct RWLock { +pub struct RwLock { lock: Mutex, cond: Condvar, state: UnsafeCell<State>, } -pub type MovableRWLock = RWLock; +pub type MovableRwLock = RwLock; enum State { Unlocked, @@ -15,8 +15,8 @@ enum State { Writing, } -unsafe impl Send for RWLock {} -unsafe impl Sync for RWLock {} +unsafe impl Send for RwLock {} +unsafe impl Sync for RwLock {} // This rwlock implementation is a relatively simple implementation which has a // condition variable for readers/writers as well as a mutex protecting the @@ -26,9 +26,9 @@ unsafe impl Sync for RWLock {} // hopefully correct this implementation is very likely to want to be changed in // the future. -impl RWLock { - pub const fn new() -> RWLock { - RWLock { lock: Mutex::new(), cond: Condvar::new(), state: UnsafeCell::new(State::Unlocked) } +impl RwLock { + pub const fn new() -> RwLock { + RwLock { lock: Mutex::new(), cond: Condvar::new(), state: UnsafeCell::new(State::Unlocked) } } #[inline]
diff --git a/library/std/src/sys/windows/c.rs b/library/std/src/sys/windows/c.rs index 0edf43e..336264d 100644 --- a/library/std/src/sys/windows/c.rs +++ b/library/std/src/sys/windows/c.rs
@@ -274,6 +274,9 @@ pub struct ipv6_mreq { pub const STATUS_DELETE_PENDING: NTSTATUS = 0xc0000056_u32 as _; pub const STATUS_INVALID_PARAMETER: NTSTATUS = 0xc000000d_u32 as _; +pub const STATUS_PENDING: NTSTATUS = 0x103 as _; +pub const STATUS_END_OF_FILE: NTSTATUS = 0xC0000011_u32 as _; + // Equivalent to the `NT_SUCCESS` C preprocessor macro. // See: https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/using-ntstatus-values pub fn nt_success(status: NTSTATUS) -> bool { @@ -316,15 +319,33 @@ fn default() -> Self { } } #[repr(C)] -pub struct IO_STATUS_BLOCK { - pub Pointer: *mut c_void, - pub Information: usize, +union IO_STATUS_BLOCK_union { + Status: NTSTATUS, + Pointer: *mut c_void, } -impl Default for IO_STATUS_BLOCK { +impl Default for IO_STATUS_BLOCK_union { fn default() -> Self { - Self { Pointer: ptr::null_mut(), Information: 0 } + Self { Pointer: ptr::null_mut() } } } +#[repr(C)] +#[derive(Default)] +pub struct IO_STATUS_BLOCK { + u: IO_STATUS_BLOCK_union, + pub Information: usize, +} + +pub type LPOVERLAPPED_COMPLETION_ROUTINE = unsafe extern "system" fn( + dwErrorCode: DWORD, + dwNumberOfBytesTransfered: DWORD, + lpOverlapped: *mut OVERLAPPED, +); + +type IO_APC_ROUTINE = unsafe extern "system" fn( + ApcContext: *mut c_void, + IoStatusBlock: *mut IO_STATUS_BLOCK, + Reserved: ULONG, +); #[repr(C)] #[cfg(not(target_pointer_width = "64"))] @@ -891,6 +912,7 @@ pub fn CreateThread( pub fn WaitForSingleObject(hHandle: HANDLE, dwMilliseconds: DWORD) -> DWORD; pub fn SwitchToThread() -> BOOL; pub fn Sleep(dwMilliseconds: DWORD); + pub fn SleepEx(dwMilliseconds: DWORD, bAlertable: BOOL) -> DWORD; pub fn GetProcessId(handle: HANDLE) -> DWORD; pub fn CopyFileExW( lpExistingFileName: LPCWSTR, @@ -957,12 +979,19 @@ pub fn ReadFile( lpNumberOfBytesRead: LPDWORD, lpOverlapped: LPOVERLAPPED, ) -> BOOL; - pub fn WriteFile( + pub fn ReadFileEx( + hFile: BorrowedHandle<'_>, + lpBuffer: LPVOID, + nNumberOfBytesToRead: DWORD, + lpOverlapped: LPOVERLAPPED, + lpCompletionRoutine: LPOVERLAPPED_COMPLETION_ROUTINE, + ) -> BOOL; + pub fn WriteFileEx( hFile: BorrowedHandle<'_>, lpBuffer: LPVOID, nNumberOfBytesToWrite: DWORD, - lpNumberOfBytesWritten: LPDWORD, lpOverlapped: LPOVERLAPPED, + lpCompletionRoutine: LPOVERLAPPED_COMPLETION_ROUTINE, ) -> BOOL; pub fn CloseHandle(hObject: HANDLE) -> BOOL; pub fn MoveFileExW(lpExistingFileName: LPCWSTR, lpNewFileName: LPCWSTR, dwFlags: DWORD) @@ -1247,6 +1276,32 @@ pub fn NtCreateFile( ) -> NTSTATUS { panic!("`NtCreateFile` not available"); } + pub fn NtReadFile( + FileHandle: BorrowedHandle<'_>, + Event: HANDLE, + ApcRoutine: Option<IO_APC_ROUTINE>, + ApcContext: *mut c_void, + IoStatusBlock: &mut IO_STATUS_BLOCK, + Buffer: *mut crate::mem::MaybeUninit<u8>, + Length: ULONG, + ByteOffset: Option<&LARGE_INTEGER>, + Key: Option<&ULONG> + ) -> NTSTATUS { + panic!("`NtReadFile` not available"); + } + pub fn NtWriteFile( + FileHandle: BorrowedHandle<'_>, + Event: HANDLE, + ApcRoutine: Option<IO_APC_ROUTINE>, + ApcContext: *mut c_void, + IoStatusBlock: &mut IO_STATUS_BLOCK, + Buffer: *const u8, + Length: ULONG, + ByteOffset: Option<&LARGE_INTEGER>, + Key: Option<&ULONG> + ) -> NTSTATUS { + panic!("`NtWriteFile` not available"); + } pub fn RtlNtStatusToDosError( Status: NTSTATUS ) -> ULONG {
diff --git a/library/std/src/sys/windows/handle.rs b/library/std/src/sys/windows/handle.rs index e5c9567..ef9a8bd 100644 --- a/library/std/src/sys/windows/handle.rs +++ b/library/std/src/sys/windows/handle.rs
@@ -74,20 +74,10 @@ unsafe fn from_raw_handle(raw_handle: RawHandle) -> Self { impl Handle { pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> { - let mut read = 0; - let len = cmp::min(buf.len(), <c::DWORD>::MAX as usize) as c::DWORD; - let res = cvt(unsafe { - c::ReadFile( - self.as_handle(), - buf.as_mut_ptr() as c::LPVOID, - len, - &mut read, - ptr::null_mut(), - ) - }); + let res = unsafe { self.synchronous_read(buf.as_mut_ptr().cast(), buf.len(), None) }; match res { - Ok(_) => Ok(read as usize), + Ok(read) => Ok(read as usize), // The special treatment of BrokenPipe is to deal with Windows // pipe semantics, which yields this error when *reading* from @@ -109,42 +99,23 @@ pub fn is_read_vectored(&self) -> bool { } pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> { - let mut read = 0; - let len = cmp::min(buf.len(), <c::DWORD>::MAX as usize) as c::DWORD; - let res = unsafe { - let mut overlapped: c::OVERLAPPED = mem::zeroed(); - overlapped.Offset = offset as u32; - overlapped.OffsetHigh = (offset >> 32) as u32; - cvt(c::ReadFile( - self.as_handle(), - buf.as_mut_ptr() as c::LPVOID, - len, - &mut read, - &mut overlapped, - )) - }; + let res = + unsafe { self.synchronous_read(buf.as_mut_ptr().cast(), buf.len(), Some(offset)) }; + match res { - Ok(_) => Ok(read as usize), + Ok(read) => Ok(read as usize), Err(ref e) if e.raw_os_error() == Some(c::ERROR_HANDLE_EOF as i32) => Ok(0), Err(e) => Err(e), } } pub fn read_buf(&self, buf: &mut ReadBuf<'_>) -> io::Result<()> { - let mut read = 0; - let len = cmp::min(buf.remaining(), <c::DWORD>::MAX as usize) as c::DWORD; - let res = cvt(unsafe { - c::ReadFile( - self.as_handle(), - buf.unfilled_mut().as_mut_ptr() as c::LPVOID, - len, - &mut read, - ptr::null_mut(), - ) - }); + let res = unsafe { + self.synchronous_read(buf.unfilled_mut().as_mut_ptr(), buf.remaining(), None) + }; match res { - Ok(_) => { + Ok(read) => { // Safety: `read` bytes were written to the initialized portion of the buffer unsafe { buf.assume_init(read as usize); @@ -221,18 +192,7 @@ pub fn cancel_io(&self) -> io::Result<()> { } pub fn write(&self, buf: &[u8]) -> io::Result<usize> { - let mut amt = 0; - let len = cmp::min(buf.len(), <c::DWORD>::MAX as usize) as c::DWORD; - cvt(unsafe { - c::WriteFile( - self.as_handle(), - buf.as_ptr() as c::LPVOID, - len, - &mut amt, - ptr::null_mut(), - ) - })?; - Ok(amt as usize) + self.synchronous_write(&buf, None) } pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { @@ -245,21 +205,7 @@ pub fn is_write_vectored(&self) -> bool { } pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> { - let mut written = 0; - let len = cmp::min(buf.len(), <c::DWORD>::MAX as usize) as c::DWORD; - unsafe { - let mut overlapped: c::OVERLAPPED = mem::zeroed(); - overlapped.Offset = offset as u32; - overlapped.OffsetHigh = (offset >> 32) as u32; - cvt(c::WriteFile( - self.as_handle(), - buf.as_ptr() as c::LPVOID, - len, - &mut written, - &mut overlapped, - ))?; - } - Ok(written as usize) + self.synchronous_write(&buf, Some(offset)) } pub fn try_clone(&self) -> io::Result<Self> { @@ -274,6 +220,97 @@ pub fn duplicate( ) -> io::Result<Self> { Ok(Self(self.0.duplicate(access, inherit, options)?)) } + + /// Performs a synchronous read. + /// + /// If the handle is opened for asynchronous I/O then this abort the process. + /// See #81357. + /// + /// If `offset` is `None` then the current file position is used. + unsafe fn synchronous_read( + &self, + buf: *mut mem::MaybeUninit<u8>, + len: usize, + offset: Option<u64>, + ) -> io::Result<usize> { + let mut io_status = c::IO_STATUS_BLOCK::default(); + + // The length is clamped at u32::MAX. + let len = cmp::min(len, c::DWORD::MAX as usize) as c::DWORD; + let status = c::NtReadFile( + self.as_handle(), + ptr::null_mut(), + None, + ptr::null_mut(), + &mut io_status, + buf, + len, + offset.map(|n| n as _).as_ref(), + None, + ); + match status { + // If the operation has not completed then abort the process. + // Doing otherwise means that the buffer and stack may be written to + // after this function returns. + c::STATUS_PENDING => { + eprintln!("I/O error: operation failed to complete synchronously"); + crate::process::abort(); + } + + // Return `Ok(0)` when there's nothing more to read. + c::STATUS_END_OF_FILE => Ok(0), + + // Success! + status if c::nt_success(status) => Ok(io_status.Information), + + status => { + let error = c::RtlNtStatusToDosError(status); + Err(io::Error::from_raw_os_error(error as _)) + } + } + } + + /// Performs a synchronous write. + /// + /// If the handle is opened for asynchronous I/O then this abort the process. + /// See #81357. + /// + /// If `offset` is `None` then the current file position is used. + fn synchronous_write(&self, buf: &[u8], offset: Option<u64>) -> io::Result<usize> { + let mut io_status = c::IO_STATUS_BLOCK::default(); + + // The length is clamped at u32::MAX. + let len = cmp::min(buf.len(), c::DWORD::MAX as usize) as c::DWORD; + let status = unsafe { + c::NtWriteFile( + self.as_handle(), + ptr::null_mut(), + None, + ptr::null_mut(), + &mut io_status, + buf.as_ptr(), + len, + offset.map(|n| n as _).as_ref(), + None, + ) + }; + match status { + // If the operation has not completed then abort the process. + // Doing otherwise means that the buffer may be read and the stack + // written to after this function returns. + c::STATUS_PENDING => { + rtabort!("I/O error: operation failed to complete synchronously"); + } + + // Success! + status if c::nt_success(status) => Ok(io_status.Information), + + status => { + let error = unsafe { c::RtlNtStatusToDosError(status) }; + Err(io::Error::from_raw_os_error(error as _)) + } + } + } } impl<'a> Read for &'a Handle {
diff --git a/library/std/src/sys/windows/locks/mod.rs b/library/std/src/sys/windows/locks/mod.rs index 5634f10..35bd591 100644 --- a/library/std/src/sys/windows/locks/mod.rs +++ b/library/std/src/sys/windows/locks/mod.rs
@@ -3,4 +3,4 @@ mod rwlock; pub use condvar::{Condvar, MovableCondvar}; pub use mutex::{MovableMutex, Mutex, ReentrantMutex}; -pub use rwlock::{MovableRWLock, RWLock}; +pub use rwlock::{MovableRwLock, RwLock};
diff --git a/library/std/src/sys/windows/locks/rwlock.rs b/library/std/src/sys/windows/locks/rwlock.rs index b7a5b1e..1290665 100644 --- a/library/std/src/sys/windows/locks/rwlock.rs +++ b/library/std/src/sys/windows/locks/rwlock.rs
@@ -1,18 +1,18 @@ use crate::cell::UnsafeCell; use crate::sys::c; -pub struct RWLock { +pub struct RwLock { inner: UnsafeCell<c::SRWLOCK>, } -pub type MovableRWLock = RWLock; +pub type MovableRwLock = RwLock; -unsafe impl Send for RWLock {} -unsafe impl Sync for RWLock {} +unsafe impl Send for RwLock {} +unsafe impl Sync for RwLock {} -impl RWLock { - pub const fn new() -> RWLock { - RWLock { inner: UnsafeCell::new(c::SRWLOCK_INIT) } +impl RwLock { + pub const fn new() -> RwLock { + RwLock { inner: UnsafeCell::new(c::SRWLOCK_INIT) } } #[inline] pub unsafe fn read(&self) {
diff --git a/library/std/src/sys/windows/pipe.rs b/library/std/src/sys/windows/pipe.rs index 63d3d6c..df4f1b2 100644 --- a/library/std/src/sys/windows/pipe.rs +++ b/library/std/src/sys/windows/pipe.rs
@@ -173,6 +173,15 @@ fn random_number() -> usize { } } +// Abstracts over `ReadFileEx` and `WriteFileEx` +type AlertableIoFn = unsafe extern "system" fn( + BorrowedHandle<'_>, + c::LPVOID, + c::DWORD, + c::LPOVERLAPPED, + c::LPOVERLAPPED_COMPLETION_ROUTINE, +) -> c::BOOL; + impl AnonPipe { pub fn handle(&self) -> &Handle { &self.inner @@ -182,7 +191,19 @@ pub fn into_handle(self) -> Handle { } pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> { - self.inner.read(buf) + let result = unsafe { + let len = crate::cmp::min(buf.len(), c::DWORD::MAX as usize) as c::DWORD; + self.alertable_io_internal(c::ReadFileEx, buf.as_mut_ptr() as _, len) + }; + + match result { + // The special treatment of BrokenPipe is to deal with Windows + // pipe semantics, which yields this error when *reading* from + // a pipe after the other end has closed; we interpret that as + // EOF on the pipe. + Err(ref e) if e.kind() == io::ErrorKind::BrokenPipe => Ok(0), + _ => result, + } } pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { @@ -195,7 +216,10 @@ pub fn is_read_vectored(&self) -> bool { } pub fn write(&self, buf: &[u8]) -> io::Result<usize> { - self.inner.write(buf) + unsafe { + let len = crate::cmp::min(buf.len(), c::DWORD::MAX as usize) as c::DWORD; + self.alertable_io_internal(c::WriteFileEx, buf.as_ptr() as _, len) + } } pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { @@ -206,6 +230,99 @@ pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { pub fn is_write_vectored(&self) -> bool { self.inner.is_write_vectored() } + + /// Synchronizes asynchronous reads or writes using our anonymous pipe. + /// + /// This is a wrapper around [`ReadFileEx`] or [`WriteFileEx`] that uses + /// [Asynchronous Procedure Call] (APC) to synchronize reads or writes. + /// + /// Note: This should not be used for handles we don't create. + /// + /// # Safety + /// + /// `buf` must be a pointer to a buffer that's valid for reads or writes + /// up to `len` bytes. The `AlertableIoFn` must be either `ReadFileEx` or `WriteFileEx` + /// + /// [`ReadFileEx`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-readfileex + /// [`WriteFileEx`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-writefileex + /// [Asynchronous Procedure Call]: https://docs.microsoft.com/en-us/windows/win32/sync/asynchronous-procedure-calls + unsafe fn alertable_io_internal( + &self, + io: AlertableIoFn, + buf: c::LPVOID, + len: c::DWORD, + ) -> io::Result<usize> { + // Use "alertable I/O" to synchronize the pipe I/O. + // This has four steps. + // + // STEP 1: Start the asynchronous I/O operation. + // This simply calls either `ReadFileEx` or `WriteFileEx`, + // giving it a pointer to the buffer and callback function. + // + // STEP 2: Enter an alertable state. + // The callback set in step 1 will not be called until the thread + // enters an "alertable" state. This can be done using `SleepEx`. + // + // STEP 3: The callback + // Once the I/O is complete and the thread is in an alertable state, + // the callback will be run on the same thread as the call to + // `ReadFileEx` or `WriteFileEx` done in step 1. + // In the callback we simply set the result of the async operation. + // + // STEP 4: Return the result. + // At this point we'll have a result from the callback function + // and can simply return it. Note that we must not return earlier, + // while the I/O is still in progress. + + // The result that will be set from the asynchronous callback. + let mut async_result: Option<AsyncResult> = None; + struct AsyncResult { + error: u32, + transfered: u32, + } + + // STEP 3: The callback. + unsafe extern "system" fn callback( + dwErrorCode: u32, + dwNumberOfBytesTransfered: u32, + lpOverlapped: *mut c::OVERLAPPED, + ) { + // Set `async_result` using a pointer smuggled through `hEvent`. + let result = AsyncResult { error: dwErrorCode, transfered: dwNumberOfBytesTransfered }; + *(*lpOverlapped).hEvent.cast::<Option<AsyncResult>>() = Some(result); + } + + // STEP 1: Start the I/O operation. + let mut overlapped: c::OVERLAPPED = crate::mem::zeroed(); + // `hEvent` is unused by `ReadFileEx` and `WriteFileEx`. + // Therefore the documentation suggests using it to smuggle a pointer to the callback. + overlapped.hEvent = &mut async_result as *mut _ as *mut _; + + // Asynchronous read of the pipe. + // If successful, `callback` will be called once it completes. + let result = io(self.inner.as_handle(), buf, len, &mut overlapped, callback); + if result == c::FALSE { + // We can return here because the call failed. + // After this we must not return until the I/O completes. + return Err(io::Error::last_os_error()); + } + + // Wait indefinitely for the result. + let result = loop { + // STEP 2: Enter an alertable state. + // The second parameter of `SleepEx` is used to make this sleep alertable. + c::SleepEx(c::INFINITE, c::TRUE); + if let Some(result) = async_result { + break result; + } + }; + // STEP 4: Return the result. + // `async_result` is always `Some` at this point + match result.error { + c::ERROR_SUCCESS => Ok(result.transfered as usize), + error => Err(io::Error::from_raw_os_error(error as _)), + } + } } pub fn read2(p1: AnonPipe, v1: &mut Vec<u8>, p2: AnonPipe, v2: &mut Vec<u8>) -> io::Result<()> {
diff --git a/library/std/src/sys_common/rwlock.rs b/library/std/src/sys_common/rwlock.rs index eaee631..12e7a72 100644 --- a/library/std/src/sys_common/rwlock.rs +++ b/library/std/src/sys_common/rwlock.rs
@@ -4,14 +4,14 @@ /// /// This rwlock does not implement poisoning. /// -/// This rwlock has a const constructor ([`StaticRWLock::new`]), does not +/// This rwlock has a const constructor ([`StaticRwLock::new`]), does not /// implement `Drop` to cleanup resources. -pub struct StaticRWLock(imp::RWLock); +pub struct StaticRwLock(imp::RwLock); -impl StaticRWLock { +impl StaticRwLock { /// Creates a new rwlock for use. pub const fn new() -> Self { - Self(imp::RWLock::new()) + Self(imp::RwLock::new()) } /// Acquires shared access to the underlying lock, blocking the current @@ -19,9 +19,9 @@ pub const fn new() -> Self { /// /// The lock is automatically unlocked when the returned guard is dropped. #[inline] - pub fn read(&'static self) -> StaticRWLockReadGuard { + pub fn read(&'static self) -> StaticRwLockReadGuard { unsafe { self.0.read() }; - StaticRWLockReadGuard(&self.0) + StaticRwLockReadGuard(&self.0) } /// Acquires write access to the underlying lock, blocking the current thread @@ -29,16 +29,16 @@ pub fn read(&'static self) -> StaticRWLockReadGuard { /// /// The lock is automatically unlocked when the returned guard is dropped. #[inline] - pub fn write(&'static self) -> StaticRWLockWriteGuard { + pub fn write(&'static self) -> StaticRwLockWriteGuard { unsafe { self.0.write() }; - StaticRWLockWriteGuard(&self.0) + StaticRwLockWriteGuard(&self.0) } } #[must_use] -pub struct StaticRWLockReadGuard(&'static imp::RWLock); +pub struct StaticRwLockReadGuard(&'static imp::RwLock); -impl Drop for StaticRWLockReadGuard { +impl Drop for StaticRwLockReadGuard { #[inline] fn drop(&mut self) { unsafe { @@ -48,9 +48,9 @@ fn drop(&mut self) { } #[must_use] -pub struct StaticRWLockWriteGuard(&'static imp::RWLock); +pub struct StaticRwLockWriteGuard(&'static imp::RwLock); -impl Drop for StaticRWLockWriteGuard { +impl Drop for StaticRwLockWriteGuard { #[inline] fn drop(&mut self) { unsafe { @@ -66,15 +66,15 @@ fn drop(&mut self) { /// /// This rwlock does not implement poisoning. /// -/// This is either a wrapper around `Box<imp::RWLock>` or `imp::RWLock`, -/// depending on the platform. It is boxed on platforms where `imp::RWLock` may +/// This is either a wrapper around `Box<imp::RwLock>` or `imp::RwLock`, +/// depending on the platform. It is boxed on platforms where `imp::RwLock` may /// not be moved. -pub struct MovableRWLock(imp::MovableRWLock); +pub struct MovableRwLock(imp::MovableRwLock); -impl MovableRWLock { +impl MovableRwLock { /// Creates a new reader-writer lock for use. pub fn new() -> Self { - Self(imp::MovableRWLock::from(imp::RWLock::new())) + Self(imp::MovableRwLock::from(imp::RwLock::new())) } /// Acquires shared access to the underlying lock, blocking the current @@ -127,7 +127,7 @@ pub unsafe fn write_unlock(&self) { } } -impl Drop for MovableRWLock { +impl Drop for MovableRwLock { fn drop(&mut self) { unsafe { self.0.destroy() }; }
diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs index a41cb02..fc307c5 100644 --- a/library/std/src/thread/local.rs +++ b/library/std/src/thread/local.rs
@@ -980,7 +980,7 @@ pub unsafe fn get<F: FnOnce() -> T>(&self, init: F) -> Option<&'static T> { unsafe fn try_initialize<F: FnOnce() -> T>(&self, init: F) -> Option<&'static T> { // SAFETY: See comment above (this function doc). if !mem::needs_drop::<T>() || unsafe { self.try_register_dtor() } { - // SAFETY: See comment above (his function doc). + // SAFETY: See comment above (this function doc). Some(unsafe { self.inner.initialize(init) }) } else { None
diff --git a/library/test/src/console.rs b/library/test/src/console.rs index 56eef83..dc0123c 100644 --- a/library/test/src/console.rs +++ b/library/test/src/console.rs
@@ -103,12 +103,7 @@ pub fn write_log_result( exec_time: Option<&TestExecTime>, ) -> io::Result<()> { self.write_log(|| { - let TestDesc { - name, - #[cfg(not(bootstrap))] - ignore_message, - .. - } = test; + let TestDesc { name, ignore_message, .. } = test; format!( "{} {}", match *result { @@ -116,14 +111,11 @@ pub fn write_log_result( TestResult::TrFailed => "failed".to_owned(), TestResult::TrFailedMsg(ref msg) => format!("failed: {msg}"), TestResult::TrIgnored => { - #[cfg(not(bootstrap))] if let Some(msg) = ignore_message { format!("ignored: {msg}") } else { "ignored".to_owned() } - #[cfg(bootstrap)] - "ignored".to_owned() } TestResult::TrBench(ref bs) => fmt_bench_samples(bs), TestResult::TrTimedFail => "failed (time limit exceeded)".to_owned(),
diff --git a/library/test/src/formatters/json.rs b/library/test/src/formatters/json.rs index 737921c..c07fdaf 100644 --- a/library/test/src/formatters/json.rs +++ b/library/test/src/formatters/json.rs
@@ -120,22 +120,16 @@ fn write_result( Some(&*format!(r#""message": "{}""#, EscapedString(m))), ), - TestResult::TrIgnored => { - #[cfg(not(bootstrap))] - return self.write_event( - "test", - desc.name.as_slice(), - "ignored", - exec_time, - stdout, - desc.ignore_message - .map(|msg| format!(r#""message": "{}""#, EscapedString(msg))) - .as_deref(), - ); - - #[cfg(bootstrap)] - self.write_event("test", desc.name.as_slice(), "ignored", exec_time, stdout, None) - } + TestResult::TrIgnored => self.write_event( + "test", + desc.name.as_slice(), + "ignored", + exec_time, + stdout, + desc.ignore_message + .map(|msg| format!(r#""message": "{}""#, EscapedString(msg))) + .as_deref(), + ), TestResult::TrBench(ref bs) => { let median = bs.ns_iter_summ.median as usize;
diff --git a/library/test/src/formatters/pretty.rs b/library/test/src/formatters/pretty.rs index 9b407df..6942022 100644 --- a/library/test/src/formatters/pretty.rs +++ b/library/test/src/formatters/pretty.rs
@@ -218,12 +218,7 @@ fn write_result( match *result { TestResult::TrOk => self.write_ok()?, TestResult::TrFailed | TestResult::TrFailedMsg(_) => self.write_failed()?, - TestResult::TrIgnored => { - #[cfg(not(bootstrap))] - self.write_ignored(desc.ignore_message)?; - #[cfg(bootstrap)] - self.write_ignored(None)?; - } + TestResult::TrIgnored => self.write_ignored(desc.ignore_message)?, TestResult::TrBench(ref bs) => { self.write_bench()?; self.write_plain(&format!(": {}", fmt_bench_samples(bs)))?;
diff --git a/library/test/src/formatters/terse.rs b/library/test/src/formatters/terse.rs index fb40f86..5dace8b 100644 --- a/library/test/src/formatters/terse.rs +++ b/library/test/src/formatters/terse.rs
@@ -11,8 +11,9 @@ types::TestDesc, }; -// insert a '\n' after 100 tests in quiet mode -const QUIET_MODE_MAX_COLUMN: usize = 100; +// We insert a '\n' when the output hits 100 columns in quiet mode. 88 test +// result chars leaves 12 chars for a progress count like " 11704/12853". +const QUIET_MODE_MAX_COLUMN: usize = 88; pub(crate) struct TerseFormatter<T> { out: OutputLocation<T>, @@ -65,7 +66,7 @@ pub fn write_short_result( ) -> io::Result<()> { self.write_pretty(result, color)?; if self.test_count % QUIET_MODE_MAX_COLUMN == QUIET_MODE_MAX_COLUMN - 1 { - // we insert a new line every 100 dots in order to flush the + // We insert a new line regularly in order to flush the // screen when dealing with line-buffered output (e.g., piping to // `stamp` in the rust CI). let out = format!(" {}/{}\n", self.test_count + 1, self.total_test_count);
diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs index 889f7cb9..0c748da 100644 --- a/library/test/src/lib.rs +++ b/library/test/src/lib.rs
@@ -21,7 +21,6 @@ #![feature(staged_api)] #![feature(process_exitcode_internals)] #![feature(test)] -#![feature(total_cmp)] // Public reexports pub use self::bench::{black_box, Bencher};
diff --git a/library/test/src/tests.rs b/library/test/src/tests.rs index 8329e97..0b81aff 100644 --- a/library/test/src/tests.rs +++ b/library/test/src/tests.rs
@@ -61,7 +61,6 @@ fn one_ignored_one_unignored_test() -> Vec<TestDescAndFn> { desc: TestDesc { name: StaticTestName("1"), ignore: true, - #[cfg(not(bootstrap))] ignore_message: None, should_panic: ShouldPanic::No, compile_fail: false, @@ -74,7 +73,6 @@ fn one_ignored_one_unignored_test() -> Vec<TestDescAndFn> { desc: TestDesc { name: StaticTestName("2"), ignore: false, - #[cfg(not(bootstrap))] ignore_message: None, should_panic: ShouldPanic::No, compile_fail: false, @@ -95,7 +93,6 @@ fn f() { desc: TestDesc { name: StaticTestName("whatever"), ignore: true, - #[cfg(not(bootstrap))] ignore_message: None, should_panic: ShouldPanic::No, compile_fail: false, @@ -117,7 +114,6 @@ fn f() {} desc: TestDesc { name: StaticTestName("whatever"), ignore: true, - #[cfg(not(bootstrap))] ignore_message: None, should_panic: ShouldPanic::No, compile_fail: false, @@ -143,7 +139,6 @@ fn f() { desc: TestDesc { name: StaticTestName("whatever"), ignore: false, - #[cfg(not(bootstrap))] ignore_message: None, should_panic: ShouldPanic::Yes, compile_fail: false, @@ -169,7 +164,6 @@ fn f() { desc: TestDesc { name: StaticTestName("whatever"), ignore: false, - #[cfg(not(bootstrap))] ignore_message: None, should_panic: ShouldPanic::YesWithMessage("error message"), compile_fail: false, @@ -200,7 +194,6 @@ fn f() { desc: TestDesc { name: StaticTestName("whatever"), ignore: false, - #[cfg(not(bootstrap))] ignore_message: None, should_panic: ShouldPanic::YesWithMessage(expected), compile_fail: false, @@ -235,7 +228,6 @@ fn f() { desc: TestDesc { name: StaticTestName("whatever"), ignore: false, - #[cfg(not(bootstrap))] ignore_message: None, should_panic: ShouldPanic::YesWithMessage(expected), compile_fail: false, @@ -262,7 +254,6 @@ fn f() {} desc: TestDesc { name: StaticTestName("whatever"), ignore: false, - #[cfg(not(bootstrap))] ignore_message: None, should_panic, compile_fail: false, @@ -297,7 +288,6 @@ fn f() {} desc: TestDesc { name: StaticTestName("whatever"), ignore: false, - #[cfg(not(bootstrap))] ignore_message: None, should_panic: ShouldPanic::No, compile_fail: false, @@ -333,7 +323,6 @@ fn f() {} desc: TestDesc { name: StaticTestName("whatever"), ignore: false, - #[cfg(not(bootstrap))] ignore_message: None, should_panic: ShouldPanic::No, compile_fail: false, @@ -373,7 +362,6 @@ fn typed_test_desc(test_type: TestType) -> TestDesc { TestDesc { name: StaticTestName("whatever"), ignore: false, - #[cfg(not(bootstrap))] ignore_message: None, should_panic: ShouldPanic::No, compile_fail: false, @@ -486,7 +474,6 @@ pub fn exclude_should_panic_option() { desc: TestDesc { name: StaticTestName("3"), ignore: false, - #[cfg(not(bootstrap))] ignore_message: None, should_panic: ShouldPanic::Yes, compile_fail: false, @@ -511,7 +498,6 @@ fn tests() -> Vec<TestDescAndFn> { desc: TestDesc { name: StaticTestName(name), ignore: false, - #[cfg(not(bootstrap))] ignore_message: None, should_panic: ShouldPanic::No, compile_fail: false, @@ -601,7 +587,6 @@ fn testfn() {} desc: TestDesc { name: DynTestName((*name).clone()), ignore: false, - #[cfg(not(bootstrap))] ignore_message: None, should_panic: ShouldPanic::No, compile_fail: false, @@ -753,7 +738,6 @@ fn f(_: &mut Bencher) {} let desc = TestDesc { name: StaticTestName("f"), ignore: false, - #[cfg(not(bootstrap))] ignore_message: None, should_panic: ShouldPanic::No, compile_fail: false, @@ -776,7 +760,6 @@ fn f(b: &mut Bencher) { let desc = TestDesc { name: StaticTestName("f"), ignore: false, - #[cfg(not(bootstrap))] ignore_message: None, should_panic: ShouldPanic::No, compile_fail: false, @@ -793,7 +776,6 @@ fn should_sort_failures_before_printing_them() { let test_a = TestDesc { name: StaticTestName("a"), ignore: false, - #[cfg(not(bootstrap))] ignore_message: None, should_panic: ShouldPanic::No, compile_fail: false, @@ -804,7 +786,6 @@ fn should_sort_failures_before_printing_them() { let test_b = TestDesc { name: StaticTestName("b"), ignore: false, - #[cfg(not(bootstrap))] ignore_message: None, should_panic: ShouldPanic::No, compile_fail: false,
diff --git a/library/test/src/types.rs b/library/test/src/types.rs index 1084fb9..ffb1efe 100644 --- a/library/test/src/types.rs +++ b/library/test/src/types.rs
@@ -117,7 +117,6 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { pub struct TestDesc { pub name: TestName, pub ignore: bool, - #[cfg(not(bootstrap))] pub ignore_message: Option<&'static str>, pub should_panic: options::ShouldPanic, pub compile_fail: bool,
diff --git a/library/unwind/build.rs b/library/unwind/build.rs index a3f5224..61d3f45 100644 --- a/library/unwind/build.rs +++ b/library/unwind/build.rs
@@ -40,8 +40,6 @@ fn main() { // This is handled in the target spec with late_link_args_[static|dynamic] } else if target.contains("uwp-windows-gnu") { println!("cargo:rustc-link-lib=unwind"); - } else if target.contains("fuchsia") { - println!("cargo:rustc-link-lib=unwind"); } else if target.contains("haiku") { println!("cargo:rustc-link-lib=gcc_s"); } else if target.contains("redox") {
diff --git a/library/unwind/src/lib.rs b/library/unwind/src/lib.rs index 82f1e63..a01b560 100644 --- a/library/unwind/src/lib.rs +++ b/library/unwind/src/lib.rs
@@ -1,7 +1,6 @@ #![no_std] #![unstable(feature = "panic_unwind", issue = "32837")] #![feature(link_cfg)] -#![cfg_attr(bootstrap, feature(native_link_modifiers))] #![feature(native_link_modifiers_bundle)] #![feature(nll)] #![feature(staged_api)]
diff --git a/src/bootstrap/bin/rustdoc.rs b/src/bootstrap/bin/rustdoc.rs index ad38008..4bba2eb 100644 --- a/src/bootstrap/bin/rustdoc.rs +++ b/src/bootstrap/bin/rustdoc.rs
@@ -15,6 +15,10 @@ fn main() { let libdir = env::var_os("RUSTDOC_LIBDIR").expect("RUSTDOC_LIBDIR was not set"); let sysroot = env::var_os("RUSTC_SYSROOT").expect("RUSTC_SYSROOT was not set"); + // Detect whether or not we're a build script depending on whether --target + // is passed (a bit janky...) + let target = args.windows(2).find(|w| &*w[0] == "--target").and_then(|w| w[1].to_str()); + use std::str::FromStr; let verbose = match env::var("RUSTC_VERBOSE") { @@ -26,10 +30,18 @@ fn main() { dylib_path.insert(0, PathBuf::from(libdir.clone())); let mut cmd = Command::new(rustdoc); - cmd.args(&args) - .arg("--sysroot") - .arg(&sysroot) - .env(dylib_path_var(), env::join_paths(&dylib_path).unwrap()); + + if target.is_some() { + // The stage0 compiler has a special sysroot distinct from what we + // actually downloaded, so we just always pass the `--sysroot` option, + // unless one is already set. + if !args.iter().any(|arg| arg == "--sysroot") { + cmd.arg("--sysroot").arg(&sysroot); + } + } + + cmd.args(&args); + cmd.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap()); // Force all crates compiled by this compiler to (a) be unstable and (b) // allow the `rustc_private` feature to link to other unstable crates
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 71b8f3c..0b6bdf4 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py
@@ -678,7 +678,7 @@ # The latter one does not exist on NixOS when using tmpfs as root. try: with open("/etc/os-release", "r") as f: - if not any(line.strip() == "ID=nixos" for line in f): + if not any(l.strip() in ["ID=nixos", "ID='nixos'", 'ID="nixos"'] for l in f): return except FileNotFoundError: return
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index e816f9b..8c06a00 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs
@@ -835,6 +835,18 @@ pub fn sysroot_libdir_relative(&self, compiler: Compiler) -> &Path { } } + pub fn rustc_lib_paths(&self, compiler: Compiler) -> Vec<PathBuf> { + let mut dylib_dirs = vec![self.rustc_libdir(compiler)]; + + // Ensure that the downloaded LLVM libraries can be found. + if self.config.llvm_from_ci { + let ci_llvm_lib = self.out.join(&*compiler.host.triple).join("ci-llvm").join("lib"); + dylib_dirs.push(ci_llvm_lib); + } + + dylib_dirs + } + /// Adds the compiler's directory of dynamic libraries to `cmd`'s dynamic /// library lookup path. pub fn add_rustc_lib_path(&self, compiler: Compiler, cmd: &mut Command) { @@ -845,15 +857,7 @@ pub fn add_rustc_lib_path(&self, compiler: Compiler, cmd: &mut Command) { return; } - let mut dylib_dirs = vec![self.rustc_libdir(compiler)]; - - // Ensure that the downloaded LLVM libraries can be found. - if self.config.llvm_from_ci { - let ci_llvm_lib = self.out.join(&*compiler.host.triple).join("ci-llvm").join("lib"); - dylib_dirs.push(ci_llvm_lib); - } - - add_dylib_path(dylib_dirs, cmd); + add_dylib_path(self.rustc_lib_paths(compiler), cmd); } /// Gets a path to the compiler specified.
diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index be96597..fdd1581 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs
@@ -896,6 +896,7 @@ fn run(self, builder: &Builder<'_>) -> GeneratedTarball { cmd.arg("vendor") .arg("--sync") .arg(builder.src.join("./src/tools/rust-analyzer/Cargo.toml")) + .arg("--sync") .arg(builder.src.join("./compiler/rustc_codegen_cranelift/Cargo.toml")) .current_dir(&plain_dst_src); builder.run(&mut cmd);
diff --git a/src/bootstrap/setup.rs b/src/bootstrap/setup.rs index aff2b6c..b730730 100644 --- a/src/bootstrap/setup.rs +++ b/src/bootstrap/setup.rs
@@ -342,7 +342,7 @@ fn install_git_hook_maybe(src_path: &Path) -> io::Result<()> { dst.display(), e ), - Ok(_) => println!("Linked `src/etc/pre-commit.sh` to `.git/hooks/pre-push`"), + Ok(_) => println!("Linked `src/etc/pre-push.sh` to `.git/hooks/pre-push`"), }; } else { println!("Ok, skipping installation!");
diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index a9ca89b..fc1c2f0 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs
@@ -379,22 +379,14 @@ pub struct ErrorIndex { impl ErrorIndex { pub fn command(builder: &Builder<'_>) -> Command { - // This uses stage-1 to match the behavior of building rustdoc. - // Error-index-generator links with the rustdoc library, so we want to - // use the same librustdoc to avoid building rustdoc twice (and to - // avoid building the compiler an extra time). This uses - // saturating_sub to deal with building with stage 0. (Using stage 0 - // isn't recommended, since it will fail if any new error index tests - // use new syntax, but it should work otherwise.) - let compiler = builder.compiler(builder.top_stage.saturating_sub(1), builder.config.build); + // Error-index-generator links with the rustdoc library, so we need to add `rustc_lib_paths` + // for rustc_private and libLLVM.so, and `sysroot_lib` for libstd, etc. + let host = builder.config.build; + let compiler = builder.compiler_for(builder.top_stage, host, host); let mut cmd = Command::new(builder.ensure(ErrorIndex { compiler })); - add_dylib_path( - vec![ - PathBuf::from(&builder.sysroot_libdir(compiler, compiler.host)), - builder.rustc_libdir(compiler), - ], - &mut cmd, - ); + let mut dylib_paths = builder.rustc_lib_paths(compiler); + dylib_paths.push(PathBuf::from(&builder.sysroot_libdir(compiler, compiler.host))); + add_dylib_path(dylib_paths, &mut cmd); cmd } }
diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs index 30d9665..b78ca37 100644 --- a/src/bootstrap/util.rs +++ b/src/bootstrap/util.rs
@@ -63,7 +63,7 @@ pub fn libdir(target: TargetSelection) -> &'static str { } /// Adds a list of lookup paths to `cmd`'s dynamic library lookup path. -/// If The dylib_path_par is already set for this cmd, the old value will be overwritten! +/// If the dylib_path_var is already set for this cmd, the old value will be overwritten! pub fn add_dylib_path(path: Vec<PathBuf>, cmd: &mut Command) { let mut list = dylib_path(); for path in path { @@ -308,10 +308,10 @@ pub fn is_valid_test_suite_arg<'a, P: AsRef<Path>>( let abs_path = builder.src.join(path); let exists = abs_path.is_dir() || abs_path.is_file(); if !exists { - if let Some(p) = abs_path.to_str() { - builder.info(&format!("Warning: Skipping \"{}\": not a regular file or directory", p)); - } - return None; + panic!( + "Invalid test suite filter \"{}\": file or directory does not exist", + abs_path.display() + ); } // Since test suite paths are themselves directories, if we don't // specify a directory or file, we'll get an empty string here
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version index fcbb537..bbde4be 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version +++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version
@@ -1 +1 @@ -0.8.4 \ No newline at end of file +0.8.5 \ No newline at end of file
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 37c2473..e6ef3c2 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs
@@ -116,22 +116,14 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Option<GenericBound> { ) } hir::GenericBound::Trait(ref t, modifier) => { - // `T: ~const Drop` is not equivalent to `T: Drop`, and we don't currently document `~const` bounds - // because of its experimental status, so just don't show these. // `T: ~const Destruct` is hidden because `T: Destruct` is a no-op. if modifier == hir::TraitBoundModifier::MaybeConst - && [cx.tcx.lang_items().drop_trait(), cx.tcx.lang_items().destruct_trait()] - .iter() - .any(|tr| *tr == Some(t.trait_ref.trait_def_id().unwrap())) + && cx.tcx.lang_items().destruct_trait() + == Some(t.trait_ref.trait_def_id().unwrap()) { return None; } - #[cfg(bootstrap)] - { - // FIXME: remove `lang_items().drop_trait()` from above logic, - // as well as the comment about `~const Drop` because it was renamed to `Destruct`. - } GenericBound::TraitBound(t.clean(cx), modifier) } })
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index bd64e2b..9d5ae68 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs
@@ -1,3 +1,4 @@ +use rustc_ast::NodeId; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::{self, Lrc}; use rustc_errors::emitter::{Emitter, EmitterWriter}; @@ -17,7 +18,7 @@ use rustc_session::DiagnosticOutput; use rustc_session::Session; use rustc_span::symbol::sym; -use rustc_span::{source_map, Span}; +use rustc_span::{source_map, Span, Symbol}; use std::cell::RefCell; use std::lazy::SyncLazy; @@ -38,6 +39,7 @@ crate traits_in_scope: DefIdMap<Vec<TraitCandidate>>, crate all_traits: Option<Vec<DefId>>, crate all_trait_impls: Option<Vec<DefId>>, + crate all_macro_rules: FxHashMap<Symbol, Res<NodeId>>, } crate struct DocContext<'tcx> { @@ -143,6 +145,8 @@ impl<'tcx> DocContext<'tcx> { source_map: Option<Lrc<source_map::SourceMap>>, debugging_opts: &DebuggingOptions, ) -> rustc_errors::Handler { + let fallback_bundle = + rustc_errors::fallback_fluent_bundle(false).expect("failed to load fallback fluent bundle"); let emitter: Box<dyn Emitter + sync::Send> = match error_format { ErrorOutputType::HumanReadable(kind) => { let (short, color_config) = kind.unzip(); @@ -150,6 +154,8 @@ impl<'tcx> DocContext<'tcx> { EmitterWriter::stderr( color_config, source_map.map(|sm| sm as _), + None, + fallback_bundle, short, debugging_opts.teach, debugging_opts.terminal_width, @@ -166,6 +172,8 @@ impl<'tcx> DocContext<'tcx> { JsonEmitter::stderr( None, source_map, + None, + fallback_bundle, pretty, json_rendered, debugging_opts.terminal_width,
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index c4201e2..50ae22b 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs
@@ -537,12 +537,31 @@ fn drop(&mut self) { // Any errors in parsing should also appear when the doctest is compiled for real, so just // send all the errors that librustc_ast emits directly into a `Sink` instead of stderr. let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); - supports_color = - EmitterWriter::stderr(ColorConfig::Auto, None, false, false, Some(80), false) - .supports_color(); + let fallback_bundle = rustc_errors::fallback_fluent_bundle(false) + .expect("failed to load fallback fluent bundle"); + supports_color = EmitterWriter::stderr( + ColorConfig::Auto, + None, + None, + fallback_bundle.clone(), + false, + false, + Some(80), + false, + ) + .supports_color(); - let emitter = - EmitterWriter::new(box io::sink(), None, false, false, false, None, false); + let emitter = EmitterWriter::new( + box io::sink(), + None, + None, + fallback_bundle, + false, + false, + false, + None, + false, + ); // FIXME(misdreavus): pass `-Z treat-err-as-bug` to the doctest parser let handler = Handler::with_emitter(false, None, box emitter); @@ -1000,7 +1019,6 @@ fn add_test(&mut self, test: String, config: LangString, line: usize) { Ignore::None => false, Ignore::Some(ref ignores) => ignores.iter().any(|s| target_str.contains(s)), }, - #[cfg(not(bootstrap))] ignore_message: None, // compiler failures are test failures should_panic: test::ShouldPanic::No,
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index ac07547..12da165 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs
@@ -597,11 +597,11 @@ fn document_item_info( ) { let item_infos = short_item_info(item, cx, parent); if !item_infos.is_empty() { - w.write_str("<div class=\"item-info\">"); + w.write_str("<span class=\"item-info\">"); for info in item_infos { w.write_str(&info); } - w.write_str("</div>"); + w.write_str("</span>"); } }
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 3ad376b..99d7475 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs
@@ -1769,7 +1769,7 @@ fn write_size_of_layout(w: &mut Buffer, layout: Layout<'_>, tag_size: u64) { let tag_size = if let TagEncoding::Niche { .. } = tag_encoding { 0 - } else if let Primitive::Int(i, _) = tag.value { + } else if let Primitive::Int(i, _) = tag.primitive() { i.size().bytes() } else { span_bug!(tcx.def_span(ty_def_id), "tag is neither niche nor int")
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index ee265b8..68c88b551 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -737,6 +737,10 @@ border: none; } +.item-info { + display: block; +} + .content .item-info code { font-size: 0.875rem; }
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index f59222b..0fcfabb 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs
@@ -10,6 +10,7 @@ #![feature(control_flow_enum)] #![feature(box_syntax)] #![feature(drain_filter)] +#![feature(let_chains)] #![feature(let_else)] #![feature(nll)] #![feature(test)] @@ -771,6 +772,7 @@ fn main_options(options: config::Options) -> MainResult { let externs = options.externs.clone(); let render_options = options.render_options.clone(); let scrape_examples_options = options.scrape_examples_options.clone(); + let document_private = options.render_options.document_private; let config = core::create_config(options); interface::create_compiler_and_run(config, |compiler| { @@ -791,7 +793,12 @@ fn main_options(options: config::Options) -> MainResult { let (resolver, resolver_caches) = { let (krate, resolver, _) = &*abort_on_err(queries.expansion(), sess).peek(); let resolver_caches = resolver.borrow_mut().access(|resolver| { - collect_intra_doc_links::early_resolve_intra_doc_links(resolver, krate, externs) + collect_intra_doc_links::early_resolve_intra_doc_links( + resolver, + krate, + externs, + document_private, + ) }); (resolver.clone(), resolver_caches) };
diff --git a/src/librustdoc/passes/check_code_block_syntax.rs b/src/librustdoc/passes/check_code_block_syntax.rs index 8d9b337..465dd52 100644 --- a/src/librustdoc/passes/check_code_block_syntax.rs +++ b/src/librustdoc/passes/check_code_block_syntax.rs
@@ -32,7 +32,9 @@ struct SyntaxChecker<'a, 'tcx> { impl<'a, 'tcx> SyntaxChecker<'a, 'tcx> { fn check_rust_syntax(&self, item: &clean::Item, dox: &str, code_block: RustCodeBlock) { let buffer = Lrc::new(Lock::new(Buffer::default())); - let emitter = BufferEmitter { buffer: Lrc::clone(&buffer) }; + let fallback_bundle = rustc_errors::fallback_fluent_bundle(false) + .expect("failed to load fallback fluent bundle"); + let emitter = BufferEmitter { buffer: Lrc::clone(&buffer), fallback_bundle }; let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); let handler = Handler::with_emitter(false, None, Box::new(emitter)); @@ -171,12 +173,14 @@ struct Buffer { struct BufferEmitter { buffer: Lrc<Lock<Buffer>>, + fallback_bundle: Lrc<rustc_errors::FluentBundle>, } impl Emitter for BufferEmitter { fn emit_diagnostic(&mut self, diag: &Diagnostic) { let mut buffer = self.buffer.borrow_mut(); - buffer.messages.push(format!("error from rustc: {}", diag.message[0].0)); + // FIXME(davidtwco): need to support translation here eventually + buffer.messages.push(format!("error from rustc: {}", diag.message[0].0.expect_str())); if diag.is_error() { buffer.has_errors = true; } @@ -185,4 +189,12 @@ fn emit_diagnostic(&mut self, diag: &Diagnostic) { fn source_map(&self) -> Option<&Lrc<SourceMap>> { None } + + fn fluent_bundle(&self) -> Option<&Lrc<rustc_errors::FluentBundle>> { + None + } + + fn fallback_fluent_bundle(&self) -> &Lrc<rustc_errors::FluentBundle> { + &self.fallback_bundle + } }
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 2129814..c1b1139 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -2,14 +2,12 @@ //! //! [RFC 1946]: https://github.com/rust-lang/rfcs/blob/master/text/1946-intra-rustdoc-links.md +use pulldown_cmark::LinkType; use rustc_data_structures::{fx::FxHashMap, intern::Interned, stable_set::FxHashSet}; use rustc_errors::{Applicability, Diagnostic}; -use rustc_hir::def::{ - DefKind, - Namespace::{self, *}, - PerNS, -}; -use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_ID}; +use rustc_hir::def::Namespace::*; +use rustc_hir::def::{DefKind, Namespace, PerNS}; +use rustc_hir::def_id::{DefId, CRATE_DEF_ID}; use rustc_hir::Mutability; use rustc_middle::ty::{DefIdTree, Ty, TyCtxt}; use rustc_middle::{bug, span_bug, ty}; @@ -19,10 +17,7 @@ use rustc_span::{BytePos, DUMMY_SP}; use smallvec::{smallvec, SmallVec}; -use pulldown_cmark::LinkType; - use std::borrow::Cow; -use std::convert::{TryFrom, TryInto}; use std::fmt::Write; use std::mem; use std::ops::Range; @@ -487,25 +482,13 @@ fn resolve_macro( item_id: ItemId, module_id: DefId, ) -> Result<Res, ResolutionFailure<'a>> { - self.cx.enter_resolver(|resolver| { - // NOTE: this needs 2 separate lookups because `resolve_rustdoc_path` doesn't take - // lexical scope into account (it ignores all macros not defined at the mod-level) - debug!("resolving {} as a macro in the module {:?}", path_str, module_id); - if let Some(res) = resolver.resolve_rustdoc_path(path_str, MacroNS, module_id) { - // don't resolve builtins like `#[derive]` - if let Ok(res) = res.try_into() { - return Ok(res); - } - } - if let Some(&res) = resolver.all_macros().get(&Symbol::intern(path_str)) { - return Ok(res.try_into().unwrap()); - } - Err(ResolutionFailure::NotResolved { + self.resolve_path(path_str, MacroNS, item_id, module_id).ok_or_else(|| { + ResolutionFailure::NotResolved { item_id, module_id, partial_res: None, unresolved: path_str.into(), - }) + } }) } @@ -539,6 +522,21 @@ fn resolve_self_ty(&self, path_str: &str, ns: Namespace, item_id: ItemId) -> Opt }) } + /// HACK: Try to search the macro name in the list of all `macro_rules` items in the crate. + /// Used when nothing else works, may often give an incorrect result. + fn resolve_macro_rules(&self, path_str: &str, ns: Namespace) -> Option<Res> { + if ns != MacroNS { + return None; + } + + self.cx + .resolver_caches + .all_macro_rules + .get(&Symbol::intern(path_str)) + .copied() + .and_then(|res| res.try_into().ok()) + } + /// Convenience wrapper around `resolve_rustdoc_path`. /// /// This also handles resolving `true` and `false` as booleans. @@ -560,7 +558,8 @@ fn resolve_path( .cx .enter_resolver(|resolver| resolver.resolve_rustdoc_path(path_str, ns, module_id)) .and_then(|res| res.try_into().ok()) - .or_else(|| resolve_primitive(path_str, ns)); + .or_else(|| resolve_primitive(path_str, ns)) + .or_else(|| self.resolve_macro_rules(path_str, ns)); debug!("{} resolved to {:?} in namespace {:?}", path_str, result, ns); result } @@ -1043,16 +1042,11 @@ fn visit_item(&mut self, item: &Item) { // so we know which module it came from. for (parent_module, doc) in item.attrs.collapsed_doc_value_by_module_level() { debug!("combined_docs={}", doc); - - let (krate, parent_node) = if let Some(id) = parent_module { - (id.krate, Some(id)) - } else { - (item.def_id.krate(), parent_node) - }; // NOTE: if there are links that start in one crate and end in another, this will not resolve them. // This is a degenerate case and it's not supported by rustdoc. + let parent_node = parent_module.or(parent_node); for md_link in markdown_links(&doc) { - let link = self.resolve_link(&item, &doc, parent_node, krate, md_link); + let link = self.resolve_link(&item, &doc, parent_node, md_link); if let Some(link) = link { self.cx.cache.intra_doc_links.entry(item.def_id).or_default().push(link); } @@ -1187,7 +1181,6 @@ fn resolve_link( item: &Item, dox: &str, parent_node: Option<DefId>, - krate: CrateNum, ori_link: MarkdownLink, ) -> Option<ItemLink> { trace!("considering link '{}'", ori_link.link); @@ -1199,7 +1192,7 @@ fn resolve_link( link_range: ori_link.range.clone(), }; - let PreprocessingInfo { path_str, disambiguator, extra_fragment, link_text } = + let PreprocessingInfo { ref path_str, disambiguator, extra_fragment, link_text } = match preprocess_link(&ori_link)? { Ok(x) => x, Err(err) => { @@ -1221,7 +1214,6 @@ fn resolve_link( return None; } }; - let mut path_str = &*path_str; let inner_docs = item.inner_docs(self.cx.tcx); @@ -1239,7 +1231,7 @@ fn resolve_link( let base_node = if item.is_mod() && inner_docs { self.mod_ids.last().copied() } else { parent_node }; - let Some(mut module_id) = base_node else { + let Some(module_id) = base_node else { // This is a bug. debug!("attempting to resolve item without parent module: {}", path_str); resolution_failure( @@ -1252,26 +1244,6 @@ fn resolve_link( return None; }; - let resolved_self; - let is_lone_crate = path_str == "crate"; - if path_str.starts_with("crate::") || is_lone_crate { - use rustc_span::def_id::CRATE_DEF_INDEX; - - // HACK(jynelson): rustc_resolve thinks that `crate` is the crate currently being documented. - // But rustdoc wants it to mean the crate this item was originally present in. - // To work around this, remove it and resolve relative to the crate root instead. - // HACK(jynelson)(2): If we just strip `crate::` then suddenly primitives become ambiguous - // (consider `crate::char`). Instead, change it to `self::`. This works because 'self' is now the crate root. - // FIXME(#78696): This doesn't always work. - if is_lone_crate { - path_str = "self"; - } else { - resolved_self = format!("self::{}", &path_str["crate::".len()..]); - path_str = &resolved_self; - } - module_id = DefId { krate, index: CRATE_DEF_INDEX }; - } - let (mut res, fragment) = self.resolve_with_disambiguator_cached( ResolutionInfo { item_id: item.def_id,
diff --git a/src/librustdoc/passes/collect_intra_doc_links/early.rs b/src/librustdoc/passes/collect_intra_doc_links/early.rs index 75e952c..dffceff 100644 --- a/src/librustdoc/passes/collect_intra_doc_links/early.rs +++ b/src/librustdoc/passes/collect_intra_doc_links/early.rs
@@ -1,4 +1,4 @@ -use crate::clean; +use crate::clean::Attributes; use crate::core::ResolverCaches; use crate::html::markdown::markdown_links; use crate::passes::collect_intra_doc_links::preprocess_link; @@ -22,53 +22,52 @@ resolver: &mut Resolver<'_>, krate: &ast::Crate, externs: Externs, + document_private_items: bool, ) -> ResolverCaches { - let mut loader = IntraLinkCrateLoader { + let mut link_resolver = EarlyDocLinkResolver { resolver, current_mod: CRATE_DEF_ID, visited_mods: Default::default(), traits_in_scope: Default::default(), all_traits: Default::default(), all_trait_impls: Default::default(), + document_private_items, }; - // Because of the `crate::` prefix, any doc comment can reference - // the crate root's set of in-scope traits. This line makes sure - // it's available. - loader.add_traits_in_scope(CRATE_DEF_ID.to_def_id()); - // Overridden `visit_item` below doesn't apply to the crate root, // so we have to visit its attributes and reexports separately. - loader.load_links_in_attrs(&krate.attrs); - loader.process_module_children_or_reexports(CRATE_DEF_ID.to_def_id()); - visit::walk_crate(&mut loader, krate); - loader.add_foreign_traits_in_scope(); + link_resolver.load_links_in_attrs(&krate.attrs); + link_resolver.process_module_children_or_reexports(CRATE_DEF_ID.to_def_id()); + visit::walk_crate(&mut link_resolver, krate); + link_resolver.process_extern_impls(); // FIXME: somehow rustdoc is still missing crates even though we loaded all // the known necessary crates. Load them all unconditionally until we find a way to fix this. // DO NOT REMOVE THIS without first testing on the reproducer in // https://github.com/jyn514/objr/commit/edcee7b8124abf0e4c63873e8422ff81beb11ebb for (extern_name, _) in externs.iter().filter(|(_, entry)| entry.add_prelude) { - loader.resolver.resolve_rustdoc_path(extern_name, TypeNS, CRATE_DEF_ID.to_def_id()); + link_resolver.resolver.resolve_rustdoc_path(extern_name, TypeNS, CRATE_DEF_ID.to_def_id()); } ResolverCaches { - traits_in_scope: loader.traits_in_scope, - all_traits: Some(loader.all_traits), - all_trait_impls: Some(loader.all_trait_impls), + traits_in_scope: link_resolver.traits_in_scope, + all_traits: Some(link_resolver.all_traits), + all_trait_impls: Some(link_resolver.all_trait_impls), + all_macro_rules: link_resolver.resolver.take_all_macro_rules(), } } -struct IntraLinkCrateLoader<'r, 'ra> { +struct EarlyDocLinkResolver<'r, 'ra> { resolver: &'r mut Resolver<'ra>, current_mod: LocalDefId, visited_mods: DefIdSet, traits_in_scope: DefIdMap<Vec<TraitCandidate>>, all_traits: Vec<DefId>, all_trait_impls: Vec<DefId>, + document_private_items: bool, } -impl IntraLinkCrateLoader<'_, '_> { +impl EarlyDocLinkResolver<'_, '_> { fn add_traits_in_scope(&mut self, def_id: DefId) { // Calls to `traits_in_scope` are expensive, so try to avoid them if only possible. // Keys in the `traits_in_scope` cache are always module IDs. @@ -103,67 +102,83 @@ fn add_traits_in_parent_scope(&mut self, def_id: DefId) { /// That pass filters impls using type-based information, but we don't yet have such /// information here, so we just conservatively calculate traits in scope for *all* modules /// having impls in them. - fn add_foreign_traits_in_scope(&mut self) { - for cnum in Vec::from_iter(self.resolver.cstore().crates_untracked()) { - // FIXME: Due to #78696 rustdoc can query traits in scope for any crate root. - self.add_traits_in_scope(cnum.as_def_id()); + fn process_extern_impls(&mut self) { + // FIXME: Need to resolve doc links on all these impl and trait items below. + // Resolving links in already existing crates may trigger loading of new crates. + let mut start_cnum = 0; + loop { + let crates = Vec::from_iter(self.resolver.cstore().crates_untracked()); + for &cnum in &crates[start_cnum..] { + let all_traits = + Vec::from_iter(self.resolver.cstore().traits_in_crate_untracked(cnum)); + let all_trait_impls = + Vec::from_iter(self.resolver.cstore().trait_impls_in_crate_untracked(cnum)); + let all_inherent_impls = + Vec::from_iter(self.resolver.cstore().inherent_impls_in_crate_untracked(cnum)); + let all_incoherent_impls = Vec::from_iter( + self.resolver.cstore().incoherent_impls_in_crate_untracked(cnum), + ); - let all_traits = Vec::from_iter(self.resolver.cstore().traits_in_crate_untracked(cnum)); - let all_trait_impls = - Vec::from_iter(self.resolver.cstore().trait_impls_in_crate_untracked(cnum)); - let all_inherent_impls = - Vec::from_iter(self.resolver.cstore().inherent_impls_in_crate_untracked(cnum)); - let all_incoherent_impls = - Vec::from_iter(self.resolver.cstore().incoherent_impls_in_crate_untracked(cnum)); - - // Querying traits in scope is expensive so we try to prune the impl and traits lists - // using privacy, private traits and impls from other crates are never documented in - // the current crate, and links in their doc comments are not resolved. - for &def_id in &all_traits { - if self.resolver.cstore().visibility_untracked(def_id) == Visibility::Public { + // Querying traits in scope is expensive so we try to prune the impl and traits lists + // using privacy, private traits and impls from other crates are never documented in + // the current crate, and links in their doc comments are not resolved. + for &def_id in &all_traits { + if self.resolver.cstore().visibility_untracked(def_id) == Visibility::Public { + self.add_traits_in_parent_scope(def_id); + } + } + for &(trait_def_id, impl_def_id, simplified_self_ty) in &all_trait_impls { + if self.resolver.cstore().visibility_untracked(trait_def_id) + == Visibility::Public + && simplified_self_ty.and_then(|ty| ty.def()).map_or(true, |ty_def_id| { + self.resolver.cstore().visibility_untracked(ty_def_id) + == Visibility::Public + }) + { + self.add_traits_in_parent_scope(impl_def_id); + } + } + for (ty_def_id, impl_def_id) in all_inherent_impls { + if self.resolver.cstore().visibility_untracked(ty_def_id) == Visibility::Public + { + self.add_traits_in_parent_scope(impl_def_id); + } + } + for def_id in all_incoherent_impls { self.add_traits_in_parent_scope(def_id); } - } - for &(trait_def_id, impl_def_id, simplified_self_ty) in &all_trait_impls { - if self.resolver.cstore().visibility_untracked(trait_def_id) == Visibility::Public - && simplified_self_ty.and_then(|ty| ty.def()).map_or(true, |ty_def_id| { - self.resolver.cstore().visibility_untracked(ty_def_id) == Visibility::Public - }) - { - self.add_traits_in_parent_scope(impl_def_id); - } - } - for (ty_def_id, impl_def_id) in all_inherent_impls { - if self.resolver.cstore().visibility_untracked(ty_def_id) == Visibility::Public { - self.add_traits_in_parent_scope(impl_def_id); - } - } - for def_id in all_incoherent_impls { - self.add_traits_in_parent_scope(def_id); + + self.all_traits.extend(all_traits); + self.all_trait_impls + .extend(all_trait_impls.into_iter().map(|(_, def_id, _)| def_id)); } - self.all_traits.extend(all_traits); - self.all_trait_impls.extend(all_trait_impls.into_iter().map(|(_, def_id, _)| def_id)); + if crates.len() > start_cnum { + start_cnum = crates.len(); + } else { + break; + } } } fn load_links_in_attrs(&mut self, attrs: &[ast::Attribute]) { - // FIXME: this needs to consider reexport inlining. - let attrs = clean::Attributes::from_ast(attrs, None); - for (parent_module, doc) in attrs.collapsed_doc_value_by_module_level() { - let module_id = parent_module.unwrap_or(self.current_mod.to_def_id()); - - self.add_traits_in_scope(module_id); - + let module_id = self.current_mod.to_def_id(); + let mut need_traits_in_scope = false; + for (doc_module, doc) in + Attributes::from_ast(attrs, None).collapsed_doc_value_by_module_level() + { + assert_eq!(doc_module, None); for link in markdown_links(&doc.as_str()) { - let path_str = if let Some(Ok(x)) = preprocess_link(&link) { - x.path_str - } else { - continue; - }; - self.resolver.resolve_rustdoc_path(&path_str, TypeNS, module_id); + if let Some(Ok(pinfo)) = preprocess_link(&link) { + self.resolver.resolve_rustdoc_path(&pinfo.path_str, TypeNS, module_id); + need_traits_in_scope = true; + } } } + + if need_traits_in_scope { + self.add_traits_in_scope(module_id); + } } /// When reexports are inlined, they are replaced with item which they refer to, those items @@ -175,32 +190,41 @@ fn process_module_children_or_reexports(&mut self, module_id: DefId) { } for child in self.resolver.module_children_or_reexports(module_id) { - if child.vis == Visibility::Public { - if let Some(def_id) = child.res.opt_def_id() { - self.add_traits_in_parent_scope(def_id); - } - if let Res::Def(DefKind::Mod, module_id) = child.res { - self.process_module_children_or_reexports(module_id); + // This condition should give a superset of `denied` from `fn clean_use_statement`. + if child.vis == Visibility::Public + || self.document_private_items + && child.vis != Visibility::Restricted(module_id) + && module_id.is_local() + { + if let Some(def_id) = child.res.opt_def_id() && !def_id.is_local() { + // FIXME: Need to resolve doc links on all these extern items + // reached through reexports. + let scope_id = match child.res { + Res::Def(DefKind::Variant, ..) => self.resolver.parent(def_id).unwrap(), + _ => def_id, + }; + self.add_traits_in_parent_scope(scope_id); // Outer attribute scope + if let Res::Def(DefKind::Mod, ..) = child.res { + self.add_traits_in_scope(def_id); // Inner attribute scope + } + // Traits are processed in `add_extern_traits_in_scope`. + if let Res::Def(DefKind::Mod | DefKind::Enum, ..) = child.res { + self.process_module_children_or_reexports(def_id); + } } } } } } -impl Visitor<'_> for IntraLinkCrateLoader<'_, '_> { +impl Visitor<'_> for EarlyDocLinkResolver<'_, '_> { fn visit_item(&mut self, item: &ast::Item) { + self.load_links_in_attrs(&item.attrs); // Outer attribute scope if let ItemKind::Mod(..) = item.kind { let old_mod = mem::replace(&mut self.current_mod, self.resolver.local_def_id(item.id)); - - // A module written with a outline doc comments will resolve traits relative - // to the parent module. Make sure the parent module's traits-in-scope are - // loaded, even if the module itself has no doc comments. - self.add_traits_in_parent_scope(self.current_mod.to_def_id()); - - self.load_links_in_attrs(&item.attrs); + self.load_links_in_attrs(&item.attrs); // Inner attribute scope self.process_module_children_or_reexports(self.current_mod.to_def_id()); visit::walk_item(self, item); - self.current_mod = old_mod; } else { match item.kind { @@ -212,7 +236,6 @@ fn visit_item(&mut self, item: &ast::Item) { } _ => {} } - self.load_links_in_attrs(&item.attrs); visit::walk_item(self, item); } }
diff --git a/src/stage0.json b/src/stage0.json index 5990ab4..952fc78 100644 --- a/src/stage0.json +++ b/src/stage0.json
@@ -2,347 +2,347 @@ "__comment": "Generated by `./x.py run src/tools/bump-stage0`. Run that command again to update the bootstrap compiler.", "dist_server": "https://static.rust-lang.org", "compiler": { - "date": "2022-02-22", + "date": "2022-04-05", "version": "beta" }, "rustfmt": { - "date": "2022-02-23", + "date": "2022-04-05", "version": "nightly" }, "checksums_sha256": { - "dist/2022-02-22/cargo-beta-aarch64-apple-darwin.tar.gz": "5b23653987a4157a80be39e7c3560f79b1b40ecdb30ae156170e02f659020e78", - "dist/2022-02-22/cargo-beta-aarch64-apple-darwin.tar.xz": "f2e8b34a2b57d9aa876b60d081689371aa2802e4e6ea38329785f2cba3c40dec", - "dist/2022-02-22/cargo-beta-aarch64-pc-windows-msvc.tar.gz": "57d51d004175a2c05892b4edb347300c42cf5764d52f6aabc905e8cd8cb60330", - "dist/2022-02-22/cargo-beta-aarch64-pc-windows-msvc.tar.xz": "5c0c7698b31394e531dc005b48b6ab78dbf74914cf7daef8e7cc41791adaa061", - "dist/2022-02-22/cargo-beta-aarch64-unknown-linux-gnu.tar.gz": "1257e6ba753b1328a22730b53da7db3064797d4bda5e02ee79566bec31cf60c3", - "dist/2022-02-22/cargo-beta-aarch64-unknown-linux-gnu.tar.xz": "12289ddd9564f7bd25eadfb182d67fbff275244faeb281d918998ba578f5923a", - "dist/2022-02-22/cargo-beta-aarch64-unknown-linux-musl.tar.gz": "8d4d767930996e35c66b2208056b3c57da7cce642650ff3e12ca3e7f8c612d9d", - "dist/2022-02-22/cargo-beta-aarch64-unknown-linux-musl.tar.xz": "a0e0ceeb786273d33d79e939e6aeb015d1e960c88675bd582815ff31312c0948", - "dist/2022-02-22/cargo-beta-arm-unknown-linux-gnueabi.tar.gz": "bd92f426ee10d84d162a78955e29d4da7c4c76808d17a81ad599777e76dc8869", - "dist/2022-02-22/cargo-beta-arm-unknown-linux-gnueabi.tar.xz": "844c40ed33b03d1cd7a0a82995ef02e33a450155cf1bab36e7b5cddf61ce7ebf", - "dist/2022-02-22/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz": "0a8e1a8ca38be1356aadf8f6e2f51d2b83ec27c87f3c63c0dc85dba5337b3139", - "dist/2022-02-22/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz": "de54fbd0cdd17e74e576fc1ad2147542fb82a845ac336c7efb284c6ffaab21c9", - "dist/2022-02-22/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz": "561b7566dd155b6ea6ae2dd1f6de6ae49b3104df7f6ad5bba59e2505e4a2386b", - "dist/2022-02-22/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz": "eff55c73491c83b109c2cd4e67f8e82314ddd9abcdbfcc358fb8c2423b31aa8c", - "dist/2022-02-22/cargo-beta-i686-pc-windows-gnu.tar.gz": "3766d773de8332b0b6bbff26bdbeb090eaddf12badc37c91280cf26825400796", - "dist/2022-02-22/cargo-beta-i686-pc-windows-gnu.tar.xz": "55e3553aacaab2139e15d231cb7c328f3abedf6c7014be64fab98b657b12dff3", - "dist/2022-02-22/cargo-beta-i686-pc-windows-msvc.tar.gz": "b59118825ceee16f18a73de57da9de3db35715d9c53fe50c9dd3eaaaac0cf234", - "dist/2022-02-22/cargo-beta-i686-pc-windows-msvc.tar.xz": "f530b478e8de8a1e23f73d0a7f9467835c02f5d5c29cabcaf6b7c8191753d23d", - "dist/2022-02-22/cargo-beta-i686-unknown-linux-gnu.tar.gz": "40354386ce0a62ae2851ed9cd82e86ff7da8fbce0a0232ba63b71b1ea583af8f", - "dist/2022-02-22/cargo-beta-i686-unknown-linux-gnu.tar.xz": "d480890b820adf734e4c952e7fc78636b679684ed9bcceb73c4596fb1d45c8e3", - "dist/2022-02-22/cargo-beta-mips-unknown-linux-gnu.tar.gz": "36575bdbde3af9f33467608d123b145a35a708c6814e8e66be3736cf38fcf4b8", - "dist/2022-02-22/cargo-beta-mips-unknown-linux-gnu.tar.xz": "977da6dd9a6865b125222d0a2067d95de6dc1042533df14bb8598e3160cd26f8", - "dist/2022-02-22/cargo-beta-mips64-unknown-linux-gnuabi64.tar.gz": "bac180c4c4d26acb42916f489abdc9bcc98683de2f9437ef56b00b624338db74", - "dist/2022-02-22/cargo-beta-mips64-unknown-linux-gnuabi64.tar.xz": "48640b94de8f38bc1c285c6c7a3f973c461d7336acfbec1b2f1eab09294929bf", - "dist/2022-02-22/cargo-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "870e51831fdb84e927b4556d3f6e1882bd8d3a542d36fd9c59a52333b7671e9d", - "dist/2022-02-22/cargo-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "898ea5ba25d4503092cdbeda226947c4465515e684945dbd16b9009881f1c2c0", - "dist/2022-02-22/cargo-beta-mipsel-unknown-linux-gnu.tar.gz": "b5177d9199b585710cf0f9cf65b9d5e9e3372e869a6a1445119566878737358c", - "dist/2022-02-22/cargo-beta-mipsel-unknown-linux-gnu.tar.xz": "9aa14abb02c8ccd4f9b684c02a544776e0936919f8f7e46698f85a69b7dbcd2d", - "dist/2022-02-22/cargo-beta-powerpc-unknown-linux-gnu.tar.gz": "9d6bd864f629a957172c7fbd20c7549d88248a42f259e6be9f779b4bbb4b09bd", - "dist/2022-02-22/cargo-beta-powerpc-unknown-linux-gnu.tar.xz": "988929cb1e75d053c1b081a8a672310447e630195175fd1e54dc5d0ec35783df", - "dist/2022-02-22/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz": "1b32b43d0ec4989d048223ffdc914656c693ea978e38543b45b1d0c78a6f2c2e", - "dist/2022-02-22/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz": "cd52c1191291ad23dee3a5eea11cb30d2b39e5be56cfbeba72d63add0c1f8689", - "dist/2022-02-22/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz": "54126eee55aadba389058e4114e57898604398a3638cec33cb06f0b08f19c293", - "dist/2022-02-22/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz": "04c0333e2ed44f0c6c24583f8dd08041bff444024407b5b15ca4679830d00748", - "dist/2022-02-22/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz": "d06c620327fbfbff716ac80c569fa3f93d21a137653226c3417a32978d7c21fa", - "dist/2022-02-22/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz": "dc9c6058c0612b9e75f17785571f334e3ab07d7d41e7e6892a9f176a032efbfb", - "dist/2022-02-22/cargo-beta-s390x-unknown-linux-gnu.tar.gz": "41740c9043a17a6f94ccc9b1ce3e651bd5c1d40082573c2603fc467e3e7211d6", - "dist/2022-02-22/cargo-beta-s390x-unknown-linux-gnu.tar.xz": "9f35c90f54fd109dc89101dc4f400c1e2274c73dd830ea47032f6669f17d2281", - "dist/2022-02-22/cargo-beta-x86_64-apple-darwin.tar.gz": "bb2df47156ed411068df28b2f3da9cbd1a43e87da92b79b08f49c9ec1b7acf9a", - "dist/2022-02-22/cargo-beta-x86_64-apple-darwin.tar.xz": "1e28f97bba0788d8666ea99dc6794f14246248d2215ca954523a022f32f0032a", - "dist/2022-02-22/cargo-beta-x86_64-pc-windows-gnu.tar.gz": "ec819340d489948ca3376011e504163b2b8aa4a795757b76c680d7827a894d51", - "dist/2022-02-22/cargo-beta-x86_64-pc-windows-gnu.tar.xz": "74e39561dec9a133d98e85f05659353fe5123b813e2042a6e1d1aeff44f8f018", - "dist/2022-02-22/cargo-beta-x86_64-pc-windows-msvc.tar.gz": "43c4071dde2a487211ccb8b70738dd9f2bff6d629c10c676387bcf3dd1bbdbe5", - "dist/2022-02-22/cargo-beta-x86_64-pc-windows-msvc.tar.xz": "14aa403752daef201d9c62efaf342fa9070f1acd15417a212840dec9b04e0bf6", - "dist/2022-02-22/cargo-beta-x86_64-unknown-freebsd.tar.gz": "dd186508224dddd5fd701741913bfabfc0a11ac4ec3268e4089ff20a9e6db851", - "dist/2022-02-22/cargo-beta-x86_64-unknown-freebsd.tar.xz": "051a08c9a74150e706f683c96ed1a89531d75622a379e738f27c838317f1aa0e", - "dist/2022-02-22/cargo-beta-x86_64-unknown-illumos.tar.gz": "ed980715be8e3e8354656e09b0b8fd265a1009c7af3c77a0da7ee297c746d465", - "dist/2022-02-22/cargo-beta-x86_64-unknown-illumos.tar.xz": "119943b8a0c62839de252a372960c93124b99de1b918122d2798dadac8658918", - "dist/2022-02-22/cargo-beta-x86_64-unknown-linux-gnu.tar.gz": "1738f1416773c85571414162ba894a753db03fcac9770012358f64db341fedd3", - "dist/2022-02-22/cargo-beta-x86_64-unknown-linux-gnu.tar.xz": "eac6a6deb3a7cf0d9d6c0d474cf3af2c3fb6a27f047c59e39549af219a04e487", - "dist/2022-02-22/cargo-beta-x86_64-unknown-linux-musl.tar.gz": "20d7ee9d7234395840b2478681ce4d79bf71045ae218d61f6b54ab9476dc39a1", - "dist/2022-02-22/cargo-beta-x86_64-unknown-linux-musl.tar.xz": "3eaf0ea2187a5483738aef57c1a72e90fd7d2f1f43d161b4312a88a2afb5fb36", - "dist/2022-02-22/cargo-beta-x86_64-unknown-netbsd.tar.gz": "7359595da468c6a22e42c8cc1918034e1efada2458281354d378c6921fd839bb", - "dist/2022-02-22/cargo-beta-x86_64-unknown-netbsd.tar.xz": "901fced3b888c3d117b7ce5dae9f670b5a3251572d6e2dc2b143c734e38ac683", - "dist/2022-02-22/rust-std-beta-aarch64-apple-darwin.tar.gz": "dca112bb73d3db03df91770cda1a90f130fa19e80657bae8c70c9737a1739f0b", - "dist/2022-02-22/rust-std-beta-aarch64-apple-darwin.tar.xz": "5d86a54ac7a3da08eee4401cbdca416b88f47e3f873bf77aa09f9d8259bde015", - "dist/2022-02-22/rust-std-beta-aarch64-apple-ios-sim.tar.gz": "7496f9dc8cab45f14ff01c3ceb7938dd2532b802903aade5775f1311e29a2191", - "dist/2022-02-22/rust-std-beta-aarch64-apple-ios-sim.tar.xz": "fb0704f0b2dd9cbee2a7b887963c15fd5c3391425632362161d59e94c81b608e", - "dist/2022-02-22/rust-std-beta-aarch64-apple-ios.tar.gz": "b63c47df8f9ee3a498248898d465dd24c2de842d3a61e2a7850fc10348c65080", - "dist/2022-02-22/rust-std-beta-aarch64-apple-ios.tar.xz": "d25ee7959831231a1661f95ca11bd3fbd5cb177ae8cd82bb3fb33889e8a081df", - "dist/2022-02-22/rust-std-beta-aarch64-fuchsia.tar.gz": "06fa5e122904ff03b1e0e9218a58b7c492c3cbb57e2d26e255171f6c7734f5b7", - "dist/2022-02-22/rust-std-beta-aarch64-fuchsia.tar.xz": "8b4a60e54a255c5eb45545c78c4b43d78527777f874a8a9b215999b414c3dbec", - "dist/2022-02-22/rust-std-beta-aarch64-linux-android.tar.gz": "7209d2f4fb41fe00afee1d49246228fecd955930abac317f7ae608a4eb27f834", - "dist/2022-02-22/rust-std-beta-aarch64-linux-android.tar.xz": "ad8aac4d753c357fb39408c01567a95710f95c73b5589d37304f6d8eedf43ea9", - "dist/2022-02-22/rust-std-beta-aarch64-pc-windows-msvc.tar.gz": "0e25c7a39e32cd3dff61a2972df5e5a08f743d505d0a1e99a26768b3d0abc44a", - "dist/2022-02-22/rust-std-beta-aarch64-pc-windows-msvc.tar.xz": "63f7d6967c920135bfdc45e4867579ffe5858d1608777bae0c64e3bb74180bc9", - "dist/2022-02-22/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz": "e1688baa8a9681e8975885def8ef160da31f79d4b767fdfffda0eb4a281c4a20", - "dist/2022-02-22/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz": "07acb0382de4c967421ad62367c4585e567ac16f82b2c6d2bac4218999ea217e", - "dist/2022-02-22/rust-std-beta-aarch64-unknown-linux-musl.tar.gz": "9abe9e57210890632319ae175e4ff10d4c05d505820e6e6d4b694a84e57b3e53", - "dist/2022-02-22/rust-std-beta-aarch64-unknown-linux-musl.tar.xz": "cf9edb113ce62b71b7e6d535c2d0c153fb0041a86ccf22393c7fa1bde99ff589", - "dist/2022-02-22/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz": "1d378a8eff18de4487f6edda01f9c9f991b0f3dc575be062d5faa04f0489dff1", - "dist/2022-02-22/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz": "84c23145e5ce8fe37088d413e3bc4072cbe662feb0400895e91e924515c4d8ac", - "dist/2022-02-22/rust-std-beta-aarch64-unknown-none.tar.gz": "04a154058d8014608bbde9e70a85bb1943c58053ac64119ea84be70a1a085c35", - "dist/2022-02-22/rust-std-beta-aarch64-unknown-none.tar.xz": "6edde8a372c29756b54fccf54232fee7899625eb6c5529658024028ae4f8a471", - "dist/2022-02-22/rust-std-beta-arm-linux-androideabi.tar.gz": "b1670696b4aa52daa390a5c9ce26056507a11ff883d98ed6e84a7f04b38ee7a2", - "dist/2022-02-22/rust-std-beta-arm-linux-androideabi.tar.xz": "2cb4a03fb3b8d8556c359c4d4f1823dbef3a22f0483e43f41ee154333a202ec8", - "dist/2022-02-22/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz": "46f7ba3b96a9088f242a0ad191ca320529d9798d8842d41accd14622fb7b6750", - "dist/2022-02-22/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz": "091190cccf966aeb6d387fb6542ad43f7f38b6843a13309f92df2f759a4045dd", - "dist/2022-02-22/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz": "4d1740f7d33566e2642d1618d9c6cd0c0650d39af5d428dfd993a4f65e27e3c6", - "dist/2022-02-22/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz": "4d4c2f1fb3319030b978d1343b80a34c22b3c4df58ef1dbce9eddc42a0e9ac41", - "dist/2022-02-22/rust-std-beta-arm-unknown-linux-musleabi.tar.gz": "d7ad7df20a41f7df39fd0973f37740d0c732468de6e099febc13db7f871860b4", - "dist/2022-02-22/rust-std-beta-arm-unknown-linux-musleabi.tar.xz": "598c5ab98d3a3ffeb4f3aaf5535d8947e6ae6d45aa0071438f9490dd63acf7b5", - "dist/2022-02-22/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz": "46d2276ab614e5f4d1f990824fd2b67c9398c669a01698c8a4b157bd45e3eedb", - "dist/2022-02-22/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz": "f404d2c3d89ae820112a324a3c5bf127efb6fb31813138c0fde99948eea7d76f", - "dist/2022-02-22/rust-std-beta-armebv7r-none-eabi.tar.gz": "8c8c547387db74673c1954b8ac1cdeff5b726d432581649bc60f988acb0352e2", - "dist/2022-02-22/rust-std-beta-armebv7r-none-eabi.tar.xz": "2942966353af6f1a29c3266e1f35e3f1bf49a7d555a6034dda72c31b7e83b89d", - "dist/2022-02-22/rust-std-beta-armebv7r-none-eabihf.tar.gz": "3b80afad86c655b5be24ddb8348c3d5781006053c14932ab2855be525c35108b", - "dist/2022-02-22/rust-std-beta-armebv7r-none-eabihf.tar.xz": "3b55016a3f27aa0381eb502e2d732aa9397aac117e98d4fb4721587b62ac7842", - "dist/2022-02-22/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz": "2c17d2a504c4f7aa581731bbfa9eecc1638b9bdc8800d136da1a6d248ec70e76", - "dist/2022-02-22/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz": "78dcb72afa5187b7ae91a1ccc2e7978b30cab8eaaa46cb09a62266868c866ad3", - "dist/2022-02-22/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz": "d42741e9ea6f23fc88dada5e9339cf7fb3015d3713335b77543afeaafdfcbb53", - "dist/2022-02-22/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz": "ecd0e30fbd08fc8dbf478ddfb7a48b619b84b04c687bdcd56259b64f9ccedea1", - "dist/2022-02-22/rust-std-beta-armv7-linux-androideabi.tar.gz": "b4fedc281f748c443232bf061fde9dccbf415eec62053103a270613689c4cf1a", - "dist/2022-02-22/rust-std-beta-armv7-linux-androideabi.tar.xz": "bae884d552a8d234efa795b5b56524cb834f06c77000e926bc0bd1446387174d", - "dist/2022-02-22/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz": "116c08ac9ca36e0d3d0bb86d0d25db8f19b508d851b93c6a738711400e1faf93", - "dist/2022-02-22/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz": "d15b7e02a7fdf7d45d0269b4c739a96dda4f22ef70d7a3a2b098527b34f81b76", - "dist/2022-02-22/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz": "86390d1528d0382109ae094005b35d84ccb5e6bc670a490d2c8e27010efafb13", - "dist/2022-02-22/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz": "fb23bfcadc53baf72793718b051710a6bfa6575f8fb7104925157681b1efdc3f", - "dist/2022-02-22/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz": "f34cce7af6d123b9c509f28d63f10397ebbea74b6181b819d022f700521dec7d", - "dist/2022-02-22/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz": "2777e62cbd8ddd5dce730f4a6671dffac132ecf194a8840178d178296264879e", - "dist/2022-02-22/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz": "4e6f11b82e57c60ab5e4329bcb0c5384f9bc2044ee8f194c3022949855389ab8", - "dist/2022-02-22/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz": "a45eaf577ddf69ebd8eb7b112bf2b79ffa7a3360ef959f6bfb5f0a5e634ede48", - "dist/2022-02-22/rust-std-beta-armv7a-none-eabi.tar.gz": "66fc6787cf5060b8d279d325ef745dc37206335a9e279bb7f3687b6564f3bdab", - "dist/2022-02-22/rust-std-beta-armv7a-none-eabi.tar.xz": "3996d7a5e7721262fed35af65949523510544eb3942c97dbcd231f84770edb7a", - "dist/2022-02-22/rust-std-beta-armv7r-none-eabi.tar.gz": "be50c97fd48c7209b2b452f3f9c00cca1fd26f8482b4c5bec46b9a32dbbf9cf1", - "dist/2022-02-22/rust-std-beta-armv7r-none-eabi.tar.xz": "4f74859110079c69ff3a84a4c4110ec4df7d4ce7bf4886a9115defc11174f41e", - "dist/2022-02-22/rust-std-beta-armv7r-none-eabihf.tar.gz": "1d29241da65cedfd665917fdc0ae8d66eaf847280c57ebfa630d6e4993232642", - "dist/2022-02-22/rust-std-beta-armv7r-none-eabihf.tar.xz": "a3898ab71f6fb6f0a0b85f706d74fc75330eaded7e4fde7e9903ad375b2c4c9e", - "dist/2022-02-22/rust-std-beta-asmjs-unknown-emscripten.tar.gz": "6c895e95c55cb55a40a24cbe381a5ce6ed5d50a6ce97781c33429fb846449a9d", - "dist/2022-02-22/rust-std-beta-asmjs-unknown-emscripten.tar.xz": "524b781dc177afef5fa70b13a80961d26ecfae25c331dc967127ed9964c29f98", - "dist/2022-02-22/rust-std-beta-i586-pc-windows-msvc.tar.gz": "43fae07717c4b20690c6d0843f43e10581e656346fcc1363cbb2f90efcbab93c", - "dist/2022-02-22/rust-std-beta-i586-pc-windows-msvc.tar.xz": "20c2d659ed82a128cb31d4fed737d79245edf84101b1ad58e4b694784c181aa1", - "dist/2022-02-22/rust-std-beta-i586-unknown-linux-gnu.tar.gz": "240c51132bb92b3e5d0b3abd281c1d317aae0cdc23ac5d06b465fd6a3a783913", - "dist/2022-02-22/rust-std-beta-i586-unknown-linux-gnu.tar.xz": "b8aafd530bc9f888b2d73d2ddb232501e481999faed06026994bfbc479adc892", - "dist/2022-02-22/rust-std-beta-i586-unknown-linux-musl.tar.gz": "0f36dd856386e03f34288c0fb720b86cb31969b1db5c90f6ab6329319b344b40", - "dist/2022-02-22/rust-std-beta-i586-unknown-linux-musl.tar.xz": "5bc340d21f80eb420ceafe5d7eb40651dc00dbbbb8ccde59ff88d6843ac93cda", - "dist/2022-02-22/rust-std-beta-i686-linux-android.tar.gz": "9eed175b238e5b7f2d7600233cda65efe570050f501680be8e08d98a54028123", - "dist/2022-02-22/rust-std-beta-i686-linux-android.tar.xz": "d6b106f23ac95537191b460847ce38b7e7f6ebb120561cb2b4497ec40d53217d", - "dist/2022-02-22/rust-std-beta-i686-pc-windows-gnu.tar.gz": "51b91d661906c4c6e54bfd34c16aa874447da706f15413c9f6caa7943e49b165", - "dist/2022-02-22/rust-std-beta-i686-pc-windows-gnu.tar.xz": "1d8b8c856e3eb75578a187a483074b2d78ea6c6047018a8110d685a9b6f59812", - "dist/2022-02-22/rust-std-beta-i686-pc-windows-msvc.tar.gz": "be373ef9dbc40c44be1cce66d6a37379670d8c6073d2e3ee0c010e08b8d0290e", - "dist/2022-02-22/rust-std-beta-i686-pc-windows-msvc.tar.xz": "97a8cabc18f4745c856e8a51deeb3b2cfaad15aa854dd8bf50d742c498375802", - "dist/2022-02-22/rust-std-beta-i686-unknown-freebsd.tar.gz": "4dfdaa7fa0d282dfcc8a919fbc077fb5a987820ea920a3f443ad286c3f16e134", - "dist/2022-02-22/rust-std-beta-i686-unknown-freebsd.tar.xz": "e9fef55eaf2302ae80b411bef7d3c52b9a2f8e5e80b1e629541722508aea629c", - "dist/2022-02-22/rust-std-beta-i686-unknown-linux-gnu.tar.gz": "05b2bdc3bdcc5853d4b44423031e82452d040c74d5b3832e03910c25c752e70f", - "dist/2022-02-22/rust-std-beta-i686-unknown-linux-gnu.tar.xz": "1038a6415b9f68c63cecb98b0ad860a0f424d7053e4fc6cc52c3054cdd9b3c56", - "dist/2022-02-22/rust-std-beta-i686-unknown-linux-musl.tar.gz": "588b13f016e2fd49c4261a230dde062f68de10d8b128e1b801071f6fb04e42b4", - "dist/2022-02-22/rust-std-beta-i686-unknown-linux-musl.tar.xz": "91dd6f3c85b28dc1aa0636bcfda1156c97fbb1322156c2a600bc66e2bac22627", - "dist/2022-02-22/rust-std-beta-mips-unknown-linux-gnu.tar.gz": "140af043ae006d47e7b19badfede6aa684c455b18df6d7da4a7c2437a9d303e8", - "dist/2022-02-22/rust-std-beta-mips-unknown-linux-gnu.tar.xz": "0ec24313945e2fe853c1139e729fa40e5ffec406070bd52468a23b96efd08c5d", - "dist/2022-02-22/rust-std-beta-mips-unknown-linux-musl.tar.gz": "3b4c2aa34c84d5cf6460f8fe46ba0e0596fe83403f38f0f53d8b14ecab3d7de3", - "dist/2022-02-22/rust-std-beta-mips-unknown-linux-musl.tar.xz": "53c3476fb78702570ba096d2f6becaef2b402bf8c5afa58b8d559ddbe7a379c5", - "dist/2022-02-22/rust-std-beta-mips64-unknown-linux-gnuabi64.tar.gz": "e2963c7aaa7ae70a341a67d93d52ac2911309cb1977639e85750b0dd8061bb21", - "dist/2022-02-22/rust-std-beta-mips64-unknown-linux-gnuabi64.tar.xz": "76444714fb5cdc40797c0d217536b4328484c12f2ad0f47e3635d88fc31aa958", - "dist/2022-02-22/rust-std-beta-mips64-unknown-linux-muslabi64.tar.gz": "0eeef057018f809ef008d23df65ede61b1d1695d2d5ffb6cf322e73939f789fb", - "dist/2022-02-22/rust-std-beta-mips64-unknown-linux-muslabi64.tar.xz": "efb4db958a03894289570b0383eedf47e3d3723793eab95a1336a8e4fac0a909", - "dist/2022-02-22/rust-std-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "59a15a0870013712d2d5162d180bfae71388eefb63d0ff0ee3dd30471c4feaf0", - "dist/2022-02-22/rust-std-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "46d9a7e326d582ec0d9cc674b4f2976da877b16197b0aec2ac783b3cbca8d0e2", - "dist/2022-02-22/rust-std-beta-mips64el-unknown-linux-muslabi64.tar.gz": "c6f88389945fc1802fbd271bcdfe77172d60b27b6416a6a899c29854748f93b0", - "dist/2022-02-22/rust-std-beta-mips64el-unknown-linux-muslabi64.tar.xz": "16ac29879c3fadb76ebc8ae1234dc4c2aed1809f329a95c67e5e54aa2730e9a7", - "dist/2022-02-22/rust-std-beta-mipsel-unknown-linux-gnu.tar.gz": "6c93eab95575a3327ec019c45f57564bf8c2bf92df1c9cc895de6f6b6514c695", - "dist/2022-02-22/rust-std-beta-mipsel-unknown-linux-gnu.tar.xz": "81e560c30f477cee45c866c6653fcf2b7942287547321f939ab68a849d1c680e", - "dist/2022-02-22/rust-std-beta-mipsel-unknown-linux-musl.tar.gz": "612d4169406b20abaa38362dad969008d5d3eea1b7c5a376f5ff33870879e70b", - "dist/2022-02-22/rust-std-beta-mipsel-unknown-linux-musl.tar.xz": "d39459a64250838ac6b46352de106fbd199e4e586f066123a1ffe78f52291d1d", - "dist/2022-02-22/rust-std-beta-nvptx64-nvidia-cuda.tar.gz": "ef9ada210252cf9f66e7ff6aa43855318ac6030b6a963f4f25ef227c3b50a51d", - "dist/2022-02-22/rust-std-beta-nvptx64-nvidia-cuda.tar.xz": "7ba46c4171c4776770d8a5e590e8b3e12fc85d519fe85c5db166569d353fa371", - "dist/2022-02-22/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz": "11e163b7e4884078185ac92fdba62a77468b70ffe0e4f22a6c420ff8441d12cd", - "dist/2022-02-22/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz": "3f88f0163078a219730898a77f3bf8db3df3967100931a4685bcd9d43f2b4668", - "dist/2022-02-22/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz": "68742e04b7fa9f398945363b41e8988040f53c46de6fb7b481647052d54f23ad", - "dist/2022-02-22/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz": "f978bff9ae78b26c439a3817648a63cd9e9e149bf08cf2124ef2372b5863c52e", - "dist/2022-02-22/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz": "715d0512df81db8266b1264721704ef069a78ae5ec615c772e876c119723df80", - "dist/2022-02-22/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz": "65739553817038796c9364f8e92f7b492872cc46cab9ea3535b74ce55a1b6474", - "dist/2022-02-22/rust-std-beta-riscv32i-unknown-none-elf.tar.gz": "65815e6f296c5651f4185820c2bfe9a6929d3a4aba555b453b1e21791e98586e", - "dist/2022-02-22/rust-std-beta-riscv32i-unknown-none-elf.tar.xz": "51f1a45d7fea68806220a31877c4ae2aa0be171aa594fab847ee295682afe9d2", - "dist/2022-02-22/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz": "25199052e5e2f39611c60cfb6c071337c3621eef7203090a1f1abba9959a05e5", - "dist/2022-02-22/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz": "ac272237e72fc06a2c940f643df7d614267182acdaaa883cdc2ed86baa83e955", - "dist/2022-02-22/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz": "8b6b8235a671d0ca3b0548b64197ec320975d9866f13435c069b279f95e8d8d9", - "dist/2022-02-22/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz": "f0136a97c8338e72e05bf4390ac0a828f52559b73727a9a075c137dbaa249637", - "dist/2022-02-22/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz": "7be9a45ddbdf281496520d76372a004f16b927fc6bade0ae97ad8b92d34d3d7c", - "dist/2022-02-22/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz": "47f3a3d69b0819dc681e37437618a2130f4c5aa199cad3bbbbee8bd442374ac6", - "dist/2022-02-22/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz": "8a7d37d7e022c4513877f428361312963d555f35e78978efc27f4eac2e411b6a", - "dist/2022-02-22/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz": "d530edb2ceadba90b840a691b61f267388b9022003318f489fd46c84560459b9", - "dist/2022-02-22/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz": "012398447b0236c20a3ceab1e4f6126bac120c361875f15d304e9ecb7c6781a3", - "dist/2022-02-22/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz": "c092dc1d8ee387e1ac8496b3bb412175a03efe4cf923b82ac4ec47c880986e72", - "dist/2022-02-22/rust-std-beta-s390x-unknown-linux-gnu.tar.gz": "acaeda013557588d8c9643fd0aa7ad0da5cc7c64f7aca0fc383b00f7b4a174ac", - "dist/2022-02-22/rust-std-beta-s390x-unknown-linux-gnu.tar.xz": "99c1a499bb9cfa343bf03da8abfa8f18595fedc3fb354e893fa62f67d067bd89", - "dist/2022-02-22/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz": "e07bcd62f79c9f764b6c6ea8d3744506beb8e1ee1ddb202276f116e9ee44ecc5", - "dist/2022-02-22/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz": "2283784176fc003b8ce29899b747dbdbe848fc226f963ec36a95d79b1afb0c0e", - "dist/2022-02-22/rust-std-beta-sparcv9-sun-solaris.tar.gz": "80c1613f9598db047a95be40494870942a5a4ef54c7e4a72c9fa3df9b23f64b1", - "dist/2022-02-22/rust-std-beta-sparcv9-sun-solaris.tar.xz": "9b33ce8b938978caa4164af52bbb982183fa2fa86e5f079805fb6f479c8c9aae", - "dist/2022-02-22/rust-std-beta-thumbv6m-none-eabi.tar.gz": "794c9b2cbe3e76e2dbab31d89817a7c21bdc19a59022ee652862aac025db6914", - "dist/2022-02-22/rust-std-beta-thumbv6m-none-eabi.tar.xz": "0a7afdedd20874df94e9604669926b1ce82b68774db7756312d43bbbea3e9334", - "dist/2022-02-22/rust-std-beta-thumbv7em-none-eabi.tar.gz": "19821e7291f4363f37b5ef2a1b505163cdf02e38d5b47aa980892e794e918c73", - "dist/2022-02-22/rust-std-beta-thumbv7em-none-eabi.tar.xz": "a4e0b594b756316bbaa05ebd4d0559edc9a733d5ffe84797c6e096882969ad36", - "dist/2022-02-22/rust-std-beta-thumbv7em-none-eabihf.tar.gz": "222e15bb1db6e80459616a001ca8fcad8aba9921b1161e8b9ce9e38fd9fb2d10", - "dist/2022-02-22/rust-std-beta-thumbv7em-none-eabihf.tar.xz": "72ae8a9dba6c2913ba3eaea2e96d7e744985f6c5badf170daa678c00b89e93e8", - "dist/2022-02-22/rust-std-beta-thumbv7m-none-eabi.tar.gz": "74b4d65d13262964ef180fd7a63a3d2f62c529aa3b99883e3e83815338129631", - "dist/2022-02-22/rust-std-beta-thumbv7m-none-eabi.tar.xz": "7dfacadec18736016520db4a07a677f74771db955418f4b1df6c09d871e159e9", - "dist/2022-02-22/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz": "6bf0482aecbe5d1dba551319cffa074e0a72e6ce8c2e636ead98733429bdf09c", - "dist/2022-02-22/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz": "81e9ff4577785f9d11cfbf92ee18dc6a1202147500ffa474f4a0ab099af0f7e4", - "dist/2022-02-22/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz": "bf073994172580e7b9e5a0a618ae5f58759801a8e949d2137f69191d05b146eb", - "dist/2022-02-22/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz": "8c21d837cd9e1c98db78b4c37dc03f07373184e2354880a1dd9501fc62f8b6f7", - "dist/2022-02-22/rust-std-beta-thumbv8m.base-none-eabi.tar.gz": "167f9fc5aa4d3dd68044110a346d5888d9bacc5c8d3fb1140d2687f312ddb057", - "dist/2022-02-22/rust-std-beta-thumbv8m.base-none-eabi.tar.xz": "c64177f1aab599a25d97497124c5d4e9449ecffaf96caefecc8b0a2552aacb4d", - "dist/2022-02-22/rust-std-beta-thumbv8m.main-none-eabi.tar.gz": "95de6b1fbd95287258f9caac1f805492afc9657adfada82295736d85b1b20c3c", - "dist/2022-02-22/rust-std-beta-thumbv8m.main-none-eabi.tar.xz": "d3f8c5ed80c59b1bd2c538aab63be8b39db78db3c2f49d7447092a8b97e2963c", - "dist/2022-02-22/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz": "aa0ec6f6b0d652ebde2694a8153252928cc1f41c565912da8bee5b0d225b786b", - "dist/2022-02-22/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz": "1f23bcb96112bdec4a1f45c41afef3faa95cddc5be2f693ee3e1f4f3e584c49f", - "dist/2022-02-22/rust-std-beta-wasm32-unknown-emscripten.tar.gz": "49d6ea925560f3eed75da2c7d9cefe404525702504ce0cc4cbfb3fe638814566", - "dist/2022-02-22/rust-std-beta-wasm32-unknown-emscripten.tar.xz": "13b93becc017bb6bb60212ba30d6717a1be6af139b965b15000264b48e163991", - "dist/2022-02-22/rust-std-beta-wasm32-unknown-unknown.tar.gz": "27f3dffa92ccdc8d2b3342e737b5f80b7b2dbc53a994249bf318810f4d8b4643", - "dist/2022-02-22/rust-std-beta-wasm32-unknown-unknown.tar.xz": "2236cab6b48c9c564731913dc652a2e0cc6af0d6b9a64b66cf39a6b943c410da", - "dist/2022-02-22/rust-std-beta-wasm32-wasi.tar.gz": "35ca9a19558512fc1758e9c7482246bf6a518e48d4a93a8748c07ebdb4be9d6c", - "dist/2022-02-22/rust-std-beta-wasm32-wasi.tar.xz": "3bbae2bf8423e3323155f3f336435fbd53b58cfa16107f9fa567ea77923e5ff4", - "dist/2022-02-22/rust-std-beta-x86_64-apple-darwin.tar.gz": "9a6c1808797c92da862f706f08a6482a4412e52dc9a492d06645f03c8b1c0fc6", - "dist/2022-02-22/rust-std-beta-x86_64-apple-darwin.tar.xz": "2a658172c220c047542e992a8b1440d887d809f301f3a0e23a811d586ff43dc2", - "dist/2022-02-22/rust-std-beta-x86_64-apple-ios.tar.gz": "2da9affdcc01bc9369192b40feb0797349d2084fb6ddff55e61d7b0a831272cc", - "dist/2022-02-22/rust-std-beta-x86_64-apple-ios.tar.xz": "dcf403a1d670bdb0e29d61161d268a2be9a6d31ea4055dff562e06cb72ba1c78", - "dist/2022-02-22/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz": "506ad99d890f0c1ff525a8c9f28aa4f7aec349afd78279b21d7486a88f548ef0", - "dist/2022-02-22/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz": "4f20a7b59e32266fc01c67d36ec27f68e9a44105819e1c5a1dc8823367c4914a", - "dist/2022-02-22/rust-std-beta-x86_64-fuchsia.tar.gz": "0705d9ad7e640a8a4b48c88d1997ffa57f849d1fa4cf3ae4185afd2122ed6b60", - "dist/2022-02-22/rust-std-beta-x86_64-fuchsia.tar.xz": "2b5382417346f07f105704eac3fdd4a8bfa0285804715a64d1e314a0c9ce4ef6", - "dist/2022-02-22/rust-std-beta-x86_64-linux-android.tar.gz": "03404906af39d9111316c624835a09a4326f6172f52a405b82f831c3b408ea9f", - "dist/2022-02-22/rust-std-beta-x86_64-linux-android.tar.xz": "5ff2b24d8fc552a791b609de6373afc57a8661d2769e89f4e19c5cf85be864b4", - "dist/2022-02-22/rust-std-beta-x86_64-pc-solaris.tar.gz": "a90e13d0e45a71843caa1dd960a7b032120034aa0caa4148f825e3493d65640e", - "dist/2022-02-22/rust-std-beta-x86_64-pc-solaris.tar.xz": "d176219f6fb41aa0bbb59b11801f45af29edeb24423325b162686d3fc3d3ff93", - "dist/2022-02-22/rust-std-beta-x86_64-pc-windows-gnu.tar.gz": "dd8da303ff2740b3b9ea565ed9a335f62de8c1357884660abbc4e7a9ccef7a74", - "dist/2022-02-22/rust-std-beta-x86_64-pc-windows-gnu.tar.xz": "d807829b1328527f49d318ce942dea5fd8e71a8fa16cbfe2d7444fb5a962e158", - "dist/2022-02-22/rust-std-beta-x86_64-pc-windows-msvc.tar.gz": "7ba1551ce159030125ce74ae7321e0365fb2d33758fd2a578693dec8ff817c66", - "dist/2022-02-22/rust-std-beta-x86_64-pc-windows-msvc.tar.xz": "55ab2bcc5469ff433e15c06f490af3721abd6dc468eed68ce3fb2842dacaf28e", - "dist/2022-02-22/rust-std-beta-x86_64-sun-solaris.tar.gz": "1e1b97a4840415f7efada876ddbeebf336ea4c6a0d0fab4238ce1f490e6450a3", - "dist/2022-02-22/rust-std-beta-x86_64-sun-solaris.tar.xz": "20377a3a7eb39727c3c4202a35569c52362f486fdc3ea451a0d9cc5ccc95ae4f", - "dist/2022-02-22/rust-std-beta-x86_64-unknown-freebsd.tar.gz": "5c3116945faee33a8a45f911d270c19ad979f3c3f11af2dc769173b6b8f93564", - "dist/2022-02-22/rust-std-beta-x86_64-unknown-freebsd.tar.xz": "852b0fa691ce59a509cf8c414407a8ea1bed362cf52007ceaa0d240533a3b6d1", - "dist/2022-02-22/rust-std-beta-x86_64-unknown-illumos.tar.gz": "66081135debd54f351c3117428aae95ca160895effd7c8c5d3c9eacdcc18dafd", - "dist/2022-02-22/rust-std-beta-x86_64-unknown-illumos.tar.xz": "80bd080495367c9cad59a356e410aa200aee03690ad38d817ff9020e2c46b7eb", - "dist/2022-02-22/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz": "42b513b8d24d66f582c4cab8d61414012c34a25d7f65679985ab68e2cdfc0fed", - "dist/2022-02-22/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz": "18c5bdfc09da2789c79d4b7ec8e0703699acbd2528efc13a249043517e415031", - "dist/2022-02-22/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz": "f12be56fd501f1305be77f31e7021c79749e60286d27f68c4c6fbaf9326b6b18", - "dist/2022-02-22/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz": "f9445ebb056c31cce13267e7ca1416aa01c482e6d0968044c1c90193a4ab7ecf", - "dist/2022-02-22/rust-std-beta-x86_64-unknown-linux-musl.tar.gz": "46724764c0c9ef57ca9e74ebcfefbfc4053d0aec9827219e3a8f70d7661d4f00", - "dist/2022-02-22/rust-std-beta-x86_64-unknown-linux-musl.tar.xz": "9ec841afae859c5d2f386a0ba333cb7f1055718645de6a46cc429e1ab6388a8d", - "dist/2022-02-22/rust-std-beta-x86_64-unknown-netbsd.tar.gz": "224c80a3babc99ed5ab0f2c2376a730606a49adf99b26ac1039b98e96972bb49", - "dist/2022-02-22/rust-std-beta-x86_64-unknown-netbsd.tar.xz": "a6011d4c075ac5f7c8fb64dca3388e659c18fb95b104ff5ba661e614015607e4", - "dist/2022-02-22/rust-std-beta-x86_64-unknown-redox.tar.gz": "ca11ca60fc78827a87e202060f6892b2513c4e7ee7af637c9f5ffc73512258b5", - "dist/2022-02-22/rust-std-beta-x86_64-unknown-redox.tar.xz": "a2df3333acdda56303a8607151538d4e3f0ccbb5e7ad0ce538c2daa16927a2aa", - "dist/2022-02-22/rustc-beta-aarch64-apple-darwin.tar.gz": "14e52bfeaaa4e1040c9ac2a1ef5ce55c6f862187d789ff07bfc10397d5302b2d", - "dist/2022-02-22/rustc-beta-aarch64-apple-darwin.tar.xz": "43e8d608a04b8c1037e3d6fae9c90aad0317b109176a9016b8327bca34346e4d", - "dist/2022-02-22/rustc-beta-aarch64-pc-windows-msvc.tar.gz": "507d7533e80f022031e27698664bedd4c0e02334b008fa1276e0b4094c616a11", - "dist/2022-02-22/rustc-beta-aarch64-pc-windows-msvc.tar.xz": "798d75848e5fe551d70feeaab10cd77709e218c34d65fefc8392667942e5da93", - "dist/2022-02-22/rustc-beta-aarch64-unknown-linux-gnu.tar.gz": "ce50f8abc2070654681d073db6d36ca0e36806a9af0e23d7273771713756b3c9", - "dist/2022-02-22/rustc-beta-aarch64-unknown-linux-gnu.tar.xz": "4654ae2341a8a62d7bc2facf85bcba483f3bb083d51e7127c8b3c18a63a31180", - "dist/2022-02-22/rustc-beta-aarch64-unknown-linux-musl.tar.gz": "e66559d3acd1fd17c0fed9f106e51865e5de85438ff2eb2add4032a29ee4947b", - "dist/2022-02-22/rustc-beta-aarch64-unknown-linux-musl.tar.xz": "648ca772d54e95a6066115dedc6b04b9874875bb0950f1cabef99d91c16083d2", - "dist/2022-02-22/rustc-beta-arm-unknown-linux-gnueabi.tar.gz": "737c865a96af5ea78492bccb1341025b25dcd6449229cbf085524296bcd232d9", - "dist/2022-02-22/rustc-beta-arm-unknown-linux-gnueabi.tar.xz": "484ecf1f2f940e4d46596dbf6697ff6d94edd90739769f63985415a360e65703", - "dist/2022-02-22/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz": "503e5827abbe658d4caa91432506121e3f3ed5d3d1896a7fe1f6b4dd38c5ba1a", - "dist/2022-02-22/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz": "c0001b8f07436a1765569b857b7f1c0ed81dfb87de8ada1e534c2cde1ce866e8", - "dist/2022-02-22/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz": "e39e0f013d02d2a340c62abfa58b37095fb0df828e5678c94f6611e3b03e3670", - "dist/2022-02-22/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz": "9aa60dba618f60f3099c0b2b14ca55a15187fc6858c45bde482bc40d324acefa", - "dist/2022-02-22/rustc-beta-i686-pc-windows-gnu.tar.gz": "4ee632be637fea478c42f2c77a24f8146b6b982bb0c9c9a19d5e83a6cf0d49ca", - "dist/2022-02-22/rustc-beta-i686-pc-windows-gnu.tar.xz": "ba4d659c22647102ed0ce4fa1b7121df788479838b6de08058a7ccd14923293c", - "dist/2022-02-22/rustc-beta-i686-pc-windows-msvc.tar.gz": "9d37026d3efcd15c18eae8a35d5c91089b0094ca3fa2a09c07a9022a246ab5bf", - "dist/2022-02-22/rustc-beta-i686-pc-windows-msvc.tar.xz": "2edb8490cc2a02821f1c088f0bb9576e8c6a511654209da940de0aec42210dca", - "dist/2022-02-22/rustc-beta-i686-unknown-linux-gnu.tar.gz": "3cd3297af97a6343bdd92457837aaa80f775f2efe64417856a51f6540b703151", - "dist/2022-02-22/rustc-beta-i686-unknown-linux-gnu.tar.xz": "c3497504066a953efbcc28840b6b7f1bf2799ec7aaa987d806cd56b874a9304a", - "dist/2022-02-22/rustc-beta-mips-unknown-linux-gnu.tar.gz": "a15c0cc57cee5ba21dcfba2c9e6ebc940e4aab635832d487e5db3adaf9749325", - "dist/2022-02-22/rustc-beta-mips-unknown-linux-gnu.tar.xz": "95d249a9c96253771e197adc86175acde4fa866f84aac84dc299df7bfee4985c", - "dist/2022-02-22/rustc-beta-mips64-unknown-linux-gnuabi64.tar.gz": "7c0b48e2e3af9807a5b460cc453534f821850522b43ca66e918f42312f634a16", - "dist/2022-02-22/rustc-beta-mips64-unknown-linux-gnuabi64.tar.xz": "aeb58f5b1dc9c96813f421763fa75b19219cdfa24100faa5ff833f70b56b8087", - "dist/2022-02-22/rustc-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "1ad4c58f78cf006b1243bdb3e4261ffc9d21c6eaa7ac2adad588173fa6bcba73", - "dist/2022-02-22/rustc-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "c119c341da94a30f569fbc1edeaf7d6e0083f6e16ef7aa219d3c499aae351ba5", - "dist/2022-02-22/rustc-beta-mipsel-unknown-linux-gnu.tar.gz": "b61616e8eeac33c979ee37f5938dd6ee5c308f58a6c2beb8a1f50c7e3506820f", - "dist/2022-02-22/rustc-beta-mipsel-unknown-linux-gnu.tar.xz": "bc5a46ef0c7e761f619e8cffb8dd1818a32551ca14be88649b2e2582f905bdec", - "dist/2022-02-22/rustc-beta-powerpc-unknown-linux-gnu.tar.gz": "6331d582c1130652d939f22eda45ce1b321b577d34affefc0cc0d54050460d28", - "dist/2022-02-22/rustc-beta-powerpc-unknown-linux-gnu.tar.xz": "bc5cb07aef32ef637b25850e443e737725c4cac7f513207d79f9520bd41888d7", - "dist/2022-02-22/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz": "a00742e6898e49363ee8478ec4f3d2cbfc778c540233d308b7ce88bdc7bc5dc0", - "dist/2022-02-22/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz": "ad3a5f983ce1ff07948c962f885bf7adf182543e8cb04630a3feaafe43b8a56a", - "dist/2022-02-22/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz": "4b620d1c6e97436100dd2135ea4e380c5c7f5a480a9dc615601343dfbe30bab6", - "dist/2022-02-22/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz": "92ef427c03064dbb5e5f3cdd00fa86a754a6b67961534c37256d8dbe127a097e", - "dist/2022-02-22/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz": "4e050159e2a61217dcf3b622f5fab7bc18a1110ab2e87f161879545b7da52fe4", - "dist/2022-02-22/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz": "bea23024681fb2bac5f1531969d494a421e48d19148a77b7be797298c6e162d0", - "dist/2022-02-22/rustc-beta-s390x-unknown-linux-gnu.tar.gz": "efc8e427beffd618501b1c14562c9b1a78958831737eb849507c00ebf0ad6e90", - "dist/2022-02-22/rustc-beta-s390x-unknown-linux-gnu.tar.xz": "c361166049cfdc1de3a3fa8f11061ea770d76f38623db0ede269366bb7f82d99", - "dist/2022-02-22/rustc-beta-x86_64-apple-darwin.tar.gz": "4c2c12f423036eadae0b328381426e7e43d7cb7a83e4fe06a4c88576e164d010", - "dist/2022-02-22/rustc-beta-x86_64-apple-darwin.tar.xz": "628d767591c8e5ece33de3e23e262fc55d6294513bbb537efbdb4b81f29f40a1", - "dist/2022-02-22/rustc-beta-x86_64-pc-windows-gnu.tar.gz": "06a2f1e96caf3737c5bfed4bdfb219a4f8b3484339d42651005dbc03eea634ed", - "dist/2022-02-22/rustc-beta-x86_64-pc-windows-gnu.tar.xz": "1892a79bb57dc0498db1ea467ea70455ec6bf4f55b5d014bd53170be81abb9d0", - "dist/2022-02-22/rustc-beta-x86_64-pc-windows-msvc.tar.gz": "1d55ec78eb3be79cffe3cd3dbaf300f9fec74f2f0d7559098c7a04002da75788", - "dist/2022-02-22/rustc-beta-x86_64-pc-windows-msvc.tar.xz": "6bf18b2583840dddebdd2f71b65e6986afb2c5ce03d9641a112afcdb443e3850", - "dist/2022-02-22/rustc-beta-x86_64-unknown-freebsd.tar.gz": "047906362381a6ea3c575e508fb80d12c269b104866c9a2b816c0702b67753f0", - "dist/2022-02-22/rustc-beta-x86_64-unknown-freebsd.tar.xz": "b186691e919123365da36a4368ed5d1b78b81e46583b9c282a909004998a396c", - "dist/2022-02-22/rustc-beta-x86_64-unknown-illumos.tar.gz": "c8c60d2aa4645a18578eba0a637b4f9ebfabeec0992cf75515013be87fb34a00", - "dist/2022-02-22/rustc-beta-x86_64-unknown-illumos.tar.xz": "a126ae90761c130a1e9afd69b547b2c37486472a6fdc5c21f07f4298a2b92f65", - "dist/2022-02-22/rustc-beta-x86_64-unknown-linux-gnu.tar.gz": "ebea0afac2fab2a014c11ed97d6beb75578cc0ec985e5f8f8bc09b1c01615307", - "dist/2022-02-22/rustc-beta-x86_64-unknown-linux-gnu.tar.xz": "c40d047cda71b01faf5048b8cebc3ac7315da6f8bd47e080183e154c3f4eb651", - "dist/2022-02-22/rustc-beta-x86_64-unknown-linux-musl.tar.gz": "6f017936f0bcb0b98ff733887383a8ae8902eba9014b6fe674a7aa379d681ade", - "dist/2022-02-22/rustc-beta-x86_64-unknown-linux-musl.tar.xz": "e89205f8583ea948ed82d7ff576c102bd18dd77bb9234835b3cd7c814951d69f", - "dist/2022-02-22/rustc-beta-x86_64-unknown-netbsd.tar.gz": "f6fa66459dc4b58a1b4c19c7b0590293c7ebe2685021ba0ac382b541072965d7", - "dist/2022-02-22/rustc-beta-x86_64-unknown-netbsd.tar.xz": "a65546bf3b63618ee16316c1ce552edf24f6d3d2d60dff63515ca61e69ee45a7", - "dist/2022-02-23/rustfmt-nightly-aarch64-apple-darwin.tar.gz": "8f4bc35d8e2b03db96a5d9faedb5e25155082d96621c26b90734219468904c62", - "dist/2022-02-23/rustfmt-nightly-aarch64-apple-darwin.tar.xz": "c83c48eae807ab73ebeb6324778faa1430b7efe0da6e32acb013cad9e2bb505c", - "dist/2022-02-23/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz": "00b0beac51b53a7469a6b6ef9d99309baa4b9da3e6ef08d9e5a84dcd4697ba2c", - "dist/2022-02-23/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz": "2d6dc8a6a02327d7d1fa3ab08f5a0a1cfb567a78ef6564a91050028d5f7e1eb0", - "dist/2022-02-23/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz": "88691ff2cefa6880cb4bbe2d717b5419cd0440ee0d000ff8a70f9d86d714b866", - "dist/2022-02-23/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz": "c075a7fe36931eff39f1880fce0dbb2d6d691bd4eee6f8db88b49f123e0117d0", - "dist/2022-02-23/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz": "394ee236b37b687963a0c42e40b3c6863460c302429ad00ca37c7931ea896233", - "dist/2022-02-23/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz": "74b68d4c1a7d36cca7fd1dab686bd43b04af1be5a9a07f7c42c52b0d5ebe35e4", - "dist/2022-02-23/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz": "d53edb376291a80362d4b51c8bf889f5cd3221e3e92c8db149f1d869024d4834", - "dist/2022-02-23/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz": "f26b9f9f97fce1c2de87b9d2168df0e4c3c995572dc6dcb5ac08ebb9185e8e77", - "dist/2022-02-23/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz": "2771d7d805b9fe3604d47640f969ebab005944f8b77e4d30b2b48adeec62a1f8", - "dist/2022-02-23/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz": "78f7160f9ad76a3dd6c5ac6021b9fb60ed758cbd90ae34ed2e16f3fd0a646add", - "dist/2022-02-23/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz": "f46da2d33597142d7b6d344b03cb17c5f6d9345421781b071aa84d52c3c13488", - "dist/2022-02-23/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz": "f95d077c5a5f713b26330aec15f14430731c53f4d297853d23e8a0158cb7818a", - "dist/2022-02-23/rustfmt-nightly-i686-pc-windows-gnu.tar.gz": "fd2db83f3a984d3834b8ecb1450846fd514e4ed1941095fe89d8e4217abd8c81", - "dist/2022-02-23/rustfmt-nightly-i686-pc-windows-gnu.tar.xz": "9a031255581634341287da672c7a0d7e893927faefdc9bafee50f5af53633bcc", - "dist/2022-02-23/rustfmt-nightly-i686-pc-windows-msvc.tar.gz": "13efc17049a0c032165eb8de8931069548acb2a282248f0a9a29656e8a97a5a8", - "dist/2022-02-23/rustfmt-nightly-i686-pc-windows-msvc.tar.xz": "7c684d51fd30c54203220b1505db629b37e2730686d0906d87e2b435093b52e7", - "dist/2022-02-23/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz": "8d6ca92b75866a8c238a401476f3cbf4314e8cafa098d9bbc45769926b77e534", - "dist/2022-02-23/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz": "c0609adb3c8cb75dd8e7351243fc6bf8f70701222097964262be0be3d8b6407d", - "dist/2022-02-23/rustfmt-nightly-mips-unknown-linux-gnu.tar.gz": "66eb9b3684e1f96765001989b6e8eaf03be016b9aa903ebc428f604a468ebf94", - "dist/2022-02-23/rustfmt-nightly-mips-unknown-linux-gnu.tar.xz": "7300327d6ffc0950943c480e9831e63a23af477816a9f971278e8bbc6c0e3514", - "dist/2022-02-23/rustfmt-nightly-mips64-unknown-linux-gnuabi64.tar.gz": "670c81aed32cbe72b12b5c5b9de8ca65446ae201a3e547a7039bce015884acf8", - "dist/2022-02-23/rustfmt-nightly-mips64-unknown-linux-gnuabi64.tar.xz": "9e86bddbbb0b755a7ad43fb2e20ff4cda4bd2e36d864112c75d69d142509e779", - "dist/2022-02-23/rustfmt-nightly-mips64el-unknown-linux-gnuabi64.tar.gz": "53f068e73ed65ad2a3903e7bbf80095d7dbc671e41d80780f52ffd1e1b101804", - "dist/2022-02-23/rustfmt-nightly-mips64el-unknown-linux-gnuabi64.tar.xz": "519a29e54063cbee1dca22a17624e1508d1b1a3f1d27cfdac08226c4a7d76092", - "dist/2022-02-23/rustfmt-nightly-mipsel-unknown-linux-gnu.tar.gz": "56180120aa97452fff9016b87d8e97d15e35080e65a6dde9892059d20e09cb80", - "dist/2022-02-23/rustfmt-nightly-mipsel-unknown-linux-gnu.tar.xz": "20604ae6826adfae2fbd67815a770a46d51f6aea7d5da73a54c66118645e76a3", - "dist/2022-02-23/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz": "3f0c4fa31ff93aab3b586def6202a9a2b63c7ce2509e707992f941b7bbd43ecb", - "dist/2022-02-23/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz": "d4eb5cb900b51018d83a0e1f0f50b12bd61f19cb7afc69f614c2fdeff446d323", - "dist/2022-02-23/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz": "3991a0259b758588ad2166ba5b7b10c79e777941a87f27bcbad4ee7422a240e0", - "dist/2022-02-23/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz": "2f507613d2cf82288f318bcd70c2d750dd06228699486ba7233ffb08f27baa03", - "dist/2022-02-23/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz": "811a37b83c293cf05780f62befaeecc69d5e847c407df3f355c27a69fffacd9c", - "dist/2022-02-23/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz": "99d5577c5766c6ddbba567306ba798ce62fbf92f9a6a227e46cb8c78ba04dda0", - "dist/2022-02-23/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz": "bac95ae187e4bae372de1ae20fe87eac02a45956bd4dcca71870cf2431b5abb5", - "dist/2022-02-23/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz": "a2501c6790552f2472891bd3298b0c9038e6dc3e826d060772ed396b2ca45f53", - "dist/2022-02-23/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz": "1e7a476248c2dc64ac2f65cfa74c0949f170c418674cb692ccf1c1cdccfdabd6", - "dist/2022-02-23/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz": "85fbac21530f0007da71dc979056f69cf267b2ed870e1d9deb71538a0f46b4c2", - "dist/2022-02-23/rustfmt-nightly-x86_64-apple-darwin.tar.gz": "6e7ba1d83b61ce690c857bc197f3c0a1cf0cb2afd3c4c7f16fdb4079f460ce6f", - "dist/2022-02-23/rustfmt-nightly-x86_64-apple-darwin.tar.xz": "6611703fcd9ec8ba9fa1837be5736c2b2833532cdcc152c5e3429d1994ac624a", - "dist/2022-02-23/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz": "e1350f9b420888776ab85bf2bc3e762c04a0ca8fe72e82d2d21215d4601f67ee", - "dist/2022-02-23/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz": "0cd5343e4e2db2f68026a2d55ae5e91cff2402dd1657bc03d9bf131264d9a75f", - "dist/2022-02-23/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz": "e1a81be6159fb9e28cb1f35ac4508a09a0be86edf6ab39db08988a5bbefa9e76", - "dist/2022-02-23/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz": "d5073cb4c148ef6e664c1fe17b02900e5f6ee0cf39710cad55887ebd919e797d", - "dist/2022-02-23/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz": "63a0018ed3b7bf94dca3db30be7a1d6940a7559cdd0ca408c366551e2f5e6863", - "dist/2022-02-23/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz": "85924719f0bfa06024496e550edfb6556a7b90e42d7d2d810b52f5bcef4401b0", - "dist/2022-02-23/rustfmt-nightly-x86_64-unknown-illumos.tar.gz": "ddd2d19ef69ecebb3d654769b06cba5da5c366f01167298ee581f7cd934c637e", - "dist/2022-02-23/rustfmt-nightly-x86_64-unknown-illumos.tar.xz": "9178284a64238c7778b521c5a105034efbbb85039b619e3ebb1247b83334bd7d", - "dist/2022-02-23/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz": "7ab236ced294c39de4bb563e9ebaed04c906a4ccfd1932138d37d6d03f75cae7", - "dist/2022-02-23/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz": "f392f5b890506e63407204998c3b9b9529dea8a7bdff2319bc202da6fa07c3b9", - "dist/2022-02-23/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz": "647da2183d93846ac5225b99117846a07a90975bdf1b5075e86601dcf97d1ecf", - "dist/2022-02-23/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz": "9c3be22743d1d9120d16ae47d035f788ba809207bdddeb8746828ea914dd90e4", - "dist/2022-02-23/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz": "4c396836a92122b0594568a288fedaca9f5bdd58a7a2013882a1afd17ef69de2", - "dist/2022-02-23/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz": "0ae2188987be65bfad882878e7a1365310c2cc28504f7ad8400fd759dbc40684" + "dist/2022-04-05/cargo-beta-aarch64-apple-darwin.tar.gz": "d522845ac8c2644378575b25a742fa1e77030a0ef3e45703fa40b3fc96e2fb28", + "dist/2022-04-05/cargo-beta-aarch64-apple-darwin.tar.xz": "9ebed4b378565e9218f4d415d84b36fc78c92ff8f2a0b5360d5199353dbb2402", + "dist/2022-04-05/cargo-beta-aarch64-pc-windows-msvc.tar.gz": "88e973cd6c4fd1307ed614b7480984ef9b0101b06571f6d241082904acfc4b6b", + "dist/2022-04-05/cargo-beta-aarch64-pc-windows-msvc.tar.xz": "dd13d493e02853f7399d886a8a74bfa621c5b2552ae2f50b6000c1dcbb76bd82", + "dist/2022-04-05/cargo-beta-aarch64-unknown-linux-gnu.tar.gz": "d1d46f8492b1ebd9c3e1845e14d83d49bd03490c6f11f7be9f046c16d8040602", + "dist/2022-04-05/cargo-beta-aarch64-unknown-linux-gnu.tar.xz": "95d521fb4530f9fed33ad82227cf0ab517d6ea160549fda8ebefaf66d44e400d", + "dist/2022-04-05/cargo-beta-aarch64-unknown-linux-musl.tar.gz": "28f126c940bdf7fbbe27b64e7057f13a5fe03364b38c9898df2aaac9f682a60f", + "dist/2022-04-05/cargo-beta-aarch64-unknown-linux-musl.tar.xz": "ad107be697369008d1fade995cc20c044f9ee53713835a3641f91b2b93dd9e2c", + "dist/2022-04-05/cargo-beta-arm-unknown-linux-gnueabi.tar.gz": "7fd5000abc9afe72cab7117f64dcdd737003a57302b7289c3113cf1a14d8e454", + "dist/2022-04-05/cargo-beta-arm-unknown-linux-gnueabi.tar.xz": "5b7576d67dacc763d4d9be0e3be53aa7a1753cb71cd52d82cde79a142afe3541", + "dist/2022-04-05/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz": "6ec9fbbc71d5e98535673e1e568cd5440c241ce466e1fc9eddf1cac99af7f86d", + "dist/2022-04-05/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz": "4e534c1960382f6084a0250060a048254470c1f498bbc28064878c1029232271", + "dist/2022-04-05/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz": "b59bf7b126c91ac4bda9daefa2403bdc25f7240d72e7bd651d1e9f8e53041d61", + "dist/2022-04-05/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz": "e71597532634725eba7dcd85faf0fcb9bdf2fcf372c0a03e9d507ab1420b5576", + "dist/2022-04-05/cargo-beta-i686-pc-windows-gnu.tar.gz": "38b0ec02eb2acc51c7088542d3642b2c55c0e042f6d8c1ab3de84652c587411f", + "dist/2022-04-05/cargo-beta-i686-pc-windows-gnu.tar.xz": "a194fe60bee39f765e4478107c4a5cc23ccb0d25042b0fa9dd1d5a758e7ae5cf", + "dist/2022-04-05/cargo-beta-i686-pc-windows-msvc.tar.gz": "4467065f716670ef5c305d70b68e5375bf542514fdf6645dc92b43759e76213a", + "dist/2022-04-05/cargo-beta-i686-pc-windows-msvc.tar.xz": "78829f8a16ca9e5c389141b050c7b120115420f966a37888320fdc76886ead1d", + "dist/2022-04-05/cargo-beta-i686-unknown-linux-gnu.tar.gz": "26c423f1667bb0bbede80069be29272877e9ce8f75345f7391f5d1260ec900c1", + "dist/2022-04-05/cargo-beta-i686-unknown-linux-gnu.tar.xz": "b9753f612d59e7d30c3775bcfcaad76df7d0607ad5bdb81041cd40b5690b6239", + "dist/2022-04-05/cargo-beta-mips-unknown-linux-gnu.tar.gz": "5e200db1460c1f0bf43fce499debc9602b09c518f13570f6f6f8c86f83ee0f11", + "dist/2022-04-05/cargo-beta-mips-unknown-linux-gnu.tar.xz": "8c60fa42bf03826c4cd1eea5d96b57e1772381713d780ea3810cbff62ec23041", + "dist/2022-04-05/cargo-beta-mips64-unknown-linux-gnuabi64.tar.gz": "9fcdd60c22211be46e50103a315e0f905d225c61aa42c468760fcd7894dce62d", + "dist/2022-04-05/cargo-beta-mips64-unknown-linux-gnuabi64.tar.xz": "ba188f3ab64897109d2039756c01b43b30008479687a76aa236f50ffc99b9b2d", + "dist/2022-04-05/cargo-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "18717f3f965fe3b2182f5791451caa938eb8f0ca5e8c1c6ee0eb32b735c50392", + "dist/2022-04-05/cargo-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "ba6d2dc52ce330745d8b543906cd0c81114c2f7e22900f6565d1bede93667d59", + "dist/2022-04-05/cargo-beta-mipsel-unknown-linux-gnu.tar.gz": "47e74be39cf947641e37a8f2d41c49b63aba4467b86c89219edee5933b6c92d1", + "dist/2022-04-05/cargo-beta-mipsel-unknown-linux-gnu.tar.xz": "dea6a2f11dd8fa9f93f8e1781d3c7faa04d29dded20f4938cbee60b15e523feb", + "dist/2022-04-05/cargo-beta-powerpc-unknown-linux-gnu.tar.gz": "f559462b323bf183e8f1f20fb509309e4e88b593f872becd42214f771e860973", + "dist/2022-04-05/cargo-beta-powerpc-unknown-linux-gnu.tar.xz": "bd5e9774ddec783e085c9837204de7122eb0469098f93d0768e30ebe3ee165f1", + "dist/2022-04-05/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz": "78cba227c038364f02c7ed5d01c5e26ac1bf069f7f0a97e54b9911dde8114c3a", + "dist/2022-04-05/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz": "63514e4afb11b57b58304f246a603ad336b6e95ce6d288cd9d4b834b8e531eab", + "dist/2022-04-05/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz": "5495f5a77fd354c2d8ed9de86052a1c6528092afdc8af66be532859dddafcd5d", + "dist/2022-04-05/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz": "4ab4e7674bb927919dc7e4a3a6037978c260ff97966a18409c4b9ae4e1802c4a", + "dist/2022-04-05/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz": "9baf8bceb40d728eb1ed47ea572d1b890fd36762ad7b119c9de6f7378682fe7b", + "dist/2022-04-05/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz": "0ef8e9ed9e401a688af6aab9f928ff6b860ddd5449f0becb2216d2206f45ec45", + "dist/2022-04-05/cargo-beta-s390x-unknown-linux-gnu.tar.gz": "d442fb0a4b8f56f7c008d53b15ba2a34d6e08701e0a69b2204e9c64ef32eb4c9", + "dist/2022-04-05/cargo-beta-s390x-unknown-linux-gnu.tar.xz": "5a4d757fbdbd0581e26ce997e33663789630d20620cd3fefc70ab866849c3850", + "dist/2022-04-05/cargo-beta-x86_64-apple-darwin.tar.gz": "03d0ec29bdffbe606e70a96614e44e0e65eaba38ecae4a9aca2e202a8891eb56", + "dist/2022-04-05/cargo-beta-x86_64-apple-darwin.tar.xz": "76149cbf429502b9c1fc71a6bff9d38b24f575bc43caf26143552e2658bde544", + "dist/2022-04-05/cargo-beta-x86_64-pc-windows-gnu.tar.gz": "ef7bbf4aaf758aa8c3ef74e68f8a39a6b1b2bad0ecfc90a0a49ceee41f5aef80", + "dist/2022-04-05/cargo-beta-x86_64-pc-windows-gnu.tar.xz": "23d15d39aacfbb1cc382cf2e88d9d688827c867e1b4778ab24d66579e766bd22", + "dist/2022-04-05/cargo-beta-x86_64-pc-windows-msvc.tar.gz": "20b0427583732b542b1274837d61b4f25a72c3810433d91bd31013daebfca54d", + "dist/2022-04-05/cargo-beta-x86_64-pc-windows-msvc.tar.xz": "827699b4f5ad3a810d2cbae8fb0c0e3b2724b054d7b7505cebd1af5efbeb592c", + "dist/2022-04-05/cargo-beta-x86_64-unknown-freebsd.tar.gz": "bcbd4379d77d42bdb665a8583daae4bf101b0f3f6588c148c80d72f1c60c5267", + "dist/2022-04-05/cargo-beta-x86_64-unknown-freebsd.tar.xz": "832c90d532ffcba10039f1244bf06c7121ddd3b7fd7c0d913b62fd0ad82e1dce", + "dist/2022-04-05/cargo-beta-x86_64-unknown-illumos.tar.gz": "7af1097744bfaa50b7d019025fc8b940363f9f5665f5247edf8374115ce074cd", + "dist/2022-04-05/cargo-beta-x86_64-unknown-illumos.tar.xz": "f6d2a741b41e26877a3c5f0a8337ebd563370b839c69091acf9535a1c2d6046c", + "dist/2022-04-05/cargo-beta-x86_64-unknown-linux-gnu.tar.gz": "477b6914f38919af61ecb2889032ffc2b12fee6ef85967a28bab6baf71df4baf", + "dist/2022-04-05/cargo-beta-x86_64-unknown-linux-gnu.tar.xz": "e91b851cd4a2cac68264bb47431943556e6b8c30df74d8a755e655df171acb47", + "dist/2022-04-05/cargo-beta-x86_64-unknown-linux-musl.tar.gz": "3218da520fd9fa9f70f78b1fbf2d69b74842d1cfd3e578eb5b4233b0632d2525", + "dist/2022-04-05/cargo-beta-x86_64-unknown-linux-musl.tar.xz": "5e492a006cef711748772bf3b6e25fdf400316d1392a8391fc005a88d6d8cf0f", + "dist/2022-04-05/cargo-beta-x86_64-unknown-netbsd.tar.gz": "b5164be552ff72bb0f19076c8ae3d0057ef6cf219df032d34130f98abfa07feb", + "dist/2022-04-05/cargo-beta-x86_64-unknown-netbsd.tar.xz": "d641e7e17c4720f961f52353a0a5214683b019a3acf1c1939d9f9710053496cb", + "dist/2022-04-05/rust-std-beta-aarch64-apple-darwin.tar.gz": "d81a9d0e3e6fe59849977a77acb3b3aebbf76465176a03a45cde34982488dc80", + "dist/2022-04-05/rust-std-beta-aarch64-apple-darwin.tar.xz": "001be52129c7e9d08cad4c337eee8515dbe71c17bf06dccbb4b17b6deb59eaed", + "dist/2022-04-05/rust-std-beta-aarch64-apple-ios-sim.tar.gz": "ebf3720b48a89422c473aa40645f8b4e02164b2e57a66e477c320836dfda8589", + "dist/2022-04-05/rust-std-beta-aarch64-apple-ios-sim.tar.xz": "dcaea0924b93a34f8ed5a3043fc752a7fdd74e93747584b4852582601ad4e0c7", + "dist/2022-04-05/rust-std-beta-aarch64-apple-ios.tar.gz": "713438516e54c2451327d15b62ec02439fb1734897e5193dbef4c74a72c3b3d9", + "dist/2022-04-05/rust-std-beta-aarch64-apple-ios.tar.xz": "6ddc798abdeb7b10389fbd1d4870df7c64983a1f2a2aaddebe3ec3a10c7124b9", + "dist/2022-04-05/rust-std-beta-aarch64-fuchsia.tar.gz": "7d74750469755e6171e5ee467eb82f9da6fc659f54eb0713656bcdd0effb1770", + "dist/2022-04-05/rust-std-beta-aarch64-fuchsia.tar.xz": "c1023c97eb2be40c80f83e7fe5b20367cffb3e52515f5e0ecf45201835088d78", + "dist/2022-04-05/rust-std-beta-aarch64-linux-android.tar.gz": "7819b5e29f097b32408fead0fc281ac8fa477cec0141688e0a82233cf37789ab", + "dist/2022-04-05/rust-std-beta-aarch64-linux-android.tar.xz": "51ff2b862d2d6bbc2610041011ed0ef3fae0647d422dbda1613cfc9d900652e9", + "dist/2022-04-05/rust-std-beta-aarch64-pc-windows-msvc.tar.gz": "ab90419c8552c7bd7e5381ae6d15788d7b4f8f903395ec2b5b7ef1d561453805", + "dist/2022-04-05/rust-std-beta-aarch64-pc-windows-msvc.tar.xz": "6b293b6df7f7b22ddd0dc1dada083176ae60df3624ee29430106c04f0ee4f262", + "dist/2022-04-05/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz": "104c2f1c3b84024fb03e13da89a0a416d67659a8dc8b582e28c7697fe3f43224", + "dist/2022-04-05/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz": "35d7787bc6c2d123e6b5e8ccb0ea0070a674050ff3dab80283e4c193b8617f37", + "dist/2022-04-05/rust-std-beta-aarch64-unknown-linux-musl.tar.gz": "00fd161285c90a65134a31152dcab92dafd82ca41f94bde84b6beb94dd98e934", + "dist/2022-04-05/rust-std-beta-aarch64-unknown-linux-musl.tar.xz": "c3bf923b7025fd3ddb70f79b36ac540f1a3a0d065eefe0e650ce8a3cdadb7a7f", + "dist/2022-04-05/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz": "05788212f632c0b83c7aa83ceace41efaba1b90066dccdb40e2ba8e5ebc1b405", + "dist/2022-04-05/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz": "3095a6a9d5ed80cece5ea0dade7bc00790055ac789866c0c51c6e05134f4b26f", + "dist/2022-04-05/rust-std-beta-aarch64-unknown-none.tar.gz": "9cc86be630b5ec83447fb1595a0afecb22a05d9ce89d73af39fb4edc43c37a8c", + "dist/2022-04-05/rust-std-beta-aarch64-unknown-none.tar.xz": "43437ce5b50c45e757957d2d7df354ca6e244b77081d03bde8e519cac2d03fa1", + "dist/2022-04-05/rust-std-beta-arm-linux-androideabi.tar.gz": "1f30c740549ab4ee2641ab08f7339798a69a13edf4ee928462d7fe5c3d49e1c2", + "dist/2022-04-05/rust-std-beta-arm-linux-androideabi.tar.xz": "64032f816c38fb0ea0db6be3c69de702ba6301800cb7c437f547257c3c88ad72", + "dist/2022-04-05/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz": "54de198103c4a8c2463261e7e4fbbf0104294e5a56e663fc75b4f6606d7e5609", + "dist/2022-04-05/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz": "50e690bb090230e61a70d34d4191a3a8aedc7e2079ceeb70bc780ae718fa5719", + "dist/2022-04-05/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz": "56040245d9707a90f62ce33ed45c75110b1f5de50c98b4276d3b0303ca457ca0", + "dist/2022-04-05/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz": "ea33048f8bd7057b80db565ead072ba3830ac54e9cd9120514d86c0a71398138", + "dist/2022-04-05/rust-std-beta-arm-unknown-linux-musleabi.tar.gz": "627ff5136cb18eeaae03303cb265f5492a57f53fb329fe0d362084697d4de4d5", + "dist/2022-04-05/rust-std-beta-arm-unknown-linux-musleabi.tar.xz": "d996b8ee3452f5d4dfd758b5ac835dd77ee9f050496d1745fa553901812b843f", + "dist/2022-04-05/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz": "86303fe3be5da53633630de44f58ee11475624d4ef4bce4f8a91d48f80bc03da", + "dist/2022-04-05/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz": "14dc9ed9584f7c55967831c97862cfd3cc7ae5e6cbc65936e4ecd0bd9d75fb30", + "dist/2022-04-05/rust-std-beta-armebv7r-none-eabi.tar.gz": "be874fc36bf175eed366db71d0905974153a3339bc84f8abda83c482197a4235", + "dist/2022-04-05/rust-std-beta-armebv7r-none-eabi.tar.xz": "c10c6cf39bf5f5360eddc1a6caedb79ba04ab227336e718b3a45f4a2f3c357c6", + "dist/2022-04-05/rust-std-beta-armebv7r-none-eabihf.tar.gz": "6b429165fe0d52c6dfa74beef81d6b136f7fc35cd60ba2637af64f5195c7a018", + "dist/2022-04-05/rust-std-beta-armebv7r-none-eabihf.tar.xz": "c4913f09cc858f0f2b9870f12714de055e1658b4b708ec78a1cc14428e72912c", + "dist/2022-04-05/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz": "64ab028aa4d304c7a4a09bcaadb45f094f3c76fd17eb72afb29cc57d127ef743", + "dist/2022-04-05/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz": "4e2de3902e62ced0910bcc63d425a06e46c003ebc7111d0308637385817582f2", + "dist/2022-04-05/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz": "8847d73f6da535f4cb700c5da8e9f330710663cd8486bb014c0c67dfe238237e", + "dist/2022-04-05/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz": "85568b12784c98a331ccf6e2719a6d56261356d87a1142e4a72b9f7438a82380", + "dist/2022-04-05/rust-std-beta-armv7-linux-androideabi.tar.gz": "825fb7e878534ac9e3c05240ba52110bf253602cb39aba8aef31f54695d06cc5", + "dist/2022-04-05/rust-std-beta-armv7-linux-androideabi.tar.xz": "8ec0897de57b4e920a2419aa5af36fe421276306e61e6e0263f056f6769ff0b0", + "dist/2022-04-05/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz": "6664d7becfe4bcfda1e86eccf3f20cd549d9b7f3d3fc72f70f53da36a91016b8", + "dist/2022-04-05/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz": "13da845aab759efa0e690731beee1a51d662083aac6bb03451501bd21332397e", + "dist/2022-04-05/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz": "fe311715bee972d5b5ef669c93fa9d5d39a6ff5309d9f82150c0f3be72222d3b", + "dist/2022-04-05/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz": "e2937e4c67a6e5af57e79149d8595a24a6114bc877cd13dd568e719dce28162e", + "dist/2022-04-05/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz": "24209ff3a9431b58f0f7846a8f673c81488429efe6947049ac9c19523d071d83", + "dist/2022-04-05/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz": "ed1cde412c615ffa422f27cf347b8276c68281528cdd6d2642f290ccfbdf2ba5", + "dist/2022-04-05/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz": "b028af36212e244ce2eaf213bcc68c52783425a982465d422202fe2d1ad806ab", + "dist/2022-04-05/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz": "5b4fe3ec165f16cb29d7660b762ad8de84d9c56d9cac90b11d521de3162485d4", + "dist/2022-04-05/rust-std-beta-armv7a-none-eabi.tar.gz": "2cfab91a43151c6680932212732f4bb689dd93a7252e08b291ec56a02ea7642f", + "dist/2022-04-05/rust-std-beta-armv7a-none-eabi.tar.xz": "503cb200deab12a4cbe8f907823d1e3b63bf2729d1a878e7b7a3d495415f4036", + "dist/2022-04-05/rust-std-beta-armv7r-none-eabi.tar.gz": "b4b756f4c8100a377211cc74d5040fd23bb0231b45841fc8929067f8435a3871", + "dist/2022-04-05/rust-std-beta-armv7r-none-eabi.tar.xz": "44de1090cf49659dd983c081af9c675c9d24721e7510c2748f50befd92810c6e", + "dist/2022-04-05/rust-std-beta-armv7r-none-eabihf.tar.gz": "d6bca5dbb5f985b4c3a4b917311e3ceeefc3ba43fd6b4416b1d07136f405e47c", + "dist/2022-04-05/rust-std-beta-armv7r-none-eabihf.tar.xz": "4f9acc7d81e54d6a725d69bbfaaadb10a0bf4481495548513ff0b96fb3b4f85a", + "dist/2022-04-05/rust-std-beta-asmjs-unknown-emscripten.tar.gz": "01b157479a25a19f8ff499d3993521c3d1b7920880b247599279c428146d9de7", + "dist/2022-04-05/rust-std-beta-asmjs-unknown-emscripten.tar.xz": "b1393e5f200af7d3bcebfbcffb95a9edbb66005cf9413283884e520cd0105eaa", + "dist/2022-04-05/rust-std-beta-i586-pc-windows-msvc.tar.gz": "4086ce54630c7444d886900877bcfb3af0a33fa9c5770f42172a6963c20207f4", + "dist/2022-04-05/rust-std-beta-i586-pc-windows-msvc.tar.xz": "ada0ff31c61640d247f709964322001ef187ef96864618d225ce66af76868b85", + "dist/2022-04-05/rust-std-beta-i586-unknown-linux-gnu.tar.gz": "137d56c7afa91f9a53191cf213e5f457604a1ee4d13e9132bf730bb5045eedc8", + "dist/2022-04-05/rust-std-beta-i586-unknown-linux-gnu.tar.xz": "985d7efef52c800a839d8cf7bceeaa1ed44863e83596516507c617619ce744cd", + "dist/2022-04-05/rust-std-beta-i586-unknown-linux-musl.tar.gz": "73d9aab23a0674c9816a987ca24c584a75a934ced077e04787161208c8ccc92c", + "dist/2022-04-05/rust-std-beta-i586-unknown-linux-musl.tar.xz": "6c6e1bdc49286fe1dbad8a597902e8ea73c0562057e43d78fec9024cd31fc255", + "dist/2022-04-05/rust-std-beta-i686-linux-android.tar.gz": "6cebb5c0ab887358d2d948d072d3c436e9f987cf482423d9d55364e9416d492d", + "dist/2022-04-05/rust-std-beta-i686-linux-android.tar.xz": "a04b26ae9b558489dcc7abc5e632c0382ebe248803152407b0ca8702ead246ef", + "dist/2022-04-05/rust-std-beta-i686-pc-windows-gnu.tar.gz": "78dad5e34af6dd72549d04e59bf059bb28ada4bc6a2d2396b07b9d6eddc5b1d0", + "dist/2022-04-05/rust-std-beta-i686-pc-windows-gnu.tar.xz": "03cfd3a7b6ac10338cd6219811cd2b9e67e5e40adcfef6c725e14c571c9c00ef", + "dist/2022-04-05/rust-std-beta-i686-pc-windows-msvc.tar.gz": "61df958b515e51e2e44e2130f19a1e2a41e246af99e2ebe73b08fd2203b38268", + "dist/2022-04-05/rust-std-beta-i686-pc-windows-msvc.tar.xz": "aec3ba484f261d9feb4f81525b56b656dac1ad9af584b946dd85b643ee201202", + "dist/2022-04-05/rust-std-beta-i686-unknown-freebsd.tar.gz": "62669de085e1cdd6bebfc0a6ed74ece54807104c67256c75753e3d2269b450ad", + "dist/2022-04-05/rust-std-beta-i686-unknown-freebsd.tar.xz": "7bb82ba3e26bb4ae4558719d474322012cb09b1fdcab570d1d7dc7c3562023a6", + "dist/2022-04-05/rust-std-beta-i686-unknown-linux-gnu.tar.gz": "22324f33d7be09df91263375535ca93d92372b8dfb320df0ba909f333a900458", + "dist/2022-04-05/rust-std-beta-i686-unknown-linux-gnu.tar.xz": "8911af3a77bf067dd9ef4ee556ab2e13feafee33b0bb1c63b3cc1ae80042a30f", + "dist/2022-04-05/rust-std-beta-i686-unknown-linux-musl.tar.gz": "34b7b615bb5ff1bc7910683ae6f6fa7750119a6e0512df945979969b695a5fd0", + "dist/2022-04-05/rust-std-beta-i686-unknown-linux-musl.tar.xz": "d8614a9116f07ca652e15d7809d79ac50228dbf553ed1d7123a3e9d74a297f1f", + "dist/2022-04-05/rust-std-beta-mips-unknown-linux-gnu.tar.gz": "803aec35491c632565c178100ea8803bb90f841cab99453ee726b846b887f7db", + "dist/2022-04-05/rust-std-beta-mips-unknown-linux-gnu.tar.xz": "a85292e8eeef5a2eee4a16d0188f432602893a6bca6d971daebb1bbaa3d7cf4b", + "dist/2022-04-05/rust-std-beta-mips-unknown-linux-musl.tar.gz": "faaf96182517e399d73b7242ad1ba8798cb49da0bed66fdc31aa04eb916bfcea", + "dist/2022-04-05/rust-std-beta-mips-unknown-linux-musl.tar.xz": "6ceb46cb6495a76960e08f041b5595f954a2ffa41b786b951d58fefa6753dc51", + "dist/2022-04-05/rust-std-beta-mips64-unknown-linux-gnuabi64.tar.gz": "0be7806f821b84cf53001964f1985c3a7a5c2df22575ba81e1f925fbf06b6e5f", + "dist/2022-04-05/rust-std-beta-mips64-unknown-linux-gnuabi64.tar.xz": "b71f46228685f926bdb6bf675fb6c0b2a32e28a5b095b7375c5fed2c9067b423", + "dist/2022-04-05/rust-std-beta-mips64-unknown-linux-muslabi64.tar.gz": "55662bfa7ae485b1a2d655179588ec2b5936aae4f9998533559330d382f5731e", + "dist/2022-04-05/rust-std-beta-mips64-unknown-linux-muslabi64.tar.xz": "e58994d0a1b3624c36ba0c547ff621ca3ec331ac0bd3d58222919ddab0beb3ce", + "dist/2022-04-05/rust-std-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "e0c0bb542516fa0159285e3770a469833ac95ec5fc663d39c3e01906f467b094", + "dist/2022-04-05/rust-std-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "21ef3db32ea221d631c0a81f5034fb63e8bf76f7f39c1957c5d16929bd64bf17", + "dist/2022-04-05/rust-std-beta-mips64el-unknown-linux-muslabi64.tar.gz": "ad3da919ca0fcbffdb84ea8f415bed2a2fb2f61e816aaaf28e8854a9850103f6", + "dist/2022-04-05/rust-std-beta-mips64el-unknown-linux-muslabi64.tar.xz": "cb02f50e74534bbd805094b1e83c35d0a2e00dcbd75dd85f3517774f42e8fe1c", + "dist/2022-04-05/rust-std-beta-mipsel-unknown-linux-gnu.tar.gz": "64350c36afa85b35b02dc1255fcc09abf2592e08a05aa0ea67794ef13442dcd8", + "dist/2022-04-05/rust-std-beta-mipsel-unknown-linux-gnu.tar.xz": "894e0337a31935a13d26d2710a70b4526e1caa26aa0c9cd37981d2569b8ada31", + "dist/2022-04-05/rust-std-beta-mipsel-unknown-linux-musl.tar.gz": "cd5e15813a24234812e4a281fccb76f6aa2110c87a0043d4b5c60fdf3b272701", + "dist/2022-04-05/rust-std-beta-mipsel-unknown-linux-musl.tar.xz": "dea915cd8f79c3d78b063bebd86a9c6e88749f6a436ac16c6dee463bc9504f0a", + "dist/2022-04-05/rust-std-beta-nvptx64-nvidia-cuda.tar.gz": "af860ff78396796a125c9d3029f85e898ac0c0fb738956d5a9fb9432efd61770", + "dist/2022-04-05/rust-std-beta-nvptx64-nvidia-cuda.tar.xz": "a6470fa586262bf78b91bb4b59e6f15c6df9028f4b3aace8589ddeb12dbf7ea6", + "dist/2022-04-05/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz": "9b147bfd00a0f2cd7aeefb67b03cb08b7d2eb2661410dbc3afee30dcb1c7931c", + "dist/2022-04-05/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz": "4791c88990892a0aa3e41bd5e0d3c70a3e08714e0d46c00e58a14944f4be3d6a", + "dist/2022-04-05/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz": "d5ddb7a2ada5c0f10a1cfaa18ed9f454ba044bcc20070be35e104e33eca2a954", + "dist/2022-04-05/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz": "8eaa648476c02b86662d0eb20255d63f49295853733082aa7200e1d22565aa5c", + "dist/2022-04-05/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz": "fecc0c637feeaf867ed63d198169948373dd6b00cecb7c5deb00e2719a70f403", + "dist/2022-04-05/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz": "77932b3620e2a9642b91e7526f0c08f6fc7d96eb1506aae9382b9ceba5098ab8", + "dist/2022-04-05/rust-std-beta-riscv32i-unknown-none-elf.tar.gz": "37b5042d8d1dfc8f0edbd02766b0e47dd90f68a7465cc3f8a2ffb09ef605b11d", + "dist/2022-04-05/rust-std-beta-riscv32i-unknown-none-elf.tar.xz": "73b317b51e033076205f7c7c7c28877fa61e837cadfc97bd1899211c22ab1160", + "dist/2022-04-05/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz": "8f82803e3fd1304c8fc03d49cf9e41e8f7b605f84c94739706e0c7606c448e6e", + "dist/2022-04-05/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz": "1e6b7f7d5732446bfe865ee16183efc30fedfdb9dae45131c8cb59bf683348bf", + "dist/2022-04-05/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz": "beef2e14c29146435c9a3bdfad2a98298294b916672a73131202c72cc697df6c", + "dist/2022-04-05/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz": "f9aab3ca9bb4072a5e2e4682ab23fb5b4a071da7cc8b8e3844a4407e8e33fe6b", + "dist/2022-04-05/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz": "eda983cd1775f24b96b660ef3536f06df30385c40bfec46d8cfb8d35c27763d9", + "dist/2022-04-05/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz": "3168538fc3a537c15c0c994f3ccd46548b14727b46f95f8244e9068e68bb64e5", + "dist/2022-04-05/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz": "6e8681fc5c2b6258b669780438f3d10544a9236f288ae6a173bdd293ab710544", + "dist/2022-04-05/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz": "5abe0a935eaca18193ede75b59780b33c98dcfef2d38e96ea3dda10c30d192f6", + "dist/2022-04-05/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz": "94c55ad771f08611bebbb9395357cbd6001e0c3fe575c9dde2ad683015743cdf", + "dist/2022-04-05/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz": "77fc488d1ac4e4c6418980ec33a82aa0fd1f8c4a58cf14b681037d170bcd597f", + "dist/2022-04-05/rust-std-beta-s390x-unknown-linux-gnu.tar.gz": "5f909d74e47c38cdcdbfe784e78e2aafdfbca5d5cd385c8d0b466628030e5433", + "dist/2022-04-05/rust-std-beta-s390x-unknown-linux-gnu.tar.xz": "cb11de42adff210b131519581a11287ec67740bab4478f16bc1cfd56f7dcfc9f", + "dist/2022-04-05/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz": "68dc6686aa0b27e569d50c5ca0d607d4efe4c9d8990ba87ad8a2aa328dec8616", + "dist/2022-04-05/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz": "b2bf5ba8a83a15dfcc41598f794e3d3c83dbf915215b4f919e07a9047b1ffdb9", + "dist/2022-04-05/rust-std-beta-sparcv9-sun-solaris.tar.gz": "86a21737572edd36cb91e45941923c672252630d195f58fb94d7d8d49b8617c9", + "dist/2022-04-05/rust-std-beta-sparcv9-sun-solaris.tar.xz": "7aec356bec19a94d15b117e774cb42a8eb3564308ca02f60d79b65f43bd36af6", + "dist/2022-04-05/rust-std-beta-thumbv6m-none-eabi.tar.gz": "d755a31f9facef7dbc1476fb803f1bb912a4eabf70facbceaa2c23b5d38a482b", + "dist/2022-04-05/rust-std-beta-thumbv6m-none-eabi.tar.xz": "d62dadcb8bbfc1018937daaaacb28118e63fd7fc539ef62e88cf6e1efe7be0b8", + "dist/2022-04-05/rust-std-beta-thumbv7em-none-eabi.tar.gz": "df0f49f983f0c9d110bdf170643f08d0206e7979cc654bdddd70eac717334efc", + "dist/2022-04-05/rust-std-beta-thumbv7em-none-eabi.tar.xz": "6fe836a2ea7df03c1a88d823cb0557af888b0020c2389bf5027735c9dbccbcd0", + "dist/2022-04-05/rust-std-beta-thumbv7em-none-eabihf.tar.gz": "facb752255f0f86ef7a03d8013cf77221263423658d0dce9b75b94e518947de3", + "dist/2022-04-05/rust-std-beta-thumbv7em-none-eabihf.tar.xz": "8d63d9acd7af3e43bafdbef1953c111f4c13088af4c962802f12b38ae38073b8", + "dist/2022-04-05/rust-std-beta-thumbv7m-none-eabi.tar.gz": "e5e1eb0bd5fc3a5af561dd9bcf0839c53e36672a11c4dec55ade5a2f59804508", + "dist/2022-04-05/rust-std-beta-thumbv7m-none-eabi.tar.xz": "3ee0776ff315bcc48d62ace2aa8f8e520fee1a5c27a75abdb89a5093cbd70212", + "dist/2022-04-05/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz": "83150b0bd0827db25739e21afdc28a571cab9cf528eb7bde39d6457ab26fd28b", + "dist/2022-04-05/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz": "1d24ee3b0e3b34f88c54e76bff867a77a35ce74c055311d82f3bde23cae0988b", + "dist/2022-04-05/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz": "87411b8d0954c450b83dc1b805c94af4cc7907ccfc346e129e5d6909e716cebc", + "dist/2022-04-05/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz": "de9ab4a162f426eba6eb5a355ca0d2d12ba1286599cdc1adc8f4a779e507052e", + "dist/2022-04-05/rust-std-beta-thumbv8m.base-none-eabi.tar.gz": "24ca6e156c3eda6c8c790eb5d7c99e39c4394deb9224b495c90641bc828639b4", + "dist/2022-04-05/rust-std-beta-thumbv8m.base-none-eabi.tar.xz": "00bc42ff2b31965cce526f46ed43301966da1b57b694e4c4e5089928ecd13f31", + "dist/2022-04-05/rust-std-beta-thumbv8m.main-none-eabi.tar.gz": "3ea54fc5075d6f99db9e2d31a92fd000108500017d80cae6e6349e2ea43a7708", + "dist/2022-04-05/rust-std-beta-thumbv8m.main-none-eabi.tar.xz": "8809512122417753d6e72b2ae90637e8b339a3f72a51bd4ad53b3a152a992b16", + "dist/2022-04-05/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz": "bcff8f5e765b8bbfdc3a5c6cb08cb796c90f3435986587b0744d40c226e8f551", + "dist/2022-04-05/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz": "925605849a16cc8e9a0d5ae5b523a321fd7e80ebb8fced627d7ac90845e20261", + "dist/2022-04-05/rust-std-beta-wasm32-unknown-emscripten.tar.gz": "64ef3fc95b97e5dc6a4e70bf383ffaab836a227f86427c8eadb01c1ed1d85a08", + "dist/2022-04-05/rust-std-beta-wasm32-unknown-emscripten.tar.xz": "377aa739f9c9aec814031b260def0629b87d932f06bedbc6cff9c997911c7263", + "dist/2022-04-05/rust-std-beta-wasm32-unknown-unknown.tar.gz": "2f8d832b5cbcf8072e5ebccd5d569b351a3265aab0ac60f580fe326def9f40a4", + "dist/2022-04-05/rust-std-beta-wasm32-unknown-unknown.tar.xz": "4b6582d922280377297412496e443becae006a0c7b170dec0b75885322615876", + "dist/2022-04-05/rust-std-beta-wasm32-wasi.tar.gz": "31487c5f709ac9bb89bc20215cb806b5c83cc604f6fbf858939c7f1be9759a3c", + "dist/2022-04-05/rust-std-beta-wasm32-wasi.tar.xz": "712f2663bfcc2e67a797390a872e2d440f24474c92644818667b2bf741f938e6", + "dist/2022-04-05/rust-std-beta-x86_64-apple-darwin.tar.gz": "120f9ce8080d7fb25d50f0a055e708a14570c6ec98543008580c72d0037fb1db", + "dist/2022-04-05/rust-std-beta-x86_64-apple-darwin.tar.xz": "969c54f4aa028ad51087a41b556d6692b02ae240b805cc0a6d52cf0f4a5ae2b9", + "dist/2022-04-05/rust-std-beta-x86_64-apple-ios.tar.gz": "6a6b2485d5e012e53345a777b112c94563e0c8ce28845a8c68aa04b09196b59e", + "dist/2022-04-05/rust-std-beta-x86_64-apple-ios.tar.xz": "58a8643415ba08bda6cff638012de2b2d3d3d8c953808006dda74f65efae8210", + "dist/2022-04-05/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz": "c757c0e207d77edac9305714e056984affe6e97d6fb59a7b70dfe62de39458a1", + "dist/2022-04-05/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz": "561bb7ddb8eb5cdf33e4608f772c2a021504d0a9eb73536c66b30095545da05d", + "dist/2022-04-05/rust-std-beta-x86_64-fuchsia.tar.gz": "d8fa9b75e173766ecafe150aa8162860dcf93f2340a5dad5fa2529619a5ae05a", + "dist/2022-04-05/rust-std-beta-x86_64-fuchsia.tar.xz": "182c4809af23b0a0f6a0d3ef5f9f7f4cbd846ecc62d459f5aef840871f9fe7d5", + "dist/2022-04-05/rust-std-beta-x86_64-linux-android.tar.gz": "44f09c699a1543581bfcbea834b654dbd165826d80476d6bf4fa3cbf4e90dff9", + "dist/2022-04-05/rust-std-beta-x86_64-linux-android.tar.xz": "6c019c7ecaf340f27b42a87885e4918b736f9a8ef139773092a33bc42d8f27cf", + "dist/2022-04-05/rust-std-beta-x86_64-pc-solaris.tar.gz": "fff1f8b4192be1bd4f701b356094c0a5ce3fc8da4878d29cbf6dfb7476c371f2", + "dist/2022-04-05/rust-std-beta-x86_64-pc-solaris.tar.xz": "b8991973df37f86ccb4c09082caff85f7ddae365d2fa554db6ba26795b263051", + "dist/2022-04-05/rust-std-beta-x86_64-pc-windows-gnu.tar.gz": "fdab2938d8f835dc6244b8aae81989de11c46adb413a9feeca11986453dc5f2c", + "dist/2022-04-05/rust-std-beta-x86_64-pc-windows-gnu.tar.xz": "4d860de3ff0b5327736d23296365bb65761b4c14dbbc683201286d9fee2fd58e", + "dist/2022-04-05/rust-std-beta-x86_64-pc-windows-msvc.tar.gz": "b0e1942912bed10275f65bd525971a7c5fbf03c92bb3a3d2934b35004ca9f109", + "dist/2022-04-05/rust-std-beta-x86_64-pc-windows-msvc.tar.xz": "40ba2150b24081cb1a1268c196fc27a15d771cda3136fbb838d6cfa8535758bd", + "dist/2022-04-05/rust-std-beta-x86_64-sun-solaris.tar.gz": "4d4a43484120e6c0cd46ad66f2c3b9bb46532d8cedb3d899e11aa575638bee2e", + "dist/2022-04-05/rust-std-beta-x86_64-sun-solaris.tar.xz": "546cfcbc48405ea55f702866e7ab2581dcf99abf3d38d97a8736db5ebad72eda", + "dist/2022-04-05/rust-std-beta-x86_64-unknown-freebsd.tar.gz": "dc84510940fd620db639ebfb127e398adbbb13639979cc8855d4a8485363da52", + "dist/2022-04-05/rust-std-beta-x86_64-unknown-freebsd.tar.xz": "d457f1c09dd446e30e94e4bcb1e3b5fde9cc54080cbe5e0a329ee810ab07d312", + "dist/2022-04-05/rust-std-beta-x86_64-unknown-illumos.tar.gz": "1e6b9a255ece3599af1614f47a086422632082ab2e4dd8382f4a23c48865bc84", + "dist/2022-04-05/rust-std-beta-x86_64-unknown-illumos.tar.xz": "7420f5442c1835830c93340ed4cec54c58a104978b54fccb80c4015b9614b9bd", + "dist/2022-04-05/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz": "b3e69ff8e1725c8a0b61c79be8d2f2d396cda1dd13d2a3d1f87667ca426253ed", + "dist/2022-04-05/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz": "beaff8b113d35826c062d7c7f76b773e45d0e878e059c42de5411406906368a6", + "dist/2022-04-05/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz": "bc27fd39c6e67451235aa8f14bd6f4a1018379cf52131ab3924134d6294ea54f", + "dist/2022-04-05/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz": "4b2ada52b6bd53e786cd5494b6bbbcbc8d7ec6812359b4d1a1a5a25c64e190f6", + "dist/2022-04-05/rust-std-beta-x86_64-unknown-linux-musl.tar.gz": "7f1464a804086c7709d5198abde76f6470fd1c36fdebca664e41ebaeeff8b1a0", + "dist/2022-04-05/rust-std-beta-x86_64-unknown-linux-musl.tar.xz": "6c570824abd6478c104a55147d6d54e6b785222ea15ffd00c59caee373a78bfe", + "dist/2022-04-05/rust-std-beta-x86_64-unknown-netbsd.tar.gz": "17c6e9204cfdf32fb8db4a7ade73dda300a35c515fc017804593d76590f537d9", + "dist/2022-04-05/rust-std-beta-x86_64-unknown-netbsd.tar.xz": "738f9f96914b20a9e97195d75bc806563fbe4554dc30e02fda58dece420a2790", + "dist/2022-04-05/rust-std-beta-x86_64-unknown-redox.tar.gz": "f0846eed5e5692deb83d01ea36792691232b2449f430c0433375e13efa014142", + "dist/2022-04-05/rust-std-beta-x86_64-unknown-redox.tar.xz": "2ea808655537de27b207fb61b2245048d124cff21edd52ac388838fcbd1d13c1", + "dist/2022-04-05/rustc-beta-aarch64-apple-darwin.tar.gz": "ee587d1e4f90b0662ca8fd845b5b945b5bdeaf09ef51a48c082ccd5ad5582060", + "dist/2022-04-05/rustc-beta-aarch64-apple-darwin.tar.xz": "4d7f7800088d21ec7450a7b7cfe1a00d10ef832919895b7eadd948cc60c2ea51", + "dist/2022-04-05/rustc-beta-aarch64-pc-windows-msvc.tar.gz": "2e96658cea6c5dd9a05490a2a03062e9faa8a19dc359e0751e36834fe0ef8d37", + "dist/2022-04-05/rustc-beta-aarch64-pc-windows-msvc.tar.xz": "401257ac9451f86f2a8306805dffcc77b2d02d2957c2509e7397d640c650a971", + "dist/2022-04-05/rustc-beta-aarch64-unknown-linux-gnu.tar.gz": "8ed21a78a71fcad7ef9c37d5da5f6bfc728947b036996ce280f49076526d41a4", + "dist/2022-04-05/rustc-beta-aarch64-unknown-linux-gnu.tar.xz": "cf81292f92477f22220feaf07d4c151ef59a6f3fc73770a52ed02064cca3eb65", + "dist/2022-04-05/rustc-beta-aarch64-unknown-linux-musl.tar.gz": "8d64fa488a87a8bb8a7ac4bdf4cd5bf258e5231b98b84361199ff414833ba354", + "dist/2022-04-05/rustc-beta-aarch64-unknown-linux-musl.tar.xz": "4e1ccc5114bbc888a382db706dea497e9a5cfe95de221fc5ddb07942de804964", + "dist/2022-04-05/rustc-beta-arm-unknown-linux-gnueabi.tar.gz": "bead69bf19b04a5dfba77da2831e034224cf87d91867c4f14abdd4c0efdf862c", + "dist/2022-04-05/rustc-beta-arm-unknown-linux-gnueabi.tar.xz": "cf5f6849862fe528ffa3f7620d04150b3ac034ee985bbd0a45d6139e14b1314e", + "dist/2022-04-05/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz": "21d2f05ec33cf2c11359e785a74ee2997076f8aa11777e241855266f6d7b68a6", + "dist/2022-04-05/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz": "299a57e0d25333e1de955a12c69f1cd97da6163ebea681aba4a52601b08d7b26", + "dist/2022-04-05/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz": "f7460821d2f4289e72f4be807a72c16ac61496bf5732b3c846f6b6e8a43fd669", + "dist/2022-04-05/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz": "da22ccbaafafd05b18587c1c33ea8c12c083129d4accdfe728c32a9c341d8b12", + "dist/2022-04-05/rustc-beta-i686-pc-windows-gnu.tar.gz": "7be21e73f6d48e0765c102f2dc5b2e3ce57f00e5f9dae6cdcc354b7444acf6bc", + "dist/2022-04-05/rustc-beta-i686-pc-windows-gnu.tar.xz": "b964692919697ec8d5d8d4d4b41579d9fa805ce93c5efb56c3106e5c223f86bd", + "dist/2022-04-05/rustc-beta-i686-pc-windows-msvc.tar.gz": "629942cacf1ab50e5273de51bb786c4258f4efe83748180c27caecbedae6e2c8", + "dist/2022-04-05/rustc-beta-i686-pc-windows-msvc.tar.xz": "7a3b57b8f34c5ea10bee2142edd625b70bd8765761593da9fb0ffb76f30e0e7b", + "dist/2022-04-05/rustc-beta-i686-unknown-linux-gnu.tar.gz": "7cae7e0c0690f302064b768ef7daffe500a7b8767c1ea985d5f9706f41137f5e", + "dist/2022-04-05/rustc-beta-i686-unknown-linux-gnu.tar.xz": "74395a6013a4589b5d39af2d5780c8bf6420256d7159030f248f584bfec018b4", + "dist/2022-04-05/rustc-beta-mips-unknown-linux-gnu.tar.gz": "cfd2fe4c26207346f04d6c4e2e8dee1c9a42fef6663b6eff1029f30c06492efc", + "dist/2022-04-05/rustc-beta-mips-unknown-linux-gnu.tar.xz": "aafea47e80244a136f87640e0b482898362d73a8b4f80ebcf6a539a268713350", + "dist/2022-04-05/rustc-beta-mips64-unknown-linux-gnuabi64.tar.gz": "0d23c8b6e50d1788b46b45c7df4720076829cfe45a926edece8b99223ec02f35", + "dist/2022-04-05/rustc-beta-mips64-unknown-linux-gnuabi64.tar.xz": "89a452f3820732daa166adc30b232261b86019ded316efdb42266b0bbaa09957", + "dist/2022-04-05/rustc-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "30ba547c1e6b802b99d01ebbab93e7209a9abc701174079fd8f4651146926545", + "dist/2022-04-05/rustc-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "172dcf58d1b68b56ad28dc00571a31457da8e9cd9a02be0a0eb816924ef5617d", + "dist/2022-04-05/rustc-beta-mipsel-unknown-linux-gnu.tar.gz": "829459c4f165c80a8009c75860122c93dfbe7984b0ec4517a605973a82f86e42", + "dist/2022-04-05/rustc-beta-mipsel-unknown-linux-gnu.tar.xz": "46c50f7d1e84abcd31160de933be9a4557da5e141ee60e84dfb8bff5fc99efd5", + "dist/2022-04-05/rustc-beta-powerpc-unknown-linux-gnu.tar.gz": "313bf23cfa02982a59a2fed4301af0abc787969a493e437124a7bde76e73559c", + "dist/2022-04-05/rustc-beta-powerpc-unknown-linux-gnu.tar.xz": "c5599b35c68a06c16d7a467b4a7fbf4584b4e4ec2ef6ce8504e6d2cc57ea78c0", + "dist/2022-04-05/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz": "29d148d3b71f344d63d4fc8ca3809ea11dd4de58afaa0eac11047ee7772f7690", + "dist/2022-04-05/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz": "c5614d7fe9c4a388d7e5902ee37aaaada479ff3ba0eebb63f5539fd83b5200ae", + "dist/2022-04-05/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz": "29ce9644866ee2bbcf60668efb389255081b9c905ab1ccb34781c4b4258b5964", + "dist/2022-04-05/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz": "98eb0d3a369a39ba71b10c140986305c29fe56f79cdb3144e5a6d1eb9cfa6a82", + "dist/2022-04-05/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz": "0a510b176d2583b52873ca444122e8aff5b17183d87eb984cc3042b70125f685", + "dist/2022-04-05/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz": "85231536c338281263cf9f4f9fc4c4148f0ad87e436b368a13e45bf75dab382a", + "dist/2022-04-05/rustc-beta-s390x-unknown-linux-gnu.tar.gz": "c998a37c27666f5eab87133df5b2b5f6c636df0375321a2dba149f8375bb2adc", + "dist/2022-04-05/rustc-beta-s390x-unknown-linux-gnu.tar.xz": "50551f01002b91c14bf6e9232555764594e041fb3953b2d4c64ed48e904dc8f2", + "dist/2022-04-05/rustc-beta-x86_64-apple-darwin.tar.gz": "9dc62cef50cc1af0e5b790aefb475ab002a3e6e9abfe449bbd35c33c0e2694b0", + "dist/2022-04-05/rustc-beta-x86_64-apple-darwin.tar.xz": "088b67dcdc7bd2b79b438666fc1013d7fea31d603d50548dceddbdb6149f1c69", + "dist/2022-04-05/rustc-beta-x86_64-pc-windows-gnu.tar.gz": "95ecf36825fd88d6f7b1717248a8dd1863c8e249af69d66594912964c4b9d06a", + "dist/2022-04-05/rustc-beta-x86_64-pc-windows-gnu.tar.xz": "3ea5b4bc1e4e07e45a01df5519bd905c99726a0962e984059ad500243061f3e2", + "dist/2022-04-05/rustc-beta-x86_64-pc-windows-msvc.tar.gz": "31f9226104cc55f67ea01db73a76e631937dee4e8b7e9561cb199cbbb02b33db", + "dist/2022-04-05/rustc-beta-x86_64-pc-windows-msvc.tar.xz": "b054a6eadbfeebf1d8ccdbad8f323e65f32830095aaf512df80e65ec63900480", + "dist/2022-04-05/rustc-beta-x86_64-unknown-freebsd.tar.gz": "17774e9e0678f1825b92fee1e9bed6fe56c8baf76ee43c9608b13985359f2911", + "dist/2022-04-05/rustc-beta-x86_64-unknown-freebsd.tar.xz": "5b461322da60b08554f2557deb69485d3991abf13b75750a307c004d6547a42f", + "dist/2022-04-05/rustc-beta-x86_64-unknown-illumos.tar.gz": "404e9bc04cc7330989d34cb8597814ee576ceee31fccbb932576171cd0dc2fca", + "dist/2022-04-05/rustc-beta-x86_64-unknown-illumos.tar.xz": "5fa0cde302fb7abe148315116f5a499a76971d7bd7353043f1a4361510030a4d", + "dist/2022-04-05/rustc-beta-x86_64-unknown-linux-gnu.tar.gz": "a38030a213dc78b5030c03e40f1e6d533518e89fb88eed4632526c9297c7bd45", + "dist/2022-04-05/rustc-beta-x86_64-unknown-linux-gnu.tar.xz": "8595bf3845f559a9f7ddf63807ac535739592f4b61a62b028b63dd3db812fd6c", + "dist/2022-04-05/rustc-beta-x86_64-unknown-linux-musl.tar.gz": "c8184f26eed43d4d059f0d39eb58da781ac8cd1546ae26be55d5e4aaf617bfc7", + "dist/2022-04-05/rustc-beta-x86_64-unknown-linux-musl.tar.xz": "2cdf12d740ec570ae6999cb1334b84c24b5a5e4c0a97863b6085423c814caa93", + "dist/2022-04-05/rustc-beta-x86_64-unknown-netbsd.tar.gz": "24bf12c22c765678cf4ea6860b3caaaccfd2762f473db40a6617a377df11b098", + "dist/2022-04-05/rustc-beta-x86_64-unknown-netbsd.tar.xz": "64e3a7fd4027e3c93a147196b9ba1e0a2d43f1263d053c71e179fd2529c66a95", + "dist/2022-04-05/rustfmt-nightly-aarch64-apple-darwin.tar.gz": "63a0c7abc8a755a6946a7f17dcf04ee925f138d1c50d2ccce9ae8af53526d95f", + "dist/2022-04-05/rustfmt-nightly-aarch64-apple-darwin.tar.xz": "a1ecb5efe8f1232336f9f8c0d3b7ed87d6de64ec8ec11f1aca0cc08ed46fef42", + "dist/2022-04-05/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz": "fdee076495e8314a4b24de97736da154eb5db6dcecfe629153a05dcd903e9b45", + "dist/2022-04-05/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz": "5d845c73478bc38ab42fb16dd138b82c8a44fab6b0787b5635140eb418516b79", + "dist/2022-04-05/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz": "dec1f8535a8edee8aaade80c87dacad690c0a158c4775ee0c9d9e580e1ea47bd", + "dist/2022-04-05/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz": "2b91b40a7b2af113210b386991c966758da6defab7e6c5c610574496513ab5ed", + "dist/2022-04-05/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz": "85da42f4c758c88418f952dfe919b8eeba654ee75c72d87f2d56257fb2248efd", + "dist/2022-04-05/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz": "0c4aade052166886439598db875872efa8fa5b2aa49e27271f57cec68e6a464a", + "dist/2022-04-05/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz": "44312f3a088159f78f6cb5e6518aea2727d61681b8a37d71bc414fd1310d1160", + "dist/2022-04-05/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz": "1cf420d4c8e8af78d5bd5aa95e662182c7a90a24e549cbf23f59e7444b0e45da", + "dist/2022-04-05/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz": "019fa75361e72cfd813c4ba9be8d48774a4a0cff1870b0e343278527dc62dedb", + "dist/2022-04-05/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz": "1be1e449ef8c299ef269baeba36c612746afdb16d59d9af8575ef67d5a4a4a3a", + "dist/2022-04-05/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz": "8a03f3f1126fe7312c3e86fd0162ae7ce82111f477c00f7884b47e74776e4192", + "dist/2022-04-05/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz": "05345ba340c9eff4dc2893438a1bdeb047269a54f66cb2fcfd6f05f5a6706b07", + "dist/2022-04-05/rustfmt-nightly-i686-pc-windows-gnu.tar.gz": "9e5cc2cae5e40b9a964f4f52c20f9566d1d401b696a3eeeb322f34c907eb1d45", + "dist/2022-04-05/rustfmt-nightly-i686-pc-windows-gnu.tar.xz": "db8991874c2f3a1e1ab92c2160cda4c9b1b567fd7b73a610f071e3a59682f585", + "dist/2022-04-05/rustfmt-nightly-i686-pc-windows-msvc.tar.gz": "4729ed2d654cc84e4afc4cdbad7a2609783c2e01ff1442aa2b7209cc1793eeeb", + "dist/2022-04-05/rustfmt-nightly-i686-pc-windows-msvc.tar.xz": "1c92a4124af30627a44690177dfb9a47aae9794bb2a6f22dd0171c4d0740ce7d", + "dist/2022-04-05/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz": "4efb1ceabe3387eb9cb6663718ebef3cdcfc401ebd57557a1f71075c82db5443", + "dist/2022-04-05/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz": "1485487c0fe779ea52c387a41776418f82649bf11dff56c65eebc9836c447741", + "dist/2022-04-05/rustfmt-nightly-mips-unknown-linux-gnu.tar.gz": "83af3e32a9e04e89fc0db69c96ee4de144464fc63daa9c15b5339b2b98dc29b3", + "dist/2022-04-05/rustfmt-nightly-mips-unknown-linux-gnu.tar.xz": "6cd906bfac78de1ec92a53ddee54fbaa437280c413411aae678fd87db9df11c6", + "dist/2022-04-05/rustfmt-nightly-mips64-unknown-linux-gnuabi64.tar.gz": "00bd1e70d9cf308fe4b48cae7188272068d8f98e782e40c74d6e1af20dad3984", + "dist/2022-04-05/rustfmt-nightly-mips64-unknown-linux-gnuabi64.tar.xz": "51b3192cfa8a9ad4e6981a6fc7a57fd50059d3182e67425a1c036db37b67c1c7", + "dist/2022-04-05/rustfmt-nightly-mips64el-unknown-linux-gnuabi64.tar.gz": "b81e01d392d4d498be39b99ba4cbf24324248647d15eb470526421954596f2bf", + "dist/2022-04-05/rustfmt-nightly-mips64el-unknown-linux-gnuabi64.tar.xz": "e8c6a23e762c4f81030e8c7449e0d49fb60c058893e4ca2110012db8d4a9be43", + "dist/2022-04-05/rustfmt-nightly-mipsel-unknown-linux-gnu.tar.gz": "64e38687c204feb1dcfd19aec7af93cea724548d5c1e74b38a69a29017c6d721", + "dist/2022-04-05/rustfmt-nightly-mipsel-unknown-linux-gnu.tar.xz": "0bc3ac22801cdd0fd6e71d172f61cc3249c6e61b6333e748eb47624d4ef60748", + "dist/2022-04-05/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz": "9d03b1724dbacf126f626abc9c71c4461f75f6b1c71c5132c1ab1b4ae39363ee", + "dist/2022-04-05/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz": "3fda672627eaa0f69d7492f55cae4d769bd421c671a74960d77bfd5021dc71c7", + "dist/2022-04-05/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz": "265c0238b9878c454d65c361968d63b6d55b69f82adbf27fc626d333d093c212", + "dist/2022-04-05/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz": "c50dc03c50d8e0222c959867f621772e7cac5df72d4487f6f6082898ed1fd1b0", + "dist/2022-04-05/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz": "3b28fb9c8b8050fc3a06a4591bd90c7c2a42859aa61177572f60f1fed0bbd46a", + "dist/2022-04-05/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz": "2153976482c3bb6babf8602d7751a4bfa99ee96397d42efb91c38652e652bde9", + "dist/2022-04-05/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz": "7c2fdd326f5ebfcb7ad3c732954c2ca34191d40422eb7b318331219d282f34b7", + "dist/2022-04-05/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz": "38fe0ede661a71ca4010359c9e6d8c4656c2da4e13dbc9c7cd0b98481406bcd4", + "dist/2022-04-05/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz": "4b682444c300d130087d77ab595fe829d1cfd4d08bc22aeda4042ad818b0402d", + "dist/2022-04-05/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz": "c9d39631dae71e15702b194b7f4dd3dced040fa731dd2f8aeb892368f3637cbc", + "dist/2022-04-05/rustfmt-nightly-x86_64-apple-darwin.tar.gz": "ee7c5a878da4b33761eb2991792833da41673d5bd5916ad8aefec83350e9cf3d", + "dist/2022-04-05/rustfmt-nightly-x86_64-apple-darwin.tar.xz": "54147e40db10a73e22d6aa20b40d5cd64c79b0b1afa57758cbd6809bd7ba62a0", + "dist/2022-04-05/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz": "e019b5a55a66755794f03eeadd927cfc839a2745c5865c5a53230bd5a961a296", + "dist/2022-04-05/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz": "a7c0a92a4e34e2bb3d58166525bf10a400b643a0791b352b29ff25d8eee9a842", + "dist/2022-04-05/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz": "4a9f16df3b8bbd38d43a1a585c29ba5b95dd7d60e4ee6df3063fdd36d1b64acb", + "dist/2022-04-05/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz": "4af11a257914be44e8aff5e6d0e586282b12b52f326ecc95d2c58a921154606c", + "dist/2022-04-05/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz": "06cb18eb062ac90f1d77f2b0f09d0220a265790e0b80c3549360eef72af14dee", + "dist/2022-04-05/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz": "37b671df4350aa5320174965eac84e05063a35dc0549f1aec035724fff143f0d", + "dist/2022-04-05/rustfmt-nightly-x86_64-unknown-illumos.tar.gz": "4949b3846cb5dfd7e52abd081631397d7614c16782b8f4eec90aefdac927dfad", + "dist/2022-04-05/rustfmt-nightly-x86_64-unknown-illumos.tar.xz": "35a92e775b602d21d23bae702c5ac0de2c9eeba1da6e009084a95b448af8a689", + "dist/2022-04-05/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz": "f595603b8c255486801e62716133fa8460b63130e94a5c935dd48ec1189b1074", + "dist/2022-04-05/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz": "dc67ea19eb872659763784b716b8d264e654db5897d2a6766810623605af94b0", + "dist/2022-04-05/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz": "3e969a8904fe06c1299534d5bb334dea7b9b45321a155d189f2ab6c0781299a2", + "dist/2022-04-05/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz": "b7a8f67c8da8c148bf1c33df7bffc76c8c3ca430d4e0ab8c4b261a2aaa98dc67", + "dist/2022-04-05/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz": "7b0e15340585812b597a68c5e6ab778346db3de5d6af7c41fa0cb710e6bf130b", + "dist/2022-04-05/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz": "9fdb4e1e5afb2c3b110a605383ae2da844e1a5d87285a2475af4bf8d8dde5291" } }
diff --git a/src/test/mir-opt/const_goto_storage.match_nested_if.ConstGoto.diff b/src/test/mir-opt/const_goto_storage.match_nested_if.ConstGoto.diff new file mode 100644 index 0000000..aee7e22 --- /dev/null +++ b/src/test/mir-opt/const_goto_storage.match_nested_if.ConstGoto.diff
@@ -0,0 +1,102 @@ +- // MIR for `match_nested_if` before ConstGoto ++ // MIR for `match_nested_if` after ConstGoto + + fn match_nested_if() -> bool { + let mut _0: bool; // return place in scope 0 at $DIR/const_goto_storage.rs:2:25: 2:29 + let _1: bool; // in scope 0 at $DIR/const_goto_storage.rs:3:9: 3:12 +- let mut _2: (); // in scope 0 at $DIR/const_goto_storage.rs:3:21: 3:23 +- let mut _3: bool; // in scope 0 at $DIR/const_goto_storage.rs:4:15: 8:10 +- let mut _4: bool; // in scope 0 at $DIR/const_goto_storage.rs:4:18: 4:76 +- let mut _5: bool; // in scope 0 at $DIR/const_goto_storage.rs:4:21: 4:52 +- let mut _6: bool; // in scope 0 at $DIR/const_goto_storage.rs:4:24: 4:28 ++ let mut _2: bool; // in scope 0 at $DIR/const_goto_storage.rs:4:24: 4:28 + scope 1 { + debug val => _1; // in scope 1 at $DIR/const_goto_storage.rs:3:9: 3:12 + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/const_goto_storage.rs:3:9: 3:12 +- StorageLive(_2); // scope 0 at $DIR/const_goto_storage.rs:3:21: 3:23 +- StorageLive(_3); // scope 0 at $DIR/const_goto_storage.rs:4:15: 8:10 +- StorageLive(_4); // scope 0 at $DIR/const_goto_storage.rs:4:18: 4:76 +- StorageLive(_5); // scope 0 at $DIR/const_goto_storage.rs:4:21: 4:52 +- StorageLive(_6); // scope 0 at $DIR/const_goto_storage.rs:4:24: 4:28 +- _6 = const true; // scope 0 at $DIR/const_goto_storage.rs:4:24: 4:28 +- switchInt(move _6) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/const_goto_storage.rs:4:24: 4:28 ++ StorageLive(_2); // scope 0 at $DIR/const_goto_storage.rs:4:24: 4:28 ++ _2 = const true; // scope 0 at $DIR/const_goto_storage.rs:4:24: 4:28 ++ switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/const_goto_storage.rs:4:24: 4:28 + } + + bb1: { +- _5 = const true; // scope 0 at $DIR/const_goto_storage.rs:4:31: 4:35 +- goto -> bb3; // scope 0 at $DIR/const_goto_storage.rs:4:21: 4:52 +- } +- +- bb2: { +- _5 = const false; // scope 0 at $DIR/const_goto_storage.rs:4:45: 4:50 +- goto -> bb3; // scope 0 at $DIR/const_goto_storage.rs:4:21: 4:52 +- } +- +- bb3: { +- StorageDead(_6); // scope 0 at $DIR/const_goto_storage.rs:4:51: 4:52 +- switchInt(move _5) -> [false: bb5, otherwise: bb4]; // scope 0 at $DIR/const_goto_storage.rs:4:21: 4:52 +- } +- +- bb4: { +- _4 = const true; // scope 0 at $DIR/const_goto_storage.rs:4:55: 4:59 +- goto -> bb6; // scope 0 at $DIR/const_goto_storage.rs:4:18: 4:76 +- } +- +- bb5: { +- _4 = const false; // scope 0 at $DIR/const_goto_storage.rs:4:69: 4:74 +- goto -> bb6; // scope 0 at $DIR/const_goto_storage.rs:4:18: 4:76 +- } +- +- bb6: { +- StorageDead(_5); // scope 0 at $DIR/const_goto_storage.rs:4:75: 4:76 +- switchInt(move _4) -> [false: bb8, otherwise: bb7]; // scope 0 at $DIR/const_goto_storage.rs:4:18: 4:76 +- } +- +- bb7: { +- _3 = const true; // scope 0 at $DIR/const_goto_storage.rs:5:13: 5:17 +- goto -> bb9; // scope 0 at $DIR/const_goto_storage.rs:4:15: 8:10 +- } +- +- bb8: { +- _3 = const false; // scope 0 at $DIR/const_goto_storage.rs:7:13: 7:18 +- goto -> bb9; // scope 0 at $DIR/const_goto_storage.rs:4:15: 8:10 +- } +- +- bb9: { +- switchInt(move _3) -> [false: bb11, otherwise: bb10]; // scope 0 at $DIR/const_goto_storage.rs:4:15: 8:10 +- } +- +- bb10: { +- StorageDead(_4); // scope 0 at $DIR/const_goto_storage.rs:8:9: 8:10 +- StorageDead(_3); // scope 0 at $DIR/const_goto_storage.rs:8:9: 8:10 ++ StorageDead(_2); // scope 0 at $DIR/const_goto_storage.rs:4:51: 4:52 + _1 = const true; // scope 0 at $DIR/const_goto_storage.rs:10:17: 10:21 +- goto -> bb12; // scope 0 at $DIR/const_goto_storage.rs:10:17: 10:21 ++ goto -> bb3; // scope 0 at $DIR/const_goto_storage.rs:10:17: 10:21 + } + +- bb11: { +- StorageDead(_4); // scope 0 at $DIR/const_goto_storage.rs:8:9: 8:10 +- StorageDead(_3); // scope 0 at $DIR/const_goto_storage.rs:8:9: 8:10 ++ bb2: { ++ StorageDead(_2); // scope 0 at $DIR/const_goto_storage.rs:4:51: 4:52 + _1 = const false; // scope 0 at $DIR/const_goto_storage.rs:12:14: 12:19 +- goto -> bb12; // scope 0 at $DIR/const_goto_storage.rs:12:14: 12:19 ++ goto -> bb3; // scope 0 at $DIR/const_goto_storage.rs:12:14: 12:19 + } + +- bb12: { +- StorageDead(_2); // scope 0 at $DIR/const_goto_storage.rs:13:6: 13:7 ++ bb3: { + _0 = _1; // scope 1 at $DIR/const_goto_storage.rs:14:5: 14:8 + StorageDead(_1); // scope 0 at $DIR/const_goto_storage.rs:15:1: 15:2 + return; // scope 0 at $DIR/const_goto_storage.rs:15:2: 15:2 + } + } +
diff --git a/src/test/mir-opt/const_goto_storage.rs b/src/test/mir-opt/const_goto_storage.rs new file mode 100644 index 0000000..4ef68e7 --- /dev/null +++ b/src/test/mir-opt/const_goto_storage.rs
@@ -0,0 +1,19 @@ +// EMIT_MIR const_goto_storage.match_nested_if.ConstGoto.diff +fn match_nested_if() -> bool { + let val = match () { + () if if if if true { true } else { false } { true } else { false } { + true + } else { + false + } => + { + true + } + _ => false, + }; + val +} + +fn main() { + let _ = match_nested_if(); +}
diff --git a/src/test/mir-opt/const_prop/invalid_constant.main.ConstProp.diff b/src/test/mir-opt/const_prop/invalid_constant.main.ConstProp.diff index f2a1b9d..cf6d8a5 100644 --- a/src/test/mir-opt/const_prop/invalid_constant.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/invalid_constant.main.ConstProp.diff
@@ -3,56 +3,70 @@ fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/invalid_constant.rs:15:11: 15:11 - let _1: main::InvalidChar; // in scope 0 at $DIR/invalid_constant.rs:21:9: 21:22 - let mut _3: main::InvalidTag; // in scope 0 at $DIR/invalid_constant.rs:28:25: 28:46 - let mut _5: main::NoVariants; // in scope 0 at $DIR/invalid_constant.rs:35:35: 35:56 + let _1: char; // in scope 0 at $DIR/invalid_constant.rs:21:9: 21:22 + let mut _2: main::InvalidChar; // in scope 0 at $DIR/invalid_constant.rs:21:34: 21:63 + let mut _4: E; // in scope 0 at $DIR/invalid_constant.rs:28:25: 28:59 + let mut _5: main::InvalidTag; // in scope 0 at $DIR/invalid_constant.rs:28:34: 28:55 + let mut _7: Empty; // in scope 0 at $DIR/invalid_constant.rs:35:35: 35:73 + let mut _8: main::NoVariants; // in scope 0 at $DIR/invalid_constant.rs:35:44: 35:65 scope 1 { debug _invalid_char => _1; // in scope 1 at $DIR/invalid_constant.rs:21:9: 21:22 - let _2: [main::InvalidTag; 1]; // in scope 1 at $DIR/invalid_constant.rs:28:9: 28:21 - scope 2 { - debug _invalid_tag => _2; // in scope 2 at $DIR/invalid_constant.rs:28:9: 28:21 - let _4: [main::NoVariants; 1]; // in scope 2 at $DIR/invalid_constant.rs:35:9: 35:31 - scope 3 { - debug _enum_without_variants => _4; // in scope 3 at $DIR/invalid_constant.rs:35:9: 35:31 - let _6: main::Str<"���">; // in scope 3 at $DIR/invalid_constant.rs:39:9: 39:22 - scope 4 { - debug _non_utf8_str => _6; // in scope 4 at $DIR/invalid_constant.rs:39:9: 39:22 + let _3: [E; 1]; // in scope 1 at $DIR/invalid_constant.rs:28:9: 28:21 + scope 3 { + debug _invalid_tag => _3; // in scope 3 at $DIR/invalid_constant.rs:28:9: 28:21 + let _6: [Empty; 1]; // in scope 3 at $DIR/invalid_constant.rs:35:9: 35:31 + scope 5 { + debug _enum_without_variants => _6; // in scope 5 at $DIR/invalid_constant.rs:35:9: 35:31 + let _9: main::Str<"���">; // in scope 5 at $DIR/invalid_constant.rs:39:9: 39:22 + scope 7 { + debug _non_utf8_str => _9; // in scope 7 at $DIR/invalid_constant.rs:39:9: 39:22 } } + scope 6 { + } } + scope 4 { + } + } + scope 2 { } bb0: { StorageLive(_1); // scope 0 at $DIR/invalid_constant.rs:21:9: 21:22 -- _1 = const { InvalidChar { int: 0x110001 } }; // scope 0 at $DIR/invalid_constant.rs:21:25: 21:64 -+ _1 = const InvalidChar { int: 1114113_u32, chr: {transmute(0x00110001): char} }; // scope 0 at $DIR/invalid_constant.rs:21:25: 21:64 - // mir::Constant - // + span: $DIR/invalid_constant.rs:21:25: 21:64 -- // + literal: Const { ty: InvalidChar, val: Unevaluated(main::{constant#0}, [main::InvalidChar], None) } -+ // + literal: Const { ty: InvalidChar, val: Value(Scalar(0x00110001)) } - StorageLive(_2); // scope 1 at $DIR/invalid_constant.rs:28:9: 28:21 - StorageLive(_3); // scope 1 at $DIR/invalid_constant.rs:28:25: 28:46 - (_3.0: u32) = const 4_u32; // scope 1 at $DIR/invalid_constant.rs:28:25: 28:46 -- _2 = [move _3]; // scope 1 at $DIR/invalid_constant.rs:28:24: 28:47 -+ _2 = [const InvalidTag { int: 4_u32, e: Scalar(0x00000004): E }]; // scope 1 at $DIR/invalid_constant.rs:28:24: 28:47 + StorageLive(_2); // scope 2 at $DIR/invalid_constant.rs:21:34: 21:63 + (_2.0: u32) = const 1114113_u32; // scope 2 at $DIR/invalid_constant.rs:21:34: 21:63 +- _1 = (_2.1: char); // scope 2 at $DIR/invalid_constant.rs:21:34: 21:67 ++ _1 = const {transmute(0x00110001): char}; // scope 2 at $DIR/invalid_constant.rs:21:34: 21:67 + StorageDead(_2); // scope 0 at $DIR/invalid_constant.rs:21:69: 21:70 + StorageLive(_3); // scope 1 at $DIR/invalid_constant.rs:28:9: 28:21 + StorageLive(_4); // scope 1 at $DIR/invalid_constant.rs:28:25: 28:59 + StorageLive(_5); // scope 4 at $DIR/invalid_constant.rs:28:34: 28:55 + (_5.0: u32) = const 4_u32; // scope 4 at $DIR/invalid_constant.rs:28:34: 28:55 +- _4 = (_5.1: E); // scope 4 at $DIR/invalid_constant.rs:28:34: 28:57 +- _3 = [move _4]; // scope 1 at $DIR/invalid_constant.rs:28:24: 28:60 ++ _4 = const Scalar(0x00000004): E; // scope 4 at $DIR/invalid_constant.rs:28:34: 28:57 + // mir::Constant -+ // + span: $DIR/invalid_constant.rs:28:24: 28:47 -+ // + literal: Const { ty: InvalidTag, val: Value(Scalar(0x00000004)) } - StorageDead(_3); // scope 1 at $DIR/invalid_constant.rs:28:46: 28:47 - StorageLive(_4); // scope 2 at $DIR/invalid_constant.rs:35:9: 35:31 - StorageLive(_5); // scope 2 at $DIR/invalid_constant.rs:35:35: 35:56 - (_5.0: u32) = const 0_u32; // scope 2 at $DIR/invalid_constant.rs:35:35: 35:56 -- _4 = [move _5]; // scope 2 at $DIR/invalid_constant.rs:35:34: 35:57 -+ _4 = [const NoVariants { int: 0_u32, empty: Scalar(<ZST>): Empty }]; // scope 2 at $DIR/invalid_constant.rs:35:34: 35:57 ++ // + span: $DIR/invalid_constant.rs:28:34: 28:57 ++ // + literal: Const { ty: E, val: Value(Scalar(0x00000004)) } ++ _3 = [const Scalar(0x00000004): E]; // scope 1 at $DIR/invalid_constant.rs:28:24: 28:60 + // mir::Constant -+ // + span: $DIR/invalid_constant.rs:35:34: 35:57 -+ // + literal: Const { ty: NoVariants, val: Value(Scalar(0x00000000)) } - StorageDead(_5); // scope 2 at $DIR/invalid_constant.rs:35:56: 35:57 - StorageLive(_6); // scope 3 at $DIR/invalid_constant.rs:39:9: 39:22 ++ // + span: $DIR/invalid_constant.rs:28:24: 28:60 ++ // + literal: Const { ty: E, val: Value(Scalar(0x00000004)) } + StorageDead(_4); // scope 1 at $DIR/invalid_constant.rs:28:59: 28:60 + StorageDead(_5); // scope 1 at $DIR/invalid_constant.rs:28:60: 28:61 + StorageLive(_6); // scope 3 at $DIR/invalid_constant.rs:35:9: 35:31 + StorageLive(_7); // scope 3 at $DIR/invalid_constant.rs:35:35: 35:73 + StorageLive(_8); // scope 6 at $DIR/invalid_constant.rs:35:44: 35:65 + (_8.0: u32) = const 0_u32; // scope 6 at $DIR/invalid_constant.rs:35:44: 35:65 + nop; // scope 6 at $DIR/invalid_constant.rs:35:44: 35:71 + nop; // scope 3 at $DIR/invalid_constant.rs:35:34: 35:74 + StorageDead(_7); // scope 3 at $DIR/invalid_constant.rs:35:73: 35:74 + StorageDead(_8); // scope 3 at $DIR/invalid_constant.rs:35:74: 35:75 + StorageLive(_9); // scope 5 at $DIR/invalid_constant.rs:39:9: 39:22 nop; // scope 0 at $DIR/invalid_constant.rs:15:11: 42:2 + StorageDead(_9); // scope 5 at $DIR/invalid_constant.rs:42:1: 42:2 StorageDead(_6); // scope 3 at $DIR/invalid_constant.rs:42:1: 42:2 - StorageDead(_4); // scope 2 at $DIR/invalid_constant.rs:42:1: 42:2 - StorageDead(_2); // scope 1 at $DIR/invalid_constant.rs:42:1: 42:2 + StorageDead(_3); // scope 1 at $DIR/invalid_constant.rs:42:1: 42:2 StorageDead(_1); // scope 0 at $DIR/invalid_constant.rs:42:1: 42:2 return; // scope 0 at $DIR/invalid_constant.rs:42:2: 42:2 }
diff --git a/src/test/mir-opt/const_prop/invalid_constant.rs b/src/test/mir-opt/const_prop/invalid_constant.rs index 492ef40..0337a7c 100644 --- a/src/test/mir-opt/const_prop/invalid_constant.rs +++ b/src/test/mir-opt/const_prop/invalid_constant.rs
@@ -18,21 +18,21 @@ union InvalidChar { int: u32, chr: char, } - let _invalid_char = const { InvalidChar { int: 0x110001 } }; + let _invalid_char = unsafe { InvalidChar { int: 0x110001 }.chr }; // An enum with an invalid tag. Regression test for #93688. union InvalidTag { int: u32, e: E, } - let _invalid_tag = [InvalidTag { int: 4 }]; + let _invalid_tag = [unsafe { InvalidTag { int: 4 }.e }]; // An enum without variants. Regression test for #94073. union NoVariants { int: u32, empty: Empty, } - let _enum_without_variants = [NoVariants { int: 0 }]; + let _enum_without_variants = [unsafe { NoVariants { int: 0 }.empty }]; // A non-UTF-8 string slice. Regression test for #75763 and #78520. struct Str<const S: &'static str>;
diff --git a/src/test/mir-opt/derefer_test.main.Derefer.diff b/src/test/mir-opt/derefer_test.main.Derefer.diff new file mode 100644 index 0000000..e9a4565 --- /dev/null +++ b/src/test/mir-opt/derefer_test.main.Derefer.diff
@@ -0,0 +1,60 @@ +- // MIR for `main` before Derefer ++ // MIR for `main` after Derefer + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/derefer_test.rs:2:11: 2:11 + let mut _1: (i32, i32); // in scope 0 at $DIR/derefer_test.rs:3:9: 3:14 + let mut _3: &mut (i32, i32); // in scope 0 at $DIR/derefer_test.rs:4:22: 4:28 ++ let mut _6: &mut (i32, i32); // in scope 0 at $DIR/derefer_test.rs:5:13: 5:26 ++ let mut _7: &mut (i32, i32); // in scope 0 at $DIR/derefer_test.rs:6:13: 6:26 + scope 1 { + debug a => _1; // in scope 1 at $DIR/derefer_test.rs:3:9: 3:14 + let mut _2: (i32, &mut (i32, i32)); // in scope 1 at $DIR/derefer_test.rs:4:9: 4:14 + scope 2 { + debug b => _2; // in scope 2 at $DIR/derefer_test.rs:4:9: 4:14 + let _4: &mut i32; // in scope 2 at $DIR/derefer_test.rs:5:9: 5:10 + scope 3 { + debug x => _4; // in scope 3 at $DIR/derefer_test.rs:5:9: 5:10 + let _5: &mut i32; // in scope 3 at $DIR/derefer_test.rs:6:9: 6:10 + scope 4 { + debug y => _5; // in scope 4 at $DIR/derefer_test.rs:6:9: 6:10 + } + } + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/derefer_test.rs:3:9: 3:14 + (_1.0: i32) = const 42_i32; // scope 0 at $DIR/derefer_test.rs:3:17: 3:24 + (_1.1: i32) = const 43_i32; // scope 0 at $DIR/derefer_test.rs:3:17: 3:24 + StorageLive(_2); // scope 1 at $DIR/derefer_test.rs:4:9: 4:14 + StorageLive(_3); // scope 1 at $DIR/derefer_test.rs:4:22: 4:28 + _3 = &mut _1; // scope 1 at $DIR/derefer_test.rs:4:22: 4:28 + (_2.0: i32) = const 99_i32; // scope 1 at $DIR/derefer_test.rs:4:17: 4:29 + (_2.1: &mut (i32, i32)) = move _3; // scope 1 at $DIR/derefer_test.rs:4:17: 4:29 + StorageDead(_3); // scope 1 at $DIR/derefer_test.rs:4:28: 4:29 + StorageLive(_4); // scope 2 at $DIR/derefer_test.rs:5:9: 5:10 +- _4 = &mut ((*(_2.1: &mut (i32, i32))).0: i32); // scope 2 at $DIR/derefer_test.rs:5:13: 5:26 ++ StorageLive(_6); // scope 2 at $DIR/derefer_test.rs:5:13: 5:26 ++ _6 = move (_2.1: &mut (i32, i32)); // scope 2 at $DIR/derefer_test.rs:5:13: 5:26 ++ _4 = &mut ((*_6).0: i32); // scope 2 at $DIR/derefer_test.rs:5:13: 5:26 ++ StorageDead(_6); // scope 3 at $DIR/derefer_test.rs:6:9: 6:10 + StorageLive(_5); // scope 3 at $DIR/derefer_test.rs:6:9: 6:10 +- _5 = &mut ((*(_2.1: &mut (i32, i32))).1: i32); // scope 3 at $DIR/derefer_test.rs:6:13: 6:26 ++ StorageLive(_7); // scope 3 at $DIR/derefer_test.rs:6:13: 6:26 ++ _7 = move (_2.1: &mut (i32, i32)); // scope 3 at $DIR/derefer_test.rs:6:13: 6:26 ++ _5 = &mut ((*_7).1: i32); // scope 3 at $DIR/derefer_test.rs:6:13: 6:26 ++ StorageDead(_7); // scope 0 at $DIR/derefer_test.rs:2:11: 7:2 + _0 = const (); // scope 0 at $DIR/derefer_test.rs:2:11: 7:2 + StorageDead(_5); // scope 3 at $DIR/derefer_test.rs:7:1: 7:2 + StorageDead(_4); // scope 2 at $DIR/derefer_test.rs:7:1: 7:2 + StorageDead(_2); // scope 1 at $DIR/derefer_test.rs:7:1: 7:2 + StorageDead(_1); // scope 0 at $DIR/derefer_test.rs:7:1: 7:2 + return; // scope 0 at $DIR/derefer_test.rs:7:2: 7:2 ++ } ++ ++ bb1 (cleanup): { ++ resume; // scope 0 at $DIR/derefer_test.rs:2:1: 7:2 + } + } +
diff --git a/src/test/mir-opt/derefer_test.rs b/src/test/mir-opt/derefer_test.rs new file mode 100644 index 0000000..2ebc0d3 --- /dev/null +++ b/src/test/mir-opt/derefer_test.rs
@@ -0,0 +1,7 @@ +// EMIT_MIR derefer_test.main.Derefer.diff +fn main() { + let mut a = (42,43); + let mut b = (99, &mut a); + let x = &mut (*b.1).0; + let y = &mut (*b.1).1; +}
diff --git a/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir b/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir index 9264d41..a18ff0e 100644 --- a/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir +++ b/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir
@@ -10,6 +10,7 @@ debug self => _4; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL let mut _5: &mut T; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL let mut _6: &mut T; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL + let mut _7: std::boxed::Box<T>; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL } bb0: { @@ -19,7 +20,10 @@ _4 = &mut (*_1); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15 StorageLive(_5); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL StorageLive(_6); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL - _6 = &mut (*(*_4)); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL + StorageLive(_7); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL + _7 = move (*_4); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL + _6 = &mut (*_7); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL + StorageDead(_7); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL _5 = &mut (*_6); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL _3 = &mut (*_5); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL StorageDead(_6); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
diff --git a/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir b/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir index 422bf74..d079ba5 100644 --- a/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir +++ b/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir
@@ -7,13 +7,17 @@ let mut _3: &std::boxed::Box<T>; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:18:5: 18:15 scope 1 (inlined <Box<T> as AsRef<T>>::as_ref) { // at $DIR/issue-58867-inline-as-ref-as-mut.rs:18:5: 18:15 debug self => _3; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL + let mut _4: std::boxed::Box<T>; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL } bb0: { StorageLive(_2); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:18:5: 18:15 StorageLive(_3); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:18:5: 18:15 _3 = &(*_1); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:18:5: 18:15 - _2 = &(*(*_3)); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL + StorageLive(_4); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL + _4 = move (*_3); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL + _2 = &(*_4); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL + StorageDead(_4); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL _0 = &(*_2); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:18:5: 18:15 StorageDead(_3); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:18:14: 18:15 StorageDead(_2); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:19:1: 19:2
diff --git a/src/test/mir-opt/lower_array_len.array_bound.NormalizeArrayLen.diff b/src/test/mir-opt/lower_array_len.array_bound.NormalizeArrayLen.diff index d6c1c92..2e03467 100644 --- a/src/test/mir-opt/lower_array_len.array_bound.NormalizeArrayLen.diff +++ b/src/test/mir-opt/lower_array_len.array_bound.NormalizeArrayLen.diff
@@ -64,5 +64,9 @@ StorageDead(_3); // scope 0 at $DIR/lower_array_len.rs:11:5: 11:6 return; // scope 0 at $DIR/lower_array_len.rs:12:2: 12:2 } + + bb6 (cleanup): { + resume; // scope 0 at $DIR/lower_array_len.rs:6:1: 12:2 + } }
diff --git a/src/test/mir-opt/lower_array_len.array_bound_mut.NormalizeArrayLen.diff b/src/test/mir-opt/lower_array_len.array_bound_mut.NormalizeArrayLen.diff index 11fc20a..6aa77a9 100644 --- a/src/test/mir-opt/lower_array_len.array_bound_mut.NormalizeArrayLen.diff +++ b/src/test/mir-opt/lower_array_len.array_bound_mut.NormalizeArrayLen.diff
@@ -77,5 +77,9 @@ StorageDead(_3); // scope 0 at $DIR/lower_array_len.rs:24:5: 24:6 return; // scope 0 at $DIR/lower_array_len.rs:25:2: 25:2 } + + bb7 (cleanup): { + resume; // scope 0 at $DIR/lower_array_len.rs:17:1: 25:2 + } }
diff --git a/src/test/mir-opt/lower_array_len.array_len.NormalizeArrayLen.diff b/src/test/mir-opt/lower_array_len.array_len.NormalizeArrayLen.diff index 892fdda..b415824 100644 --- a/src/test/mir-opt/lower_array_len.array_len.NormalizeArrayLen.diff +++ b/src/test/mir-opt/lower_array_len.array_len.NormalizeArrayLen.diff
@@ -26,5 +26,9 @@ StorageDead(_2); // scope 0 at $DIR/lower_array_len.rs:31:13: 31:14 return; // scope 0 at $DIR/lower_array_len.rs:32:2: 32:2 } + + bb2 (cleanup): { + resume; // scope 0 at $DIR/lower_array_len.rs:30:1: 32:2 + } }
diff --git a/src/test/mir-opt/lower_array_len.array_len_by_value.NormalizeArrayLen.diff b/src/test/mir-opt/lower_array_len.array_len_by_value.NormalizeArrayLen.diff index 201fffb..92ec7a3 100644 --- a/src/test/mir-opt/lower_array_len.array_len_by_value.NormalizeArrayLen.diff +++ b/src/test/mir-opt/lower_array_len.array_len_by_value.NormalizeArrayLen.diff
@@ -26,5 +26,9 @@ StorageDead(_2); // scope 0 at $DIR/lower_array_len.rs:38:13: 38:14 return; // scope 0 at $DIR/lower_array_len.rs:39:2: 39:2 } + + bb2 (cleanup): { + resume; // scope 0 at $DIR/lower_array_len.rs:37:1: 39:2 + } }
diff --git a/src/test/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.diff b/src/test/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.diff index 13241d8..2210ad5 100644 --- a/src/test/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.diff +++ b/src/test/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.diff
@@ -59,5 +59,9 @@ StorageDead(_3); // scope 0 at $DIR/lower_slice_len.rs:9:5: 9:6 return; // scope 0 at $DIR/lower_slice_len.rs:10:2: 10:2 } + + bb6 (cleanup): { + resume; // scope 0 at $DIR/lower_slice_len.rs:4:1: 10:2 + } }
diff --git a/src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.32bit.diff b/src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.32bit.diff index 0511b59..2dfb2e1 100644 --- a/src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.32bit.diff +++ b/src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.32bit.diff
@@ -4,80 +4,36 @@ fn match_nested_if() -> bool { let mut _0: bool; // return place in scope 0 at $DIR/matches_reduce_branches.rs:39:25: 39:29 let _1: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:40:9: 40:12 - let mut _2: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76 - let mut _3: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52 - let mut _4: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28 -+ let mut _5: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28 -+ let mut _6: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52 -+ let mut _7: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76 + let mut _2: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28 ++ let mut _3: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28 scope 1 { debug val => _1; // in scope 1 at $DIR/matches_reduce_branches.rs:40:9: 40:12 } bb0: { StorageLive(_1); // scope 0 at $DIR/matches_reduce_branches.rs:40:9: 40:12 - StorageLive(_2); // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76 - StorageLive(_3); // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52 - StorageLive(_4); // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28 - _4 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28 -- switchInt(move _4) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28 + StorageLive(_2); // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28 + _2 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28 +- switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28 - } - - bb1: { -- _3 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:41:31: 41:35 -- goto -> bb3; // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52 ++ StorageLive(_3); // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28 ++ _3 = move _2; // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28 + StorageDead(_2); // scope 0 at $DIR/matches_reduce_branches.rs:41:51: 41:52 +- _1 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:47:13: 47:17 +- goto -> bb3; // scope 0 at $DIR/matches_reduce_branches.rs:47:13: 47:17 - } - - bb2: { -- _3 = const false; // scope 0 at $DIR/matches_reduce_branches.rs:41:45: 41:50 -- goto -> bb3; // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52 +- StorageDead(_2); // scope 0 at $DIR/matches_reduce_branches.rs:41:51: 41:52 +- _1 = const false; // scope 0 at $DIR/matches_reduce_branches.rs:49:14: 49:19 +- goto -> bb3; // scope 0 at $DIR/matches_reduce_branches.rs:49:14: 49:19 - } - - bb3: { -+ StorageLive(_5); // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28 -+ _5 = move _4; // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28 -+ _3 = Ne(_5, const false); // scope 0 at $DIR/matches_reduce_branches.rs:41:45: 41:50 -+ StorageDead(_5); // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28 - StorageDead(_4); // scope 0 at $DIR/matches_reduce_branches.rs:41:51: 41:52 -- switchInt(move _3) -> [false: bb5, otherwise: bb4]; // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52 -- } -- -- bb4: { -- _2 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:41:55: 41:59 -- goto -> bb6; // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76 -- } -- -- bb5: { -- _2 = const false; // scope 0 at $DIR/matches_reduce_branches.rs:41:69: 41:74 -- goto -> bb6; // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76 -- } -- -- bb6: { -+ StorageLive(_6); // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52 -+ _6 = move _3; // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52 -+ _2 = Ne(_6, const false); // scope 0 at $DIR/matches_reduce_branches.rs:41:69: 41:74 -+ StorageDead(_6); // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52 - StorageDead(_3); // scope 0 at $DIR/matches_reduce_branches.rs:41:75: 41:76 -- switchInt(move _2) -> [false: bb8, otherwise: bb7]; // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76 -- } -- -- bb7: { -+ StorageLive(_7); // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76 -+ _7 = move _2; // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76 - StorageDead(_2); // scope 0 at $DIR/matches_reduce_branches.rs:45:9: 45:10 -- _1 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:47:13: 47:17 -- goto -> bb9; // scope 0 at $DIR/matches_reduce_branches.rs:47:13: 47:17 -- } -- -- bb8: { -- StorageDead(_2); // scope 0 at $DIR/matches_reduce_branches.rs:45:9: 45:10 -- _1 = const false; // scope 0 at $DIR/matches_reduce_branches.rs:49:14: 49:19 -- goto -> bb9; // scope 0 at $DIR/matches_reduce_branches.rs:49:14: 49:19 -- } -- -- bb9: { -+ _1 = Ne(_7, const false); // scope 0 at $DIR/matches_reduce_branches.rs:49:14: 49:19 -+ StorageDead(_7); // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76 ++ _1 = Ne(_3, const false); // scope 0 at $DIR/matches_reduce_branches.rs:49:14: 49:19 ++ StorageDead(_3); // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28 _0 = _1; // scope 1 at $DIR/matches_reduce_branches.rs:51:5: 51:8 StorageDead(_1); // scope 0 at $DIR/matches_reduce_branches.rs:52:1: 52:2 return; // scope 0 at $DIR/matches_reduce_branches.rs:52:2: 52:2
diff --git a/src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.64bit.diff b/src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.64bit.diff index 0511b59..2dfb2e1 100644 --- a/src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.64bit.diff +++ b/src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.64bit.diff
@@ -4,80 +4,36 @@ fn match_nested_if() -> bool { let mut _0: bool; // return place in scope 0 at $DIR/matches_reduce_branches.rs:39:25: 39:29 let _1: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:40:9: 40:12 - let mut _2: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76 - let mut _3: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52 - let mut _4: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28 -+ let mut _5: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28 -+ let mut _6: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52 -+ let mut _7: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76 + let mut _2: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28 ++ let mut _3: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28 scope 1 { debug val => _1; // in scope 1 at $DIR/matches_reduce_branches.rs:40:9: 40:12 } bb0: { StorageLive(_1); // scope 0 at $DIR/matches_reduce_branches.rs:40:9: 40:12 - StorageLive(_2); // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76 - StorageLive(_3); // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52 - StorageLive(_4); // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28 - _4 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28 -- switchInt(move _4) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28 + StorageLive(_2); // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28 + _2 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28 +- switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28 - } - - bb1: { -- _3 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:41:31: 41:35 -- goto -> bb3; // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52 ++ StorageLive(_3); // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28 ++ _3 = move _2; // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28 + StorageDead(_2); // scope 0 at $DIR/matches_reduce_branches.rs:41:51: 41:52 +- _1 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:47:13: 47:17 +- goto -> bb3; // scope 0 at $DIR/matches_reduce_branches.rs:47:13: 47:17 - } - - bb2: { -- _3 = const false; // scope 0 at $DIR/matches_reduce_branches.rs:41:45: 41:50 -- goto -> bb3; // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52 +- StorageDead(_2); // scope 0 at $DIR/matches_reduce_branches.rs:41:51: 41:52 +- _1 = const false; // scope 0 at $DIR/matches_reduce_branches.rs:49:14: 49:19 +- goto -> bb3; // scope 0 at $DIR/matches_reduce_branches.rs:49:14: 49:19 - } - - bb3: { -+ StorageLive(_5); // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28 -+ _5 = move _4; // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28 -+ _3 = Ne(_5, const false); // scope 0 at $DIR/matches_reduce_branches.rs:41:45: 41:50 -+ StorageDead(_5); // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28 - StorageDead(_4); // scope 0 at $DIR/matches_reduce_branches.rs:41:51: 41:52 -- switchInt(move _3) -> [false: bb5, otherwise: bb4]; // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52 -- } -- -- bb4: { -- _2 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:41:55: 41:59 -- goto -> bb6; // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76 -- } -- -- bb5: { -- _2 = const false; // scope 0 at $DIR/matches_reduce_branches.rs:41:69: 41:74 -- goto -> bb6; // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76 -- } -- -- bb6: { -+ StorageLive(_6); // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52 -+ _6 = move _3; // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52 -+ _2 = Ne(_6, const false); // scope 0 at $DIR/matches_reduce_branches.rs:41:69: 41:74 -+ StorageDead(_6); // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52 - StorageDead(_3); // scope 0 at $DIR/matches_reduce_branches.rs:41:75: 41:76 -- switchInt(move _2) -> [false: bb8, otherwise: bb7]; // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76 -- } -- -- bb7: { -+ StorageLive(_7); // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76 -+ _7 = move _2; // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76 - StorageDead(_2); // scope 0 at $DIR/matches_reduce_branches.rs:45:9: 45:10 -- _1 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:47:13: 47:17 -- goto -> bb9; // scope 0 at $DIR/matches_reduce_branches.rs:47:13: 47:17 -- } -- -- bb8: { -- StorageDead(_2); // scope 0 at $DIR/matches_reduce_branches.rs:45:9: 45:10 -- _1 = const false; // scope 0 at $DIR/matches_reduce_branches.rs:49:14: 49:19 -- goto -> bb9; // scope 0 at $DIR/matches_reduce_branches.rs:49:14: 49:19 -- } -- -- bb9: { -+ _1 = Ne(_7, const false); // scope 0 at $DIR/matches_reduce_branches.rs:49:14: 49:19 -+ StorageDead(_7); // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76 ++ _1 = Ne(_3, const false); // scope 0 at $DIR/matches_reduce_branches.rs:49:14: 49:19 ++ StorageDead(_3); // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28 _0 = _1; // scope 1 at $DIR/matches_reduce_branches.rs:51:5: 51:8 StorageDead(_1); // scope 0 at $DIR/matches_reduce_branches.rs:52:1: 52:2 return; // scope 0 at $DIR/matches_reduce_branches.rs:52:2: 52:2
diff --git a/src/test/mir-opt/uninhabited_fallthrough_elimination.eliminate_fallthrough.UninhabitedEnumBranching.diff b/src/test/mir-opt/uninhabited_fallthrough_elimination.eliminate_fallthrough.UninhabitedEnumBranching.diff index 7e843b6..868eeb6 100644 --- a/src/test/mir-opt/uninhabited_fallthrough_elimination.eliminate_fallthrough.UninhabitedEnumBranching.diff +++ b/src/test/mir-opt/uninhabited_fallthrough_elimination.eliminate_fallthrough.UninhabitedEnumBranching.diff
@@ -9,7 +9,7 @@ bb0: { _2 = discriminant(_1); // scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:22:11: 22:12 - switchInt(move _2) -> [1_isize: bb3, 2_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:22:5: 22:12 -+ switchInt(move _2) -> [1_isize: bb3, 2_isize: bb2, otherwise: bb5]; // scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:22:5: 22:12 ++ switchInt(move _2) -> [1_isize: bb3, 2_isize: bb2, otherwise: bb6]; // scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:22:5: 22:12 } bb1: { @@ -29,9 +29,13 @@ bb4: { return; // scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:27:2: 27:2 + } + + bb5 (cleanup): { + resume; // scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:21:1: 27:2 + } + -+ bb5: { ++ bb6: { + unreachable; // scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:25:14: 25:15 } }
diff --git a/src/test/mir-opt/uninhabited_fallthrough_elimination.keep_fallthrough.UninhabitedEnumBranching.diff b/src/test/mir-opt/uninhabited_fallthrough_elimination.keep_fallthrough.UninhabitedEnumBranching.diff index 5da011d..33c1458 100644 --- a/src/test/mir-opt/uninhabited_fallthrough_elimination.keep_fallthrough.UninhabitedEnumBranching.diff +++ b/src/test/mir-opt/uninhabited_fallthrough_elimination.keep_fallthrough.UninhabitedEnumBranching.diff
@@ -30,5 +30,9 @@ bb4: { return; // scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:18:2: 18:2 } + + bb5 (cleanup): { + resume; // scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:12:1: 18:2 + } }
diff --git a/src/test/mir-opt/unreachable.main.UnreachablePropagation.diff b/src/test/mir-opt/unreachable.main.UnreachablePropagation.diff index 08312bd..380844f 100644 --- a/src/test/mir-opt/unreachable.main.UnreachablePropagation.diff +++ b/src/test/mir-opt/unreachable.main.UnreachablePropagation.diff
@@ -64,6 +64,10 @@ _0 = const (); // scope 0 at $DIR/unreachable.rs:19:6: 19:6 StorageDead(_1); // scope 0 at $DIR/unreachable.rs:20:1: 20:2 return; // scope 0 at $DIR/unreachable.rs:20:2: 20:2 +- } +- +- bb7 (cleanup): { +- resume; // scope 0 at $DIR/unreachable.rs:8:1: 20:2 } }
diff --git a/src/test/mir-opt/unreachable_diverging.main.UnreachablePropagation.diff b/src/test/mir-opt/unreachable_diverging.main.UnreachablePropagation.diff index e5867cc..e26990b 100644 --- a/src/test/mir-opt/unreachable_diverging.main.UnreachablePropagation.diff +++ b/src/test/mir-opt/unreachable_diverging.main.UnreachablePropagation.diff
@@ -69,6 +69,10 @@ StorageDead(_1); // scope 0 at $DIR/unreachable_diverging.rs:20:1: 20:2 StorageDead(_2); // scope 0 at $DIR/unreachable_diverging.rs:20:1: 20:2 return; // scope 0 at $DIR/unreachable_diverging.rs:20:2: 20:2 +- } +- +- bb7 (cleanup): { +- resume; // scope 0 at $DIR/unreachable_diverging.rs:12:1: 20:2 } }
diff --git a/src/test/run-make/const_fn_mir/dump.mir b/src/test/run-make/const_fn_mir/dump.mir index f02bccc..4e89369 100644 --- a/src/test/run-make/const_fn_mir/dump.mir +++ b/src/test/run-make/const_fn_mir/dump.mir
@@ -23,6 +23,10 @@ _0 = move (_1.0: i32); // scope 0 at main.rs:5:5: 5:10 return; // scope 0 at main.rs:6:2: 6:2 } + + bb2 (cleanup): { + resume; // scope 0 at main.rs:4:1: 6:2 + } } fn main() -> () {
diff --git a/src/test/run-make/translation/Makefile b/src/test/run-make/translation/Makefile new file mode 100644 index 0000000..22a3bf5 --- /dev/null +++ b/src/test/run-make/translation/Makefile
@@ -0,0 +1,33 @@ +include ../../run-make-fulldeps/tools.mk + +# This test uses `ln -s` rather than copying to save testing time, but its +# usage doesn't work on Windows. +# ignore-windows + +SYSROOT:=$(shell $(RUSTC) --print sysroot) +FAKEROOT=$(TMPDIR)/fakeroot + +all: normal custom sysroot + +normal: basic-translation.rs + $(RUSTC) $< 2>&1 | grep "struct literal body without path" + +custom: basic-translation.rs basic-translation.ftl + $(RUSTC) $< -Ztranslate-additional-ftl=$(CURDIR)/basic-translation.ftl 2>&1 | grep "this is a test message" + +# Make a local copy of the sysroot and add the custom locale to it. +sysroot: basic-translation.rs basic-translation.ftl + mkdir $(FAKEROOT) + ln -s $(SYSROOT)/* $(FAKEROOT) + rm -f $(FAKEROOT)/lib + mkdir $(FAKEROOT)/lib + ln -s $(SYSROOT)/lib/* $(FAKEROOT)/lib + rm -f $(FAKEROOT)/lib/rustlib + mkdir $(FAKEROOT)/lib/rustlib + ln -s $(SYSROOT)/lib/rustlib/* $(FAKEROOT)/lib/rustlib + rm -f $(FAKEROOT)/lib/rustlib/src + mkdir $(FAKEROOT)/lib/rustlib/src + ln -s $(SYSROOT)/lib/rustlib/src/* $(FAKEROOT)/lib/rustlib/src + mkdir -p $(FAKEROOT)/share/locale/zh-CN/ + ln -s $(CURDIR)/basic-translation.ftl $(FAKEROOT)/share/locale/zh-CN/basic-translation.ftl + $(RUSTC) $< --sysroot $(FAKEROOT) -Ztranslate-lang=zh-CN 2>&1 | grep "this is a test message"
diff --git a/src/test/run-make/translation/basic-translation.ftl b/src/test/run-make/translation/basic-translation.ftl new file mode 100644 index 0000000..4681b87 --- /dev/null +++ b/src/test/run-make/translation/basic-translation.ftl
@@ -0,0 +1,2 @@ +parser-struct-literal-body-without-path = this is a test message + .suggestion = this is a test suggestion
diff --git a/src/test/run-make/translation/basic-translation.rs b/src/test/run-make/translation/basic-translation.rs new file mode 100644 index 0000000..b8f5bff --- /dev/null +++ b/src/test/run-make/translation/basic-translation.rs
@@ -0,0 +1,18 @@ +// Exact error being tested isn't relevant, it just needs to be known that it uses Fluent-backed +// diagnostics. + +struct Foo { + val: (), +} + +fn foo() -> Foo { + val: (), +} + +fn main() { + let x = foo(); + x.val == 42; + let x = { + val: (), + }; +}
diff --git a/src/test/rustdoc-gui/item-info-overflow.goml b/src/test/rustdoc-gui/item-info-overflow.goml new file mode 100644 index 0000000..4ff719b --- /dev/null +++ b/src/test/rustdoc-gui/item-info-overflow.goml
@@ -0,0 +1,28 @@ +// This test ensures that the "item-info" elements don't overflow. +goto: file://|DOC_PATH|/lib2/struct.LongItemInfo.html +// We set a fixed size so there is no chance of "random" resize. +size: (1200, 870) +// Logically, the "item-decl" and the "item-info" should have the same scroll width. +compare-elements-property: (".docblock.item-decl", ".item-info", ["scrollWidth"]) +assert-property: (".item-info", {"scrollWidth": "890"}) +// Just to be sure we're comparing the correct "item-info": +assert-text: ( + ".item-info", + "This is supported on Android or Linux or Emscripten or DragonFly BSD", + STARTS_WITH, +) + +// Checking the "item-info" on an impl block as well: +goto: file://|DOC_PATH|/lib2/struct.LongItemInfo2.html +compare-elements-property: ( + "#impl-SimpleTrait .item-info", + "#impl-SimpleTrait + .docblock", + ["scrollWidth"], +) +assert-property: ("#impl-SimpleTrait .item-info", {"scrollWidth": "866"}) +// Just to be sure we're comparing the correct "item-info": +assert-text: ( + "#impl-SimpleTrait .item-info", + "This is supported on Android or Linux or Emscripten or DragonFly BSD", + STARTS_WITH, +)
diff --git a/src/test/rustdoc-gui/src/lib2/lib.rs b/src/test/rustdoc-gui/src/lib2/lib.rs index 5b6d236..83e86c4 100644 --- a/src/test/rustdoc-gui/src/lib2/lib.rs +++ b/src/test/rustdoc-gui/src/lib2/lib.rs
@@ -120,3 +120,13 @@ pub struct HasALongTraitWithParams {} pub trait LongTraitWithParamsBananaBananaBanana<T> {} impl LongTraitWithParamsBananaBananaBanana<usize> for HasALongTraitWithParams {} + +#[doc(cfg(any(target_os = "android", target_os = "linux", target_os = "emscripten", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd")))] +pub struct LongItemInfo; + +pub trait SimpleTrait {} +pub struct LongItemInfo2; + +/// Some docs. +#[doc(cfg(any(target_os = "android", target_os = "linux", target_os = "emscripten", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd")))] +impl SimpleTrait for LongItemInfo2 {}
diff --git a/src/test/rustdoc-ui/intra-doc/assoc-mod-inner-outer.rs b/src/test/rustdoc-ui/intra-doc/assoc-mod-inner-outer.rs new file mode 100644 index 0000000..b4ce344 --- /dev/null +++ b/src/test/rustdoc-ui/intra-doc/assoc-mod-inner-outer.rs
@@ -0,0 +1,19 @@ +// Traits in scope are collected for doc links in both outer and inner module attributes. + +// check-pass +// aux-build: assoc-mod-inner-outer-dep.rs + +extern crate assoc_mod_inner_outer_dep; +pub use assoc_mod_inner_outer_dep::*; + +#[derive(Clone)] +pub struct Struct; + +pub mod outer1 { + /// [crate::Struct::clone] + pub mod inner {} +} + +pub mod outer2 { + //! [crate::Struct::clone] +}
diff --git a/src/test/rustdoc-ui/intra-doc/auxiliary/assoc-mod-inner-outer-dep.rs b/src/test/rustdoc-ui/intra-doc/auxiliary/assoc-mod-inner-outer-dep.rs new file mode 100644 index 0000000..7a11a16 --- /dev/null +++ b/src/test/rustdoc-ui/intra-doc/auxiliary/assoc-mod-inner-outer-dep.rs
@@ -0,0 +1,11 @@ +#[derive(Clone)] +pub struct Struct; + +pub mod dep_outer1 { + /// [crate::Struct::clone] + pub mod inner {} +} + +pub mod dep_outer2 { + //! [crate::Struct::clone] +}
diff --git a/src/test/rustdoc-ui/intra-doc/crate-nonexistent.rs b/src/test/rustdoc-ui/intra-doc/crate-nonexistent.rs new file mode 100644 index 0000000..ceecfa6 --- /dev/null +++ b/src/test/rustdoc-ui/intra-doc/crate-nonexistent.rs
@@ -0,0 +1,5 @@ +#![deny(rustdoc::broken_intra_doc_links)] + +/// [crate::DoesNotExist] +//~^ ERROR unresolved link to `crate::DoesNotExist` +pub struct Item;
diff --git a/src/test/rustdoc-ui/intra-doc/crate-nonexistent.stderr b/src/test/rustdoc-ui/intra-doc/crate-nonexistent.stderr new file mode 100644 index 0000000..a69b1c5 --- /dev/null +++ b/src/test/rustdoc-ui/intra-doc/crate-nonexistent.stderr
@@ -0,0 +1,14 @@ +error: unresolved link to `crate::DoesNotExist` + --> $DIR/crate-nonexistent.rs:3:6 + | +LL | /// [crate::DoesNotExist] + | ^^^^^^^^^^^^^^^^^^^ no item named `DoesNotExist` in module `crate_nonexistent` + | +note: the lint level is defined here + --> $DIR/crate-nonexistent.rs:1:9 + | +LL | #![deny(rustdoc::broken_intra_doc_links)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error +
diff --git a/src/test/rustdoc-ui/intra-doc/global-path.rs b/src/test/rustdoc-ui/intra-doc/global-path.rs new file mode 100644 index 0000000..cc7a5fa --- /dev/null +++ b/src/test/rustdoc-ui/intra-doc/global-path.rs
@@ -0,0 +1,8 @@ +// Doc link path with empty prefix that resolves to "extern prelude" instead of a module. + +// check-pass +// edition:2018 + +/// [::Unresolved] +//~^ WARN unresolved link to `::Unresolved` +pub struct Item;
diff --git a/src/test/rustdoc-ui/intra-doc/global-path.stderr b/src/test/rustdoc-ui/intra-doc/global-path.stderr new file mode 100644 index 0000000..02379cd --- /dev/null +++ b/src/test/rustdoc-ui/intra-doc/global-path.stderr
@@ -0,0 +1,10 @@ +warning: unresolved link to `::Unresolved` + --> $DIR/global-path.rs:6:6 + | +LL | /// [::Unresolved] + | ^^^^^^^^^^^^ no item named `` in scope + | + = note: `#[warn(rustdoc::broken_intra_doc_links)]` on by default + +warning: 1 warning emitted +
diff --git a/src/test/rustdoc/intra-doc/crate-relative-assoc.rs b/src/test/rustdoc/intra-doc/crate-relative-assoc.rs new file mode 100644 index 0000000..d4a0ecc --- /dev/null +++ b/src/test/rustdoc/intra-doc/crate-relative-assoc.rs
@@ -0,0 +1,17 @@ +pub mod io { + pub trait Read { + fn read(&mut self); + } +} + +pub mod bufreader { + // @has crate_relative_assoc/bufreader/index.html '//a/@href' 'struct.TcpStream.html#method.read' + //! [`crate::TcpStream::read`] + use crate::io::Read; +} + +pub struct TcpStream; + +impl crate::io::Read for TcpStream { + fn read(&mut self) {} +}
diff --git a/src/test/rustdoc/issue-95633.rs b/src/test/rustdoc/issue-95633.rs new file mode 100644 index 0000000..a71d0a0 --- /dev/null +++ b/src/test/rustdoc/issue-95633.rs
@@ -0,0 +1,7 @@ +// compile-flags: --document-private-items + +// This ensures that no ICE is triggered when rustdoc is run on this code. + +mod stdlib { + pub (crate) use std::i8; +}
diff --git a/src/test/rustdoc/rfc-2632-const-trait-impl.rs b/src/test/rustdoc/rfc-2632-const-trait-impl.rs index 2adf69f..c5353c4 100644 --- a/src/test/rustdoc/rfc-2632-const-trait-impl.rs +++ b/src/test/rustdoc/rfc-2632-const-trait-impl.rs
@@ -11,50 +11,40 @@ pub struct S<T>(T); // @!has foo/trait.Tr.html '//pre[@class="rust trait"]/code/a[@class="trait"]' '~const' -// @!has - '//pre[@class="rust trait"]/code/a[@class="trait"]' 'Drop' // @has - '//pre[@class="rust trait"]/code/a[@class="trait"]' 'Clone' // @!has - '//pre[@class="rust trait"]/code/span[@class="where"]' '~const' -// @!has - '//pre[@class="rust trait"]/code/span[@class="where"]' 'Drop' // @has - '//pre[@class="rust trait"]/code/span[@class="where"]' ': Clone' pub trait Tr<T> { // @!has - '//div[@id="method.a"]/h4[@class="code-header"]' '~const' - // @!has - '//div[@id="method.a"]/h4[@class="code-header"]/a[@class="trait"]' 'Drop' // @has - '//div[@id="method.a"]/h4[@class="code-header"]/a[@class="trait"]' 'Clone' // @!has - '//div[@id="method.a"]/h4[@class="code-header"]/span[@class="where"]' '~const' - // @!has - '//div[@id="method.a"]/h4[@class="code-header"]/span[@class="where fmt-newline"]' 'Drop' // @has - '//div[@id="method.a"]/h4[@class="code-header"]/span[@class="where fmt-newline"]' ': Clone' #[default_method_body_is_const] - fn a<A: ~const Drop + ~const Clone>() where Option<A>: ~const Drop + ~const Clone {} + fn a<A: ~const Clone>() where Option<A>: ~const Clone {} } // @!has - '//section[@id="impl-Tr%3CT%3E"]/h3[@class="code-header in-band"]' '~const' -// @!has - '//section[@id="impl-Tr%3CT%3E"]/h3[@class="code-header in-band"]/a[@class="trait"]' 'Drop' // @has - '//section[@id="impl-Tr%3CT%3E"]/h3[@class="code-header in-band"]/a[@class="trait"]' 'Clone' // @!has - '//section[@id="impl-Tr%3CT%3E"]/h3[@class="code-header in-band"]/span[@class="where"]' '~const' -// @!has - '//section[@id="impl-Tr%3CT%3E"]/h3[@class="code-header in-band"]/span[@class="where fmt-newline"]' 'Drop' // @has - '//section[@id="impl-Tr%3CT%3E"]/h3[@class="code-header in-band"]/span[@class="where fmt-newline"]' ': Clone' -impl<T: ~const Drop + ~const Clone> const Tr<T> for T where Option<T>: ~const Drop + ~const Clone { - fn a<A: ~const Drop + ~const Clone>() where Option<A>: ~const Drop + ~const Clone {} +impl<T: ~const Clone> const Tr<T> for T where Option<T>: ~const Clone { + fn a<A: ~const Clone>() where Option<A>: ~const Clone {} } // @!has foo/fn.foo.html '//pre[@class="rust fn"]/code/a[@class="trait"]' '~const' -// @!has - '//pre[@class="rust fn"]/code/a[@class="trait"]' 'Drop' // @has - '//pre[@class="rust fn"]/code/a[@class="trait"]' 'Clone' // @!has - '//pre[@class="rust fn"]/code/span[@class="where fmt-newline"]' '~const' -// @!has - '//pre[@class="rust fn"]/code/span[@class="where fmt-newline"]' 'Drop' // @has - '//pre[@class="rust fn"]/code/span[@class="where fmt-newline"]' ': Clone' -pub const fn foo<F: ~const Drop + ~const Clone>() where Option<F>: ~const Drop + ~const Clone { +pub const fn foo<F: ~const Clone>() where Option<F>: ~const Clone { F::a() } impl<T> S<T> { // @!has foo/struct.S.html '//section[@id="method.foo"]/h4[@class="code-header"]' '~const' - // @!has - '//section[@id="method.foo"]/h4[@class="code-header"]/a[@class="trait"]' 'Drop' // @has - '//section[@id="method.foo"]/h4[@class="code-header"]/a[@class="trait"]' 'Clone' // @!has - '//section[@id="method.foo"]/h4[@class="code-header"]/span[@class="where"]' '~const' - // @!has - '//section[@id="method.foo"]/h4[@class="code-header"]/span[@class="where fmt-newline"]' 'Drop' // @has - '//section[@id="method.foo"]/h4[@class="code-header"]/span[@class="where fmt-newline"]' ': Clone' - pub const fn foo<B: ~const Drop + ~const Clone>() where B: ~const Drop + ~const Clone { + pub const fn foo<B: ~const Clone>() where B: ~const Clone { B::a() } }
diff --git a/src/test/rustdoc/stability.rs b/src/test/rustdoc/stability.rs index 4ff06d9..90be205 100644 --- a/src/test/rustdoc/stability.rs +++ b/src/test/rustdoc/stability.rs
@@ -4,7 +4,7 @@ pub struct Unstable { // @has stability/struct.Unstable.html \ - // '//div[@class="item-info"]//div[@class="stab unstable"]' \ + // '//span[@class="item-info"]//div[@class="stab unstable"]' \ // 'This is a nightly-only experimental API' // @count stability/struct.Unstable.html '//span[@class="stab unstable"]' 0 pub foo: u32,
diff --git a/src/test/ui-fulldeps/session-derive-errors.rs b/src/test/ui-fulldeps/session-derive-errors.rs index 140aaad..adec548 100644 --- a/src/test/ui-fulldeps/session-derive-errors.rs +++ b/src/test/ui-fulldeps/session-derive-errors.rs
@@ -11,8 +11,8 @@ #![crate_type = "lib"] extern crate rustc_span; -use rustc_span::Span; use rustc_span::symbol::Ident; +use rustc_span::Span; extern crate rustc_macros; use rustc_macros::SessionDiagnostic; @@ -26,12 +26,15 @@ extern crate rustc_session; #[derive(SessionDiagnostic)] -#[message = "Hello, world!"] -#[error = "E0123"] +#[error(code = "E0123", slug = "hello-world")] struct Hello {} #[derive(SessionDiagnostic)] -#[error = "E0123"] +#[warning(code = "E0123", slug = "hello-world")] +struct HelloWarn {} + +#[derive(SessionDiagnostic)] +#[error(code = "E0123", slug = "foo")] //~^ ERROR `#[derive(SessionDiagnostic)]` can only be used on structs enum SessionDiagnosticOnEnum { Foo, @@ -39,228 +42,387 @@ enum SessionDiagnosticOnEnum { } #[derive(SessionDiagnostic)] +#[error(code = "E0123", slug = "foo")] #[error = "E0123"] -#[label = "This is in the wrong place"] -//~^ ERROR `#[label = ...]` is not a valid SessionDiagnostic struct attribute -struct WrongPlace {} +//~^ ERROR `#[error = ...]` is not a valid `SessionDiagnostic` struct attribute +struct WrongStructAttrStyle {} #[derive(SessionDiagnostic)] -#[error = "E0123"] +#[nonsense(code = "E0123", slug = "foo")] +//~^ ERROR `#[nonsense(...)]` is not a valid `SessionDiagnostic` struct attribute +//~^^ ERROR diagnostic kind not specified +//~^^^ ERROR cannot find attribute `nonsense` in this scope +struct InvalidStructAttr {} + +#[derive(SessionDiagnostic)] +#[error("E0123")] +//~^ ERROR `#[error("...")]` is not a valid `SessionDiagnostic` struct attribute +//~^^ ERROR `slug` not specified +struct InvalidLitNestedAttr {} + +#[derive(SessionDiagnostic)] +#[error(nonsense, code = "E0123", slug = "foo")] +//~^ ERROR `#[error(nonsense)]` is not a valid `SessionDiagnostic` struct attribute +struct InvalidNestedStructAttr {} + +#[derive(SessionDiagnostic)] +#[error(nonsense("foo"), code = "E0123", slug = "foo")] +//~^ ERROR `#[error(nonsense(...))]` is not a valid `SessionDiagnostic` struct attribute +struct InvalidNestedStructAttr1 {} + +#[derive(SessionDiagnostic)] +#[error(nonsense = "...", code = "E0123", slug = "foo")] +//~^ ERROR `#[error(nonsense = ...)]` is not a valid `SessionDiagnostic` struct attribute +struct InvalidNestedStructAttr2 {} + +#[derive(SessionDiagnostic)] +#[error(nonsense = 4, code = "E0123", slug = "foo")] +//~^ ERROR `#[error(nonsense = ...)]` is not a valid `SessionDiagnostic` struct attribute +struct InvalidNestedStructAttr3 {} + +#[derive(SessionDiagnostic)] +#[error(code = "E0123", slug = "foo")] struct WrongPlaceField { - #[suggestion = "this is the wrong kind of attribute"] -//~^ ERROR `#[suggestion = ...]` is not a valid SessionDiagnostic field attribute + #[suggestion = "bar"] + //~^ ERROR `#[suggestion = ...]` is not a valid `SessionDiagnostic` field attribute sp: Span, } #[derive(SessionDiagnostic)] -#[message = "Hello, world!"] -#[error = "E0123"] -#[error = "E0456"] //~ ERROR `error` specified multiple times +#[error(code = "E0123", slug = "foo")] +#[error(code = "E0456", slug = "bar")] //~ ERROR `error` specified multiple times struct ErrorSpecifiedTwice {} #[derive(SessionDiagnostic)] -#[message = "Hello, world!"] -#[error = "E0123"] -#[lint = "some_useful_lint"] //~ ERROR `lint` specified when `error` was already specified -struct LintSpecifiedAfterError {} +#[error(code = "E0123", slug = "foo")] +#[warning(code = "E0293", slug = "bar")] +//~^ ERROR `warning` specified when `error` was already specified +struct WarnSpecifiedAfterError {} #[derive(SessionDiagnostic)] -#[message = "Some lint message"] -#[error = "E0123"] -struct LintButHasErrorCode {} +#[error(code = "E0456", code = "E0457", slug = "bar")] //~ ERROR `code` specified multiple times +struct CodeSpecifiedTwice {} #[derive(SessionDiagnostic)] -struct ErrorCodeNotProvided {} //~ ERROR `code` not specified - -// FIXME: Uncomment when emitting lints is supported. -/* -#[derive(SessionDiagnostic)] -#[message = "Hello, world!"] -#[lint = "clashing_extern_declarations"] -#[lint = "improper_ctypes"] // FIXME: ERROR `lint` specified multiple times -struct LintSpecifiedTwice {} +#[error(code = "E0456", slug = "foo", slug = "bar")] //~ ERROR `slug` specified multiple times +struct SlugSpecifiedTwice {} #[derive(SessionDiagnostic)] -#[lint = "Some lint message"] -#[message = "Some error message"] -#[error = "E0123"] // ERROR `error` specified when `lint` was already specified -struct ErrorSpecifiedAfterLint {} -*/ +struct KindNotProvided {} //~ ERROR diagnostic kind not specified #[derive(SessionDiagnostic)] -#[error = "E0123"] +#[error(code = "E0456")] //~ ERROR `slug` not specified +struct SlugNotProvided {} + +#[derive(SessionDiagnostic)] +#[error(slug = "foo")] +struct CodeNotProvided {} + +#[derive(SessionDiagnostic)] +#[error(code = "E0123", slug = "foo")] +struct MessageWrongType { + #[primary_span] + //~^ ERROR `#[primary_span]` attribute can only be applied to fields of type `Span` + foo: String, +} + +#[derive(SessionDiagnostic)] +#[error(code = "E0123", slug = "foo")] +struct InvalidPathFieldAttr { + #[nonsense] + //~^ ERROR `#[nonsense]` is not a valid `SessionDiagnostic` field attribute + //~^^ ERROR cannot find attribute `nonsense` in this scope + foo: String, +} + +#[derive(SessionDiagnostic)] +#[error(code = "E0123", slug = "foo")] struct ErrorWithField { name: String, - #[message = "This error has a field, and references {name}"] - span: Span + #[label = "bar"] + span: Span, } #[derive(SessionDiagnostic)] -#[error = "E0123"] +#[error(code = "E0123", slug = "foo")] struct ErrorWithMessageAppliedToField { - #[message = "this message is applied to a String field"] - //~^ ERROR the `#[message = "..."]` attribute can only be applied to fields of type Span + #[label = "bar"] + //~^ ERROR the `#[label = ...]` attribute can only be applied to fields of type `Span` name: String, } #[derive(SessionDiagnostic)] -#[error = "E0123"] -#[message = "This error has a field, and references {name}"] -//~^ ERROR `name` doesn't refer to a field on this type +#[error(code = "E0123", slug = "foo")] struct ErrorWithNonexistentField { - span: Span + #[suggestion(message = "bar", code = "{name}")] + //~^ ERROR `name` doesn't refer to a field on this type + suggestion: (Span, Applicability), } #[derive(SessionDiagnostic)] -#[error = "E0123"] -#[message = "This is missing a closing brace: {name"] //~^ ERROR invalid format string: expected `'}'` +#[error(code = "E0123", slug = "foo")] struct ErrorMissingClosingBrace { + #[suggestion(message = "bar", code = "{name")] + suggestion: (Span, Applicability), name: String, - span: Span + val: usize, } #[derive(SessionDiagnostic)] -#[error = "E0123"] -#[message = "This is missing an opening brace: name}"] //~^ ERROR invalid format string: unmatched `}` +#[error(code = "E0123", slug = "foo")] struct ErrorMissingOpeningBrace { + #[suggestion(message = "bar", code = "name}")] + suggestion: (Span, Applicability), name: String, - span: Span + val: usize, } #[derive(SessionDiagnostic)] -#[error = "E0123"] -#[message = "Something something"] +#[error(code = "E0123", slug = "foo")] struct LabelOnSpan { - #[label = "See here"] - sp: Span + #[label = "bar"] + sp: Span, } #[derive(SessionDiagnostic)] -#[error = "E0123"] -#[message = "Something something"] +#[error(code = "E0123", slug = "foo")] struct LabelOnNonSpan { - #[label = "See here"] - //~^ ERROR The `#[label = ...]` attribute can only be applied to fields of type Span + #[label = "bar"] + //~^ ERROR the `#[label = ...]` attribute can only be applied to fields of type `Span` id: u32, } #[derive(SessionDiagnostic)] -#[error = "E0123"] +#[error(code = "E0123", slug = "foo")] struct Suggest { - #[suggestion(message = "This is a suggestion", code = "This is the suggested code")] - #[suggestion_short(message = "This is a suggestion", code = "This is the suggested code")] - #[suggestion_hidden(message = "This is a suggestion", code = "This is the suggested code")] - #[suggestion_verbose(message = "This is a suggestion", code = "This is the suggested code")] + #[suggestion(message = "bar", code = "This is the suggested code")] + #[suggestion_short(message = "qux", code = "This is the suggested code")] + #[suggestion_hidden(message = "foobar", code = "This is the suggested code")] + #[suggestion_verbose(message = "fooqux", code = "This is the suggested code")] suggestion: (Span, Applicability), } #[derive(SessionDiagnostic)] -#[error = "E0123"] +#[error(code = "E0123", slug = "foo")] struct SuggestWithoutCode { - #[suggestion(message = "This is a suggestion")] + #[suggestion(message = "bar")] suggestion: (Span, Applicability), } #[derive(SessionDiagnostic)] -#[error = "E0123"] +#[error(code = "E0123", slug = "foo")] struct SuggestWithBadKey { - #[suggestion(nonsense = "This is nonsense")] - //~^ ERROR `nonsense` is not a valid key for `#[suggestion(...)]` + #[suggestion(nonsense = "bar")] + //~^ ERROR `#[suggestion(nonsense = ...)]` is not a valid `SessionDiagnostic` field attribute suggestion: (Span, Applicability), } #[derive(SessionDiagnostic)] -#[error = "E0123"] +#[error(code = "E0123", slug = "foo")] struct SuggestWithShorthandMsg { - #[suggestion(msg = "This is a suggestion")] - //~^ ERROR `msg` is not a valid key for `#[suggestion(...)]` + #[suggestion(msg = "bar")] + //~^ ERROR `#[suggestion(msg = ...)]` is not a valid `SessionDiagnostic` field attribute suggestion: (Span, Applicability), } #[derive(SessionDiagnostic)] -#[error = "E0123"] +#[error(code = "E0123", slug = "foo")] struct SuggestWithoutMsg { - #[suggestion(code = "This is suggested code")] - //~^ ERROR missing suggestion message + #[suggestion(code = "bar")] suggestion: (Span, Applicability), } #[derive(SessionDiagnostic)] -#[error = "E0123"] +#[error(code = "E0123", slug = "foo")] struct SuggestWithTypesSwapped { - #[suggestion(message = "This is a message", code = "This is suggested code")] + #[suggestion(message = "bar", code = "This is suggested code")] suggestion: (Applicability, Span), } #[derive(SessionDiagnostic)] -#[error = "E0123"] +#[error(code = "E0123", slug = "foo")] struct SuggestWithWrongTypeApplicabilityOnly { - #[suggestion(message = "This is a message", code = "This is suggested code")] + #[suggestion(message = "bar", code = "This is suggested code")] //~^ ERROR wrong field type for suggestion suggestion: Applicability, } #[derive(SessionDiagnostic)] -#[error = "E0123"] -struct SuggestWithSpanOnly{ - #[suggestion(message = "This is a message", code = "This is suggested code")] +#[error(code = "E0123", slug = "foo")] +struct SuggestWithSpanOnly { + #[suggestion(message = "bar", code = "This is suggested code")] suggestion: Span, } #[derive(SessionDiagnostic)] -#[error = "E0123"] +#[error(code = "E0123", slug = "foo")] struct SuggestWithDuplicateSpanAndApplicability { - #[suggestion(message = "This is a message", code = "This is suggested code")] - //~^ ERROR type of field annotated with `#[suggestion(...)]` contains more than one Span + #[suggestion(message = "bar", code = "This is suggested code")] + //~^ ERROR type of field annotated with `#[suggestion(...)]` contains more than one `Span` suggestion: (Span, Span, Applicability), } #[derive(SessionDiagnostic)] -#[error = "E0123"] +#[error(code = "E0123", slug = "foo")] struct SuggestWithDuplicateApplicabilityAndSpan { - #[suggestion(message = "This is a message", code = "This is suggested code")] + #[suggestion(message = "bar", code = "This is suggested code")] //~^ ERROR type of field annotated with `#[suggestion(...)]` contains more than one suggestion: (Applicability, Applicability, Span), } #[derive(SessionDiagnostic)] -#[error = "E0123"] +#[error(code = "E0123", slug = "foo")] struct WrongKindOfAnnotation { - #[label("wrong kind of annotation for label")] - //~^ ERROR invalid annotation list `#[label(...)]` + #[label("bar")] + //~^ ERROR `#[label(...)]` is not a valid `SessionDiagnostic` field attribute z: Span, } #[derive(SessionDiagnostic)] -#[error = "E0123"] -#[message = "Something something else"] +#[error(code = "E0123", slug = "foo")] struct OptionsInErrors { - #[label = "Label message"] + #[label = "bar"] label: Option<Span>, - #[suggestion(message = "suggestion message")] + #[suggestion(message = "bar")] opt_sugg: Option<(Span, Applicability)>, } #[derive(SessionDiagnostic)] -#[error = "E0456"] +#[error(code = "E0456", slug = "foo")] struct MoveOutOfBorrowError<'tcx> { name: Ident, ty: Ty<'tcx>, - #[message = "cannot move {ty} out of borrow"] - #[label = "cannot move out of borrow"] + #[primary_span] + #[label = "bar"] span: Span, - #[label = "`{ty}` first borrowed here"] + #[label = "qux"] other_span: Span, - #[suggestion(message = "consider cloning here", code = "{name}.clone()")] + #[suggestion(message = "bar", code = "{name}.clone()")] opt_sugg: Option<(Span, Applicability)>, } #[derive(SessionDiagnostic)] -#[error = "E0123"] +#[error(code = "E0123", slug = "foo")] struct ErrorWithLifetime<'a> { - #[message = "Some message that references {name}"] + #[label = "bar"] span: Span, name: &'a str, } + +#[derive(SessionDiagnostic)] +#[error(code = "E0123", slug = "foo")] +struct ErrorWithDefaultLabelAttr<'a> { + #[label] + span: Span, + name: &'a str, +} + +#[derive(SessionDiagnostic)] +//~^ ERROR no method named `into_diagnostic_arg` found for struct `Hello` in the current scope +#[error(code = "E0123", slug = "foo")] +struct ArgFieldWithoutSkip { + #[primary_span] + span: Span, + other: Hello, +} + +#[derive(SessionDiagnostic)] +#[error(code = "E0123", slug = "foo")] +struct ArgFieldWithSkip { + #[primary_span] + span: Span, + // `Hello` does not implement `IntoDiagnosticArg` so this would result in an error if + // not for `#[skip_arg]`. + #[skip_arg] + other: Hello, +} + +#[derive(SessionDiagnostic)] +#[error(code = "E0123", slug = "foo")] +struct ErrorWithSpannedNote { + #[note] + span: Span, +} + +#[derive(SessionDiagnostic)] +#[error(code = "E0123", slug = "foo")] +struct ErrorWithSpannedNoteCustom { + #[note = "bar"] + span: Span, +} + +#[derive(SessionDiagnostic)] +#[error(code = "E0123", slug = "foo")] +#[note] +struct ErrorWithNote { + val: String, +} + +#[derive(SessionDiagnostic)] +#[error(code = "E0123", slug = "foo")] +#[note = "bar"] +struct ErrorWithNoteCustom { + val: String, +} + +#[derive(SessionDiagnostic)] +#[error(code = "E0123", slug = "foo")] +struct ErrorWithSpannedHelp { + #[help] + span: Span, +} + +#[derive(SessionDiagnostic)] +#[error(code = "E0123", slug = "foo")] +struct ErrorWithSpannedHelpCustom { + #[help = "bar"] + span: Span, +} + +#[derive(SessionDiagnostic)] +#[error(code = "E0123", slug = "foo")] +#[help] +struct ErrorWithHelp { + val: String, +} + +#[derive(SessionDiagnostic)] +#[error(code = "E0123", slug = "foo")] +#[help = "bar"] +struct ErrorWithHelpCustom { + val: String, +} + +#[derive(SessionDiagnostic)] +#[help] +//~^ ERROR `#[help]` must come after `#[error(..)]` or `#[warn(..)]` +#[error(code = "E0123", slug = "foo")] +struct ErrorWithHelpWrongOrder { + val: String, +} + +#[derive(SessionDiagnostic)] +#[help = "bar"] +//~^ ERROR `#[help = ...]` must come after `#[error(..)]` or `#[warn(..)]` +#[error(code = "E0123", slug = "foo")] +struct ErrorWithHelpCustomWrongOrder { + val: String, +} + +#[derive(SessionDiagnostic)] +#[note] +//~^ ERROR `#[note]` must come after `#[error(..)]` or `#[warn(..)]` +#[error(code = "E0123", slug = "foo")] +struct ErrorWithNoteWrongOrder { + val: String, +} + +#[derive(SessionDiagnostic)] +#[note = "bar"] +//~^ ERROR `#[note = ...]` must come after `#[error(..)]` or `#[warn(..)]` +#[error(code = "E0123", slug = "foo")] +struct ErrorWithNoteCustomWrongOrder { + val: String, +}
diff --git a/src/test/ui-fulldeps/session-derive-errors.stderr b/src/test/ui-fulldeps/session-derive-errors.stderr index c7853f5..a528ae1 100644 --- a/src/test/ui-fulldeps/session-derive-errors.stderr +++ b/src/test/ui-fulldeps/session-derive-errors.stderr
@@ -1,7 +1,7 @@ error: `#[derive(SessionDiagnostic)]` can only be used on structs - --> $DIR/session-derive-errors.rs:34:1 + --> $DIR/session-derive-errors.rs:37:1 | -LL | / #[error = "E0123"] +LL | / #[error(code = "E0123", slug = "foo")] LL | | LL | | enum SessionDiagnosticOnEnum { LL | | Foo, @@ -9,132 +9,285 @@ LL | | } | |_^ -error: `#[label = ...]` is not a valid SessionDiagnostic struct attribute - --> $DIR/session-derive-errors.rs:43:1 +error: `#[error = ...]` is not a valid `SessionDiagnostic` struct attribute + --> $DIR/session-derive-errors.rs:46:1 | -LL | #[label = "This is in the wrong place"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[error = "E0123"] + | ^^^^^^^^^^^^^^^^^^ -error: `#[suggestion = ...]` is not a valid SessionDiagnostic field attribute - --> $DIR/session-derive-errors.rs:50:5 +error: `#[nonsense(...)]` is not a valid `SessionDiagnostic` struct attribute + --> $DIR/session-derive-errors.rs:51:1 | -LL | #[suggestion = "this is the wrong kind of attribute"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[nonsense(code = "E0123", slug = "foo")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: diagnostic kind not specified + --> $DIR/session-derive-errors.rs:51:1 + | +LL | / #[nonsense(code = "E0123", slug = "foo")] +LL | | +LL | | +LL | | +LL | | struct InvalidStructAttr {} + | |___________________________^ + | + = help: use the `#[error(...)]` attribute to create an error + +error: `#[error("...")]` is not a valid `SessionDiagnostic` struct attribute + --> $DIR/session-derive-errors.rs:58:9 + | +LL | #[error("E0123")] + | ^^^^^^^ + +error: `slug` not specified + --> $DIR/session-derive-errors.rs:58:1 + | +LL | / #[error("E0123")] +LL | | +LL | | +LL | | struct InvalidLitNestedAttr {} + | |______________________________^ + | + = help: use the `#[error(slug = "...")]` attribute to set this diagnostic's slug + +error: `#[error(nonsense)]` is not a valid `SessionDiagnostic` struct attribute + --> $DIR/session-derive-errors.rs:64:9 + | +LL | #[error(nonsense, code = "E0123", slug = "foo")] + | ^^^^^^^^ + +error: `#[error(nonsense(...))]` is not a valid `SessionDiagnostic` struct attribute + --> $DIR/session-derive-errors.rs:69:9 + | +LL | #[error(nonsense("foo"), code = "E0123", slug = "foo")] + | ^^^^^^^^^^^^^^^ + +error: `#[error(nonsense = ...)]` is not a valid `SessionDiagnostic` struct attribute + --> $DIR/session-derive-errors.rs:74:9 + | +LL | #[error(nonsense = "...", code = "E0123", slug = "foo")] + | ^^^^^^^^^^^^^^^^ + +error: `#[error(nonsense = ...)]` is not a valid `SessionDiagnostic` struct attribute + --> $DIR/session-derive-errors.rs:79:9 + | +LL | #[error(nonsense = 4, code = "E0123", slug = "foo")] + | ^^^^^^^^^^^^ + | + = help: value must be a string + +error: `#[suggestion = ...]` is not a valid `SessionDiagnostic` field attribute + --> $DIR/session-derive-errors.rs:86:5 + | +LL | #[suggestion = "bar"] + | ^^^^^^^^^^^^^^^^^^^^^ error: `error` specified multiple times - --> $DIR/session-derive-errors.rs:58:11 + --> $DIR/session-derive-errors.rs:93:1 | -LL | #[error = "E0456"] - | ^^^^^^^ +LL | #[error(code = "E0456", slug = "bar")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: previously specified here + --> $DIR/session-derive-errors.rs:92:1 + | +LL | #[error(code = "E0123", slug = "foo")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: `lint` specified when `error` was already specified - --> $DIR/session-derive-errors.rs:64:10 +error: `warning` specified when `error` was already specified + --> $DIR/session-derive-errors.rs:98:1 | -LL | #[lint = "some_useful_lint"] - | ^^^^^^^^^^^^^^^^^^ +LL | #[warning(code = "E0293", slug = "bar")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: previously specified here + --> $DIR/session-derive-errors.rs:97:1 + | +LL | #[error(code = "E0123", slug = "foo")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: `code` not specified - --> $DIR/session-derive-errors.rs:73:1 +error: `code` specified multiple times + --> $DIR/session-derive-errors.rs:103:32 | -LL | struct ErrorCodeNotProvided {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[error(code = "E0456", code = "E0457", slug = "bar")] + | ^^^^^^^ | - = help: use the [code = "..."] attribute to set this diagnostic's error code +note: previously specified here + --> $DIR/session-derive-errors.rs:103:16 + | +LL | #[error(code = "E0456", code = "E0457", slug = "bar")] + | ^^^^^^^ -error: the `#[message = "..."]` attribute can only be applied to fields of type Span - --> $DIR/session-derive-errors.rs:101:5 +error: `slug` specified multiple times + --> $DIR/session-derive-errors.rs:107:46 | -LL | #[message = "this message is applied to a String field"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[error(code = "E0456", slug = "foo", slug = "bar")] + | ^^^^^ + | +note: previously specified here + --> $DIR/session-derive-errors.rs:107:32 + | +LL | #[error(code = "E0456", slug = "foo", slug = "bar")] + | ^^^^^ + +error: diagnostic kind not specified + --> $DIR/session-derive-errors.rs:111:1 + | +LL | struct KindNotProvided {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: use the `#[error(...)]` attribute to create an error + +error: `slug` not specified + --> $DIR/session-derive-errors.rs:114:1 + | +LL | / #[error(code = "E0456")] +LL | | struct SlugNotProvided {} + | |_________________________^ + | + = help: use the `#[error(slug = "...")]` attribute to set this diagnostic's slug + +error: the `#[primary_span]` attribute can only be applied to fields of type `Span` + --> $DIR/session-derive-errors.rs:124:5 + | +LL | #[primary_span] + | ^^^^^^^^^^^^^^^ + +error: `#[nonsense]` is not a valid `SessionDiagnostic` field attribute + --> $DIR/session-derive-errors.rs:132:5 + | +LL | #[nonsense] + | ^^^^^^^^^^^ + +error: the `#[label = ...]` attribute can only be applied to fields of type `Span` + --> $DIR/session-derive-errors.rs:149:5 + | +LL | #[label = "bar"] + | ^^^^^^^^^^^^^^^^ error: `name` doesn't refer to a field on this type - --> $DIR/session-derive-errors.rs:108:1 + --> $DIR/session-derive-errors.rs:157:42 | -LL | #[message = "This error has a field, and references {name}"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[suggestion(message = "bar", code = "{name}")] + | ^^^^^^^^ error: invalid format string: expected `'}'` but string was terminated - --> $DIR/session-derive-errors.rs:116:1 + --> $DIR/session-derive-errors.rs:162:16 | LL | #[derive(SessionDiagnostic)] - | ----------------- in this derive macro expansion -LL | #[error = "E0123"] - | - because of this opening brace -LL | #[message = "This is missing a closing brace: {name"] - | ^ expected `'}'` in format string + | - ^ expected `'}'` in format string + | | + | because of this opening brace | = note: if you intended to print `{`, you can escape it using `{{` = note: this error originates in the derive macro `SessionDiagnostic` (in Nightly builds, run with -Z macro-backtrace for more info) error: invalid format string: unmatched `}` found - --> $DIR/session-derive-errors.rs:125:1 + --> $DIR/session-derive-errors.rs:172:15 | LL | #[derive(SessionDiagnostic)] - | ----------------- in this derive macro expansion -LL | #[error = "E0123"] -LL | #[message = "This is missing an opening brace: name}"] - | ^ unmatched `}` in format string + | ^ unmatched `}` in format string | = note: if you intended to print `}`, you can escape it using `}}` = note: this error originates in the derive macro `SessionDiagnostic` (in Nightly builds, run with -Z macro-backtrace for more info) -error: The `#[label = ...]` attribute can only be applied to fields of type Span - --> $DIR/session-derive-errors.rs:144:5 +error: the `#[label = ...]` attribute can only be applied to fields of type `Span` + --> $DIR/session-derive-errors.rs:192:5 | -LL | #[label = "See here"] - | ^^^^^^^^^^^^^^^^^^^^^ +LL | #[label = "bar"] + | ^^^^^^^^^^^^^^^^ -error: `nonsense` is not a valid key for `#[suggestion(...)]` - --> $DIR/session-derive-errors.rs:169:18 +error: `#[suggestion(nonsense = ...)]` is not a valid `SessionDiagnostic` field attribute + --> $DIR/session-derive-errors.rs:217:18 | -LL | #[suggestion(nonsense = "This is nonsense")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[suggestion(nonsense = "bar")] + | ^^^^^^^^^^^^^^^^ -error: `msg` is not a valid key for `#[suggestion(...)]` - --> $DIR/session-derive-errors.rs:177:18 +error: `#[suggestion(msg = ...)]` is not a valid `SessionDiagnostic` field attribute + --> $DIR/session-derive-errors.rs:225:18 | -LL | #[suggestion(msg = "This is a suggestion")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: missing suggestion message - --> $DIR/session-derive-errors.rs:185:7 - | -LL | #[suggestion(code = "This is suggested code")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: provide a suggestion message using #[suggestion(message = "...")] +LL | #[suggestion(msg = "bar")] + | ^^^^^^^^^^^ error: wrong field type for suggestion - --> $DIR/session-derive-errors.rs:200:5 + --> $DIR/session-derive-errors.rs:247:5 | -LL | / #[suggestion(message = "This is a message", code = "This is suggested code")] +LL | / #[suggestion(message = "bar", code = "This is suggested code")] LL | | LL | | suggestion: Applicability, | |_____________________________^ | - = help: #[suggestion(...)] should be applied to fields of type Span or (Span, Applicability) + = help: `#[suggestion(...)]` should be applied to fields of type `Span` or `(Span, Applicability)` -error: type of field annotated with `#[suggestion(...)]` contains more than one Span - --> $DIR/session-derive-errors.rs:215:5 +error: type of field annotated with `#[suggestion(...)]` contains more than one `Span` + --> $DIR/session-derive-errors.rs:262:5 | -LL | / #[suggestion(message = "This is a message", code = "This is suggested code")] +LL | / #[suggestion(message = "bar", code = "This is suggested code")] LL | | LL | | suggestion: (Span, Span, Applicability), | |___________________________________________^ error: type of field annotated with `#[suggestion(...)]` contains more than one Applicability - --> $DIR/session-derive-errors.rs:223:5 + --> $DIR/session-derive-errors.rs:270:5 | -LL | / #[suggestion(message = "This is a message", code = "This is suggested code")] +LL | / #[suggestion(message = "bar", code = "This is suggested code")] LL | | LL | | suggestion: (Applicability, Applicability, Span), | |____________________________________________________^ -error: invalid annotation list `#[label(...)]` - --> $DIR/session-derive-errors.rs:231:7 +error: `#[label(...)]` is not a valid `SessionDiagnostic` field attribute + --> $DIR/session-derive-errors.rs:278:5 | -LL | #[label("wrong kind of annotation for label")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[label("bar")] + | ^^^^^^^^^^^^^^^ -error: aborting due to 18 previous errors +error: `#[help]` must come after `#[error(..)]` or `#[warn(..)]` + --> $DIR/session-derive-errors.rs:399:1 + | +LL | #[help] + | ^^^^^^^ +error: `#[help = ...]` must come after `#[error(..)]` or `#[warn(..)]` + --> $DIR/session-derive-errors.rs:407:1 + | +LL | #[help = "bar"] + | ^^^^^^^^^^^^^^^ + +error: `#[note]` must come after `#[error(..)]` or `#[warn(..)]` + --> $DIR/session-derive-errors.rs:415:1 + | +LL | #[note] + | ^^^^^^^ + +error: `#[note = ...]` must come after `#[error(..)]` or `#[warn(..)]` + --> $DIR/session-derive-errors.rs:423:1 + | +LL | #[note = "bar"] + | ^^^^^^^^^^^^^^^ + +error: cannot find attribute `nonsense` in this scope + --> $DIR/session-derive-errors.rs:51:3 + | +LL | #[nonsense(code = "E0123", slug = "foo")] + | ^^^^^^^^ + +error: cannot find attribute `nonsense` in this scope + --> $DIR/session-derive-errors.rs:132:7 + | +LL | #[nonsense] + | ^^^^^^^^ + +error[E0599]: no method named `into_diagnostic_arg` found for struct `Hello` in the current scope + --> $DIR/session-derive-errors.rs:322:10 + | +LL | struct Hello {} + | ------------ method `into_diagnostic_arg` not found for this +... +LL | #[derive(SessionDiagnostic)] + | ^^^^^^^^^^^^^^^^^ method not found in `Hello` + | + = note: this error originates in the derive macro `SessionDiagnostic` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 37 previous errors + +For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/allocator/not-an-allocator.rs b/src/test/ui/allocator/not-an-allocator.rs index 417c371..4a538d4 100644 --- a/src/test/ui/allocator/not-an-allocator.rs +++ b/src/test/ui/allocator/not-an-allocator.rs
@@ -1,8 +1,8 @@ #[global_allocator] static A: usize = 0; -//~^ the trait bound `usize: -//~| the trait bound `usize: -//~| the trait bound `usize: -//~| the trait bound `usize: +//~^ ERROR E0277 +//~| ERROR E0277 +//~| ERROR E0277 +//~| ERROR E0277 fn main() {}
diff --git a/src/test/ui/allocator/not-an-allocator.stderr b/src/test/ui/allocator/not-an-allocator.stderr index c0f6118..62bb067 100644 --- a/src/test/ui/allocator/not-an-allocator.stderr +++ b/src/test/ui/allocator/not-an-allocator.stderr
@@ -6,6 +6,7 @@ LL | static A: usize = 0; | ^^^^^ the trait `GlobalAlloc` is not implemented for `usize` | + = help: the trait `GlobalAlloc` is implemented for `System` = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied @@ -16,6 +17,7 @@ LL | static A: usize = 0; | ^^^^^ the trait `GlobalAlloc` is not implemented for `usize` | + = help: the trait `GlobalAlloc` is implemented for `System` = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied @@ -26,6 +28,7 @@ LL | static A: usize = 0; | ^^^^^ the trait `GlobalAlloc` is not implemented for `usize` | + = help: the trait `GlobalAlloc` is implemented for `System` = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied @@ -36,6 +39,7 @@ LL | static A: usize = 0; | ^^^^^ the trait `GlobalAlloc` is not implemented for `usize` | + = help: the trait `GlobalAlloc` is implemented for `System` = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 4 previous errors
diff --git a/src/test/ui/array-slice-vec/repeat_empty_ok.stderr b/src/test/ui/array-slice-vec/repeat_empty_ok.stderr index 85baa12..eba1a8e 100644 --- a/src/test/ui/array-slice-vec/repeat_empty_ok.stderr +++ b/src/test/ui/array-slice-vec/repeat_empty_ok.stderr
@@ -5,6 +5,10 @@ | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `Header<'_>` | = note: the `Copy` trait is required because the repeated element will be copied +help: consider annotating `Header<'_>` with `#[derive(Copy)]` + | +LL | #[derive(Copy)] + | error[E0277]: the trait bound `Header<'_>: Copy` is not satisfied --> $DIR/repeat_empty_ok.rs:13:19 @@ -13,6 +17,10 @@ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `Header<'_>` | = note: the `Copy` trait is required because the repeated element will be copied +help: consider annotating `Header<'_>` with `#[derive(Copy)]` + | +LL | #[derive(Copy)] + | error: aborting due to 2 previous errors
diff --git a/src/test/ui/associated-item/associated-item-enum.stderr b/src/test/ui/associated-item/associated-item-enum.stderr index cadf554..d52b2b3 100644 --- a/src/test/ui/associated-item/associated-item-enum.stderr +++ b/src/test/ui/associated-item/associated-item-enum.stderr
@@ -17,7 +17,10 @@ | --------- variant or associated item `mispellable_trait` not found here ... LL | Enum::mispellable_trait(); - | ^^^^^^^^^^^^^^^^^ variant or associated item not found in `Enum` + | ^^^^^^^^^^^^^^^^^ + | | + | variant or associated item not found in `Enum` + | help: there is an associated function with a similar name: `misspellable` error[E0599]: no variant or associated item named `MISPELLABLE` found for enum `Enum` in the current scope --> $DIR/associated-item-enum.rs:19:11
diff --git a/src/test/ui/associated-types/associated-types-path-2.stderr b/src/test/ui/associated-types/associated-types-path-2.stderr index f56631b..2d8d513 100644 --- a/src/test/ui/associated-types/associated-types-path-2.stderr +++ b/src/test/ui/associated-types/associated-types-path-2.stderr
@@ -15,8 +15,7 @@ LL | f1(2u32, 4u32); | ^^ the trait `Foo` is not implemented for `u32` | - = help: the following implementations were found: - <i32 as Foo> + = help: the trait `Foo` is implemented for `i32` note: required by a bound in `f1` --> $DIR/associated-types-path-2.rs:13:14 | @@ -29,8 +28,7 @@ LL | f1(2u32, 4u32); | ^^^^ the trait `Foo` is not implemented for `u32` | - = help: the following implementations were found: - <i32 as Foo> + = help: the trait `Foo` is implemented for `i32` error[E0277]: the trait bound `u32: Foo` is not satisfied --> $DIR/associated-types-path-2.rs:35:8 @@ -40,8 +38,7 @@ | | | required by a bound introduced by this call | - = help: the following implementations were found: - <i32 as Foo> + = help: the trait `Foo` is implemented for `i32` note: required by a bound in `f1` --> $DIR/associated-types-path-2.rs:13:14 | @@ -54,8 +51,7 @@ LL | f1(2u32, 4i32); | ^^^^ the trait `Foo` is not implemented for `u32` | - = help: the following implementations were found: - <i32 as Foo> + = help: the trait `Foo` is implemented for `i32` error[E0308]: mismatched types --> $DIR/associated-types-path-2.rs:41:18
diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.nll.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.nll.stderr index 01f8008..55532d6 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.nll.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.nll.stderr
@@ -10,8 +10,8 @@ | ^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` | = help: consider adding the following bound: `'a: 'b` - = note: requirement occurs because of the type Type<'_>, which makes the generic argument '_ invariant - = note: the struct Type<'a> is invariant over the parameter 'a + = note: requirement occurs because of the type `Type<'_>`, which makes the generic argument `'_` invariant + = note: the struct `Type<'a>` is invariant over the parameter `'a` = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance error: lifetime may not live long enough @@ -26,8 +26,8 @@ | ^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` | = help: consider adding the following bound: `'b: 'a` - = note: requirement occurs because of the type Type<'_>, which makes the generic argument '_ invariant - = note: the struct Type<'a> is invariant over the parameter 'a + = note: requirement occurs because of the type `Type<'_>`, which makes the generic argument `'_` invariant + = note: the struct `Type<'a>` is invariant over the parameter `'a` = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance help: `'a` and `'b` must be the same: replace one with the other
diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.oneuse.nll.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.oneuse.nll.stderr index e925a42..fd9eb05 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.oneuse.nll.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.oneuse.nll.stderr
@@ -10,8 +10,8 @@ | ^^^^^^^^^ argument requires that `'a` must outlive `'b` | = help: consider adding the following bound: `'a: 'b` - = note: requirement occurs because of the type Type<'_>, which makes the generic argument '_ invariant - = note: the struct Type<'a> is invariant over the parameter 'a + = note: requirement occurs because of the type `Type<'_>`, which makes the generic argument `'_` invariant + = note: the struct `Type<'a>` is invariant over the parameter `'a` = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance error: lifetime may not live long enough @@ -26,8 +26,8 @@ | ^^^^^^^^^ argument requires that `'b` must outlive `'a` | = help: consider adding the following bound: `'b: 'a` - = note: requirement occurs because of the type Type<'_>, which makes the generic argument '_ invariant - = note: the struct Type<'a> is invariant over the parameter 'a + = note: requirement occurs because of the type `Type<'_>`, which makes the generic argument `'_` invariant + = note: the struct `Type<'a>` is invariant over the parameter `'a` = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance help: `'a` and `'b` must be the same: replace one with the other
diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.nll.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.nll.stderr index 0457f14..5a7ead7 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.nll.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.nll.stderr
@@ -7,8 +7,8 @@ LL | bar(foo, x) | ^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` | - = note: requirement occurs because of the type Type<'_>, which makes the generic argument '_ invariant - = note: the struct Type<'a> is invariant over the parameter 'a + = note: requirement occurs because of the type `Type<'_>`, which makes the generic argument `'_` invariant + = note: the struct `Type<'a>` is invariant over the parameter `'a` = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance error: aborting due to previous error
diff --git a/src/test/ui/associated-types/defaults-suitability.stderr b/src/test/ui/associated-types/defaults-suitability.stderr index 6c63c01..43541c5 100644 --- a/src/test/ui/associated-types/defaults-suitability.stderr +++ b/src/test/ui/associated-types/defaults-suitability.stderr
@@ -9,6 +9,10 @@ | LL | type Ty: Clone = NotClone; | ^^^^^ required by this bound in `Tr::Ty` +help: consider annotating `NotClone` with `#[derive(Clone)]` + | +LL | #[derive(Clone)] + | error[E0277]: the trait bound `NotClone: Clone` is not satisfied --> $DIR/defaults-suitability.rs:22:15 @@ -24,6 +28,10 @@ LL | { LL | type Ty = NotClone; | -- required by a bound in this +help: consider annotating `NotClone` with `#[derive(Clone)]` + | +LL | #[derive(Clone)] + | error[E0277]: the trait bound `T: Clone` is not satisfied --> $DIR/defaults-suitability.rs:28:23
diff --git a/src/test/ui/associated-types/hr-associated-type-bound-1.stderr b/src/test/ui/associated-types/hr-associated-type-bound-1.stderr index ec28ca2..73b5e10 100644 --- a/src/test/ui/associated-types/hr-associated-type-bound-1.stderr +++ b/src/test/ui/associated-types/hr-associated-type-bound-1.stderr
@@ -4,8 +4,7 @@ LL | type U = str; | ^^^ the trait `Clone` is not implemented for `str` | - = help: the following implementations were found: - <String as Clone> + = help: the trait `Clone` is implemented for `String` note: required by a bound in `X` --> $DIR/hr-associated-type-bound-1.rs:3:33 |
diff --git a/src/test/ui/associated-types/hr-associated-type-bound-param-1.stderr b/src/test/ui/associated-types/hr-associated-type-bound-param-1.stderr index e48ef8d..af2e616 100644 --- a/src/test/ui/associated-types/hr-associated-type-bound-param-1.stderr +++ b/src/test/ui/associated-types/hr-associated-type-bound-param-1.stderr
@@ -4,8 +4,7 @@ LL | type V = str; | ^^^ the trait `Clone` is not implemented for `str` | - = help: the following implementations were found: - <String as Clone> + = help: the trait `Clone` is implemented for `String` note: required by a bound in `Y` --> $DIR/hr-associated-type-bound-param-1.rs:4:36 |
diff --git a/src/test/ui/associated-types/hr-associated-type-bound-param-2.stderr b/src/test/ui/associated-types/hr-associated-type-bound-param-2.stderr index 2fb3af3..5809c40 100644 --- a/src/test/ui/associated-types/hr-associated-type-bound-param-2.stderr +++ b/src/test/ui/associated-types/hr-associated-type-bound-param-2.stderr
@@ -4,8 +4,7 @@ LL | T: Z<'a, u16>, | ^^^^^^^^^^ the trait `Clone` is not implemented for `str` | - = help: the following implementations were found: - <String as Clone> + = help: the trait `Clone` is implemented for `String` note: required by a bound in `Z` --> $DIR/hr-associated-type-bound-param-2.rs:6:35 | @@ -21,8 +20,7 @@ LL | T: Z<'a, u16>, | ^^^^^^^^^^ the trait `Clone` is not implemented for `str` | - = help: the following implementations were found: - <String as Clone> + = help: the trait `Clone` is implemented for `String` note: required by a bound in `Z` --> $DIR/hr-associated-type-bound-param-2.rs:6:35 | @@ -38,8 +36,7 @@ LL | type W = str; | ^^^ the trait `Clone` is not implemented for `str` | - = help: the following implementations were found: - <String as Clone> + = help: the trait `Clone` is implemented for `String` note: required by a bound in `Z` --> $DIR/hr-associated-type-bound-param-2.rs:6:35 |
diff --git a/src/test/ui/associated-types/hr-associated-type-bound-param-3.stderr b/src/test/ui/associated-types/hr-associated-type-bound-param-3.stderr index 775f45c..84d5e04 100644 --- a/src/test/ui/associated-types/hr-associated-type-bound-param-3.stderr +++ b/src/test/ui/associated-types/hr-associated-type-bound-param-3.stderr
@@ -4,8 +4,7 @@ LL | type U = str; | ^^^ the trait `Clone` is not implemented for `str` | - = help: the following implementations were found: - <String as Clone> + = help: the trait `Clone` is implemented for `String` note: required by a bound in `X` --> $DIR/hr-associated-type-bound-param-3.rs:4:33 |
diff --git a/src/test/ui/associated-types/hr-associated-type-bound-param-4.stderr b/src/test/ui/associated-types/hr-associated-type-bound-param-4.stderr index 4e9b64b..ee1d5d3 100644 --- a/src/test/ui/associated-types/hr-associated-type-bound-param-4.stderr +++ b/src/test/ui/associated-types/hr-associated-type-bound-param-4.stderr
@@ -4,8 +4,7 @@ LL | type U = str; | ^^^ the trait `Clone` is not implemented for `str` | - = help: the following implementations were found: - <String as Clone> + = help: the trait `Clone` is implemented for `String` note: required by a bound in `X` --> $DIR/hr-associated-type-bound-param-4.rs:4:36 |
diff --git a/src/test/ui/associated-types/hr-associated-type-bound-param-5.stderr b/src/test/ui/associated-types/hr-associated-type-bound-param-5.stderr index d00abf3..ece3151 100644 --- a/src/test/ui/associated-types/hr-associated-type-bound-param-5.stderr +++ b/src/test/ui/associated-types/hr-associated-type-bound-param-5.stderr
@@ -4,8 +4,7 @@ LL | type U = str; | ^^^ the trait `Clone` is not implemented for `str` | - = help: the following implementations were found: - <String as Clone> + = help: the trait `Clone` is implemented for `String` note: required by a bound in `X` --> $DIR/hr-associated-type-bound-param-5.rs:17:45 | @@ -21,8 +20,7 @@ LL | type U = str; | ^^^ the trait `Clone` is not implemented for `str` | - = help: the following implementations were found: - <String as Clone> + = help: the trait `Clone` is implemented for `String` note: required by a bound in `X` --> $DIR/hr-associated-type-bound-param-5.rs:17:45 |
diff --git a/src/test/ui/associated-types/issue-65774-1.stderr b/src/test/ui/associated-types/issue-65774-1.stderr index 82c520b..e468a1b 100644 --- a/src/test/ui/associated-types/issue-65774-1.stderr +++ b/src/test/ui/associated-types/issue-65774-1.stderr
@@ -4,6 +4,7 @@ LL | type MpuConfig: MyDisplay = T; | ^ the trait `MyDisplay` is not implemented for `T` | + = help: the trait `MyDisplay` is implemented for `&'a mut T` note: required by a bound in `MPU::MpuConfig` --> $DIR/issue-65774-1.rs:10:21 | @@ -16,6 +17,7 @@ LL | let closure = |config: &mut <S as MPU>::MpuConfig| writer.my_write(&config); | ^^^^^^^ the trait `MyDisplay` is not implemented for `T` | + = help: the trait `MyDisplay` is implemented for `&'a mut T` note: required because of the requirements on the impl of `MyDisplay` for `&mut T` --> $DIR/issue-65774-1.rs:5:24 |
diff --git a/src/test/ui/associated-types/issue-65774-2.stderr b/src/test/ui/associated-types/issue-65774-2.stderr index 349cef9..4cef4db 100644 --- a/src/test/ui/associated-types/issue-65774-2.stderr +++ b/src/test/ui/associated-types/issue-65774-2.stderr
@@ -4,6 +4,7 @@ LL | type MpuConfig: MyDisplay = T; | ^ the trait `MyDisplay` is not implemented for `T` | + = help: the trait `MyDisplay` is implemented for `&'a mut T` note: required by a bound in `MPU::MpuConfig` --> $DIR/issue-65774-2.rs:10:21 | @@ -16,6 +17,7 @@ LL | writer.my_write(valref) | ^^^^^^ the trait `MyDisplay` is not implemented for `T` | + = help: the trait `MyDisplay` is implemented for `&'a mut T` = note: required for the cast to the object type `dyn MyDisplay` error: aborting due to 2 previous errors
diff --git a/src/test/ui/associated-types/trait-with-supertraits-needing-sized-self.stderr b/src/test/ui/associated-types/trait-with-supertraits-needing-sized-self.stderr index 558b0f5..0edc9a5 100644 --- a/src/test/ui/associated-types/trait-with-supertraits-needing-sized-self.stderr +++ b/src/test/ui/associated-types/trait-with-supertraits-needing-sized-self.stderr
@@ -8,7 +8,7 @@ --> $SRC_DIR/core/src/ops/arith.rs:LL:COL | LL | pub trait Add<Rhs = Self> { - | ^^^ required by this bound in `Add` + | ^^^^^^^^^^ required by this bound in `Add` help: consider further restricting `Self` | LL | trait ArithmeticOps: Add<Output=Self> + Sub<Output=Self> + Mul<Output=Self> + Div<Output=Self> + Sized {}
diff --git a/src/test/ui/async-await/issues/issue-78654.full.stderr b/src/test/ui/async-await/issues/issue-78654.full.stderr index a9208ad..0d12a94 100644 --- a/src/test/ui/async-await/issues/issue-78654.full.stderr +++ b/src/test/ui/async-await/issues/issue-78654.full.stderr
@@ -5,10 +5,10 @@ | ^^^^^^^ not a type error[E0207]: the const parameter `H` is not constrained by the impl trait, self type, or predicates - --> $DIR/issue-78654.rs:9:12 + --> $DIR/issue-78654.rs:9:6 | LL | impl<const H: feature> Foo { - | ^ unconstrained const parameter + | ^^^^^^^^^^^^^^^^ unconstrained const parameter | = note: expressions using a const parameter must map each value to a distinct output value = note: proving the result of expressions other than the parameter are unique is not supported
diff --git a/src/test/ui/async-await/issues/issue-78654.min.stderr b/src/test/ui/async-await/issues/issue-78654.min.stderr index a9208ad..0d12a94 100644 --- a/src/test/ui/async-await/issues/issue-78654.min.stderr +++ b/src/test/ui/async-await/issues/issue-78654.min.stderr
@@ -5,10 +5,10 @@ | ^^^^^^^ not a type error[E0207]: the const parameter `H` is not constrained by the impl trait, self type, or predicates - --> $DIR/issue-78654.rs:9:12 + --> $DIR/issue-78654.rs:9:6 | LL | impl<const H: feature> Foo { - | ^ unconstrained const parameter + | ^^^^^^^^^^^^^^^^ unconstrained const parameter | = note: expressions using a const parameter must map each value to a distinct output value = note: proving the result of expressions other than the parameter are unique is not supported
diff --git a/src/test/ui/auto-traits/typeck-default-trait-impl-precedence.stderr b/src/test/ui/auto-traits/typeck-default-trait-impl-precedence.stderr index 5755778..985cdce 100644 --- a/src/test/ui/auto-traits/typeck-default-trait-impl-precedence.stderr +++ b/src/test/ui/auto-traits/typeck-default-trait-impl-precedence.stderr
@@ -4,8 +4,7 @@ LL | is_defaulted::<&'static u32>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Signed` is not implemented for `u32` | - = help: the following implementations were found: - <i32 as Signed> + = help: the trait `Signed` is implemented for `i32` note: required because of the requirements on the impl of `Defaulted` for `&'static u32` --> $DIR/typeck-default-trait-impl-precedence.rs:10:19 |
diff --git a/src/test/ui/binop/binop-mul-i32-f32.stderr b/src/test/ui/binop/binop-mul-i32-f32.stderr index 4a67fe2..21c4909 100644 --- a/src/test/ui/binop/binop-mul-i32-f32.stderr +++ b/src/test/ui/binop/binop-mul-i32-f32.stderr
@@ -5,6 +5,16 @@ | ^ no implementation for `i32 * f32` | = help: the trait `Mul<f32>` is not implemented for `i32` + = help: the following other types implement trait `Mul<Rhs>`: + <&'a f32 as Mul<f32>> + <&'a f64 as Mul<f64>> + <&'a i128 as Mul<i128>> + <&'a i16 as Mul<i16>> + <&'a i32 as Mul<i32>> + <&'a i64 as Mul<i64>> + <&'a i8 as Mul<i8>> + <&'a isize as Mul<isize>> + and 49 others error: aborting due to previous error
diff --git a/src/test/ui/binop/issue-77910-1.stderr b/src/test/ui/binop/issue-77910-1.stderr index db854ae..95ee51a 100644 --- a/src/test/ui/binop/issue-77910-1.stderr +++ b/src/test/ui/binop/issue-77910-1.stderr
@@ -16,6 +16,16 @@ | ^^^^^^^^^^^^^^^^^^ `for<'r> fn(&'r i32) -> &'r i32 {foo}` cannot be formatted using `{:?}` because it doesn't implement `Debug` | = help: the trait `Debug` is not implemented for `for<'r> fn(&'r i32) -> &'r i32 {foo}` + = help: the following other types implement trait `Debug`: + extern "C" fn() -> Ret + extern "C" fn(A) -> Ret + extern "C" fn(A, ...) -> Ret + extern "C" fn(A, B) -> Ret + extern "C" fn(A, B, ...) -> Ret + extern "C" fn(A, B, C) -> Ret + extern "C" fn(A, B, C, ...) -> Ret + extern "C" fn(A, B, C, D) -> Ret + and 68 others = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors
diff --git a/src/test/ui/binop/shift-various-bad-types.stderr b/src/test/ui/binop/shift-various-bad-types.stderr index 932a435..38db66f8 100644 --- a/src/test/ui/binop/shift-various-bad-types.stderr +++ b/src/test/ui/binop/shift-various-bad-types.stderr
@@ -5,6 +5,16 @@ | ^^ no implementation for `{integer} >> char` | = help: the trait `Shr<char>` is not implemented for `{integer}` + = help: the following other types implement trait `Shr<Rhs>`: + <&'a i128 as Shr<i128>> + <&'a i128 as Shr<i16>> + <&'a i128 as Shr<i32>> + <&'a i128 as Shr<i64>> + <&'a i128 as Shr<i8>> + <&'a i128 as Shr<isize>> + <&'a i128 as Shr<u128>> + <&'a i128 as Shr<u16>> + and 568 others error[E0277]: no implementation for `{integer} >> &str` --> $DIR/shift-various-bad-types.rs:12:8 @@ -13,6 +23,16 @@ | ^^ no implementation for `{integer} >> &str` | = help: the trait `Shr<&str>` is not implemented for `{integer}` + = help: the following other types implement trait `Shr<Rhs>`: + <&'a i128 as Shr<i128>> + <&'a i128 as Shr<i16>> + <&'a i128 as Shr<i32>> + <&'a i128 as Shr<i64>> + <&'a i128 as Shr<i8>> + <&'a i128 as Shr<isize>> + <&'a i128 as Shr<u128>> + <&'a i128 as Shr<u16>> + and 568 others error[E0277]: no implementation for `{integer} >> &Panolpy` --> $DIR/shift-various-bad-types.rs:15:8 @@ -21,6 +41,16 @@ | ^^ no implementation for `{integer} >> &Panolpy` | = help: the trait `Shr<&Panolpy>` is not implemented for `{integer}` + = help: the following other types implement trait `Shr<Rhs>`: + <&'a i128 as Shr<i128>> + <&'a i128 as Shr<i16>> + <&'a i128 as Shr<i32>> + <&'a i128 as Shr<i64>> + <&'a i128 as Shr<i8>> + <&'a i128 as Shr<isize>> + <&'a i128 as Shr<u128>> + <&'a i128 as Shr<u16>> + and 568 others error[E0308]: mismatched types --> $DIR/shift-various-bad-types.rs:25:18
diff --git a/src/test/ui/block-result/issue-22645.stderr b/src/test/ui/block-result/issue-22645.stderr index 397bdac..31663e8 100644 --- a/src/test/ui/block-result/issue-22645.stderr +++ b/src/test/ui/block-result/issue-22645.stderr
@@ -4,8 +4,7 @@ LL | b + 3 | ^ the trait `Scalar` is not implemented for `{integer}` | - = help: the following implementations were found: - <f64 as Scalar> + = help: the trait `Scalar` is implemented for `f64` note: required because of the requirements on the impl of `Add<{integer}>` for `Bob` --> $DIR/issue-22645.rs:8:19 |
diff --git a/src/test/ui/c-variadic/variadic-ffi-4.stderr b/src/test/ui/c-variadic/variadic-ffi-4.stderr index ff4da52..6f8e532 100644 --- a/src/test/ui/c-variadic/variadic-ffi-4.stderr +++ b/src/test/ui/c-variadic/variadic-ffi-4.stderr
@@ -8,8 +8,8 @@ LL | ap | ^^ function was supposed to return data with lifetime `'1` but it is returning data with lifetime `'f` | - = note: requirement occurs because of the type VaListImpl<'_>, which makes the generic argument '_ invariant - = note: the struct VaListImpl<'f> is invariant over the parameter 'f + = note: requirement occurs because of the type `VaListImpl<'_>`, which makes the generic argument `'_` invariant + = note: the struct `VaListImpl<'f>` is invariant over the parameter `'f` = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance error: lifetime may not live long enough @@ -22,8 +22,8 @@ LL | ap | ^^ function was supposed to return data with lifetime `'f` but it is returning data with lifetime `'1` | - = note: requirement occurs because of the type VaListImpl<'_>, which makes the generic argument '_ invariant - = note: the struct VaListImpl<'f> is invariant over the parameter 'f + = note: requirement occurs because of the type `VaListImpl<'_>`, which makes the generic argument `'_` invariant + = note: the struct `VaListImpl<'f>` is invariant over the parameter `'f` = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance error: lifetime may not live long enough @@ -34,8 +34,8 @@ LL | ap | ^^ returning this value requires that `'1` must outlive `'static` | - = note: requirement occurs because of the type VaListImpl<'_>, which makes the generic argument '_ invariant - = note: the struct VaListImpl<'f> is invariant over the parameter 'f + = note: requirement occurs because of the type `VaListImpl<'_>`, which makes the generic argument `'_` invariant + = note: the struct `VaListImpl<'f>` is invariant over the parameter `'f` = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance error: lifetime may not live long enough @@ -57,8 +57,8 @@ LL | *ap0 = ap1; | ^^^^ assignment requires that `'1` must outlive `'2` | - = note: requirement occurs because of the type VaListImpl<'_>, which makes the generic argument '_ invariant - = note: the struct VaListImpl<'f> is invariant over the parameter 'f + = note: requirement occurs because of the type `VaListImpl<'_>`, which makes the generic argument `'_` invariant + = note: the struct `VaListImpl<'f>` is invariant over the parameter `'f` = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance error: lifetime may not live long enough @@ -71,8 +71,8 @@ LL | *ap0 = ap1; | ^^^^ assignment requires that `'2` must outlive `'1` | - = note: requirement occurs because of the type VaListImpl<'_>, which makes the generic argument '_ invariant - = note: the struct VaListImpl<'f> is invariant over the parameter 'f + = note: requirement occurs because of the type `VaListImpl<'_>`, which makes the generic argument `'_` invariant + = note: the struct `VaListImpl<'f>` is invariant over the parameter `'f` = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance error: lifetime may not live long enough @@ -85,7 +85,7 @@ LL | ap0 = &mut ap1; | ^^^^^^^^^^^^^^ assignment requires that `'1` must outlive `'2` | - = note: requirement occurs because of a mutable reference to VaListImpl<'_> + = note: requirement occurs because of a mutable reference to `VaListImpl<'_>` = note: mutable references are invariant over their type parameter = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance @@ -99,7 +99,7 @@ LL | ap0 = &mut ap1; | ^^^^^^^^^^^^^^ assignment requires that `'2` must outlive `'1` | - = note: requirement occurs because of a mutable reference to VaListImpl<'_> + = note: requirement occurs because of a mutable reference to `VaListImpl<'_>` = note: mutable references are invariant over their type parameter = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance @@ -127,8 +127,8 @@ LL | *ap0 = ap1.clone(); | ^^^^^^^^^^^ argument requires that `'1` must outlive `'2` | - = note: requirement occurs because of the type VaListImpl<'_>, which makes the generic argument '_ invariant - = note: the struct VaListImpl<'f> is invariant over the parameter 'f + = note: requirement occurs because of the type `VaListImpl<'_>`, which makes the generic argument `'_` invariant + = note: the struct `VaListImpl<'f>` is invariant over the parameter `'f` = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance error: lifetime may not live long enough @@ -141,8 +141,8 @@ LL | *ap0 = ap1.clone(); | ^^^^^^^^^^^ argument requires that `'2` must outlive `'1` | - = note: requirement occurs because of the type VaListImpl<'_>, which makes the generic argument '_ invariant - = note: the struct VaListImpl<'f> is invariant over the parameter 'f + = note: requirement occurs because of the type `VaListImpl<'_>`, which makes the generic argument `'_` invariant + = note: the struct `VaListImpl<'f>` is invariant over the parameter `'f` = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance error: aborting due to 11 previous errors
diff --git a/src/test/ui/chalkify/chalk_initial_program.stderr b/src/test/ui/chalkify/chalk_initial_program.stderr index 7b0b3f8..343c0a3 100644 --- a/src/test/ui/chalkify/chalk_initial_program.stderr +++ b/src/test/ui/chalkify/chalk_initial_program.stderr
@@ -4,9 +4,9 @@ LL | gimme::<f32>(); | ^^^ the trait `Foo` is not implemented for `f32` | - = help: the following implementations were found: - <i32 as Foo> - <u32 as Foo> + = help: the following other types implement trait `Foo`: + i32 + u32 note: required by a bound in `gimme` --> $DIR/chalk_initial_program.rs:9:13 |
diff --git a/src/test/ui/chalkify/generic_impls.stderr b/src/test/ui/chalkify/generic_impls.stderr index 0c7fcd0..d4a8354 100644 --- a/src/test/ui/chalkify/generic_impls.stderr +++ b/src/test/ui/chalkify/generic_impls.stderr
@@ -4,8 +4,7 @@ LL | gimme::<(Option<T>, f32)>(); | ^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `(Option<T>, f32)` | - = help: the following implementations were found: - <(T, u32) as Foo> + = help: the trait `Foo` is implemented for `(T, u32)` note: required by a bound in `gimme` --> $DIR/generic_impls.rs:7:13 | @@ -18,8 +17,7 @@ LL | gimme::<(i32, f32)>(); | ^^^^^^^^^^ the trait `Foo` is not implemented for `(i32, f32)` | - = help: the following implementations were found: - <(T, u32) as Foo> + = help: the trait `Foo` is implemented for `(T, u32)` note: required by a bound in `gimme` --> $DIR/generic_impls.rs:7:13 |
diff --git a/src/test/ui/chalkify/impl_wf.stderr b/src/test/ui/chalkify/impl_wf.stderr index 2bc9f07..a142459 100644 --- a/src/test/ui/chalkify/impl_wf.stderr +++ b/src/test/ui/chalkify/impl_wf.stderr
@@ -17,8 +17,7 @@ LL | impl Baz<f32> for f32 { } | ^^^^^^^^ the trait `Foo` is not implemented for `f32` | - = help: the following implementations were found: - <i32 as Foo> + = help: the trait `Foo` is implemented for `i32` note: required by a bound in `Baz` --> $DIR/impl_wf.rs:18:31 |
diff --git a/src/test/ui/chalkify/impl_wf_2.stderr b/src/test/ui/chalkify/impl_wf_2.stderr index 30cec80..1c1df64 100644 --- a/src/test/ui/chalkify/impl_wf_2.stderr +++ b/src/test/ui/chalkify/impl_wf_2.stderr
@@ -4,8 +4,7 @@ LL | type Item = f32; | ^^^ the trait `Foo` is not implemented for `f32` | - = help: the following implementations were found: - <i32 as Foo> + = help: the trait `Foo` is implemented for `i32` note: required by a bound in `Bar::Item` --> $DIR/impl_wf_2.rs:8:16 |
diff --git a/src/test/ui/chalkify/type_inference.stderr b/src/test/ui/chalkify/type_inference.stderr index 14d43c1..508a6dd 100644 --- a/src/test/ui/chalkify/type_inference.stderr +++ b/src/test/ui/chalkify/type_inference.stderr
@@ -6,9 +6,9 @@ | | | required by a bound introduced by this call | - = help: the following implementations were found: - <i32 as Bar> - <u32 as Bar> + = help: the following other types implement trait `Bar`: + i32 + u32 note: required by a bound in `only_bar` --> $DIR/type_inference.rs:12:16 |
diff --git a/src/test/ui/chalkify/type_wf.stderr b/src/test/ui/chalkify/type_wf.stderr index 6abd8b2..7f85660 100644 --- a/src/test/ui/chalkify/type_wf.stderr +++ b/src/test/ui/chalkify/type_wf.stderr
@@ -4,8 +4,7 @@ LL | let s = S { | ^ the trait `Foo` is not implemented for `{float}` | - = help: the following implementations were found: - <i32 as Foo> + = help: the trait `Foo` is implemented for `i32` note: required by a bound in `S` --> $DIR/type_wf.rs:6:13 |
diff --git a/src/test/ui/closures/coerce-unsafe-to-closure.stderr b/src/test/ui/closures/coerce-unsafe-to-closure.stderr index 883348e..bd095c2 100644 --- a/src/test/ui/closures/coerce-unsafe-to-closure.stderr +++ b/src/test/ui/closures/coerce-unsafe-to-closure.stderr
@@ -2,11 +2,12 @@ --> $DIR/coerce-unsafe-to-closure.rs:2:44 | LL | let x: Option<&[u8]> = Some("foo").map(std::mem::transmute); - | --- ^^^^^^^^^^^^^^^^^^^ expected an `FnOnce<(&str,)>` closure, found `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, _>}` + | --- ^^^^^^^^^^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }` | | | required by a bound introduced by this call | = help: the trait `FnOnce<(&str,)>` is not implemented for `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, _>}` + = note: unsafe function cannot be called generically without an unsafe block note: required by a bound in `Option::<T>::map` --> $SRC_DIR/core/src/option.rs:LL:COL |
diff --git a/src/test/ui/coercion/coerce-issue-49593-box-never.nofallback.stderr b/src/test/ui/coercion/coerce-issue-49593-box-never.nofallback.stderr index fbaa874..a4b10a4 100644 --- a/src/test/ui/coercion/coerce-issue-49593-box-never.nofallback.stderr +++ b/src/test/ui/coercion/coerce-issue-49593-box-never.nofallback.stderr
@@ -4,6 +4,16 @@ LL | /* *mut $0 is coerced to Box<dyn Error> here */ Box::<_ /* ! */>::new(x) | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::error::Error` is not implemented for `()` | + = help: the following other types implement trait `std::error::Error`: + ! + &'a T + AccessError + AddrParseError + Arc<T> + BorrowError + BorrowMutError + Box<T> + and 42 others = note: required for the cast to the object type `dyn std::error::Error` error[E0277]: the trait bound `(): std::error::Error` is not satisfied @@ -12,6 +22,16 @@ LL | /* *mut $0 is coerced to *mut Error here */ raw_ptr_box::<_ /* ! */>(x) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::error::Error` is not implemented for `()` | + = help: the following other types implement trait `std::error::Error`: + ! + &'a T + AccessError + AddrParseError + Arc<T> + BorrowError + BorrowMutError + Box<T> + and 42 others = note: required for the cast to the object type `(dyn std::error::Error + 'static)` error: aborting due to 2 previous errors
diff --git a/src/test/ui/const-generics/associated-type-bound-fail.stderr b/src/test/ui/const-generics/associated-type-bound-fail.stderr index 9dc677e..da25582 100644 --- a/src/test/ui/const-generics/associated-type-bound-fail.stderr +++ b/src/test/ui/const-generics/associated-type-bound-fail.stderr
@@ -4,8 +4,7 @@ LL | type Assoc = u16; | ^^^ the trait `Bar<N>` is not implemented for `u16` | - = help: the following implementations were found: - <u16 as Bar<3_usize>> + = help: the trait `Bar<3_usize>` is implemented for `u16` note: required by a bound in `Foo::Assoc` --> $DIR/associated-type-bound-fail.rs:4:17 |
diff --git a/src/test/ui/const-generics/defaults/default-on-impl.stderr b/src/test/ui/const-generics/defaults/default-on-impl.stderr index ddfc0ea..4b2b057 100644 --- a/src/test/ui/const-generics/defaults/default-on-impl.stderr +++ b/src/test/ui/const-generics/defaults/default-on-impl.stderr
@@ -1,8 +1,8 @@ error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions - --> $DIR/default-on-impl.rs:3:12 + --> $DIR/default-on-impl.rs:3:6 | LL | impl<const N: usize = 1> Foo<N> {} - | ^ + | ^^^^^^^^^^^^^^^^^^ error: aborting due to previous error
diff --git a/src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr b/src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr index 81cfcb3..48c61c2 100644 --- a/src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr +++ b/src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr
@@ -4,8 +4,7 @@ LL | fn rawr() -> impl Trait { | ^^^^^^^^^^ the trait `Trait` is not implemented for `Uwu<10_u32, 12_u32>` | - = help: the following implementations were found: - <Uwu<N> as Trait> + = help: the trait `Trait` is implemented for `Uwu<N>` error[E0277]: the trait bound `Uwu<10_u32, 12_u32>: Trait` is not satisfied --> $DIR/rp_impl_trait_fail.rs:6:25 @@ -18,8 +17,7 @@ LL | | } | |_^ the trait `Trait` is not implemented for `Uwu<10_u32, 12_u32>` | - = help: the following implementations were found: - <Uwu<N> as Trait> + = help: the trait `Trait` is implemented for `Uwu<N>` error[E0277]: the trait bound `u32: Traitor<N, N>` is not satisfied --> $DIR/rp_impl_trait_fail.rs:18:26 @@ -27,7 +25,7 @@ LL | fn uwu<const N: u8>() -> impl Traitor<N> { | ^^^^^^^^^^^^^^^ the trait `Traitor<N, N>` is not implemented for `u32` | - = help: the following implementations were found: + = help: the following other types implement trait `Traitor<N, M>`: <u32 as Traitor<N, 2_u8>> <u64 as Traitor<1_u8, 2_u8>> @@ -42,7 +40,7 @@ LL | | } | |_^ the trait `Traitor<N, N>` is not implemented for `u32` | - = help: the following implementations were found: + = help: the following other types implement trait `Traitor<N, M>`: <u32 as Traitor<N, 2_u8>> <u64 as Traitor<1_u8, 2_u8>> @@ -52,9 +50,9 @@ LL | fn owo() -> impl Traitor { | ^^^^^^^^^^^^ the trait `Traitor<1_u8, 1_u8>` is not implemented for `u64` | - = help: the following implementations were found: - <u64 as Traitor<1_u8, 2_u8>> + = help: the following other types implement trait `Traitor<N, M>`: <u32 as Traitor<N, 2_u8>> + <u64 as Traitor<1_u8, 2_u8>> error[E0277]: the trait bound `u64: Traitor<1_u8, 1_u8>` is not satisfied --> $DIR/rp_impl_trait_fail.rs:24:26 @@ -67,9 +65,9 @@ LL | | } | |_^ the trait `Traitor<1_u8, 1_u8>` is not implemented for `u64` | - = help: the following implementations were found: - <u64 as Traitor<1_u8, 2_u8>> + = help: the following other types implement trait `Traitor<N, M>`: <u32 as Traitor<N, 2_u8>> + <u64 as Traitor<1_u8, 2_u8>> error: aborting due to 6 previous errors
diff --git a/src/test/ui/const-generics/defaults/trait_objects_fail.stderr b/src/test/ui/const-generics/defaults/trait_objects_fail.stderr index 13d03c2..7f8a1f7 100644 --- a/src/test/ui/const-generics/defaults/trait_objects_fail.stderr +++ b/src/test/ui/const-generics/defaults/trait_objects_fail.stderr
@@ -6,8 +6,7 @@ | | | required by a bound introduced by this call | - = help: the following implementations were found: - <u32 as Trait<2_u8>> + = help: the trait `Trait<2_u8>` is implemented for `u32` = note: required for the cast to the object type `dyn Trait` error[E0277]: the trait bound `bool: Traitor<{_: u8}, {_: u8}>` is not satisfied @@ -18,8 +17,7 @@ | | | required by a bound introduced by this call | - = help: the following implementations were found: - <bool as Traitor<2_u8, 3_u8>> + = help: the trait `Traitor<2_u8, 3_u8>` is implemented for `bool` = note: required for the cast to the object type `dyn Traitor<{_: u8}, {_: u8}>` error: aborting due to 2 previous errors
diff --git a/src/test/ui/const-generics/defaults/wfness.stderr b/src/test/ui/const-generics/defaults/wfness.stderr index facf0ae..8b405d6 100644 --- a/src/test/ui/const-generics/defaults/wfness.stderr +++ b/src/test/ui/const-generics/defaults/wfness.stderr
@@ -10,8 +10,7 @@ LL | struct WhereClause<const N: u8 = 2> where (): Trait<N>; | ^^^^^^^^ the trait `Trait<2_u8>` is not implemented for `()` | - = help: the following implementations were found: - <() as Trait<3_u8>> + = help: the trait `Trait<3_u8>` is implemented for `()` error[E0277]: the trait bound `(): Trait<1_u8>` is not satisfied --> $DIR/wfness.rs:14:13 @@ -19,8 +18,7 @@ LL | fn foo() -> DependentDefaultWfness { | ^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait<1_u8>` is not implemented for `()` | - = help: the following implementations were found: - <() as Trait<3_u8>> + = help: the trait `Trait<3_u8>` is implemented for `()` note: required by a bound in `WhereClause` --> $DIR/wfness.rs:6:47 |
diff --git a/src/test/ui/const-generics/exhaustive-value.stderr b/src/test/ui/const-generics/exhaustive-value.stderr index 1a8f4ab..9c1b086 100644 --- a/src/test/ui/const-generics/exhaustive-value.stderr +++ b/src/test/ui/const-generics/exhaustive-value.stderr
@@ -4,12 +4,16 @@ LL | <() as Foo<N>>::test() | ^^^^^^^^^^^^^^^^^^^^ the trait `Foo<N>` is not implemented for `()` | - = help: the following implementations were found: + = help: the following other types implement trait `Foo<N>`: <() as Foo<0_u8>> <() as Foo<100_u8>> <() as Foo<101_u8>> <() as Foo<102_u8>> - and 252 others + <() as Foo<103_u8>> + <() as Foo<104_u8>> + <() as Foo<105_u8>> + <() as Foo<106_u8>> + and 248 others error: aborting due to previous error
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-76595.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-76595.stderr index 3b69a40..c587a7e 100644 --- a/src/test/ui/const-generics/generic_const_exprs/issue-76595.stderr +++ b/src/test/ui/const-generics/generic_const_exprs/issue-76595.stderr
@@ -10,7 +10,7 @@ --> $DIR/issue-76595.rs:10:4 | LL | fn test<T, const P: usize>() where Bool<{core::mem::size_of::<T>() > 4}>: True { - | ^^^^ - - + | ^^^^ - -------------- help: add missing generic argument | LL | test::<2, P>();
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-85848.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-85848.stderr index 4202cba..27f5dce 100644 --- a/src/test/ui/const-generics/generic_const_exprs/issue-85848.stderr +++ b/src/test/ui/const-generics/generic_const_exprs/issue-85848.stderr
@@ -6,6 +6,7 @@ | | | required by a bound introduced by this call | + = help: the trait `Delegates<U>` is implemented for `T` note: required because of the requirements on the impl of `Contains<(), true>` for `&C` --> $DIR/issue-85848.rs:21:12 |
diff --git a/src/test/ui/const-generics/incorrect-number-of-const-args.stderr b/src/test/ui/const-generics/incorrect-number-of-const-args.stderr index bf873da..a845454 100644 --- a/src/test/ui/const-generics/incorrect-number-of-const-args.stderr +++ b/src/test/ui/const-generics/incorrect-number-of-const-args.stderr
@@ -10,7 +10,7 @@ --> $DIR/incorrect-number-of-const-args.rs:1:4 | LL | fn foo<const X: usize, const Y: usize>() -> usize { - | ^^^ - - + | ^^^ -------------- -------------- help: add missing generic argument | LL | foo::<0, Y>(); @@ -28,7 +28,7 @@ --> $DIR/incorrect-number-of-const-args.rs:1:4 | LL | fn foo<const X: usize, const Y: usize>() -> usize { - | ^^^ - - + | ^^^ -------------- -------------- error: aborting due to 2 previous errors
diff --git a/src/test/ui/const-generics/issues/issue-67185-2.stderr b/src/test/ui/const-generics/issues/issue-67185-2.stderr index 89aa3d3..c7be8e1 100644 --- a/src/test/ui/const-generics/issues/issue-67185-2.stderr +++ b/src/test/ui/const-generics/issues/issue-67185-2.stderr
@@ -4,9 +4,9 @@ LL | <u8 as Baz>::Quaks: Bar, | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `[u16; 3]` | - = help: the following implementations were found: - <[[u16; 3]; 3] as Bar> - <[u16; 4] as Bar> + = help: the following other types implement trait `Bar`: + [[u16; 3]; 3] + [u16; 4] = help: see issue #48214 = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable @@ -16,9 +16,9 @@ LL | [<u8 as Baz>::Quaks; 2]: Bar, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `[[u16; 3]; 2]` | - = help: the following implementations were found: - <[[u16; 3]; 3] as Bar> - <[u16; 4] as Bar> + = help: the following other types implement trait `Bar`: + [[u16; 3]; 3] + [u16; 4] = help: see issue #48214 = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable @@ -28,9 +28,9 @@ LL | impl Foo for FooImpl {} | ^^^ the trait `Bar` is not implemented for `[u16; 3]` | - = help: the following implementations were found: - <[[u16; 3]; 3] as Bar> - <[u16; 4] as Bar> + = help: the following other types implement trait `Bar`: + [[u16; 3]; 3] + [u16; 4] note: required by a bound in `Foo` --> $DIR/issue-67185-2.rs:15:25 | @@ -46,9 +46,9 @@ LL | impl Foo for FooImpl {} | ^^^ the trait `Bar` is not implemented for `[[u16; 3]; 2]` | - = help: the following implementations were found: - <[[u16; 3]; 3] as Bar> - <[u16; 4] as Bar> + = help: the following other types implement trait `Bar`: + [[u16; 3]; 3] + [u16; 4] note: required by a bound in `Foo` --> $DIR/issue-67185-2.rs:14:30 | @@ -64,9 +64,9 @@ LL | fn f(_: impl Foo) {} | ^^^ the trait `Bar` is not implemented for `[[u16; 3]; 2]` | - = help: the following implementations were found: - <[[u16; 3]; 3] as Bar> - <[u16; 4] as Bar> + = help: the following other types implement trait `Bar`: + [[u16; 3]; 3] + [u16; 4] note: required by a bound in `Foo` --> $DIR/issue-67185-2.rs:14:30 | @@ -82,9 +82,9 @@ LL | fn f(_: impl Foo) {} | ^^^ the trait `Bar` is not implemented for `[u16; 3]` | - = help: the following implementations were found: - <[[u16; 3]; 3] as Bar> - <[u16; 4] as Bar> + = help: the following other types implement trait `Bar`: + [[u16; 3]; 3] + [u16; 4] note: required by a bound in `Foo` --> $DIR/issue-67185-2.rs:15:25 |
diff --git a/src/test/ui/const-generics/issues/issue-68366.full.stderr b/src/test/ui/const-generics/issues/issue-68366.full.stderr index 4015fb0..ca9eb80 100644 --- a/src/test/ui/const-generics/issues/issue-68366.full.stderr +++ b/src/test/ui/const-generics/issues/issue-68366.full.stderr
@@ -1,17 +1,17 @@ error[E0207]: the const parameter `N` is not constrained by the impl trait, self type, or predicates - --> $DIR/issue-68366.rs:11:13 + --> $DIR/issue-68366.rs:11:7 | LL | impl <const N: usize> Collatz<{Some(N)}> {} - | ^ unconstrained const parameter + | ^^^^^^^^^^^^^^ unconstrained const parameter | = note: expressions using a const parameter must map each value to a distinct output value = note: proving the result of expressions other than the parameter are unique is not supported error[E0207]: the const parameter `N` is not constrained by the impl trait, self type, or predicates - --> $DIR/issue-68366.rs:17:12 + --> $DIR/issue-68366.rs:17:6 | LL | impl<const N: usize> Foo {} - | ^ unconstrained const parameter + | ^^^^^^^^^^^^^^ unconstrained const parameter | = note: expressions using a const parameter must map each value to a distinct output value = note: proving the result of expressions other than the parameter are unique is not supported
diff --git a/src/test/ui/const-generics/issues/issue-68366.min.stderr b/src/test/ui/const-generics/issues/issue-68366.min.stderr index 9f370b0..3740ced 100644 --- a/src/test/ui/const-generics/issues/issue-68366.min.stderr +++ b/src/test/ui/const-generics/issues/issue-68366.min.stderr
@@ -8,19 +8,19 @@ = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions error[E0207]: the const parameter `N` is not constrained by the impl trait, self type, or predicates - --> $DIR/issue-68366.rs:11:13 + --> $DIR/issue-68366.rs:11:7 | LL | impl <const N: usize> Collatz<{Some(N)}> {} - | ^ unconstrained const parameter + | ^^^^^^^^^^^^^^ unconstrained const parameter | = note: expressions using a const parameter must map each value to a distinct output value = note: proving the result of expressions other than the parameter are unique is not supported error[E0207]: the const parameter `N` is not constrained by the impl trait, self type, or predicates - --> $DIR/issue-68366.rs:17:12 + --> $DIR/issue-68366.rs:17:6 | LL | impl<const N: usize> Foo {} - | ^ unconstrained const parameter + | ^^^^^^^^^^^^^^ unconstrained const parameter | = note: expressions using a const parameter must map each value to a distinct output value = note: proving the result of expressions other than the parameter are unique is not supported
diff --git a/src/test/ui/const-generics/issues/issue-86820.stderr b/src/test/ui/const-generics/issues/issue-86820.stderr index f4396f2..f7b8d80 100644 --- a/src/test/ui/const-generics/issues/issue-86820.stderr +++ b/src/test/ui/const-generics/issues/issue-86820.stderr
@@ -1,14 +1,14 @@ error[E0053]: method `bit` has an incompatible const parameter type for trait - --> $DIR/issue-86820.rs:17:18 + --> $DIR/issue-86820.rs:17:12 | LL | fn bit<const I : usize>(self) -> bool { - | ^ + | ^^^^^^^^^^^^^^^ | note: the const parameter `I` has type `usize`, but the declaration in trait `Bits::bit` has type `u8` - --> $DIR/issue-86820.rs:12:18 + --> $DIR/issue-86820.rs:12:12 | LL | fn bit<const I : u8>(self) -> bool; - | ^ + | ^^^^^^^^^^^^ error: aborting due to previous error
diff --git a/src/test/ui/const-generics/min_const_generics/default_function_param.stderr b/src/test/ui/const-generics/min_const_generics/default_function_param.stderr index 07dcd57..dedad28 100644 --- a/src/test/ui/const-generics/min_const_generics/default_function_param.stderr +++ b/src/test/ui/const-generics/min_const_generics/default_function_param.stderr
@@ -1,8 +1,8 @@ error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions - --> $DIR/default_function_param.rs:3:14 + --> $DIR/default_function_param.rs:3:8 | LL | fn foo<const SIZE: usize = 5usize>() {} - | ^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error
diff --git a/src/test/ui/const-generics/occurs-check/unused-substs-1.stderr b/src/test/ui/const-generics/occurs-check/unused-substs-1.stderr index 486a298..8431d98 100644 --- a/src/test/ui/const-generics/occurs-check/unused-substs-1.stderr +++ b/src/test/ui/const-generics/occurs-check/unused-substs-1.stderr
@@ -4,8 +4,7 @@ LL | let _ = A; | ^ the trait `Bar<{_: usize}>` is not implemented for `A<{_: usize}>` | - = help: the following implementations were found: - <A<7_usize> as Bar<N>> + = help: the trait `Bar<N>` is implemented for `A<7_usize>` note: required by a bound in `A` --> $DIR/unused-substs-1.rs:9:11 |
diff --git a/src/test/ui/const-generics/parser-error-recovery/issue-89013-no-kw.stderr b/src/test/ui/const-generics/parser-error-recovery/issue-89013-no-kw.stderr index 59ba054..acfdde8 100644 --- a/src/test/ui/const-generics/parser-error-recovery/issue-89013-no-kw.stderr +++ b/src/test/ui/const-generics/parser-error-recovery/issue-89013-no-kw.stderr
@@ -17,7 +17,7 @@ --> $DIR/issue-89013-no-kw.rs:1:7 | LL | trait Foo<const N: usize> { - | ^^^ - + | ^^^ -------------- help: add missing generic argument | LL | impl Foo<N, N = 3> for Bar {
diff --git a/src/test/ui/const-generics/parser-error-recovery/issue-89013.stderr b/src/test/ui/const-generics/parser-error-recovery/issue-89013.stderr index 9d47399..d2d58c4 100644 --- a/src/test/ui/const-generics/parser-error-recovery/issue-89013.stderr +++ b/src/test/ui/const-generics/parser-error-recovery/issue-89013.stderr
@@ -29,7 +29,7 @@ --> $DIR/issue-89013.rs:1:7 | LL | trait Foo<const N: usize> { - | ^^^ - + | ^^^ -------------- help: add missing generic argument | LL | impl Foo<N, N = const 3> for Bar {
diff --git a/src/test/ui/consts/const-blocks/fn-call-in-non-const.stderr b/src/test/ui/consts/const-blocks/fn-call-in-non-const.stderr index 329c6cb..52a1669 100644 --- a/src/test/ui/consts/const-blocks/fn-call-in-non-const.stderr +++ b/src/test/ui/consts/const-blocks/fn-call-in-non-const.stderr
@@ -4,8 +4,7 @@ LL | let _: [Option<Bar>; 2] = [no_copy(); 2]; | ^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `Option<Bar>` | - = help: the following implementations were found: - <Option<T> as Copy> + = help: the trait `Copy` is implemented for `Option<T>` = note: the `Copy` trait is required because the repeated element will be copied = help: consider creating a new `const` item and initializing it with the result of the function call to be used in the repeat position, like `const VAL: Type = const_fn();` and `let x = [VAL; 42];` = help: create an inline `const` block, see RFC #2920 <https://github.com/rust-lang/rfcs/pull/2920> for more information
diff --git a/src/test/ui/consts/const-blocks/migrate-fail.stderr b/src/test/ui/consts/const-blocks/migrate-fail.stderr index 0fdbbc3..318fec6 100644 --- a/src/test/ui/consts/const-blocks/migrate-fail.stderr +++ b/src/test/ui/consts/const-blocks/migrate-fail.stderr
@@ -4,8 +4,7 @@ LL | let arr: [Option<Bar>; 2] = [x; 2]; | ^^^^^^ the trait `Copy` is not implemented for `Option<Bar>` | - = help: the following implementations were found: - <Option<T> as Copy> + = help: the trait `Copy` is implemented for `Option<T>` = note: the `Copy` trait is required because the repeated element will be copied error[E0277]: the trait bound `Option<Bar>: Copy` is not satisfied @@ -14,8 +13,7 @@ LL | let arr: [Option<Bar>; 2] = [x; 2]; | ^^^^^^ the trait `Copy` is not implemented for `Option<Bar>` | - = help: the following implementations were found: - <Option<T> as Copy> + = help: the trait `Copy` is implemented for `Option<T>` = note: the `Copy` trait is required because the repeated element will be copied error: aborting due to 2 previous errors
diff --git a/src/test/ui/consts/const-blocks/nll-fail.stderr b/src/test/ui/consts/const-blocks/nll-fail.stderr index 8122085..5a34361 100644 --- a/src/test/ui/consts/const-blocks/nll-fail.stderr +++ b/src/test/ui/consts/const-blocks/nll-fail.stderr
@@ -4,8 +4,7 @@ LL | let arr: [Option<Bar>; 2] = [x; 2]; | ^^^^^^ the trait `Copy` is not implemented for `Option<Bar>` | - = help: the following implementations were found: - <Option<T> as Copy> + = help: the trait `Copy` is implemented for `Option<T>` = note: the `Copy` trait is required because the repeated element will be copied error[E0277]: the trait bound `Option<Bar>: Copy` is not satisfied @@ -14,8 +13,7 @@ LL | let arr: [Option<Bar>; 2] = [x; 2]; | ^^^^^^ the trait `Copy` is not implemented for `Option<Bar>` | - = help: the following implementations were found: - <Option<T> as Copy> + = help: the trait `Copy` is implemented for `Option<T>` = note: the `Copy` trait is required because the repeated element will be copied error: aborting due to 2 previous errors
diff --git a/src/test/ui/consts/const-blocks/trait-error.stderr b/src/test/ui/consts/const-blocks/trait-error.stderr index 26e2848..6979ff3 100644 --- a/src/test/ui/consts/const-blocks/trait-error.stderr +++ b/src/test/ui/consts/const-blocks/trait-error.stderr
@@ -4,8 +4,7 @@ LL | [Foo(String::new()); 4]; | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `Foo<String>` | - = help: the following implementations were found: - <Foo<T> as Copy> + = help: the trait `Copy` is implemented for `Foo<T>` = note: the `Copy` trait is required because the repeated element will be copied error: aborting due to previous error
diff --git a/src/test/ui/consts/const-eval/const-eval-overflow-3b.stderr b/src/test/ui/consts/const-eval/const-eval-overflow-3b.stderr index 2b96b66..0e6be6d 100644 --- a/src/test/ui/consts/const-eval/const-eval-overflow-3b.stderr +++ b/src/test/ui/consts/const-eval/const-eval-overflow-3b.stderr
@@ -11,6 +11,16 @@ | ^ no implementation for `i8 + u8` | = help: the trait `Add<u8>` is not implemented for `i8` + = help: the following other types implement trait `Add<Rhs>`: + <&'a f32 as Add<f32>> + <&'a f64 as Add<f64>> + <&'a i128 as Add<i128>> + <&'a i16 as Add<i16>> + <&'a i32 as Add<i32>> + <&'a i64 as Add<i64>> + <&'a i8 as Add<i8>> + <&'a isize as Add<isize>> + and 48 others error: aborting due to 2 previous errors
diff --git a/src/test/ui/consts/const-eval/const-eval-overflow-4b.stderr b/src/test/ui/consts/const-eval/const-eval-overflow-4b.stderr index f59ff32..4fa017e 100644 --- a/src/test/ui/consts/const-eval/const-eval-overflow-4b.stderr +++ b/src/test/ui/consts/const-eval/const-eval-overflow-4b.stderr
@@ -11,6 +11,16 @@ | ^ no implementation for `i8 + u8` | = help: the trait `Add<u8>` is not implemented for `i8` + = help: the following other types implement trait `Add<Rhs>`: + <&'a f32 as Add<f32>> + <&'a f64 as Add<f64>> + <&'a i128 as Add<i128>> + <&'a i16 as Add<i16>> + <&'a i32 as Add<i32>> + <&'a i64 as Add<i64>> + <&'a i8 as Add<i8>> + <&'a isize as Add<isize>> + and 48 others error[E0604]: only `u8` can be cast as `char`, not `i8` --> $DIR/const-eval-overflow-4b.rs:22:13
diff --git a/src/test/ui/consts/issue-69488.rs b/src/test/ui/consts/issue-69488.rs new file mode 100644 index 0000000..46546ea --- /dev/null +++ b/src/test/ui/consts/issue-69488.rs
@@ -0,0 +1,34 @@ +// run-pass + +#![feature(const_ptr_write)] +#![feature(const_mut_refs)] + +// Or, equivalently: `MaybeUninit`. +pub union BagOfBits<T: Copy> { + uninit: (), + _storage: T, +} + +pub const fn make_1u8_bag<T: Copy>() -> BagOfBits<T> { + assert!(core::mem::size_of::<T>() >= 1); + let mut bag = BagOfBits { uninit: () }; + unsafe { (&mut bag as *mut _ as *mut u8).write(1); }; + bag +} + +pub fn check_bag<T: Copy>(bag: &BagOfBits<T>) { + let val = unsafe { (bag as *const _ as *const u8).read() }; + assert_eq!(val, 1); +} + +fn main() { + check_bag(&make_1u8_bag::<[usize; 1]>()); // Fine + check_bag(&make_1u8_bag::<usize>()); // Fine + + const CONST_ARRAY_BAG: BagOfBits<[usize; 1]> = make_1u8_bag(); + check_bag(&CONST_ARRAY_BAG); // Fine. + const CONST_USIZE_BAG: BagOfBits<usize> = make_1u8_bag(); + + // Used to panic since CTFE would make the entire `BagOfBits<usize>` uninit + check_bag(&CONST_USIZE_BAG); +}
diff --git a/src/test/ui/consts/issue-94371.rs b/src/test/ui/consts/issue-94371.rs new file mode 100644 index 0000000..de9ff73 --- /dev/null +++ b/src/test/ui/consts/issue-94371.rs
@@ -0,0 +1,16 @@ +// check-pass + +#![feature(const_swap)] +#![feature(const_mut_refs)] + +#[repr(C)] +struct Demo(u64, bool, u64, u32, u64, u64, u64); + +const C: (Demo, Demo) = { + let mut x = Demo(1, true, 3, 4, 5, 6, 7); + let mut y = Demo(10, false, 12, 13, 14, 15, 16); + std::mem::swap(&mut x, &mut y); + (x, y) +}; + +fn main() {}
diff --git a/src/test/ui/consts/too_generic_eval_ice.stderr b/src/test/ui/consts/too_generic_eval_ice.stderr index ac104ed..8de61fc 100644 --- a/src/test/ui/consts/too_generic_eval_ice.stderr +++ b/src/test/ui/consts/too_generic_eval_ice.stderr
@@ -21,6 +21,16 @@ | ^^ no implementation for `[{integer}; _] == [{integer}; 0]` | = help: the trait `PartialEq<[{integer}; 0]>` is not implemented for `[{integer}; _]` + = help: the following other types implement trait `PartialEq<Rhs>`: + <&[B] as PartialEq<[A; N]>> + <&[T] as PartialEq<Vec<U, A>>> + <&mut [B] as PartialEq<[A; N]>> + <&mut [T] as PartialEq<Vec<U, A>>> + <[A; N] as PartialEq<&[B]>> + <[A; N] as PartialEq<&mut [B]>> + <[A; N] as PartialEq<[B; N]>> + <[A; N] as PartialEq<[B]>> + and 3 others error: aborting due to 3 previous errors
diff --git a/src/test/ui/derives/derives-span-Clone-enum-struct-variant.stderr b/src/test/ui/derives/derives-span-Clone-enum-struct-variant.stderr index cc874576..7326324 100644 --- a/src/test/ui/derives/derives-span-Clone-enum-struct-variant.stderr +++ b/src/test/ui/derives/derives-span-Clone-enum-struct-variant.stderr
@@ -8,6 +8,10 @@ | ^^^^^^^^ the trait `Clone` is not implemented for `Error` | = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(Clone)]` + | +LL | #[derive(Clone)] + | error: aborting due to previous error
diff --git a/src/test/ui/derives/derives-span-Clone-enum.stderr b/src/test/ui/derives/derives-span-Clone-enum.stderr index a487063..229a4f7 100644 --- a/src/test/ui/derives/derives-span-Clone-enum.stderr +++ b/src/test/ui/derives/derives-span-Clone-enum.stderr
@@ -8,6 +8,10 @@ | ^^^^^ the trait `Clone` is not implemented for `Error` | = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(Clone)]` + | +LL | #[derive(Clone)] + | error: aborting due to previous error
diff --git a/src/test/ui/derives/derives-span-Clone-struct.stderr b/src/test/ui/derives/derives-span-Clone-struct.stderr index 4507eec..96bad9e 100644 --- a/src/test/ui/derives/derives-span-Clone-struct.stderr +++ b/src/test/ui/derives/derives-span-Clone-struct.stderr
@@ -8,6 +8,10 @@ | ^^^^^^^^ the trait `Clone` is not implemented for `Error` | = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(Clone)]` + | +LL | #[derive(Clone)] + | error: aborting due to previous error
diff --git a/src/test/ui/derives/derives-span-Clone-tuple-struct.stderr b/src/test/ui/derives/derives-span-Clone-tuple-struct.stderr index a79be7f..b61341e 100644 --- a/src/test/ui/derives/derives-span-Clone-tuple-struct.stderr +++ b/src/test/ui/derives/derives-span-Clone-tuple-struct.stderr
@@ -8,6 +8,10 @@ | ^^^^^ the trait `Clone` is not implemented for `Error` | = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(Clone)]` + | +LL | #[derive(Clone)] + | error: aborting due to previous error
diff --git a/src/test/ui/derives/derives-span-Debug-enum-struct-variant.stderr b/src/test/ui/derives/derives-span-Debug-enum-struct-variant.stderr index bdcbbf0..58a64a4 100644 --- a/src/test/ui/derives/derives-span-Debug-enum-struct-variant.stderr +++ b/src/test/ui/derives/derives-span-Debug-enum-struct-variant.stderr
@@ -10,6 +10,10 @@ = help: the trait `Debug` is not implemented for `Error` = note: add `#[derive(Debug)]` to `Error` or manually `impl Debug for Error` = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(Debug)]` + | +LL | #[derive(Debug)] + | error: aborting due to previous error
diff --git a/src/test/ui/derives/derives-span-Debug-enum.stderr b/src/test/ui/derives/derives-span-Debug-enum.stderr index 4ffb759..e9bb5f9 100644 --- a/src/test/ui/derives/derives-span-Debug-enum.stderr +++ b/src/test/ui/derives/derives-span-Debug-enum.stderr
@@ -10,6 +10,10 @@ = help: the trait `Debug` is not implemented for `Error` = note: add `#[derive(Debug)]` to `Error` or manually `impl Debug for Error` = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(Debug)]` + | +LL | #[derive(Debug)] + | error: aborting due to previous error
diff --git a/src/test/ui/derives/derives-span-Debug-struct.stderr b/src/test/ui/derives/derives-span-Debug-struct.stderr index 74d2460..0a117c0 100644 --- a/src/test/ui/derives/derives-span-Debug-struct.stderr +++ b/src/test/ui/derives/derives-span-Debug-struct.stderr
@@ -10,6 +10,10 @@ = help: the trait `Debug` is not implemented for `Error` = note: add `#[derive(Debug)]` to `Error` or manually `impl Debug for Error` = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(Debug)]` + | +LL | #[derive(Debug)] + | error: aborting due to previous error
diff --git a/src/test/ui/derives/derives-span-Debug-tuple-struct.stderr b/src/test/ui/derives/derives-span-Debug-tuple-struct.stderr index 34ddb4e..f2e90a4 100644 --- a/src/test/ui/derives/derives-span-Debug-tuple-struct.stderr +++ b/src/test/ui/derives/derives-span-Debug-tuple-struct.stderr
@@ -10,6 +10,10 @@ = help: the trait `Debug` is not implemented for `Error` = note: add `#[derive(Debug)]` to `Error` or manually `impl Debug for Error` = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(Debug)]` + | +LL | #[derive(Debug)] + | error: aborting due to previous error
diff --git a/src/test/ui/derives/derives-span-Default-struct.stderr b/src/test/ui/derives/derives-span-Default-struct.stderr index dd2cfaf..d4affd5 100644 --- a/src/test/ui/derives/derives-span-Default-struct.stderr +++ b/src/test/ui/derives/derives-span-Default-struct.stderr
@@ -8,6 +8,10 @@ | ^^^^^^^^ the trait `Default` is not implemented for `Error` | = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(Default)]` + | +LL | #[derive(Default)] + | error: aborting due to previous error
diff --git a/src/test/ui/derives/derives-span-Default-tuple-struct.stderr b/src/test/ui/derives/derives-span-Default-tuple-struct.stderr index 0674d63..129351f 100644 --- a/src/test/ui/derives/derives-span-Default-tuple-struct.stderr +++ b/src/test/ui/derives/derives-span-Default-tuple-struct.stderr
@@ -8,6 +8,10 @@ | ^^^^^ the trait `Default` is not implemented for `Error` | = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(Default)]` + | +LL | #[derive(Default)] + | error: aborting due to previous error
diff --git a/src/test/ui/derives/derives-span-Eq-enum-struct-variant.stderr b/src/test/ui/derives/derives-span-Eq-enum-struct-variant.stderr index 277454a..e3fb234 100644 --- a/src/test/ui/derives/derives-span-Eq-enum-struct-variant.stderr +++ b/src/test/ui/derives/derives-span-Eq-enum-struct-variant.stderr
@@ -13,6 +13,10 @@ LL | pub struct AssertParamIsEq<T: Eq + ?Sized> { | ^^ required by this bound in `AssertParamIsEq` = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(Eq)]` + | +LL | #[derive(Eq)] + | error: aborting due to previous error
diff --git a/src/test/ui/derives/derives-span-Eq-enum.stderr b/src/test/ui/derives/derives-span-Eq-enum.stderr index 6a48ad2..4e10c3f 100644 --- a/src/test/ui/derives/derives-span-Eq-enum.stderr +++ b/src/test/ui/derives/derives-span-Eq-enum.stderr
@@ -13,6 +13,10 @@ LL | pub struct AssertParamIsEq<T: Eq + ?Sized> { | ^^ required by this bound in `AssertParamIsEq` = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(Eq)]` + | +LL | #[derive(Eq)] + | error: aborting due to previous error
diff --git a/src/test/ui/derives/derives-span-Eq-struct.stderr b/src/test/ui/derives/derives-span-Eq-struct.stderr index 7bf83e8..bfdab05 100644 --- a/src/test/ui/derives/derives-span-Eq-struct.stderr +++ b/src/test/ui/derives/derives-span-Eq-struct.stderr
@@ -13,6 +13,10 @@ LL | pub struct AssertParamIsEq<T: Eq + ?Sized> { | ^^ required by this bound in `AssertParamIsEq` = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(Eq)]` + | +LL | #[derive(Eq)] + | error: aborting due to previous error
diff --git a/src/test/ui/derives/derives-span-Eq-tuple-struct.stderr b/src/test/ui/derives/derives-span-Eq-tuple-struct.stderr index 13e2a55..26b8be3 100644 --- a/src/test/ui/derives/derives-span-Eq-tuple-struct.stderr +++ b/src/test/ui/derives/derives-span-Eq-tuple-struct.stderr
@@ -13,6 +13,10 @@ LL | pub struct AssertParamIsEq<T: Eq + ?Sized> { | ^^ required by this bound in `AssertParamIsEq` = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(Eq)]` + | +LL | #[derive(Eq)] + | error: aborting due to previous error
diff --git a/src/test/ui/derives/derives-span-Hash-enum-struct-variant.stderr b/src/test/ui/derives/derives-span-Hash-enum-struct-variant.stderr index 7f24be9..fe5e0e9 100644 --- a/src/test/ui/derives/derives-span-Hash-enum-struct-variant.stderr +++ b/src/test/ui/derives/derives-span-Hash-enum-struct-variant.stderr
@@ -8,6 +8,10 @@ | ^^^^^^^^ the trait `Hash` is not implemented for `Error` | = note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(Hash)]` + | +LL | #[derive(Hash)] + | error: aborting due to previous error
diff --git a/src/test/ui/derives/derives-span-Hash-enum.stderr b/src/test/ui/derives/derives-span-Hash-enum.stderr index ae2921a..99785b8 100644 --- a/src/test/ui/derives/derives-span-Hash-enum.stderr +++ b/src/test/ui/derives/derives-span-Hash-enum.stderr
@@ -8,6 +8,10 @@ | ^^^^^ the trait `Hash` is not implemented for `Error` | = note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(Hash)]` + | +LL | #[derive(Hash)] + | error: aborting due to previous error
diff --git a/src/test/ui/derives/derives-span-Hash-struct.stderr b/src/test/ui/derives/derives-span-Hash-struct.stderr index 37b3af7..4db83dd 100644 --- a/src/test/ui/derives/derives-span-Hash-struct.stderr +++ b/src/test/ui/derives/derives-span-Hash-struct.stderr
@@ -8,6 +8,10 @@ | ^^^^^^^^ the trait `Hash` is not implemented for `Error` | = note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(Hash)]` + | +LL | #[derive(Hash)] + | error: aborting due to previous error
diff --git a/src/test/ui/derives/derives-span-Hash-tuple-struct.stderr b/src/test/ui/derives/derives-span-Hash-tuple-struct.stderr index 1862466..8660c97 100644 --- a/src/test/ui/derives/derives-span-Hash-tuple-struct.stderr +++ b/src/test/ui/derives/derives-span-Hash-tuple-struct.stderr
@@ -8,6 +8,10 @@ | ^^^^^ the trait `Hash` is not implemented for `Error` | = note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(Hash)]` + | +LL | #[derive(Hash)] + | error: aborting due to previous error
diff --git a/src/test/ui/derives/derives-span-Ord-enum-struct-variant.stderr b/src/test/ui/derives/derives-span-Ord-enum-struct-variant.stderr index b52c5a0..6e48332 100644 --- a/src/test/ui/derives/derives-span-Ord-enum-struct-variant.stderr +++ b/src/test/ui/derives/derives-span-Ord-enum-struct-variant.stderr
@@ -8,6 +8,10 @@ | ^^^^^^^^ the trait `Ord` is not implemented for `Error` | = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(Ord)]` + | +LL | #[derive(Ord)] + | error: aborting due to previous error
diff --git a/src/test/ui/derives/derives-span-Ord-enum.stderr b/src/test/ui/derives/derives-span-Ord-enum.stderr index 2ea0496..b05cf0a 100644 --- a/src/test/ui/derives/derives-span-Ord-enum.stderr +++ b/src/test/ui/derives/derives-span-Ord-enum.stderr
@@ -8,6 +8,10 @@ | ^^^^^ the trait `Ord` is not implemented for `Error` | = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(Ord)]` + | +LL | #[derive(Ord)] + | error: aborting due to previous error
diff --git a/src/test/ui/derives/derives-span-Ord-struct.stderr b/src/test/ui/derives/derives-span-Ord-struct.stderr index 52cf0cf..c4def34 100644 --- a/src/test/ui/derives/derives-span-Ord-struct.stderr +++ b/src/test/ui/derives/derives-span-Ord-struct.stderr
@@ -8,6 +8,10 @@ | ^^^^^^^^ the trait `Ord` is not implemented for `Error` | = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(Ord)]` + | +LL | #[derive(Ord)] + | error: aborting due to previous error
diff --git a/src/test/ui/derives/derives-span-Ord-tuple-struct.stderr b/src/test/ui/derives/derives-span-Ord-tuple-struct.stderr index ecdf8d8..a3b288d 100644 --- a/src/test/ui/derives/derives-span-Ord-tuple-struct.stderr +++ b/src/test/ui/derives/derives-span-Ord-tuple-struct.stderr
@@ -8,6 +8,10 @@ | ^^^^^ the trait `Ord` is not implemented for `Error` | = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(Ord)]` + | +LL | #[derive(Ord)] + | error: aborting due to previous error
diff --git a/src/test/ui/derives/derives-span-PartialOrd-enum-struct-variant.stderr b/src/test/ui/derives/derives-span-PartialOrd-enum-struct-variant.stderr index fc8eb1e..2d19aaf 100644 --- a/src/test/ui/derives/derives-span-PartialOrd-enum-struct-variant.stderr +++ b/src/test/ui/derives/derives-span-PartialOrd-enum-struct-variant.stderr
@@ -9,6 +9,10 @@ | = help: the trait `PartialOrd` is not implemented for `Error` = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(PartialOrd)]` + | +LL | #[derive(PartialOrd)] + | error: aborting due to previous error
diff --git a/src/test/ui/derives/derives-span-PartialOrd-enum.stderr b/src/test/ui/derives/derives-span-PartialOrd-enum.stderr index 3805349..dfbb806 100644 --- a/src/test/ui/derives/derives-span-PartialOrd-enum.stderr +++ b/src/test/ui/derives/derives-span-PartialOrd-enum.stderr
@@ -9,6 +9,10 @@ | = help: the trait `PartialOrd` is not implemented for `Error` = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(PartialOrd)]` + | +LL | #[derive(PartialOrd)] + | error: aborting due to previous error
diff --git a/src/test/ui/derives/derives-span-PartialOrd-struct.stderr b/src/test/ui/derives/derives-span-PartialOrd-struct.stderr index 1c07b98..ba63d86 100644 --- a/src/test/ui/derives/derives-span-PartialOrd-struct.stderr +++ b/src/test/ui/derives/derives-span-PartialOrd-struct.stderr
@@ -9,6 +9,10 @@ | = help: the trait `PartialOrd` is not implemented for `Error` = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(PartialOrd)]` + | +LL | #[derive(PartialOrd)] + | error: aborting due to previous error
diff --git a/src/test/ui/derives/derives-span-PartialOrd-tuple-struct.stderr b/src/test/ui/derives/derives-span-PartialOrd-tuple-struct.stderr index bf01252..7686ed8 100644 --- a/src/test/ui/derives/derives-span-PartialOrd-tuple-struct.stderr +++ b/src/test/ui/derives/derives-span-PartialOrd-tuple-struct.stderr
@@ -9,6 +9,10 @@ | = help: the trait `PartialOrd` is not implemented for `Error` = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(PartialOrd)]` + | +LL | #[derive(PartialOrd)] + | error: aborting due to previous error
diff --git a/src/test/ui/derives/deriving-no-inner-impl-error-message.stderr b/src/test/ui/derives/deriving-no-inner-impl-error-message.stderr index d64b450..451058c 100644 --- a/src/test/ui/derives/deriving-no-inner-impl-error-message.stderr +++ b/src/test/ui/derives/deriving-no-inner-impl-error-message.stderr
@@ -48,6 +48,10 @@ | ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `NoCloneOrEq` | = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `NoCloneOrEq` with `#[derive(Clone)]` + | +LL | #[derive(Clone)] + | error: aborting due to 3 previous errors
diff --git a/src/test/ui/derives/issue-91550.stderr b/src/test/ui/derives/issue-91550.stderr index bf4b7c7..1b26d75 100644 --- a/src/test/ui/derives/issue-91550.stderr +++ b/src/test/ui/derives/issue-91550.stderr
@@ -8,7 +8,7 @@ | doesn't satisfy `Value: Hash` ... LL | hs.insert(Value(0)); - | ^^^^^^ method cannot be called on `HashSet<Value>` due to unsatisfied trait bounds + | ^^^^^^ | = note: the following trait bounds were not satisfied: `Value: Eq`
diff --git a/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.stderr b/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.stderr index 8aedb42..26764bc 100644 --- a/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.stderr +++ b/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.stderr
@@ -4,7 +4,7 @@ LL | f1.foo(1usize); | ^^^ the trait `Foo<usize>` is not implemented for `Bar` | - = help: the following implementations were found: + = help: the following other types implement trait `Foo<A>`: <Bar as Foo<i32>> <Bar as Foo<u8>>
diff --git a/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr b/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr index d6d5ce4..bb17536 100644 --- a/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr +++ b/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr
@@ -4,12 +4,13 @@ LL | f1.foo(1usize); | ^^^ the trait `Foo<usize>` is not implemented for `Bar` | - = help: the following implementations were found: + = help: the following other types implement trait `Foo<A>`: <Bar as Foo<i16>> <Bar as Foo<i32>> <Bar as Foo<i8>> <Bar as Foo<u16>> - and 2 others + <Bar as Foo<u32>> + <Bar as Foo<u8>> error: aborting due to previous error
diff --git a/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr b/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr index dff9803..d27b05f 100644 --- a/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr +++ b/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr
@@ -6,12 +6,16 @@ | | | required by a bound introduced by this call | - = help: the following implementations were found: + = help: the following other types implement trait `Foo<B>`: <i8 as Foo<bool>> <i8 as Foo<u16>> <i8 as Foo<u32>> <i8 as Foo<u64>> - and 5 others + <i8 as Foo<u8>> + <u8 as Foo<bool>> + <u8 as Foo<u16>> + <u8 as Foo<u32>> + <u8 as Foo<u64>> error[E0277]: the trait bound `u8: Foo<i32>` is not satisfied --> $DIR/issue-39802-show-5-trait-impls.rs:25:21 @@ -21,12 +25,16 @@ | | | required by a bound introduced by this call | - = help: the following implementations were found: + = help: the following other types implement trait `Foo<B>`: + <i8 as Foo<bool>> + <i8 as Foo<u16>> + <i8 as Foo<u32>> + <i8 as Foo<u64>> + <i8 as Foo<u8>> <u8 as Foo<bool>> <u8 as Foo<u16>> <u8 as Foo<u32>> <u8 as Foo<u64>> - and 5 others error[E0277]: the trait bound `bool: Foo<i32>` is not satisfied --> $DIR/issue-39802-show-5-trait-impls.rs:26:21 @@ -36,12 +44,13 @@ | | | required by a bound introduced by this call | - = help: the following implementations were found: + = help: the following other types implement trait `Foo<B>`: <bool as Foo<bool>> <bool as Foo<i8>> <bool as Foo<u16>> <bool as Foo<u32>> - and 2 others + <bool as Foo<u64>> + <bool as Foo<u8>> error: aborting due to 3 previous errors
diff --git a/src/test/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.stderr b/src/test/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.stderr index 83fc37e..2698668 100644 --- a/src/test/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.stderr +++ b/src/test/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.stderr
@@ -22,6 +22,16 @@ | ^ no implementation for `{float} - {integer}` | = help: the trait `Sub<{integer}>` is not implemented for `{float}` + = help: the following other types implement trait `Sub<Rhs>`: + <&'a f32 as Sub<f32>> + <&'a f64 as Sub<f64>> + <&'a i128 as Sub<i128>> + <&'a i16 as Sub<i16>> + <&'a i32 as Sub<i32>> + <&'a i64 as Sub<i64>> + <&'a i8 as Sub<i8>> + <&'a isize as Sub<isize>> + and 48 others error: aborting due to 3 previous errors
diff --git a/src/test/ui/error-codes/E0184.stderr b/src/test/ui/error-codes/E0184.stderr index 5bfeaa5..bb3017b 100644 --- a/src/test/ui/error-codes/E0184.stderr +++ b/src/test/ui/error-codes/E0184.stderr
@@ -2,7 +2,7 @@ --> $DIR/E0184.rs:1:10 | LL | #[derive(Copy)] - | ^^^^ Copy not allowed on types with destructors + | ^^^^ `Copy` not allowed on types with destructors | = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/src/test/ui/error-codes/E0277-3.rs b/src/test/ui/error-codes/E0277-3.rs new file mode 100644 index 0000000..428be79 --- /dev/null +++ b/src/test/ui/error-codes/E0277-3.rs
@@ -0,0 +1,8 @@ +fn foo<T: PartialEq>(_: T) {} + +struct S; + +fn main() { + foo(S); + //~^ ERROR can't compare `S` with `S` +}
diff --git a/src/test/ui/error-codes/E0277-3.stderr b/src/test/ui/error-codes/E0277-3.stderr new file mode 100644 index 0000000..0127e1c --- /dev/null +++ b/src/test/ui/error-codes/E0277-3.stderr
@@ -0,0 +1,22 @@ +error[E0277]: can't compare `S` with `S` + --> $DIR/E0277-3.rs:6:9 + | +LL | foo(S); + | --- ^ no implementation for `S == S` + | | + | required by a bound introduced by this call + | + = help: the trait `PartialEq` is not implemented for `S` +note: required by a bound in `foo` + --> $DIR/E0277-3.rs:1:11 + | +LL | fn foo<T: PartialEq>(_: T) {} + | ^^^^^^^^^ required by this bound in `foo` +help: consider annotating `S` with `#[derive(PartialEq)]` + | +LL | #[derive(PartialEq)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/exclusive-drop-and-copy.stderr b/src/test/ui/exclusive-drop-and-copy.stderr index 36ee657..8649c8a 100644 --- a/src/test/ui/exclusive-drop-and-copy.stderr +++ b/src/test/ui/exclusive-drop-and-copy.stderr
@@ -2,7 +2,7 @@ --> $DIR/exclusive-drop-and-copy.rs:3:10 | LL | #[derive(Copy, Clone)] - | ^^^^ Copy not allowed on types with destructors + | ^^^^ `Copy` not allowed on types with destructors | = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -10,7 +10,7 @@ --> $DIR/exclusive-drop-and-copy.rs:10:10 | LL | #[derive(Copy, Clone)] - | ^^^^ Copy not allowed on types with destructors + | ^^^^ `Copy` not allowed on types with destructors | = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/src/test/ui/feature-gates/feature-gate-default_type_parameter_fallback.stderr b/src/test/ui/feature-gates/feature-gate-default_type_parameter_fallback.stderr index 5cd38eb..a7d5c7a 100644 --- a/src/test/ui/feature-gates/feature-gate-default_type_parameter_fallback.stderr +++ b/src/test/ui/feature-gates/feature-gate-default_type_parameter_fallback.stderr
@@ -2,7 +2,7 @@ --> $DIR/feature-gate-default_type_parameter_fallback.rs:3:8 | LL | fn avg<T=i32>(_: T) {} - | ^ + | ^^^^^ | = note: `#[deny(invalid_type_param_default)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -12,7 +12,7 @@ --> $DIR/feature-gate-default_type_parameter_fallback.rs:8:6 | LL | impl<T=i32> S<T> {} - | ^ + | ^^^^^ | = 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 #36887 <https://github.com/rust-lang/rust/issues/36887>
diff --git a/src/test/ui/feature-gates/feature-gate-trivial_bounds.stderr b/src/test/ui/feature-gates/feature-gate-trivial_bounds.stderr index 28c49c3..1b87ebd 100644 --- a/src/test/ui/feature-gates/feature-gate-trivial_bounds.stderr +++ b/src/test/ui/feature-gates/feature-gate-trivial_bounds.stderr
@@ -4,6 +4,7 @@ LL | enum E where i32: Foo { V } | ^^^^^^^^ the trait `Foo` is not implemented for `i32` | + = help: the trait `Foo` is implemented for `()` = help: see issue #48214 = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable @@ -13,6 +14,7 @@ LL | struct S where i32: Foo; | ^^^^^^^^ the trait `Foo` is not implemented for `i32` | + = help: the trait `Foo` is implemented for `()` = help: see issue #48214 = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable @@ -22,6 +24,7 @@ LL | trait T where i32: Foo {} | ^^^^^^^^ the trait `Foo` is not implemented for `i32` | + = help: the trait `Foo` is implemented for `()` = help: see issue #48214 = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable @@ -31,6 +34,7 @@ LL | union U where i32: Foo { f: i32 } | ^^^^^^^^ the trait `Foo` is not implemented for `i32` | + = help: the trait `Foo` is implemented for `()` = help: see issue #48214 = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable @@ -40,6 +44,7 @@ LL | impl Foo for () where i32: Foo { | ^^^^^^^^ the trait `Foo` is not implemented for `i32` | + = help: the trait `Foo` is implemented for `()` = help: see issue #48214 = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable @@ -49,6 +54,7 @@ LL | fn f() where i32: Foo | ^^^^^^^^ the trait `Foo` is not implemented for `i32` | + = help: the trait `Foo` is implemented for `()` = help: see issue #48214 = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
diff --git a/src/test/ui/fmt/ifmt-unimpl.stderr b/src/test/ui/fmt/ifmt-unimpl.stderr index 6e8dd79..5204afa 100644 --- a/src/test/ui/fmt/ifmt-unimpl.stderr +++ b/src/test/ui/fmt/ifmt-unimpl.stderr
@@ -4,6 +4,16 @@ LL | format!("{:X}", "3"); | ^^^ the trait `UpperHex` is not implemented for `str` | + = help: the following other types implement trait `UpperHex`: + &T + &mut T + NonZeroI128 + NonZeroI16 + NonZeroI32 + NonZeroI64 + NonZeroI8 + NonZeroIsize + and 21 others = note: required because of the requirements on the impl of `UpperHex` for `&str` note: required by a bound in `ArgumentV1::<'a>::new_upper_hex` --> $SRC_DIR/core/src/fmt/mod.rs:LL:COL
diff --git a/src/test/ui/generic-associated-types/bugs/issue-88460.stderr b/src/test/ui/generic-associated-types/bugs/issue-88460.stderr index 0b83e9d..98c304c 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-88460.stderr +++ b/src/test/ui/generic-associated-types/bugs/issue-88460.stderr
@@ -4,6 +4,7 @@ LL | test(Foo); | ^^^^ the trait `for<'a> Marker` is not implemented for `<_ as Trait>::Assoc<'a>` | + = help: the trait `Marker` is implemented for `()` note: required by a bound in `test` --> $DIR/issue-88460.rs:17:27 |
diff --git a/src/test/ui/generic-associated-types/issue-87429-associated-type-default.stderr b/src/test/ui/generic-associated-types/issue-87429-associated-type-default.stderr index e5db2f1..c6fa02c 100644 --- a/src/test/ui/generic-associated-types/issue-87429-associated-type-default.stderr +++ b/src/test/ui/generic-associated-types/issue-87429-associated-type-default.stderr
@@ -10,6 +10,10 @@ | LL | type Member<'a>: for<'b> PartialEq<Self::Member<'b>> = Foo; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Family2::Member` +help: consider annotating `Foo` with `#[derive(PartialEq)]` + | +LL | #[derive(PartialEq)] + | error: aborting due to previous error
diff --git a/src/test/ui/generic-associated-types/issue-87429-specialization.stderr b/src/test/ui/generic-associated-types/issue-87429-specialization.stderr index ca44ecf..015e0c7 100644 --- a/src/test/ui/generic-associated-types/issue-87429-specialization.stderr +++ b/src/test/ui/generic-associated-types/issue-87429-specialization.stderr
@@ -20,6 +20,10 @@ | LL | type Member<'a>: for<'b> PartialEq<Self::Member<'b>>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Family::Member` +help: consider annotating `Foo` with `#[derive(PartialEq)]` + | +LL | #[derive(PartialEq)] + | error: aborting due to previous error; 1 warning emitted
diff --git a/src/test/ui/generics/generic-impl-more-params-with-defaults.stderr b/src/test/ui/generics/generic-impl-more-params-with-defaults.stderr index 0592895..fe9b670 100644 --- a/src/test/ui/generics/generic-impl-more-params-with-defaults.stderr +++ b/src/test/ui/generics/generic-impl-more-params-with-defaults.stderr
@@ -10,7 +10,7 @@ --> $DIR/generic-impl-more-params-with-defaults.rs:5:8 | LL | struct Vec<T, A = Heap>( - | ^^^ - - + | ^^^ - -------- error: aborting due to previous error
diff --git a/src/test/ui/generics/generic-type-more-params-with-defaults.stderr b/src/test/ui/generics/generic-type-more-params-with-defaults.stderr index 500880c..7f0198f 100644 --- a/src/test/ui/generics/generic-type-more-params-with-defaults.stderr +++ b/src/test/ui/generics/generic-type-more-params-with-defaults.stderr
@@ -10,7 +10,7 @@ --> $DIR/generic-type-more-params-with-defaults.rs:5:8 | LL | struct Vec<T, A = Heap>( - | ^^^ - - + | ^^^ - -------- error: aborting due to previous error
diff --git a/src/test/ui/generics/issue-61631-default-type-param-can-reference-self-in-trait.stderr b/src/test/ui/generics/issue-61631-default-type-param-can-reference-self-in-trait.stderr index 2c397d8..6791182 100644 --- a/src/test/ui/generics/issue-61631-default-type-param-can-reference-self-in-trait.stderr +++ b/src/test/ui/generics/issue-61631-default-type-param-can-reference-self-in-trait.stderr
@@ -9,7 +9,7 @@ --> $DIR/issue-61631-default-type-param-can-reference-self-in-trait.rs:17:14 | LL | trait Tsized<P: Sized = [Self]> {} - | ^ required by this bound in `Tsized` + | ^^^^^^^^^^^^^^^^^ required by this bound in `Tsized` error: aborting due to previous error
diff --git a/src/test/ui/generics/wrong-number-of-args.stderr b/src/test/ui/generics/wrong-number-of-args.stderr index 22da0df..3b0834a 100644 --- a/src/test/ui/generics/wrong-number-of-args.stderr +++ b/src/test/ui/generics/wrong-number-of-args.stderr
@@ -287,7 +287,7 @@ --> $DIR/wrong-number-of-args.rs:78:12 | LL | struct Ty<A, B, C = &'static str>; - | ^^ - - - + | ^^ - - ---------------- error[E0107]: this struct takes at least 2 generic arguments but 0 generic arguments were supplied --> $DIR/wrong-number-of-args.rs:96:14 @@ -922,7 +922,7 @@ --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL | LL | pub struct HashMap<K, V, S = RandomState> { - | ^^^^^^^ - - - + | ^^^^^^^ - - --------------- error[E0107]: this struct takes at least 2 generic arguments but 0 generic arguments were supplied --> $DIR/wrong-number-of-args.rs:319:18
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-80706.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-80706.rs index 112227c..00a866f 100644 --- a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-80706.rs +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-80706.rs
@@ -1,4 +1,4 @@ -// check-pass +// build-pass // edition:2018 type BoxFuture<T> = std::pin::Pin<Box<dyn std::future::Future<Output=T>>>; @@ -65,6 +65,7 @@ async fn run<S>(dep: &str) where S: Storage, for<'a> SaveUser<'a>: StorageRequest<S>, + for<'a> SaveUser<'a>: StorageRequestReturnType, { User { dep }.save().await; }
diff --git a/src/test/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.nll.stderr b/src/test/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.nll.stderr index b4c54d5..f5db68e 100644 --- a/src/test/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.nll.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.nll.stderr
@@ -13,8 +13,8 @@ | |______________- in this macro invocation | = help: consider adding the following bound: `'x: 'y` - = note: requirement occurs because of the type Inv<'_>, which makes the generic argument '_ invariant - = note: the struct Inv<'a> is invariant over the parameter 'a + = note: requirement occurs because of the type `Inv<'_>`, which makes the generic argument `'_` invariant + = note: the struct `Inv<'a>` is invariant over the parameter `'a` = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance = note: this error originates in the macro `check` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -33,8 +33,8 @@ | |______________- in this macro invocation | = help: consider adding the following bound: `'x: 'y` - = note: requirement occurs because of the type Inv<'_>, which makes the generic argument '_ invariant - = note: the struct Inv<'a> is invariant over the parameter 'a + = note: requirement occurs because of the type `Inv<'_>`, which makes the generic argument `'_` invariant + = note: the struct `Inv<'a>` is invariant over the parameter `'a` = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance = note: this error originates in the macro `check` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/src/test/ui/hrtb/issue-94034.rs b/src/test/ui/hrtb/issue-94034.rs new file mode 100644 index 0000000..5239e5d --- /dev/null +++ b/src/test/ui/hrtb/issue-94034.rs
@@ -0,0 +1,96 @@ +// known-bug +// failure-status: 101 +// compile-flags: --edition=2021 --crate-type=lib +// rustc-env:RUST_BACKTRACE=0 + +// normalize-stderr-test "thread 'rustc' panicked.*" -> "thread 'rustc' panicked" +// normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> "" +// normalize-stderr-test "\nerror: internal compiler error.*\n\n" -> "" +// normalize-stderr-test "note:.*unexpectedly panicked.*\n\n" -> "" +// normalize-stderr-test "note: we would appreciate a bug report.*\n\n" -> "" +// normalize-stderr-test "note: compiler flags.*\n\n" -> "" +// normalize-stderr-test "note: rustc.*running on.*\n\n" -> "" +// normalize-stderr-test "query stack during panic:\n" -> "" +// normalize-stderr-test "we're just showing a limited slice of the query stack\n" -> "" +// normalize-stderr-test "end of query stack\n" -> "" +// normalize-stderr-test "#.*\n" -> "" + +// This should not ICE. + +use std::{ + future::Future, + marker::PhantomData, + pin::Pin, + task::{Context, Poll}, +}; + +mod object { + use super::*; + + pub trait Object<'a> { + type Error; + type Future: Future<Output = Self>; + fn create() -> Self::Future; + } + + impl<'a> Object<'a> for u8 { + type Error = (); + type Future = Pin<Box<dyn Future<Output = Self>>>; + fn create() -> Self::Future { + unimplemented!() + } + } + + impl<'a, E, A: Object<'a, Error = E>> Object<'a> for (A,) { + type Error = (); + type Future = CustomFut<'a, E, A>; + fn create() -> Self::Future { + unimplemented!() + } + } + + pub struct CustomFut<'f, E, A: Object<'f, Error = E>> { + ph: PhantomData<(A::Future,)>, + } + + impl<'f, E, A: Object<'f, Error = E>> Future for CustomFut<'f, E, A> { + type Output = (A,); + fn poll(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Self::Output> { + unimplemented!() + } + } +} + +mod async_fn { + use super::*; + + pub trait AsyncFn { + type Future: Future<Output = ()>; + fn call(&self) -> Self::Future; + } + + impl<F, Fut> AsyncFn for F + where + F: Fn() -> Fut, + Fut: Future<Output = ()>, + { + type Future = Fut; + fn call(&self) -> Self::Future { + (self)() + } + } +} + +pub async fn test() { + use self::{async_fn::AsyncFn, object::Object}; + + async fn create<T: Object<'static>>() { + T::create().await; + } + + async fn call_async_fn(inner: impl AsyncFn) { + inner.call().await; + } + + call_async_fn(create::<(u8,)>).await; +}
diff --git a/src/test/ui/hrtb/issue-94034.stderr b/src/test/ui/hrtb/issue-94034.stderr new file mode 100644 index 0000000..1d83291 --- /dev/null +++ b/src/test/ui/hrtb/issue-94034.stderr
@@ -0,0 +1 @@ +thread 'rustc' panicked
diff --git a/src/test/ui/impl-trait/cross-return-site-inference.stderr b/src/test/ui/impl-trait/cross-return-site-inference.stderr index 06afb93..d458c7b 100644 --- a/src/test/ui/impl-trait/cross-return-site-inference.stderr +++ b/src/test/ui/impl-trait/cross-return-site-inference.stderr
@@ -7,6 +7,7 @@ | ^ the trait `From<&str>` is not implemented for `impl Debug` | = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait + = help: the trait `FromResidual<Result<Infallible, E>>` is implemented for `Result<T, F>` = note: required because of the requirements on the impl of `FromResidual<Result<Infallible, &str>>` for `Result<(), impl Debug>` error[E0277]: the trait bound `impl Debug: From<&str>` is not satisfied
diff --git a/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr b/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr index 0d4f82b..f90399b 100644 --- a/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr +++ b/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr
@@ -81,7 +81,7 @@ help: use a boxed trait object if all return paths implement trait `Trait` | LL | fn bak() -> Box<dyn Trait> { unimplemented!() } - | ~~~~~~~~~~~~~~ + | ++++ + error[E0746]: return type cannot have an unboxed trait object --> $DIR/dyn-trait-return-should-be-impl-trait.rs:19:13 @@ -95,12 +95,16 @@ = note: you can create a new `enum` with a variant for each returned type help: return a boxed trait object instead | -LL ~ fn bal() -> Box<dyn Trait> { -LL | if true { -LL ~ return Box::new(Struct); -LL | } -LL ~ Box::new(42) +LL | fn bal() -> Box<dyn Trait> { + | ++++ + +help: ... and box this value | +LL | return Box::new(Struct); + | +++++++++ + +help: ... and box this value + | +LL | Box::new(42) + | +++++++++ + error[E0308]: `if` and `else` have incompatible types --> $DIR/dyn-trait-return-should-be-impl-trait.rs:29:9 @@ -126,12 +130,16 @@ = note: you can create a new `enum` with a variant for each returned type help: return a boxed trait object instead | -LL ~ fn bax() -> Box<dyn Trait> { -LL | if true { -LL ~ Box::new(Struct) -LL | } else { -LL ~ Box::new(42) +LL | fn bax() -> Box<dyn Trait> { + | ++++ + +help: ... and box this value | +LL | Box::new(Struct) + | +++++++++ + +help: ... and box this value + | +LL | Box::new(42) + | +++++++++ + error[E0308]: mismatched types --> $DIR/dyn-trait-return-should-be-impl-trait.rs:34:16
diff --git a/src/test/ui/impl-trait/equality.stderr b/src/test/ui/impl-trait/equality.stderr index 804ccbc..f14b447 100644 --- a/src/test/ui/impl-trait/equality.stderr +++ b/src/test/ui/impl-trait/equality.stderr
@@ -24,6 +24,16 @@ | ^ no implementation for `u32 + impl Foo` | = help: the trait `Add<impl Foo>` is not implemented for `u32` + = help: the following other types implement trait `Add<Rhs>`: + <&'a f32 as Add<f32>> + <&'a f64 as Add<f64>> + <&'a i128 as Add<i128>> + <&'a i16 as Add<i16>> + <&'a i32 as Add<i32>> + <&'a i64 as Add<i64>> + <&'a i8 as Add<i8>> + <&'a isize as Add<isize>> + and 48 others error: aborting due to 2 previous errors; 1 warning emitted
diff --git a/src/test/ui/impl-trait/issues/issue-62742.stderr b/src/test/ui/impl-trait/issues/issue-62742.stderr index 28068b7..70d693b 100644 --- a/src/test/ui/impl-trait/issues/issue-62742.stderr +++ b/src/test/ui/impl-trait/issues/issue-62742.stderr
@@ -4,8 +4,7 @@ LL | WrongImpl::foo(0i32); | ^^^^^^^^^ the trait `Raw<_>` is not implemented for `RawImpl<_>` | - = help: the following implementations were found: - <RawImpl<T> as Raw<[T]>> + = help: the trait `Raw<[T]>` is implemented for `RawImpl<T>` note: required by a bound in `SafeImpl` --> $DIR/issue-62742.rs:26:35 | @@ -40,8 +39,7 @@ LL | WrongImpl::<()>::foo(0i32); | ^^^^^^^^^^^^^^^ the trait `Raw<()>` is not implemented for `RawImpl<()>` | - = help: the following implementations were found: - <RawImpl<T> as Raw<[T]>> + = help: the trait `Raw<[T]>` is implemented for `RawImpl<T>` note: required by a bound in `SafeImpl` --> $DIR/issue-62742.rs:26:35 |
diff --git a/src/test/ui/impl-trait/nested-return-type2-tait.stderr b/src/test/ui/impl-trait/nested-return-type2-tait.stderr index 776c06b..81a75e3 100644 --- a/src/test/ui/impl-trait/nested-return-type2-tait.stderr +++ b/src/test/ui/impl-trait/nested-return-type2-tait.stderr
@@ -4,6 +4,7 @@ LL | fn foo() -> impl Trait<Assoc = Sendable> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Duh` is not implemented for `Sendable` | + = help: the trait `Duh` is implemented for `i32` note: required because of the requirements on the impl of `Trait` for `[closure@$DIR/nested-return-type2-tait.rs:28:5: 28:10]` --> $DIR/nested-return-type2-tait.rs:14:31 | @@ -21,6 +22,7 @@ LL | | } | |_^ the trait `Duh` is not implemented for `Sendable` | + = help: the trait `Duh` is implemented for `i32` note: required because of the requirements on the impl of `Trait` for `[closure@$DIR/nested-return-type2-tait.rs:28:5: 28:10]` --> $DIR/nested-return-type2-tait.rs:14:31 |
diff --git a/src/test/ui/impl-trait/nested-return-type2-tait2.stderr b/src/test/ui/impl-trait/nested-return-type2-tait2.stderr index 4993202..42e65e6 100644 --- a/src/test/ui/impl-trait/nested-return-type2-tait2.stderr +++ b/src/test/ui/impl-trait/nested-return-type2-tait2.stderr
@@ -4,6 +4,7 @@ LL | || 42 | ^^^^^ the trait `Duh` is not implemented for `Sendable` | + = help: the trait `Duh` is implemented for `i32` note: required because of the requirements on the impl of `Trait` for `[closure@$DIR/nested-return-type2-tait2.rs:27:5: 27:10]` --> $DIR/nested-return-type2-tait2.rs:14:31 |
diff --git a/src/test/ui/impl-trait/nested-return-type2-tait3.stderr b/src/test/ui/impl-trait/nested-return-type2-tait3.stderr index efeaf05..4d3691d 100644 --- a/src/test/ui/impl-trait/nested-return-type2-tait3.stderr +++ b/src/test/ui/impl-trait/nested-return-type2-tait3.stderr
@@ -4,6 +4,7 @@ LL | || 42 | ^^^^^ the trait `Duh` is not implemented for `impl Send` | + = help: the trait `Duh` is implemented for `i32` note: required because of the requirements on the impl of `Trait` for `[closure@$DIR/nested-return-type2-tait3.rs:26:5: 26:10]` --> $DIR/nested-return-type2-tait3.rs:14:31 |
diff --git a/src/test/ui/impl-trait/nested_impl_trait.stderr b/src/test/ui/impl-trait/nested_impl_trait.stderr index 26b48c7..bb4ae5e 100644 --- a/src/test/ui/impl-trait/nested_impl_trait.stderr +++ b/src/test/ui/impl-trait/nested_impl_trait.stderr
@@ -52,6 +52,7 @@ LL | fn bad_in_ret_position(x: impl Into<u32>) -> impl Into<impl Debug> { x } | ^^^^^^^^^^^^^^^^^^^^^ the trait `From<impl Into<u32>>` is not implemented for `impl Debug` | + = help: the trait `Into<U>` is implemented for `T` = note: required because of the requirements on the impl of `Into<impl Debug>` for `impl Into<u32>` error[E0277]: the trait bound `impl Debug: From<impl Into<u32>>` is not satisfied @@ -60,6 +61,7 @@ LL | fn bad(x: impl Into<u32>) -> impl Into<impl Debug> { x } | ^^^^^^^^^^^^^^^^^^^^^ the trait `From<impl Into<u32>>` is not implemented for `impl Debug` | + = help: the trait `Into<U>` is implemented for `T` = note: required because of the requirements on the impl of `Into<impl Debug>` for `impl Into<u32>` error: aborting due to 8 previous errors
diff --git a/src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr b/src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr index 0c595f4..10510c1 100644 --- a/src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr +++ b/src/test/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr
@@ -103,13 +103,16 @@ = note: you can create a new `enum` with a variant for each returned type help: return a boxed trait object instead | -LL ~ fn hat() -> Box<dyn std::fmt::Display> { -LL | match 13 { -LL | 0 => { -LL ~ return Box::new(0i32); -LL | } -LL | _ => { - ... +LL | fn hat() -> Box<dyn std::fmt::Display> { + | ++++ + +help: ... and box this value + | +LL | return Box::new(0i32); + | +++++++++ + +help: ... and box this value + | +LL | Box::new(1u32) + | +++++++++ + error[E0308]: `match` arms have incompatible types --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:80:14 @@ -135,12 +138,20 @@ = note: you can create a new `enum` with a variant for each returned type help: return a boxed trait object instead | -LL ~ fn pug() -> Box<dyn std::fmt::Display> { -LL | match 13 { -LL ~ 0 => Box::new(0i32), -LL ~ 1 => Box::new(1u32), -LL ~ _ => Box::new(2u32), +LL | fn pug() -> Box<dyn std::fmt::Display> { + | ++++ + +help: ... and box this value | +LL | 0 => Box::new(0i32), + | +++++++++ + +help: ... and box this value + | +LL | 1 => Box::new(1u32), + | +++++++++ + +help: ... and box this value + | +LL | _ => Box::new(2u32), + | +++++++++ + error[E0308]: `if` and `else` have incompatible types --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:89:9 @@ -166,12 +177,16 @@ = note: you can create a new `enum` with a variant for each returned type help: return a boxed trait object instead | -LL ~ fn man() -> Box<dyn std::fmt::Display> { -LL | if false { -LL ~ Box::new(0i32) -LL | } else { -LL ~ Box::new(1u32) +LL | fn man() -> Box<dyn std::fmt::Display> { + | ++++ + +help: ... and box this value | +LL | Box::new(0i32) + | +++++++++ + +help: ... and box this value + | +LL | Box::new(1u32) + | +++++++++ + error: aborting due to 14 previous errors
diff --git a/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.stderr b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.stderr index 5476bf9..6cd63db 100644 --- a/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.stderr +++ b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.stderr
@@ -5,6 +5,7 @@ | ^^^ no implementation for `Bar == (Bar, i32)` | = help: the trait `PartialEq<(Bar, i32)>` is not implemented for `Bar` + = help: the trait `PartialEq<(Foo, i32)>` is implemented for `Bar` error: aborting due to previous error
diff --git a/src/test/ui/impl-trait/where-allowed.stderr b/src/test/ui/impl-trait/where-allowed.stderr index eef20c2..58a2f79 100644 --- a/src/test/ui/impl-trait/where-allowed.stderr +++ b/src/test/ui/impl-trait/where-allowed.stderr
@@ -293,7 +293,7 @@ --> $DIR/where-allowed.rs:234:7 | LL | impl <T = impl Debug> T {} - | ^ + | ^^^^^^^^^^^^^^ | = note: `#[deny(invalid_type_param_default)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -303,7 +303,7 @@ --> $DIR/where-allowed.rs:241:36 | LL | fn in_method_generic_param_default<T = impl Debug>(_: T) {} - | ^ + | ^^^^^^^^^^^^^^ | = 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 #36887 <https://github.com/rust-lang/rust/issues/36887>
diff --git a/src/test/ui/index-help.stderr b/src/test/ui/index-help.stderr index 78a8f43..7f51a48 100644 --- a/src/test/ui/index-help.stderr +++ b/src/test/ui/index-help.stderr
@@ -5,6 +5,7 @@ | ^^^^^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[{integer}]>` is not implemented for `i32` + = help: the trait `SliceIndex<[T]>` is implemented for `usize` = note: required because of the requirements on the impl of `Index<i32>` for `Vec<{integer}>` error: aborting due to previous error
diff --git a/src/test/ui/indexing-requires-a-uint.stderr b/src/test/ui/indexing-requires-a-uint.stderr index 24f42f2..dae11a7 100644 --- a/src/test/ui/indexing-requires-a-uint.stderr +++ b/src/test/ui/indexing-requires-a-uint.stderr
@@ -5,6 +5,7 @@ | ^^^^^^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[{integer}]>` is not implemented for `u8` + = help: the trait `SliceIndex<[T]>` is implemented for `usize` = note: required because of the requirements on the impl of `Index<u8>` for `[{integer}]` error[E0308]: mismatched types
diff --git a/src/test/ui/integral-indexing.stderr b/src/test/ui/integral-indexing.stderr index fcd79d1..be33985 100644 --- a/src/test/ui/integral-indexing.stderr +++ b/src/test/ui/integral-indexing.stderr
@@ -5,6 +5,7 @@ | ^^^^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[isize]>` is not implemented for `u8` + = help: the trait `SliceIndex<[T]>` is implemented for `usize` = note: required because of the requirements on the impl of `Index<u8>` for `Vec<isize>` error[E0277]: the type `[isize]` cannot be indexed by `i8` @@ -14,6 +15,7 @@ | ^^^^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[isize]>` is not implemented for `i8` + = help: the trait `SliceIndex<[T]>` is implemented for `usize` = note: required because of the requirements on the impl of `Index<i8>` for `Vec<isize>` error[E0277]: the type `[isize]` cannot be indexed by `u32` @@ -23,6 +25,7 @@ | ^^^^^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[isize]>` is not implemented for `u32` + = help: the trait `SliceIndex<[T]>` is implemented for `usize` = note: required because of the requirements on the impl of `Index<u32>` for `Vec<isize>` error[E0277]: the type `[isize]` cannot be indexed by `i32` @@ -32,6 +35,7 @@ | ^^^^^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[isize]>` is not implemented for `i32` + = help: the trait `SliceIndex<[T]>` is implemented for `usize` = note: required because of the requirements on the impl of `Index<i32>` for `Vec<isize>` error[E0277]: the type `[u8]` cannot be indexed by `u8` @@ -41,6 +45,7 @@ | ^^^^^^^^^^^^^^^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[u8]>` is not implemented for `u8` + = help: the trait `SliceIndex<[T]>` is implemented for `usize` = note: required because of the requirements on the impl of `Index<u8>` for `[u8]` error[E0277]: the type `[u8]` cannot be indexed by `i8` @@ -50,6 +55,7 @@ | ^^^^^^^^^^^^^^^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[u8]>` is not implemented for `i8` + = help: the trait `SliceIndex<[T]>` is implemented for `usize` = note: required because of the requirements on the impl of `Index<i8>` for `[u8]` error[E0277]: the type `[u8]` cannot be indexed by `u32` @@ -59,6 +65,7 @@ | ^^^^^^^^^^^^^^^^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[u8]>` is not implemented for `u32` + = help: the trait `SliceIndex<[T]>` is implemented for `usize` = note: required because of the requirements on the impl of `Index<u32>` for `[u8]` error[E0277]: the type `[u8]` cannot be indexed by `i32` @@ -68,6 +75,7 @@ | ^^^^^^^^^^^^^^^^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[u8]>` is not implemented for `i32` + = help: the trait `SliceIndex<[T]>` is implemented for `usize` = note: required because of the requirements on the impl of `Index<i32>` for `[u8]` error: aborting due to 8 previous errors
diff --git a/src/test/ui/intrinsics/const-eval-select-bad.stderr b/src/test/ui/intrinsics/const-eval-select-bad.stderr index c03688d..79f6a58 100644 --- a/src/test/ui/intrinsics/const-eval-select-bad.stderr +++ b/src/test/ui/intrinsics/const-eval-select-bad.stderr
@@ -48,7 +48,7 @@ note: required by a bound in `const_eval_select` --> $SRC_DIR/core/src/intrinsics.rs:LL:COL | -LL | G: FnOnce<ARG, Output = RET> + ~const Drop + ~const Destruct, +LL | G: FnOnce<ARG, Output = RET> + ~const Destruct, | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `const_eval_select` error[E0271]: type mismatch resolving `<fn(i32) -> bool {bar} as FnOnce<(i32,)>>::Output == i32` @@ -60,7 +60,7 @@ note: required by a bound in `const_eval_select` --> $SRC_DIR/core/src/intrinsics.rs:LL:COL | -LL | G: FnOnce<ARG, Output = RET> + ~const Drop + ~const Destruct, +LL | G: FnOnce<ARG, Output = RET> + ~const Destruct, | ^^^^^^^^^^^^ required by this bound in `const_eval_select` error[E0631]: type mismatch in function arguments
diff --git a/src/test/ui/issues/issue-11771.stderr b/src/test/ui/issues/issue-11771.stderr index 9f25092..161fce4 100644 --- a/src/test/ui/issues/issue-11771.stderr +++ b/src/test/ui/issues/issue-11771.stderr
@@ -5,6 +5,16 @@ | ^ no implementation for `{integer} + ()` | = help: the trait `Add<()>` is not implemented for `{integer}` + = help: the following other types implement trait `Add<Rhs>`: + <&'a f32 as Add<f32>> + <&'a f64 as Add<f64>> + <&'a i128 as Add<i128>> + <&'a i16 as Add<i16>> + <&'a i32 as Add<i32>> + <&'a i64 as Add<i64>> + <&'a i8 as Add<i8>> + <&'a isize as Add<isize>> + and 48 others error[E0277]: cannot add `()` to `{integer}` --> $DIR/issue-11771.rs:8:7 @@ -13,6 +23,16 @@ | ^ no implementation for `{integer} + ()` | = help: the trait `Add<()>` is not implemented for `{integer}` + = help: the following other types implement trait `Add<Rhs>`: + <&'a f32 as Add<f32>> + <&'a f64 as Add<f64>> + <&'a i128 as Add<i128>> + <&'a i16 as Add<i16>> + <&'a i32 as Add<i32>> + <&'a i64 as Add<i64>> + <&'a i8 as Add<i8>> + <&'a isize as Add<isize>> + and 48 others error: aborting due to 2 previous errors
diff --git a/src/test/ui/issues/issue-14366.stderr b/src/test/ui/issues/issue-14366.stderr index d5dab56..b96b07c 100644 --- a/src/test/ui/issues/issue-14366.stderr +++ b/src/test/ui/issues/issue-14366.stderr
@@ -6,6 +6,10 @@ | = help: the trait `Sized` is not implemented for `str` = note: required for the cast to the object type `dyn Any` +help: consider borrowing the value, since `&str` can be coerced into `dyn Any` + | +LL | let _x = &"test" as &dyn (::std::any::Any); + | + error: aborting due to previous error
diff --git a/src/test/ui/issues/issue-18107.stderr b/src/test/ui/issues/issue-18107.stderr index 1eb6822..2847845 100644 --- a/src/test/ui/issues/issue-18107.stderr +++ b/src/test/ui/issues/issue-18107.stderr
@@ -15,7 +15,7 @@ help: use a boxed trait object if all return paths implement trait `AbstractRenderer` | LL | Box<dyn AbstractRenderer> - | + | ++++ + error: aborting due to previous error
diff --git a/src/test/ui/issues/issue-20162.stderr b/src/test/ui/issues/issue-20162.stderr index 6848c3f..d70bf6e 100644 --- a/src/test/ui/issues/issue-20162.stderr +++ b/src/test/ui/issues/issue-20162.stderr
@@ -9,6 +9,10 @@ | LL | T: Ord, | ^^^ required by this bound in `slice::<impl [T]>::sort` +help: consider annotating `X` with `#[derive(Ord)]` + | +LL | #[derive(Ord)] + | error: aborting due to previous error
diff --git a/src/test/ui/issues/issue-21160.stderr b/src/test/ui/issues/issue-21160.stderr index 300c127..2667493 100644 --- a/src/test/ui/issues/issue-21160.stderr +++ b/src/test/ui/issues/issue-21160.stderr
@@ -7,6 +7,10 @@ | ^^^ the trait `Hash` is not implemented for `Bar` | = note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Bar` with `#[derive(Hash)]` + | +LL | #[derive(Hash)] + | error: aborting due to previous error
diff --git a/src/test/ui/issues/issue-24352.stderr b/src/test/ui/issues/issue-24352.stderr index 69731bf..118f37f 100644 --- a/src/test/ui/issues/issue-24352.stderr +++ b/src/test/ui/issues/issue-24352.stderr
@@ -5,6 +5,16 @@ | ^ no implementation for `f64 - {integer}` | = help: the trait `Sub<{integer}>` is not implemented for `f64` + = help: the following other types implement trait `Sub<Rhs>`: + <&'a f32 as Sub<f32>> + <&'a f64 as Sub<f64>> + <&'a i128 as Sub<i128>> + <&'a i16 as Sub<i16>> + <&'a i32 as Sub<i32>> + <&'a i64 as Sub<i64>> + <&'a i8 as Sub<i8>> + <&'a isize as Sub<isize>> + and 48 others help: consider using a floating-point literal by writing it with `.0` | LL | 1.0f64 - 1.0
diff --git a/src/test/ui/issues/issue-32709.stderr b/src/test/ui/issues/issue-32709.stderr index b4c3f14..ed5addc 100644 --- a/src/test/ui/issues/issue-32709.stderr +++ b/src/test/ui/issues/issue-32709.stderr
@@ -7,6 +7,7 @@ | ^ the trait `From<{integer}>` is not implemented for `()` | = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait + = help: the trait `FromResidual<Result<Infallible, E>>` is implemented for `Result<T, F>` = note: required because of the requirements on the impl of `FromResidual<Result<Infallible, {integer}>>` for `Result<i32, ()>` error: aborting due to previous error
diff --git a/src/test/ui/issues/issue-34229.stderr b/src/test/ui/issues/issue-34229.stderr index 71e02f2..69ef876 100644 --- a/src/test/ui/issues/issue-34229.stderr +++ b/src/test/ui/issues/issue-34229.stderr
@@ -8,6 +8,10 @@ | = help: the trait `PartialOrd` is not implemented for `Comparable` = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Comparable` with `#[derive(PartialOrd)]` + | +LL | #[derive(PartialEq)] #[derive(PartialOrd)] + | +++++++++++++++++++++ error: aborting due to previous error
diff --git a/src/test/ui/issues/issue-34334.stderr b/src/test/ui/issues/issue-34334.stderr index cd69744..48ae2df 100644 --- a/src/test/ui/issues/issue-34334.stderr +++ b/src/test/ui/issues/issue-34334.stderr
@@ -19,6 +19,7 @@ | ^^^^^^^ value of type `Vec<(u32, _, _)>` cannot be built from `std::iter::Iterator<Item=()>` | = help: the trait `FromIterator<()>` is not implemented for `Vec<(u32, _, _)>` + = help: the trait `FromIterator<T>` is implemented for `Vec<T>` note: required by a bound in `collect` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL |
diff --git a/src/test/ui/issues/issue-45801.stderr b/src/test/ui/issues/issue-45801.stderr index 099cf4e..8967f49 100644 --- a/src/test/ui/issues/issue-45801.stderr +++ b/src/test/ui/issues/issue-45801.stderr
@@ -4,8 +4,7 @@ LL | req.get_ref::<Params>(); | ^^^^^^^ the trait `Plugin<i32>` is not implemented for `Params` | - = help: the following implementations were found: - <Params as Plugin<Foo>> + = help: the trait `Plugin<Foo>` is implemented for `Params` error: aborting due to previous error
diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr index 52ee1db..943f774 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr
@@ -2,7 +2,7 @@ --> $DIR/option-as_deref_mut.rs:2:33 | LL | let _result = &mut Some(42).as_deref_mut(); - | ^^^^^^^^^^^^ method cannot be called on `Option<{integer}>` due to unsatisfied trait bounds + | ^^^^^^^^^^^^ | = note: the following trait bounds were not satisfied: `{integer}: Deref`
diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr index 0185578..aa771e4 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr
@@ -2,7 +2,7 @@ --> $DIR/result-as_deref_mut.rs:2:31 | LL | let _result = &mut Ok(42).as_deref_mut(); - | ^^^^^^^^^^^^ method cannot be called on `Result<{integer}, _>` due to unsatisfied trait bounds + | ^^^^^^^^^^^^ | = note: the following trait bounds were not satisfied: `{integer}: Deref`
diff --git a/src/test/ui/issues/issue-50582.stderr b/src/test/ui/issues/issue-50582.stderr index 465fb9b..3d527eb 100644 --- a/src/test/ui/issues/issue-50582.stderr +++ b/src/test/ui/issues/issue-50582.stderr
@@ -14,6 +14,16 @@ | ^ no implementation for `{integer} + ()` | = help: the trait `Add<()>` is not implemented for `{integer}` + = help: the following other types implement trait `Add<Rhs>`: + <&'a f32 as Add<f32>> + <&'a f64 as Add<f64>> + <&'a i128 as Add<i128>> + <&'a i16 as Add<i16>> + <&'a i32 as Add<i32>> + <&'a i64 as Add<i64>> + <&'a i8 as Add<i8>> + <&'a isize as Add<isize>> + and 48 others error: aborting due to 2 previous errors
diff --git a/src/test/ui/issues/issue-59488.stderr b/src/test/ui/issues/issue-59488.stderr index 47fd9fd..76a47c4 100644 --- a/src/test/ui/issues/issue-59488.stderr +++ b/src/test/ui/issues/issue-59488.stderr
@@ -94,6 +94,16 @@ | ^^^^^^^^^^^^^^^^^^^^^^^ `fn(usize) -> Foo {Foo::Bar}` cannot be formatted using `{:?}` because it doesn't implement `Debug` | = help: the trait `Debug` is not implemented for `fn(usize) -> Foo {Foo::Bar}` + = help: the following other types implement trait `Debug`: + extern "C" fn() -> Ret + extern "C" fn(A) -> Ret + extern "C" fn(A, ...) -> Ret + extern "C" fn(A, B) -> Ret + extern "C" fn(A, B, ...) -> Ret + extern "C" fn(A, B, C) -> Ret + extern "C" fn(A, B, C, ...) -> Ret + extern "C" fn(A, B, C, D) -> Ret + and 68 others = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 9 previous errors
diff --git a/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr b/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr index 6a96709..d6e3925 100644 --- a/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr +++ b/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr
@@ -5,6 +5,7 @@ | ^^^^^^^ value of type `Vec<f64>` cannot be built from `std::iter::Iterator<Item=&f64>` | = help: the trait `FromIterator<&f64>` is not implemented for `Vec<f64>` + = help: the trait `FromIterator<T>` is implemented for `Vec<T>` note: required by a bound in `collect` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL | @@ -18,6 +19,7 @@ | ^^^^^^^ value of type `Vec<f64>` cannot be built from `std::iter::Iterator<Item=&f64>` | = help: the trait `FromIterator<&f64>` is not implemented for `Vec<f64>` + = help: the trait `FromIterator<T>` is implemented for `Vec<T>` note: required by a bound in `collect` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL |
diff --git a/src/test/ui/issues/issue-78957.stderr b/src/test/ui/issues/issue-78957.stderr index 703d272..fa2eaab 100644 --- a/src/test/ui/issues/issue-78957.stderr +++ b/src/test/ui/issues/issue-78957.stderr
@@ -2,13 +2,13 @@ --> $DIR/issue-78957.rs:5:16 | LL | pub struct Foo<#[inline] const N: usize>; - | ^^^^^^^^^ - not a function or closure + | ^^^^^^^^^ -------------- not a function or closure error: attribute should be applied to a function --> $DIR/issue-78957.rs:7:16 | LL | pub struct Bar<#[cold] const N: usize>; - | ^^^^^^^ - not a function + | ^^^^^^^ -------------- not a function | note: the lint level is defined here --> $DIR/issue-78957.rs:1:9 @@ -21,7 +21,7 @@ --> $DIR/issue-78957.rs:10:23 | LL | pub struct Baz<#[repr(C)] const N: usize>; - | ^ - not a struct, enum, or union + | ^ -------------- not a struct, enum, or union error[E0518]: attribute should be applied to function or closure --> $DIR/issue-78957.rs:13:17
diff --git a/src/test/ui/kindck/kindck-copy.stderr b/src/test/ui/kindck/kindck-copy.stderr index e147366..1c61c85 100644 --- a/src/test/ui/kindck/kindck-copy.stderr +++ b/src/test/ui/kindck/kindck-copy.stderr
@@ -4,12 +4,16 @@ LL | assert_copy::<&'static mut isize>(); | ^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `&'static mut isize` | - = help: the following implementations were found: - <isize as Copy> - <f32 as Copy> - <f64 as Copy> - <i128 as Copy> - and 10 others + = help: the following other types implement trait `Copy`: + f32 + f64 + i128 + i16 + i32 + i64 + i8 + isize + and 6 others note: required by a bound in `assert_copy` --> $DIR/kindck-copy.rs:5:18 | @@ -22,12 +26,16 @@ LL | assert_copy::<&'a mut isize>(); | ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `&'a mut isize` | - = help: the following implementations were found: - <isize as Copy> - <f32 as Copy> - <f64 as Copy> - <i128 as Copy> - and 10 others + = help: the following other types implement trait `Copy`: + f32 + f64 + i128 + i16 + i32 + i64 + i8 + isize + and 6 others note: required by a bound in `assert_copy` --> $DIR/kindck-copy.rs:5:18 |
diff --git a/src/test/ui/kindck/kindck-impl-type-params.nll.stderr b/src/test/ui/kindck/kindck-impl-type-params.nll.stderr index 7129bad..1772d35 100644 --- a/src/test/ui/kindck/kindck-impl-type-params.nll.stderr +++ b/src/test/ui/kindck/kindck-impl-type-params.nll.stderr
@@ -72,6 +72,7 @@ LL | let a = t as Box<dyn Gettable<String>>; | ^ the trait `Copy` is not implemented for `String` | + = help: the trait `Gettable<T>` is implemented for `S<T>` note: required because of the requirements on the impl of `Gettable<String>` for `S<String>` --> $DIR/kindck-impl-type-params.rs:14:32 | @@ -85,12 +86,17 @@ LL | let a: Box<dyn Gettable<Foo>> = t; | ^ the trait `Copy` is not implemented for `Foo` | + = help: the trait `Gettable<T>` is implemented for `S<T>` note: required because of the requirements on the impl of `Gettable<Foo>` for `S<Foo>` --> $DIR/kindck-impl-type-params.rs:14:32 | LL | impl<T: Send + Copy + 'static> Gettable<T> for S<T> {} | ^^^^^^^^^^^ ^^^^ = note: required for the cast to the object type `dyn Gettable<Foo>` +help: consider annotating `Foo` with `#[derive(Copy)]` + | +LL | #[derive(Copy)] + | error: aborting due to 6 previous errors
diff --git a/src/test/ui/kindck/kindck-impl-type-params.stderr b/src/test/ui/kindck/kindck-impl-type-params.stderr index 3558f0c..f227ac2 100644 --- a/src/test/ui/kindck/kindck-impl-type-params.stderr +++ b/src/test/ui/kindck/kindck-impl-type-params.stderr
@@ -80,6 +80,7 @@ LL | let a = t as Box<dyn Gettable<String>>; | ^ the trait `Copy` is not implemented for `String` | + = help: the trait `Gettable<T>` is implemented for `S<T>` note: required because of the requirements on the impl of `Gettable<String>` for `S<String>` --> $DIR/kindck-impl-type-params.rs:14:32 | @@ -93,12 +94,17 @@ LL | let a: Box<dyn Gettable<Foo>> = t; | ^ the trait `Copy` is not implemented for `Foo` | + = help: the trait `Gettable<T>` is implemented for `S<T>` note: required because of the requirements on the impl of `Gettable<Foo>` for `S<Foo>` --> $DIR/kindck-impl-type-params.rs:14:32 | LL | impl<T: Send + Copy + 'static> Gettable<T> for S<T> {} | ^^^^^^^^^^^ ^^^^ = note: required for the cast to the object type `dyn Gettable<Foo>` +help: consider annotating `Foo` with `#[derive(Copy)]` + | +LL | #[derive(Copy)] + | error: aborting due to 7 previous errors
diff --git a/src/test/ui/lang-items/lang-item-generic-requirements.rs b/src/test/ui/lang-items/lang-item-generic-requirements.rs index c0b958f..fbb56e5 100644 --- a/src/test/ui/lang-items/lang-item-generic-requirements.rs +++ b/src/test/ui/lang-items/lang-item-generic-requirements.rs
@@ -1,5 +1,5 @@ -// Checks that declaring a lang item with the wrong number -// of generic arguments errors rather than crashing (issue #83893, #87573, part of #9307, #79559). +// Checks that declaring a lang item with the wrong number of generic arguments errors rather than +// crashing (issue #83474, #83893, #87573, part of #9307, #79559). #![feature(lang_items, no_core)] #![no_core] @@ -25,6 +25,10 @@ trait MyIndex<'a, T> {} //~^ ERROR parameter `T` is never used //~| ERROR parameter `U` is never used +#[lang = "owned_box"] +//~^ ERROR `owned_box` language item must be applied to a struct with at least 1 generic argument +struct Foo; + // When the `start` lang item is missing generics very odd things can happen, especially when // it comes to cross-crate monomorphization #[lang = "start"] @@ -48,6 +52,9 @@ fn ice() { // Use phantomdata let _ = MyPhantomData::<(), i32>; + + // Use Foo + let _: () = Foo; } // use `start`
diff --git a/src/test/ui/lang-items/lang-item-generic-requirements.stderr b/src/test/ui/lang-items/lang-item-generic-requirements.stderr index df5a778..326f5b0 100644 --- a/src/test/ui/lang-items/lang-item-generic-requirements.stderr +++ b/src/test/ui/lang-items/lang-item-generic-requirements.stderr
@@ -32,8 +32,17 @@ LL | struct MyPhantomData<T, U>; | ------ this struct has 2 generic arguments +error[E0718]: `owned_box` language item must be applied to a struct with at least 1 generic argument + --> $DIR/lang-item-generic-requirements.rs:28:1 + | +LL | #[lang = "owned_box"] + | ^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | struct Foo; + | - this struct has 0 generic arguments + error[E0718]: `start` language item must be applied to a function with 1 generic argument - --> $DIR/lang-item-generic-requirements.rs:30:1 + --> $DIR/lang-item-generic-requirements.rs:34:1 | LL | #[lang = "start"] | ^^^^^^^^^^^^^^^^^ @@ -59,7 +68,7 @@ = help: consider removing `U` or referring to it in a field = help: if you intended `U` to be a const parameter, use `const U: usize` instead -error: aborting due to 7 previous errors +error: aborting due to 8 previous errors Some errors have detailed explanations: E0392, E0718. For more information about an error, try `rustc --explain E0392`.
diff --git a/src/test/ui/layout/debug.stderr b/src/test/ui/layout/debug.stderr index 418f780..25f7feb 100644 --- a/src/test/ui/layout/debug.stderr +++ b/src/test/ui/layout/debug.stderr
@@ -10,7 +10,7 @@ ], }, variants: Multiple { - tag: Scalar { + tag: Initialized { value: Int( I32, false, @@ -86,13 +86,11 @@ offset: Size { raw: 0, }, - scalar: Scalar { - value: Int( - I32, - false, - ), - valid_range: 0..=0, - }, + value: Int( + I32, + false, + ), + valid_range: 0..=0, }, ), align: AbiAndPrefAlign { @@ -133,14 +131,14 @@ index: 0, }, abi: ScalarPair( - Scalar { + Initialized { value: Int( I32, true, ), valid_range: 0..=4294967295, }, - Scalar { + Initialized { value: Int( I32, true, @@ -202,7 +200,7 @@ ], }, variants: Multiple { - tag: Scalar { + tag: Initialized { value: Int( I32, false, @@ -271,14 +269,14 @@ ], }, abi: ScalarPair( - Scalar { + Initialized { value: Int( I32, false, ), valid_range: 0..=1, }, - Scalar { + Initialized { value: Int( I32, true, @@ -291,13 +289,11 @@ offset: Size { raw: 0, }, - scalar: Scalar { - value: Int( - I32, - false, - ), - valid_range: 0..=1, - }, + value: Int( + I32, + false, + ), + valid_range: 0..=1, }, ), align: AbiAndPrefAlign { @@ -321,7 +317,7 @@ index: 0, }, abi: Scalar( - Scalar { + Initialized { value: Int( I32, true,
diff --git a/src/test/ui/layout/hexagon-enum.stderr b/src/test/ui/layout/hexagon-enum.stderr index 39b23cb..4db8162 100644 --- a/src/test/ui/layout/hexagon-enum.stderr +++ b/src/test/ui/layout/hexagon-enum.stderr
@@ -10,7 +10,7 @@ ], }, variants: Multiple { - tag: Scalar { + tag: Initialized { value: Int( I8, false, @@ -47,7 +47,7 @@ ], }, abi: Scalar( - Scalar { + Initialized { value: Int( I8, false, @@ -60,13 +60,11 @@ offset: Size { raw: 0, }, - scalar: Scalar { - value: Int( - I8, - false, - ), - valid_range: 0..=0, - }, + value: Int( + I8, + false, + ), + valid_range: 0..=0, }, ), align: AbiAndPrefAlign { @@ -98,7 +96,7 @@ ], }, variants: Multiple { - tag: Scalar { + tag: Initialized { value: Int( I8, false, @@ -135,7 +133,7 @@ ], }, abi: Scalar( - Scalar { + Initialized { value: Int( I8, false, @@ -148,13 +146,11 @@ offset: Size { raw: 0, }, - scalar: Scalar { - value: Int( - I8, - false, - ), - valid_range: 255..=255, - }, + value: Int( + I8, + false, + ), + valid_range: 255..=255, }, ), align: AbiAndPrefAlign { @@ -186,7 +182,7 @@ ], }, variants: Multiple { - tag: Scalar { + tag: Initialized { value: Int( I16, false, @@ -223,7 +219,7 @@ ], }, abi: Scalar( - Scalar { + Initialized { value: Int( I16, false, @@ -236,13 +232,11 @@ offset: Size { raw: 0, }, - scalar: Scalar { - value: Int( - I16, - false, - ), - valid_range: 256..=256, - }, + value: Int( + I16, + false, + ), + valid_range: 256..=256, }, ), align: AbiAndPrefAlign { @@ -274,7 +268,7 @@ ], }, variants: Multiple { - tag: Scalar { + tag: Initialized { value: Int( I32, false, @@ -311,7 +305,7 @@ ], }, abi: Scalar( - Scalar { + Initialized { value: Int( I32, false, @@ -324,13 +318,11 @@ offset: Size { raw: 0, }, - scalar: Scalar { - value: Int( - I32, - false, - ), - valid_range: 268435456..=268435456, - }, + value: Int( + I32, + false, + ), + valid_range: 268435456..=268435456, }, ), align: AbiAndPrefAlign { @@ -362,7 +354,7 @@ ], }, variants: Multiple { - tag: Scalar { + tag: Initialized { value: Int( I32, true, @@ -399,7 +391,7 @@ ], }, abi: Scalar( - Scalar { + Initialized { value: Int( I32, true, @@ -412,13 +404,11 @@ offset: Size { raw: 0, }, - scalar: Scalar { - value: Int( - I32, - true, - ), - valid_range: 2164260864..=2164260864, - }, + value: Int( + I32, + true, + ), + valid_range: 2164260864..=2164260864, }, ), align: AbiAndPrefAlign {
diff --git a/src/test/ui/layout/thumb-enum.stderr b/src/test/ui/layout/thumb-enum.stderr index 144ab02..9d1f234 100644 --- a/src/test/ui/layout/thumb-enum.stderr +++ b/src/test/ui/layout/thumb-enum.stderr
@@ -10,7 +10,7 @@ ], }, variants: Multiple { - tag: Scalar { + tag: Initialized { value: Int( I8, false, @@ -47,7 +47,7 @@ ], }, abi: Scalar( - Scalar { + Initialized { value: Int( I8, false, @@ -60,13 +60,11 @@ offset: Size { raw: 0, }, - scalar: Scalar { - value: Int( - I8, - false, - ), - valid_range: 0..=0, - }, + value: Int( + I8, + false, + ), + valid_range: 0..=0, }, ), align: AbiAndPrefAlign { @@ -98,7 +96,7 @@ ], }, variants: Multiple { - tag: Scalar { + tag: Initialized { value: Int( I8, false, @@ -135,7 +133,7 @@ ], }, abi: Scalar( - Scalar { + Initialized { value: Int( I8, false, @@ -148,13 +146,11 @@ offset: Size { raw: 0, }, - scalar: Scalar { - value: Int( - I8, - false, - ), - valid_range: 255..=255, - }, + value: Int( + I8, + false, + ), + valid_range: 255..=255, }, ), align: AbiAndPrefAlign { @@ -186,7 +182,7 @@ ], }, variants: Multiple { - tag: Scalar { + tag: Initialized { value: Int( I16, false, @@ -223,7 +219,7 @@ ], }, abi: Scalar( - Scalar { + Initialized { value: Int( I16, false, @@ -236,13 +232,11 @@ offset: Size { raw: 0, }, - scalar: Scalar { - value: Int( - I16, - false, - ), - valid_range: 256..=256, - }, + value: Int( + I16, + false, + ), + valid_range: 256..=256, }, ), align: AbiAndPrefAlign { @@ -274,7 +268,7 @@ ], }, variants: Multiple { - tag: Scalar { + tag: Initialized { value: Int( I32, false, @@ -311,7 +305,7 @@ ], }, abi: Scalar( - Scalar { + Initialized { value: Int( I32, false, @@ -324,13 +318,11 @@ offset: Size { raw: 0, }, - scalar: Scalar { - value: Int( - I32, - false, - ), - valid_range: 268435456..=268435456, - }, + value: Int( + I32, + false, + ), + valid_range: 268435456..=268435456, }, ), align: AbiAndPrefAlign { @@ -362,7 +354,7 @@ ], }, variants: Multiple { - tag: Scalar { + tag: Initialized { value: Int( I32, true, @@ -399,7 +391,7 @@ ], }, abi: Scalar( - Scalar { + Initialized { value: Int( I32, true, @@ -412,13 +404,11 @@ offset: Size { raw: 0, }, - scalar: Scalar { - value: Int( - I32, - true, - ), - valid_range: 2164260864..=2164260864, - }, + value: Int( + I32, + true, + ), + valid_range: 2164260864..=2164260864, }, ), align: AbiAndPrefAlign {
diff --git a/src/test/ui/lexer/lex-bad-char-literals-6.stderr b/src/test/ui/lexer/lex-bad-char-literals-6.stderr index 4332bde..afef0cb 100644 --- a/src/test/ui/lexer/lex-bad-char-literals-6.stderr +++ b/src/test/ui/lexer/lex-bad-char-literals-6.stderr
@@ -38,6 +38,16 @@ | ^^ no implementation for `&str == char` | = help: the trait `PartialEq<char>` is not implemented for `&str` + = help: the following other types implement trait `PartialEq<Rhs>`: + <&'a str as PartialEq<OsString>> + <&'a str as PartialEq<String>> + <&'b str as PartialEq<Cow<'a, str>>> + <String as PartialEq<&'a str>> + <String as PartialEq<Cow<'a, str>>> + <String as PartialEq<str>> + <String as PartialEq> + <str as PartialEq<Cow<'a, str>>> + and 4 others error[E0308]: mismatched types --> $DIR/lex-bad-char-literals-6.rs:15:20 @@ -54,6 +64,16 @@ | ^^ no implementation for `&str == char` | = help: the trait `PartialEq<char>` is not implemented for `&str` + = help: the following other types implement trait `PartialEq<Rhs>`: + <&'a str as PartialEq<OsString>> + <&'a str as PartialEq<String>> + <&'b str as PartialEq<Cow<'a, str>>> + <String as PartialEq<&'a str>> + <String as PartialEq<Cow<'a, str>>> + <String as PartialEq<str>> + <String as PartialEq> + <str as PartialEq<Cow<'a, str>>> + and 4 others error: aborting due to 6 previous errors
diff --git a/src/test/ui/malformed/malformed-derive-entry.stderr b/src/test/ui/malformed/malformed-derive-entry.stderr index 0ddce1b..8038834 100644 --- a/src/test/ui/malformed/malformed-derive-entry.stderr +++ b/src/test/ui/malformed/malformed-derive-entry.stderr
@@ -28,6 +28,10 @@ LL | pub trait Copy: Clone { | ^^^^^ required by this bound in `Copy` = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Test1` with `#[derive(Clone)]` + | +LL | #[derive(Clone)] + | error[E0277]: the trait bound `Test2: Clone` is not satisfied --> $DIR/malformed-derive-entry.rs:6:10 @@ -41,6 +45,10 @@ LL | pub trait Copy: Clone { | ^^^^^ required by this bound in `Copy` = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Test2` with `#[derive(Clone)]` + | +LL | #[derive(Clone)] + | error: aborting due to 5 previous errors
diff --git a/src/test/ui/match/issue-82866.rs b/src/test/ui/match/issue-82866.rs new file mode 100644 index 0000000..95cd622 --- /dev/null +++ b/src/test/ui/match/issue-82866.rs
@@ -0,0 +1,7 @@ +fn main() { + match x { + //~^ ERROR cannot find value `x` in this scope + Some::<v>(v) => (), + //~^ ERROR cannot find type `v` in this scope + } +}
diff --git a/src/test/ui/match/issue-82866.stderr b/src/test/ui/match/issue-82866.stderr new file mode 100644 index 0000000..f9e3360 --- /dev/null +++ b/src/test/ui/match/issue-82866.stderr
@@ -0,0 +1,16 @@ +error[E0425]: cannot find value `x` in this scope + --> $DIR/issue-82866.rs:2:11 + | +LL | match x { + | ^ not found in this scope + +error[E0412]: cannot find type `v` in this scope + --> $DIR/issue-82866.rs:4:16 + | +LL | Some::<v>(v) => (), + | ^ not found in this scope + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0412, E0425. +For more information about an error, try `rustc --explain E0412`.
diff --git a/src/test/ui/match/match-ref-mut-invariance.nll.stderr b/src/test/ui/match/match-ref-mut-invariance.nll.stderr index c8a7876..3b7e53c 100644 --- a/src/test/ui/match/match-ref-mut-invariance.nll.stderr +++ b/src/test/ui/match/match-ref-mut-invariance.nll.stderr
@@ -9,7 +9,7 @@ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ associated function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` | = help: consider adding the following bound: `'a: 'b` - = note: requirement occurs because of a mutable reference to &i32 + = note: requirement occurs because of a mutable reference to `&i32` = note: mutable references are invariant over their type parameter = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
diff --git a/src/test/ui/match/match-ref-mut-let-invariance.nll.stderr b/src/test/ui/match/match-ref-mut-let-invariance.nll.stderr index 11ddf14..f4d1cea 100644 --- a/src/test/ui/match/match-ref-mut-let-invariance.nll.stderr +++ b/src/test/ui/match/match-ref-mut-let-invariance.nll.stderr
@@ -10,7 +10,7 @@ | ^ associated function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` | = help: consider adding the following bound: `'a: 'b` - = note: requirement occurs because of a mutable reference to &i32 + = note: requirement occurs because of a mutable reference to `&i32` = note: mutable references are invariant over their type parameter = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
diff --git a/src/test/ui/mir/thir-constparam-temp.stderr b/src/test/ui/mir/thir-constparam-temp.stderr index 297102e..ed2766c 100644 --- a/src/test/ui/mir/thir-constparam-temp.stderr +++ b/src/test/ui/mir/thir-constparam-temp.stderr
@@ -13,10 +13,10 @@ LL | fn mut_self(&mut self) {} | ^^^^^^^^^^^^^^^^^^^^^^ note: `const` item defined here - --> $DIR/thir-constparam-temp.rs:13:14 + --> $DIR/thir-constparam-temp.rs:13:8 | LL | fn foo<const YIKES: Yikes>() { - | ^^^^^ + | ^^^^^^^^^^^^^^^^^^ warning: 1 warning emitted
diff --git a/src/test/ui/mismatched_types/binops.stderr b/src/test/ui/mismatched_types/binops.stderr index 19e921d..3de652d 100644 --- a/src/test/ui/mismatched_types/binops.stderr +++ b/src/test/ui/mismatched_types/binops.stderr
@@ -5,6 +5,16 @@ | ^ no implementation for `{integer} + Option<{integer}>` | = help: the trait `Add<Option<{integer}>>` is not implemented for `{integer}` + = help: the following other types implement trait `Add<Rhs>`: + <&'a f32 as Add<f32>> + <&'a f64 as Add<f64>> + <&'a i128 as Add<i128>> + <&'a i16 as Add<i16>> + <&'a i32 as Add<i32>> + <&'a i64 as Add<i64>> + <&'a i8 as Add<i8>> + <&'a isize as Add<isize>> + and 48 others error[E0277]: cannot subtract `Option<{integer}>` from `usize` --> $DIR/binops.rs:3:16 @@ -13,6 +23,16 @@ | ^ no implementation for `usize - Option<{integer}>` | = help: the trait `Sub<Option<{integer}>>` is not implemented for `usize` + = help: the following other types implement trait `Sub<Rhs>`: + <&'a f32 as Sub<f32>> + <&'a f64 as Sub<f64>> + <&'a i128 as Sub<i128>> + <&'a i16 as Sub<i16>> + <&'a i32 as Sub<i32>> + <&'a i64 as Sub<i64>> + <&'a i8 as Sub<i8>> + <&'a isize as Sub<isize>> + and 48 others error[E0277]: cannot multiply `{integer}` by `()` --> $DIR/binops.rs:4:7 @@ -21,6 +41,16 @@ | ^ no implementation for `{integer} * ()` | = help: the trait `Mul<()>` is not implemented for `{integer}` + = help: the following other types implement trait `Mul<Rhs>`: + <&'a f32 as Mul<f32>> + <&'a f64 as Mul<f64>> + <&'a i128 as Mul<i128>> + <&'a i16 as Mul<i16>> + <&'a i32 as Mul<i32>> + <&'a i64 as Mul<i64>> + <&'a i8 as Mul<i8>> + <&'a isize as Mul<isize>> + and 49 others error[E0277]: cannot divide `{integer}` by `&str` --> $DIR/binops.rs:5:7 @@ -29,6 +59,16 @@ | ^ no implementation for `{integer} / &str` | = help: the trait `Div<&str>` is not implemented for `{integer}` + = help: the following other types implement trait `Div<Rhs>`: + <&'a f32 as Div<f32>> + <&'a f64 as Div<f64>> + <&'a i128 as Div<i128>> + <&'a i16 as Div<i16>> + <&'a i32 as Div<i32>> + <&'a i64 as Div<i64>> + <&'a i8 as Div<i8>> + <&'a isize as Div<isize>> + and 54 others error[E0277]: can't compare `{integer}` with `String` --> $DIR/binops.rs:6:7 @@ -37,6 +77,16 @@ | ^ no implementation for `{integer} < String` and `{integer} > String` | = help: the trait `PartialOrd<String>` is not implemented for `{integer}` + = help: the following other types implement trait `PartialOrd<Rhs>`: + f32 + f64 + i128 + i16 + i32 + i64 + i8 + isize + and 6 others error[E0277]: can't compare `{integer}` with `Result<{integer}, _>` --> $DIR/binops.rs:7:7 @@ -45,6 +95,16 @@ | ^^ no implementation for `{integer} == Result<{integer}, _>` | = help: the trait `PartialEq<Result<{integer}, _>>` is not implemented for `{integer}` + = help: the following other types implement trait `PartialEq<Rhs>`: + f32 + f64 + i128 + i16 + i32 + i64 + i8 + isize + and 6 others error: aborting due to 6 previous errors
diff --git a/src/test/ui/mismatched_types/cast-rfc0401.stderr b/src/test/ui/mismatched_types/cast-rfc0401.stderr index 5f11e4d..84220ea 100644 --- a/src/test/ui/mismatched_types/cast-rfc0401.stderr +++ b/src/test/ui/mismatched_types/cast-rfc0401.stderr
@@ -224,6 +224,10 @@ | = help: the trait `Sized` is not implemented for `[u8]` = note: required for the cast to the object type `dyn Foo` +help: consider borrowing the value, since `&[u8]` can be coerced into `dyn Foo` + | +LL | let _ = &fat_v as *const dyn Foo; + | + error[E0277]: the size for values of type `str` cannot be known at compilation time --> $DIR/cast-rfc0401.rs:62:13 @@ -233,6 +237,10 @@ | = help: the trait `Sized` is not implemented for `str` = note: required for the cast to the object type `dyn Foo` +help: consider borrowing the value, since `&str` can be coerced into `dyn Foo` + | +LL | let _ = &a as *const dyn Foo; + | + error[E0606]: casting `&{float}` as `f32` is invalid --> $DIR/cast-rfc0401.rs:71:30
diff --git a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr index dc73bcd..c2515c4 100644 --- a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr +++ b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr
@@ -11,6 +11,10 @@ | LL | E: fmt::Debug, | ^^^^^^^^^^ required by this bound in `Result::<T, E>::unwrap` +help: consider annotating `Foo` with `#[derive(Debug)]` + | +LL | #[derive(Debug)] + | error: aborting due to previous error
diff --git a/src/test/ui/missing/missing-items/missing-type-parameter2.stderr b/src/test/ui/missing/missing-items/missing-type-parameter2.stderr index 3b930d7..cbceec5 100644 --- a/src/test/ui/missing/missing-items/missing-type-parameter2.stderr +++ b/src/test/ui/missing/missing-items/missing-type-parameter2.stderr
@@ -99,10 +99,10 @@ | + + error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions - --> $DIR/missing-type-parameter2.rs:6:15 + --> $DIR/missing-type-parameter2.rs:6:9 | LL | impl<T, const A: u8 = 2> X<N> {} - | ^ + | ^^^^^^^^^^^^^^^ error[E0747]: unresolved item provided when a constant was expected --> $DIR/missing-type-parameter2.rs:6:28
diff --git a/src/test/ui/never_type/defaulted-never-note.fallback.stderr b/src/test/ui/never_type/defaulted-never-note.fallback.stderr index b105f03..4c8b492 100644 --- a/src/test/ui/never_type/defaulted-never-note.fallback.stderr +++ b/src/test/ui/never_type/defaulted-never-note.fallback.stderr
@@ -4,7 +4,7 @@ LL | foo(_x); | ^^^ the trait `ImplementedForUnitButNotNever` is not implemented for `!` | - = note: this trait is implemented for `()` + = help: the trait `ImplementedForUnitButNotNever` is implemented for `()` = note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #48950 <https://github.com/rust-lang/rust/issues/48950> for more information) = help: did you intend to use the type `()` here instead? note: required by a bound in `foo`
diff --git a/src/test/ui/never_type/defaulted-never-note.rs b/src/test/ui/never_type/defaulted-never-note.rs index 54f5517..aefc739 100644 --- a/src/test/ui/never_type/defaulted-never-note.rs +++ b/src/test/ui/never_type/defaulted-never-note.rs
@@ -30,7 +30,7 @@ fn smeg() { foo(_x); //[fallback]~^ ERROR the trait bound //[fallback]~| NOTE the trait `ImplementedForUnitButNotNever` is not implemented - //[fallback]~| NOTE this trait is implemented for `()` + //[fallback]~| HELP trait `ImplementedForUnitButNotNever` is implemented for `()` //[fallback]~| NOTE this error might have been caused //[fallback]~| HELP did you intend }
diff --git a/src/test/ui/never_type/diverging-fallback-no-leak.fallback.stderr b/src/test/ui/never_type/diverging-fallback-no-leak.fallback.stderr index 72cd693..dee2b1d 100644 --- a/src/test/ui/never_type/diverging-fallback-no-leak.fallback.stderr +++ b/src/test/ui/never_type/diverging-fallback-no-leak.fallback.stderr
@@ -4,7 +4,9 @@ LL | unconstrained_arg(return); | ^^^^^^^^^^^^^^^^^ the trait `Test` is not implemented for `!` | - = note: this trait is implemented for `()` + = help: the following other types implement trait `Test`: + () + i32 = note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #48950 <https://github.com/rust-lang/rust/issues/48950> for more information) = help: did you intend to use the type `()` here instead? note: required by a bound in `unconstrained_arg`
diff --git a/src/test/ui/never_type/impl_trait_fallback2.stderr b/src/test/ui/never_type/impl_trait_fallback2.stderr index 2f50b9d..4a78e73 100644 --- a/src/test/ui/never_type/impl_trait_fallback2.stderr +++ b/src/test/ui/never_type/impl_trait_fallback2.stderr
@@ -3,6 +3,8 @@ | LL | fn should_ret_unit() -> impl T { | ^^^^^^ the trait `T` is not implemented for `()` + | + = help: the trait `T` is implemented for `i32` error: aborting due to previous error
diff --git a/src/test/ui/never_type/issue-13352.stderr b/src/test/ui/never_type/issue-13352.stderr index b98f6c9..fed780e 100644 --- a/src/test/ui/never_type/issue-13352.stderr +++ b/src/test/ui/never_type/issue-13352.stderr
@@ -5,6 +5,16 @@ | ^ no implementation for `usize + ()` | = help: the trait `Add<()>` is not implemented for `usize` + = help: the following other types implement trait `Add<Rhs>`: + <&'a f32 as Add<f32>> + <&'a f64 as Add<f64>> + <&'a i128 as Add<i128>> + <&'a i16 as Add<i16>> + <&'a i32 as Add<i32>> + <&'a i64 as Add<i64>> + <&'a i8 as Add<i8>> + <&'a isize as Add<isize>> + and 48 others error: aborting due to previous error
diff --git a/src/test/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr b/src/test/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr index a14253e..e204559 100644 --- a/src/test/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr +++ b/src/test/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr
@@ -4,8 +4,7 @@ LL | <E as From<_>>::from(never); | ^^^^^^^^^^^^^^^^^^^^ the trait `From<()>` is not implemented for `E` | - = help: the following implementations were found: - <E as From<!>> + = help: the trait `From<!>` is implemented for `E` error: aborting due to previous error
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr index cf56307..ec2c220 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr
@@ -52,8 +52,8 @@ | |______`cell_a` escapes the function body here | argument requires that `'a` must outlive `'static` | - = note: requirement occurs because of the type Cell<&'_#10r u32>, which makes the generic argument &'_#10r u32 invariant - = note: the struct Cell<T> is invariant over the parameter T + = note: requirement occurs because of the type `Cell<&'_#10r u32>`, which makes the generic argument `&'_#10r u32` invariant + = note: the struct `Cell<T>` is invariant over the parameter `T` = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance error: aborting due to previous error
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr index 453f680..234212c 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr
@@ -52,8 +52,8 @@ | |______`cell_a` escapes the function body here | argument requires that `'a` must outlive `'static` | - = note: requirement occurs because of the type Cell<&'_#11r u32>, which makes the generic argument &'_#11r u32 invariant - = note: the struct Cell<T> is invariant over the parameter T + = note: requirement occurs because of the type `Cell<&'_#11r u32>`, which makes the generic argument `&'_#11r u32` invariant + = note: the struct `Cell<T>` is invariant over the parameter `T` = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance error: aborting due to previous error
diff --git a/src/test/ui/nll/issue-50716.stderr b/src/test/ui/nll/issue-50716.base.stderr similarity index 88% rename from src/test/ui/nll/issue-50716.stderr rename to src/test/ui/nll/issue-50716.base.stderr index be68d25..0dcf064 100644 --- a/src/test/ui/nll/issue-50716.stderr +++ b/src/test/ui/nll/issue-50716.base.stderr
@@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/issue-50716.rs:14:9 + --> $DIR/issue-50716.rs:18:9 | LL | let _x = *s; | ^^ lifetime mismatch @@ -7,7 +7,7 @@ = note: expected type `<<&'a T as A>::X as Sized>` found type `<<&'static T as A>::X as Sized>` note: the lifetime `'a` as defined here... - --> $DIR/issue-50716.rs:9:8 + --> $DIR/issue-50716.rs:13:8 | LL | fn foo<'a, T: 'static>(s: Box<<&'a T as A>::X>) | ^^
diff --git a/src/test/ui/nll/issue-50716.nll.stderr b/src/test/ui/nll/issue-50716.nll.stderr index 38dd1b5..a8f4d69 100644 --- a/src/test/ui/nll/issue-50716.nll.stderr +++ b/src/test/ui/nll/issue-50716.nll.stderr
@@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/issue-50716.rs:14:14 + --> $DIR/issue-50716.rs:18:14 | LL | fn foo<'a, T: 'static>(s: Box<<&'a T as A>::X>) | -- lifetime `'a` defined here
diff --git a/src/test/ui/nll/issue-50716.rs b/src/test/ui/nll/issue-50716.rs index c2fc345..bd44d3e 100644 --- a/src/test/ui/nll/issue-50716.rs +++ b/src/test/ui/nll/issue-50716.rs
@@ -2,6 +2,10 @@ // Regression test for the issue #50716: NLL ignores lifetimes bounds // derived from `Sized` requirements +// revisions: base nll +// ignore-compare-mode-nll +//[nll] compile-flags: -Z borrowck=mir + trait A { type X: ?Sized; }
diff --git a/src/test/ui/nll/issue-52742.stderr b/src/test/ui/nll/issue-52742.base.stderr similarity index 84% rename from src/test/ui/nll/issue-52742.stderr rename to src/test/ui/nll/issue-52742.base.stderr index 67bac14..259f378 100644 --- a/src/test/ui/nll/issue-52742.stderr +++ b/src/test/ui/nll/issue-52742.base.stderr
@@ -1,16 +1,16 @@ error[E0312]: lifetime of reference outlives lifetime of borrowed content... - --> $DIR/issue-52742.rs:12:18 + --> $DIR/issue-52742.rs:17:18 | LL | self.y = b.z | ^^^ | note: ...the reference is valid for the lifetime `'_` as defined here... - --> $DIR/issue-52742.rs:10:10 + --> $DIR/issue-52742.rs:15:10 | LL | impl Foo<'_, '_> { | ^^ note: ...but the borrowed content is only valid for the anonymous lifetime defined here - --> $DIR/issue-52742.rs:11:31 + --> $DIR/issue-52742.rs:16:31 | LL | fn take_bar(&mut self, b: Bar<'_>) { | ^^^^^^^
diff --git a/src/test/ui/nll/issue-52742.nll.stderr b/src/test/ui/nll/issue-52742.nll.stderr index 0f6d6cd..6828418 100644 --- a/src/test/ui/nll/issue-52742.nll.stderr +++ b/src/test/ui/nll/issue-52742.nll.stderr
@@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/issue-52742.rs:12:9 + --> $DIR/issue-52742.rs:17:9 | LL | fn take_bar(&mut self, b: Bar<'_>) { | --------- -- let's call this `'1`
diff --git a/src/test/ui/nll/issue-52742.rs b/src/test/ui/nll/issue-52742.rs index d3e201b..5ec5770 100644 --- a/src/test/ui/nll/issue-52742.rs +++ b/src/test/ui/nll/issue-52742.rs
@@ -1,3 +1,8 @@ +// revisions: base nll +// ignore-compare-mode-nll +//[nll] compile-flags: -Z borrowck=mir + + struct Foo<'a, 'b> { x: &'a u32, y: &'b u32,
diff --git a/src/test/ui/nll/issue-55394.stderr b/src/test/ui/nll/issue-55394.base.stderr similarity index 83% rename from src/test/ui/nll/issue-55394.stderr rename to src/test/ui/nll/issue-55394.base.stderr index 197f8df..cc87954 100644 --- a/src/test/ui/nll/issue-55394.stderr +++ b/src/test/ui/nll/issue-55394.base.stderr
@@ -1,26 +1,26 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'s` due to conflicting requirements - --> $DIR/issue-55394.rs:9:9 + --> $DIR/issue-55394.rs:13:9 | LL | Foo { bar } | ^^^ | note: first, the lifetime cannot outlive the anonymous lifetime defined here... - --> $DIR/issue-55394.rs:8:17 + --> $DIR/issue-55394.rs:12:17 | LL | fn new(bar: &mut Bar) -> Self { | ^^^^^^^^ note: ...so that reference does not outlive borrowed content - --> $DIR/issue-55394.rs:9:15 + --> $DIR/issue-55394.rs:13:15 | LL | Foo { bar } | ^^^ note: but, the lifetime must be valid for the lifetime `'_` as defined here... - --> $DIR/issue-55394.rs:7:10 + --> $DIR/issue-55394.rs:11:10 | LL | impl Foo<'_> { | ^^ note: ...so that the types are compatible - --> $DIR/issue-55394.rs:9:9 + --> $DIR/issue-55394.rs:13:9 | LL | Foo { bar } | ^^^^^^^^^^^
diff --git a/src/test/ui/nll/issue-55394.nll.stderr b/src/test/ui/nll/issue-55394.nll.stderr index 24b8c84..c166c45 100644 --- a/src/test/ui/nll/issue-55394.nll.stderr +++ b/src/test/ui/nll/issue-55394.nll.stderr
@@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/issue-55394.rs:9:9 + --> $DIR/issue-55394.rs:13:9 | LL | fn new(bar: &mut Bar) -> Self { | - ---- return type is Foo<'2>
diff --git a/src/test/ui/nll/issue-55394.rs b/src/test/ui/nll/issue-55394.rs index f813d1c..9c4fcdf 100644 --- a/src/test/ui/nll/issue-55394.rs +++ b/src/test/ui/nll/issue-55394.rs
@@ -1,3 +1,7 @@ +// revisions: base nll +// ignore-compare-mode-nll +//[nll] compile-flags: -Z borrowck=mir + struct Bar; struct Foo<'s> {
diff --git a/src/test/ui/nll/issue-55401.stderr b/src/test/ui/nll/issue-55401.base.stderr similarity index 89% rename from src/test/ui/nll/issue-55401.stderr rename to src/test/ui/nll/issue-55401.base.stderr index 55c51d5..d4e9f2b 100644 --- a/src/test/ui/nll/issue-55401.stderr +++ b/src/test/ui/nll/issue-55401.base.stderr
@@ -1,12 +1,12 @@ error[E0312]: lifetime of reference outlives lifetime of borrowed content... - --> $DIR/issue-55401.rs:3:5 + --> $DIR/issue-55401.rs:7:5 | LL | *y | ^^ | = note: ...the reference is valid for the static lifetime... note: ...but the borrowed content is only valid for the lifetime `'a` as defined here - --> $DIR/issue-55401.rs:1:47 + --> $DIR/issue-55401.rs:5:47 | LL | fn static_to_a_to_static_through_ref_in_tuple<'a>(x: &'a u32) -> &'static u32 { | ^^
diff --git a/src/test/ui/nll/issue-55401.nll.stderr b/src/test/ui/nll/issue-55401.nll.stderr index 4f797f2..1318dc6 100644 --- a/src/test/ui/nll/issue-55401.nll.stderr +++ b/src/test/ui/nll/issue-55401.nll.stderr
@@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/issue-55401.rs:3:5 + --> $DIR/issue-55401.rs:7:5 | LL | fn static_to_a_to_static_through_ref_in_tuple<'a>(x: &'a u32) -> &'static u32 { | -- lifetime `'a` defined here
diff --git a/src/test/ui/nll/issue-55401.rs b/src/test/ui/nll/issue-55401.rs index fc45824..10f38c5 100644 --- a/src/test/ui/nll/issue-55401.rs +++ b/src/test/ui/nll/issue-55401.rs
@@ -1,3 +1,7 @@ +// revisions: base nll +// ignore-compare-mode-nll +//[nll] compile-flags: -Z borrowck=mir + fn static_to_a_to_static_through_ref_in_tuple<'a>(x: &'a u32) -> &'static u32 { let (ref y, _z): (&'a u32, u32) = (&22, 44); *y //~ ERROR
diff --git a/src/test/ui/nll/issue-95272.rs b/src/test/ui/nll/issue-95272.rs new file mode 100644 index 0000000..5b5308f --- /dev/null +++ b/src/test/ui/nll/issue-95272.rs
@@ -0,0 +1,17 @@ +#![feature(nll)] + +use std::cell::Cell; + +fn check<'a, 'b>(x: Cell<&'a ()>, y: Cell<&'b ()>) +where + 'a: 'b, +{ +} + +fn test<'a, 'b>(x: Cell<&'a ()>, y: Cell<&'b ()>) { + let f = check; + //~^ ERROR lifetime may not live long enough + f(x, y); +} + +fn main() {}
diff --git a/src/test/ui/nll/issue-95272.stderr b/src/test/ui/nll/issue-95272.stderr new file mode 100644 index 0000000..41346a4 --- /dev/null +++ b/src/test/ui/nll/issue-95272.stderr
@@ -0,0 +1,17 @@ +error: lifetime may not live long enough + --> $DIR/issue-95272.rs:12:13 + | +LL | fn test<'a, 'b>(x: Cell<&'a ()>, y: Cell<&'b ()>) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | let f = check; + | ^^^^^ assignment requires that `'a` must outlive `'b` + | + = help: consider adding the following bound: `'a: 'b` + = note: requirement occurs because of a function pointer to `check` + = note: the function `check` is invariant over the parameter `'a` + = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance + +error: aborting due to previous error +
diff --git a/src/test/ui/nll/lub-if.stderr b/src/test/ui/nll/lub-if.base.stderr similarity index 88% rename from src/test/ui/nll/lub-if.stderr rename to src/test/ui/nll/lub-if.base.stderr index a12c485..ea9f5d4 100644 --- a/src/test/ui/nll/lub-if.stderr +++ b/src/test/ui/nll/lub-if.base.stderr
@@ -1,25 +1,25 @@ error[E0312]: lifetime of reference outlives lifetime of borrowed content... - --> $DIR/lub-if.rs:28:9 + --> $DIR/lub-if.rs:32:9 | LL | s | ^ | = note: ...the reference is valid for the static lifetime... note: ...but the borrowed content is only valid for the lifetime `'a` as defined here - --> $DIR/lub-if.rs:23:17 + --> $DIR/lub-if.rs:27:17 | LL | pub fn opt_str2<'a>(maybestr: &'a Option<String>) -> &'static str { | ^^ error[E0312]: lifetime of reference outlives lifetime of borrowed content... - --> $DIR/lub-if.rs:35:9 + --> $DIR/lub-if.rs:41:9 | LL | s | ^ | = note: ...the reference is valid for the static lifetime... note: ...but the borrowed content is only valid for the lifetime `'a` as defined here - --> $DIR/lub-if.rs:32:17 + --> $DIR/lub-if.rs:38:17 | LL | pub fn opt_str3<'a>(maybestr: &'a Option<String>) -> &'static str { | ^^
diff --git a/src/test/ui/nll/lub-if.nll.stderr b/src/test/ui/nll/lub-if.nll.stderr index 832688f..2fd6e69 100644 --- a/src/test/ui/nll/lub-if.nll.stderr +++ b/src/test/ui/nll/lub-if.nll.stderr
@@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/lub-if.rs:28:9 + --> $DIR/lub-if.rs:32:9 | LL | pub fn opt_str2<'a>(maybestr: &'a Option<String>) -> &'static str { | -- lifetime `'a` defined here @@ -8,7 +8,7 @@ | ^ returning this value requires that `'a` must outlive `'static` error: lifetime may not live long enough - --> $DIR/lub-if.rs:35:9 + --> $DIR/lub-if.rs:41:9 | LL | pub fn opt_str3<'a>(maybestr: &'a Option<String>) -> &'static str { | -- lifetime `'a` defined here
diff --git a/src/test/ui/nll/lub-if.rs b/src/test/ui/nll/lub-if.rs index 132b838..18561d6 100644 --- a/src/test/ui/nll/lub-if.rs +++ b/src/test/ui/nll/lub-if.rs
@@ -2,6 +2,10 @@ // of the various arms, particularly in the case where regions are // involved. +// revisions: base nll +// ignore-compare-mode-nll +//[nll] compile-flags: -Z borrowck=mir + pub fn opt_str0<'a>(maybestr: &'a Option<String>) -> &'a str { if maybestr.is_none() { "(none)" @@ -25,14 +29,18 @@ pub fn opt_str2<'a>(maybestr: &'a Option<String>) -> &'static str { "(none)" } else { let s: &'a str = maybestr.as_ref().unwrap(); - s //~ ERROR E0312 + s + //[base]~^ ERROR E0312 + //[nll]~^^ ERROR lifetime may not live long enough } } pub fn opt_str3<'a>(maybestr: &'a Option<String>) -> &'static str { if maybestr.is_some() { let s: &'a str = maybestr.as_ref().unwrap(); - s //~ ERROR E0312 + s + //[base]~^ ERROR E0312 + //[nll]~^^ ERROR lifetime may not live long enough } else { "(none)" }
diff --git a/src/test/ui/nll/lub-match.stderr b/src/test/ui/nll/lub-match.base.stderr similarity index 87% rename from src/test/ui/nll/lub-match.stderr rename to src/test/ui/nll/lub-match.base.stderr index 04d50f5..3895213 100644 --- a/src/test/ui/nll/lub-match.stderr +++ b/src/test/ui/nll/lub-match.base.stderr
@@ -1,25 +1,25 @@ error[E0312]: lifetime of reference outlives lifetime of borrowed content... - --> $DIR/lub-match.rs:30:13 + --> $DIR/lub-match.rs:34:13 | LL | s | ^ | = note: ...the reference is valid for the static lifetime... note: ...but the borrowed content is only valid for the lifetime `'a` as defined here - --> $DIR/lub-match.rs:25:17 + --> $DIR/lub-match.rs:29:17 | LL | pub fn opt_str2<'a>(maybestr: &'a Option<String>) -> &'static str { | ^^ error[E0312]: lifetime of reference outlives lifetime of borrowed content... - --> $DIR/lub-match.rs:39:13 + --> $DIR/lub-match.rs:45:13 | LL | s | ^ | = note: ...the reference is valid for the static lifetime... note: ...but the borrowed content is only valid for the lifetime `'a` as defined here - --> $DIR/lub-match.rs:35:17 + --> $DIR/lub-match.rs:41:17 | LL | pub fn opt_str3<'a>(maybestr: &'a Option<String>) -> &'static str { | ^^
diff --git a/src/test/ui/nll/lub-match.nll.stderr b/src/test/ui/nll/lub-match.nll.stderr index 3a344a7..c78d0cb 100644 --- a/src/test/ui/nll/lub-match.nll.stderr +++ b/src/test/ui/nll/lub-match.nll.stderr
@@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/lub-match.rs:30:13 + --> $DIR/lub-match.rs:34:13 | LL | pub fn opt_str2<'a>(maybestr: &'a Option<String>) -> &'static str { | -- lifetime `'a` defined here @@ -8,7 +8,7 @@ | ^ returning this value requires that `'a` must outlive `'static` error: lifetime may not live long enough - --> $DIR/lub-match.rs:39:13 + --> $DIR/lub-match.rs:45:13 | LL | pub fn opt_str3<'a>(maybestr: &'a Option<String>) -> &'static str { | -- lifetime `'a` defined here
diff --git a/src/test/ui/nll/lub-match.rs b/src/test/ui/nll/lub-match.rs index 1cd4a02..084d8b9 100644 --- a/src/test/ui/nll/lub-match.rs +++ b/src/test/ui/nll/lub-match.rs
@@ -2,6 +2,10 @@ // of the various arms, particularly in the case where regions are // involved. +// revisions: base nll +// ignore-compare-mode-nll +//[nll] compile-flags: -Z borrowck=mir + pub fn opt_str0<'a>(maybestr: &'a Option<String>) -> &'a str { match *maybestr { Some(ref s) => { @@ -27,7 +31,9 @@ pub fn opt_str2<'a>(maybestr: &'a Option<String>) -> &'static str { None => "(none)", Some(ref s) => { let s: &'a str = s; - s //~ ERROR E0312 + s + //[base]~^ ERROR E0312 + //[nll]~^^ ERROR lifetime may not live long enough } } } @@ -36,7 +42,9 @@ pub fn opt_str3<'a>(maybestr: &'a Option<String>) -> &'static str { match *maybestr { Some(ref s) => { let s: &'a str = s; - s //~ ERROR E0312 + s + //[base]~^ ERROR E0312 + //[nll]~^^ ERROR lifetime may not live long enough } None => "(none)", }
diff --git a/src/test/ui/nll/type-alias-free-regions.stderr b/src/test/ui/nll/type-alias-free-regions.base.stderr similarity index 79% rename from src/test/ui/nll/type-alias-free-regions.stderr rename to src/test/ui/nll/type-alias-free-regions.base.stderr index 71f5f8f..010535f 100644 --- a/src/test/ui/nll/type-alias-free-regions.stderr +++ b/src/test/ui/nll/type-alias-free-regions.base.stderr
@@ -1,28 +1,28 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements - --> $DIR/type-alias-free-regions.rs:17:9 + --> $DIR/type-alias-free-regions.rs:21:9 | LL | C { f: b } | ^ | note: first, the lifetime cannot outlive the anonymous lifetime defined here... - --> $DIR/type-alias-free-regions.rs:16:24 + --> $DIR/type-alias-free-regions.rs:20:24 | LL | fn from_box(b: Box<B>) -> Self { | ^ note: ...so that the expression is assignable - --> $DIR/type-alias-free-regions.rs:17:16 + --> $DIR/type-alias-free-regions.rs:21:16 | LL | C { f: b } | ^ = note: expected `Box<Box<&isize>>` found `Box<Box<&isize>>` note: but, the lifetime must be valid for the lifetime `'a` as defined here... - --> $DIR/type-alias-free-regions.rs:15:6 + --> $DIR/type-alias-free-regions.rs:19:6 | LL | impl<'a> FromBox<'a> for C<'a> { | ^^ note: ...so that the types are compatible - --> $DIR/type-alias-free-regions.rs:17:9 + --> $DIR/type-alias-free-regions.rs:21:9 | LL | C { f: b } | ^^^^^^^^^^ @@ -30,30 +30,30 @@ found `C<'_>` error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements - --> $DIR/type-alias-free-regions.rs:27:16 + --> $DIR/type-alias-free-regions.rs:31:16 | LL | C { f: Box::new(b.0) } | ^^^^^^^^^^^^^ | note: first, the lifetime cannot outlive the anonymous lifetime defined here... - --> $DIR/type-alias-free-regions.rs:26:23 + --> $DIR/type-alias-free-regions.rs:30:23 | LL | fn from_tuple(b: (B,)) -> Self { | ^ note: ...so that the expression is assignable - --> $DIR/type-alias-free-regions.rs:27:25 + --> $DIR/type-alias-free-regions.rs:31:25 | LL | C { f: Box::new(b.0) } | ^^^ = note: expected `Box<&isize>` found `Box<&isize>` note: but, the lifetime must be valid for the lifetime `'a` as defined here... - --> $DIR/type-alias-free-regions.rs:25:6 + --> $DIR/type-alias-free-regions.rs:29:6 | LL | impl<'a> FromTuple<'a> for C<'a> { | ^^ note: ...so that the types are compatible - --> $DIR/type-alias-free-regions.rs:27:9 + --> $DIR/type-alias-free-regions.rs:31:9 | LL | C { f: Box::new(b.0) } | ^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/nll/type-alias-free-regions.nll.stderr b/src/test/ui/nll/type-alias-free-regions.nll.stderr index 45fd5a2..6b74660 100644 --- a/src/test/ui/nll/type-alias-free-regions.nll.stderr +++ b/src/test/ui/nll/type-alias-free-regions.nll.stderr
@@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/type-alias-free-regions.rs:17:9 + --> $DIR/type-alias-free-regions.rs:21:9 | LL | impl<'a> FromBox<'a> for C<'a> { | -- lifetime `'a` defined here @@ -9,7 +9,7 @@ | ^^^^^^^^^^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1` error: lifetime may not live long enough - --> $DIR/type-alias-free-regions.rs:27:9 + --> $DIR/type-alias-free-regions.rs:31:9 | LL | impl<'a> FromTuple<'a> for C<'a> { | -- lifetime `'a` defined here
diff --git a/src/test/ui/nll/type-alias-free-regions.rs b/src/test/ui/nll/type-alias-free-regions.rs index fd5566f..59ef034 100644 --- a/src/test/ui/nll/type-alias-free-regions.rs +++ b/src/test/ui/nll/type-alias-free-regions.rs
@@ -1,6 +1,10 @@ // Test that we don't assume that type aliases have the same type parameters // as the type they alias and then panic when we see this. +// revisions: base nll +// ignore-compare-mode-nll +//[nll] compile-flags: -Z borrowck=mir + type A<'a> = &'a isize; type B<'a> = Box<A<'a>>;
diff --git a/src/test/ui/nll/type-check-pointer-coercions.stderr b/src/test/ui/nll/type-check-pointer-coercions.stderr index b392c20..24b07ca 100644 --- a/src/test/ui/nll/type-check-pointer-coercions.stderr +++ b/src/test/ui/nll/type-check-pointer-coercions.stderr
@@ -34,7 +34,7 @@ | ^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` | = help: consider adding the following bound: `'b: 'a` - = note: requirement occurs because of a mutable pointer to &i32 + = note: requirement occurs because of a mutable pointer to `&i32` = note: mutable pointers are invariant over their type parameter = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance @@ -50,7 +50,7 @@ | ^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` | = help: consider adding the following bound: `'a: 'b` - = note: requirement occurs because of a mutable pointer to &i32 + = note: requirement occurs because of a mutable pointer to `&i32` = note: mutable pointers are invariant over their type parameter = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
diff --git a/src/test/ui/nll/type-check-pointer-comparisons.stderr b/src/test/ui/nll/type-check-pointer-comparisons.stderr index b488af8..8c88b22 100644 --- a/src/test/ui/nll/type-check-pointer-comparisons.stderr +++ b/src/test/ui/nll/type-check-pointer-comparisons.stderr
@@ -9,7 +9,7 @@ | ^ requires that `'a` must outlive `'b` | = help: consider adding the following bound: `'a: 'b` - = note: requirement occurs because of a mutable reference to &i32 + = note: requirement occurs because of a mutable reference to `&i32` = note: mutable references are invariant over their type parameter = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance @@ -24,7 +24,7 @@ | ^ requires that `'b` must outlive `'a` | = help: consider adding the following bound: `'b: 'a` - = note: requirement occurs because of a mutable reference to &i32 + = note: requirement occurs because of a mutable reference to `&i32` = note: mutable references are invariant over their type parameter = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance @@ -41,7 +41,7 @@ | ^ requires that `'a` must outlive `'b` | = help: consider adding the following bound: `'a: 'b` - = note: requirement occurs because of a mutable pointer to &i32 + = note: requirement occurs because of a mutable pointer to `&i32` = note: mutable pointers are invariant over their type parameter = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance @@ -56,7 +56,7 @@ | ^ requires that `'b` must outlive `'a` | = help: consider adding the following bound: `'b: 'a` - = note: requirement occurs because of a mutable pointer to &i32 + = note: requirement occurs because of a mutable pointer to `&i32` = note: mutable pointers are invariant over their type parameter = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance @@ -73,7 +73,7 @@ | ^ requires that `'a` must outlive `'b` | = help: consider adding the following bound: `'a: 'b` - = note: requirement occurs because of a mutable reference to &i32 + = note: requirement occurs because of a mutable reference to `&i32` = note: mutable references are invariant over their type parameter = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance @@ -88,7 +88,7 @@ | ^ requires that `'b` must outlive `'a` | = help: consider adding the following bound: `'b: 'a` - = note: requirement occurs because of a mutable reference to &i32 + = note: requirement occurs because of a mutable reference to `&i32` = note: mutable references are invariant over their type parameter = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.base.stderr similarity index 89% rename from src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr rename to src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.base.stderr index 4a6378b..ba17994 100644 --- a/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr +++ b/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.base.stderr
@@ -1,5 +1,5 @@ error[E0759]: `fn` parameter has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement - --> $DIR/constant-in-expr-inherent-1.rs:8:5 + --> $DIR/constant-in-expr-inherent-1.rs:12:5 | LL | fn foo<'a>(_: &'a u32) -> &'static u32 { | ------- this data with lifetime `'a`...
diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.nll.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.nll.stderr index c393015..0399d5f 100644 --- a/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.nll.stderr +++ b/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.nll.stderr
@@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/constant-in-expr-inherent-1.rs:8:5 + --> $DIR/constant-in-expr-inherent-1.rs:12:5 | LL | fn foo<'a>(_: &'a u32) -> &'static u32 { | -- lifetime `'a` defined here
diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.rs b/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.rs index e3a8a5f..0bd316a 100644 --- a/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.rs +++ b/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.rs
@@ -1,3 +1,7 @@ +// revisions: base nll +// ignore-compare-mode-nll +//[nll] compile-flags: -Z borrowck=mir + struct Foo<'a> { x: &'a u32 } impl<'a> Foo<'a> {
diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-normalize.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-normalize.base.stderr similarity index 83% rename from src/test/ui/nll/user-annotations/constant-in-expr-normalize.stderr rename to src/test/ui/nll/user-annotations/constant-in-expr-normalize.base.stderr index d33c4584..61efa87 100644 --- a/src/test/ui/nll/user-annotations/constant-in-expr-normalize.stderr +++ b/src/test/ui/nll/user-annotations/constant-in-expr-normalize.base.stderr
@@ -1,12 +1,12 @@ error[E0312]: lifetime of reference outlives lifetime of borrowed content... - --> $DIR/constant-in-expr-normalize.rs:18:5 + --> $DIR/constant-in-expr-normalize.rs:22:5 | LL | <() as Foo<'a>>::C | ^^^^^^^^^^^^^^^^^^ | = note: ...the reference is valid for the static lifetime... note: ...but the borrowed content is only valid for the lifetime `'a` as defined here - --> $DIR/constant-in-expr-normalize.rs:17:8 + --> $DIR/constant-in-expr-normalize.rs:21:8 | LL | fn foo<'a>(_: &'a u32) -> &'static u32 { | ^^
diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-normalize.nll.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-normalize.nll.stderr index 541a2cf..4c1e6be 100644 --- a/src/test/ui/nll/user-annotations/constant-in-expr-normalize.nll.stderr +++ b/src/test/ui/nll/user-annotations/constant-in-expr-normalize.nll.stderr
@@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/constant-in-expr-normalize.rs:18:5 + --> $DIR/constant-in-expr-normalize.rs:22:5 | LL | fn foo<'a>(_: &'a u32) -> &'static u32 { | -- lifetime `'a` defined here
diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-normalize.rs b/src/test/ui/nll/user-annotations/constant-in-expr-normalize.rs index b709543..262f0ae 100644 --- a/src/test/ui/nll/user-annotations/constant-in-expr-normalize.rs +++ b/src/test/ui/nll/user-annotations/constant-in-expr-normalize.rs
@@ -1,3 +1,7 @@ +// revisions: base nll +// ignore-compare-mode-nll +//[nll] compile-flags: -Z borrowck=mir + trait Mirror { type Me; }
diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-1.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-1.base.stderr similarity index 82% rename from src/test/ui/nll/user-annotations/constant-in-expr-trait-item-1.stderr rename to src/test/ui/nll/user-annotations/constant-in-expr-trait-item-1.base.stderr index 3ec3a2a..93f7156 100644 --- a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-1.stderr +++ b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-1.base.stderr
@@ -1,12 +1,12 @@ error[E0312]: lifetime of reference outlives lifetime of borrowed content... - --> $DIR/constant-in-expr-trait-item-1.rs:10:5 + --> $DIR/constant-in-expr-trait-item-1.rs:14:5 | LL | <() as Foo<'a>>::C | ^^^^^^^^^^^^^^^^^^ | = note: ...the reference is valid for the static lifetime... note: ...but the borrowed content is only valid for the lifetime `'a` as defined here - --> $DIR/constant-in-expr-trait-item-1.rs:9:8 + --> $DIR/constant-in-expr-trait-item-1.rs:13:8 | LL | fn foo<'a>(_: &'a u32) -> &'static u32 { | ^^
diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-1.nll.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-1.nll.stderr index ea0fcb6..990d0ae 100644 --- a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-1.nll.stderr +++ b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-1.nll.stderr
@@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/constant-in-expr-trait-item-1.rs:10:5 + --> $DIR/constant-in-expr-trait-item-1.rs:14:5 | LL | fn foo<'a>(_: &'a u32) -> &'static u32 { | -- lifetime `'a` defined here
diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-1.rs b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-1.rs index e0400b2..512edb5 100644 --- a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-1.rs +++ b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-1.rs
@@ -1,3 +1,7 @@ +// revisions: base nll +// ignore-compare-mode-nll +//[nll] compile-flags: -Z borrowck=mir + trait Foo<'a> { const C: &'a u32; }
diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-2.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-2.base.stderr similarity index 82% rename from src/test/ui/nll/user-annotations/constant-in-expr-trait-item-2.stderr rename to src/test/ui/nll/user-annotations/constant-in-expr-trait-item-2.base.stderr index b36bc3b..f43ade3 100644 --- a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-2.stderr +++ b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-2.base.stderr
@@ -1,12 +1,12 @@ error[E0312]: lifetime of reference outlives lifetime of borrowed content... - --> $DIR/constant-in-expr-trait-item-2.rs:10:5 + --> $DIR/constant-in-expr-trait-item-2.rs:14:5 | LL | <T as Foo<'a>>::C | ^^^^^^^^^^^^^^^^^ | = note: ...the reference is valid for the static lifetime... note: ...but the borrowed content is only valid for the lifetime `'a` as defined here - --> $DIR/constant-in-expr-trait-item-2.rs:9:8 + --> $DIR/constant-in-expr-trait-item-2.rs:13:8 | LL | fn foo<'a, T: Foo<'a>>() -> &'static u32 { | ^^
diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-2.nll.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-2.nll.stderr index ff549f1..8c0430f 100644 --- a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-2.nll.stderr +++ b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-2.nll.stderr
@@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/constant-in-expr-trait-item-2.rs:10:5 + --> $DIR/constant-in-expr-trait-item-2.rs:14:5 | LL | fn foo<'a, T: Foo<'a>>() -> &'static u32 { | -- lifetime `'a` defined here
diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-2.rs b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-2.rs index 73c4e57..b3dfbd9 100644 --- a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-2.rs +++ b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-2.rs
@@ -1,3 +1,7 @@ +// revisions: base nll +// ignore-compare-mode-nll +//[nll] compile-flags: -Z borrowck=mir + trait Foo<'a> { const C: &'a u32; }
diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.base.stderr similarity index 77% rename from src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.stderr rename to src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.base.stderr index 806492b..e9393aa 100644 --- a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.stderr +++ b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.base.stderr
@@ -1,16 +1,16 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements - --> $DIR/constant-in-expr-trait-item-3.rs:10:5 + --> $DIR/constant-in-expr-trait-item-3.rs:14:5 | LL | T::C | ^^^^ | note: first, the lifetime cannot outlive the lifetime `'a` as defined here... - --> $DIR/constant-in-expr-trait-item-3.rs:9:8 + --> $DIR/constant-in-expr-trait-item-3.rs:13:8 | LL | fn foo<'a, T: Foo<'a>>() -> &'static u32 { | ^^ note: ...so that the types are compatible - --> $DIR/constant-in-expr-trait-item-3.rs:10:5 + --> $DIR/constant-in-expr-trait-item-3.rs:14:5 | LL | T::C | ^^^^ @@ -18,7 +18,7 @@ found `Foo<'a>` = note: but, the lifetime must be valid for the static lifetime... note: ...so that reference does not outlive borrowed content - --> $DIR/constant-in-expr-trait-item-3.rs:10:5 + --> $DIR/constant-in-expr-trait-item-3.rs:14:5 | LL | T::C | ^^^^
diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.nll.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.nll.stderr index 7f160d8..cbcaf04 100644 --- a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.nll.stderr +++ b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.nll.stderr
@@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/constant-in-expr-trait-item-3.rs:10:5 + --> $DIR/constant-in-expr-trait-item-3.rs:14:5 | LL | fn foo<'a, T: Foo<'a>>() -> &'static u32 { | -- lifetime `'a` defined here
diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.rs b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.rs index 567e31e..6e78d94 100644 --- a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.rs +++ b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.rs
@@ -1,3 +1,7 @@ +// revisions: base nll +// ignore-compare-mode-nll +//[nll] compile-flags: -Z borrowck=mir + trait Foo<'a> { const C: &'a u32; }
diff --git a/src/test/ui/nll/where_clauses_in_structs.stderr b/src/test/ui/nll/where_clauses_in_structs.stderr index 952667d..b88c90e 100644 --- a/src/test/ui/nll/where_clauses_in_structs.stderr +++ b/src/test/ui/nll/where_clauses_in_structs.stderr
@@ -9,8 +9,8 @@ | ^ this usage requires that `'a` must outlive `'b` | = help: consider adding the following bound: `'a: 'b` - = note: requirement occurs because of the type Cell<&u32>, which makes the generic argument &u32 invariant - = note: the struct Cell<T> is invariant over the parameter T + = note: requirement occurs because of the type `Cell<&u32>`, which makes the generic argument `&u32` invariant + = note: the struct `Cell<T>` is invariant over the parameter `T` = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance error: aborting due to previous error
diff --git a/src/test/ui/not-clone-closure.stderr b/src/test/ui/not-clone-closure.stderr index a62c21f..9290979 100644 --- a/src/test/ui/not-clone-closure.stderr +++ b/src/test/ui/not-clone-closure.stderr
@@ -11,6 +11,10 @@ | ^^^^^ within `[closure@$DIR/not-clone-closure.rs:7:17: 9:6]`, the trait `Clone` is not implemented for `S` | = note: required because it appears within the type `[closure@$DIR/not-clone-closure.rs:7:17: 9:6]` +help: consider annotating `S` with `#[derive(Clone)]` + | +LL | #[derive(Clone)] + | error: aborting due to previous error
diff --git a/src/test/ui/numbers-arithmetic/not-suggest-float-literal.stderr b/src/test/ui/numbers-arithmetic/not-suggest-float-literal.stderr index ce9a08a..6aa1ad8 100644 --- a/src/test/ui/numbers-arithmetic/not-suggest-float-literal.stderr +++ b/src/test/ui/numbers-arithmetic/not-suggest-float-literal.stderr
@@ -5,6 +5,16 @@ | ^ no implementation for `u8 + {float}` | = help: the trait `Add<{float}>` is not implemented for `u8` + = help: the following other types implement trait `Add<Rhs>`: + <&'a f32 as Add<f32>> + <&'a f64 as Add<f64>> + <&'a i128 as Add<i128>> + <&'a i16 as Add<i16>> + <&'a i32 as Add<i32>> + <&'a i64 as Add<i64>> + <&'a i8 as Add<i8>> + <&'a isize as Add<isize>> + and 48 others error[E0277]: cannot add `&str` to `f64` --> $DIR/not-suggest-float-literal.rs:6:7 @@ -13,6 +23,16 @@ | ^ no implementation for `f64 + &str` | = help: the trait `Add<&str>` is not implemented for `f64` + = help: the following other types implement trait `Add<Rhs>`: + <&'a f32 as Add<f32>> + <&'a f64 as Add<f64>> + <&'a i128 as Add<i128>> + <&'a i16 as Add<i16>> + <&'a i32 as Add<i32>> + <&'a i64 as Add<i64>> + <&'a i8 as Add<i8>> + <&'a isize as Add<isize>> + and 48 others error[E0277]: cannot add `{integer}` to `f64` --> $DIR/not-suggest-float-literal.rs:11:7 @@ -21,6 +41,16 @@ | ^ no implementation for `f64 + {integer}` | = help: the trait `Add<{integer}>` is not implemented for `f64` + = help: the following other types implement trait `Add<Rhs>`: + <&'a f32 as Add<f32>> + <&'a f64 as Add<f64>> + <&'a i128 as Add<i128>> + <&'a i16 as Add<i16>> + <&'a i32 as Add<i32>> + <&'a i64 as Add<i64>> + <&'a i8 as Add<i8>> + <&'a isize as Add<isize>> + and 48 others error[E0277]: cannot subtract `{float}` from `u8` --> $DIR/not-suggest-float-literal.rs:15:7 @@ -29,6 +59,16 @@ | ^ no implementation for `u8 - {float}` | = help: the trait `Sub<{float}>` is not implemented for `u8` + = help: the following other types implement trait `Sub<Rhs>`: + <&'a f32 as Sub<f32>> + <&'a f64 as Sub<f64>> + <&'a i128 as Sub<i128>> + <&'a i16 as Sub<i16>> + <&'a i32 as Sub<i32>> + <&'a i64 as Sub<i64>> + <&'a i8 as Sub<i8>> + <&'a isize as Sub<isize>> + and 48 others error[E0277]: cannot subtract `&str` from `f64` --> $DIR/not-suggest-float-literal.rs:19:7 @@ -37,6 +77,16 @@ | ^ no implementation for `f64 - &str` | = help: the trait `Sub<&str>` is not implemented for `f64` + = help: the following other types implement trait `Sub<Rhs>`: + <&'a f32 as Sub<f32>> + <&'a f64 as Sub<f64>> + <&'a i128 as Sub<i128>> + <&'a i16 as Sub<i16>> + <&'a i32 as Sub<i32>> + <&'a i64 as Sub<i64>> + <&'a i8 as Sub<i8>> + <&'a isize as Sub<isize>> + and 48 others error[E0277]: cannot subtract `{integer}` from `f64` --> $DIR/not-suggest-float-literal.rs:24:7 @@ -45,6 +95,16 @@ | ^ no implementation for `f64 - {integer}` | = help: the trait `Sub<{integer}>` is not implemented for `f64` + = help: the following other types implement trait `Sub<Rhs>`: + <&'a f32 as Sub<f32>> + <&'a f64 as Sub<f64>> + <&'a i128 as Sub<i128>> + <&'a i16 as Sub<i16>> + <&'a i32 as Sub<i32>> + <&'a i64 as Sub<i64>> + <&'a i8 as Sub<i8>> + <&'a isize as Sub<isize>> + and 48 others error[E0277]: cannot multiply `u8` by `{float}` --> $DIR/not-suggest-float-literal.rs:28:7 @@ -53,6 +113,16 @@ | ^ no implementation for `u8 * {float}` | = help: the trait `Mul<{float}>` is not implemented for `u8` + = help: the following other types implement trait `Mul<Rhs>`: + <&'a f32 as Mul<f32>> + <&'a f64 as Mul<f64>> + <&'a i128 as Mul<i128>> + <&'a i16 as Mul<i16>> + <&'a i32 as Mul<i32>> + <&'a i64 as Mul<i64>> + <&'a i8 as Mul<i8>> + <&'a isize as Mul<isize>> + and 49 others error[E0277]: cannot multiply `f64` by `&str` --> $DIR/not-suggest-float-literal.rs:32:7 @@ -61,6 +131,16 @@ | ^ no implementation for `f64 * &str` | = help: the trait `Mul<&str>` is not implemented for `f64` + = help: the following other types implement trait `Mul<Rhs>`: + <&'a f32 as Mul<f32>> + <&'a f64 as Mul<f64>> + <&'a i128 as Mul<i128>> + <&'a i16 as Mul<i16>> + <&'a i32 as Mul<i32>> + <&'a i64 as Mul<i64>> + <&'a i8 as Mul<i8>> + <&'a isize as Mul<isize>> + and 49 others error[E0277]: cannot multiply `f64` by `{integer}` --> $DIR/not-suggest-float-literal.rs:37:7 @@ -69,6 +149,16 @@ | ^ no implementation for `f64 * {integer}` | = help: the trait `Mul<{integer}>` is not implemented for `f64` + = help: the following other types implement trait `Mul<Rhs>`: + <&'a f32 as Mul<f32>> + <&'a f64 as Mul<f64>> + <&'a i128 as Mul<i128>> + <&'a i16 as Mul<i16>> + <&'a i32 as Mul<i32>> + <&'a i64 as Mul<i64>> + <&'a i8 as Mul<i8>> + <&'a isize as Mul<isize>> + and 49 others error[E0277]: cannot divide `u8` by `{float}` --> $DIR/not-suggest-float-literal.rs:41:7 @@ -77,6 +167,16 @@ | ^ no implementation for `u8 / {float}` | = help: the trait `Div<{float}>` is not implemented for `u8` + = help: the following other types implement trait `Div<Rhs>`: + <&'a f32 as Div<f32>> + <&'a f64 as Div<f64>> + <&'a i128 as Div<i128>> + <&'a i16 as Div<i16>> + <&'a i32 as Div<i32>> + <&'a i64 as Div<i64>> + <&'a i8 as Div<i8>> + <&'a isize as Div<isize>> + and 54 others error[E0277]: cannot divide `f64` by `&str` --> $DIR/not-suggest-float-literal.rs:45:7 @@ -85,6 +185,16 @@ | ^ no implementation for `f64 / &str` | = help: the trait `Div<&str>` is not implemented for `f64` + = help: the following other types implement trait `Div<Rhs>`: + <&'a f32 as Div<f32>> + <&'a f64 as Div<f64>> + <&'a i128 as Div<i128>> + <&'a i16 as Div<i16>> + <&'a i32 as Div<i32>> + <&'a i64 as Div<i64>> + <&'a i8 as Div<i8>> + <&'a isize as Div<isize>> + and 54 others error[E0277]: cannot divide `f64` by `{integer}` --> $DIR/not-suggest-float-literal.rs:50:7 @@ -93,6 +203,16 @@ | ^ no implementation for `f64 / {integer}` | = help: the trait `Div<{integer}>` is not implemented for `f64` + = help: the following other types implement trait `Div<Rhs>`: + <&'a f32 as Div<f32>> + <&'a f64 as Div<f64>> + <&'a i128 as Div<i128>> + <&'a i16 as Div<i16>> + <&'a i32 as Div<i32>> + <&'a i64 as Div<i64>> + <&'a i8 as Div<i8>> + <&'a isize as Div<isize>> + and 54 others error: aborting due to 12 previous errors
diff --git a/src/test/ui/numbers-arithmetic/suggest-float-literal.stderr b/src/test/ui/numbers-arithmetic/suggest-float-literal.stderr index eb0be78..988379e 100644 --- a/src/test/ui/numbers-arithmetic/suggest-float-literal.stderr +++ b/src/test/ui/numbers-arithmetic/suggest-float-literal.stderr
@@ -5,6 +5,16 @@ | ^ no implementation for `f32 + {integer}` | = help: the trait `Add<{integer}>` is not implemented for `f32` + = help: the following other types implement trait `Add<Rhs>`: + <&'a f32 as Add<f32>> + <&'a f64 as Add<f64>> + <&'a i128 as Add<i128>> + <&'a i16 as Add<i16>> + <&'a i32 as Add<i32>> + <&'a i64 as Add<i64>> + <&'a i8 as Add<i8>> + <&'a isize as Add<isize>> + and 48 others help: consider using a floating-point literal by writing it with `.0` | LL | x + 100.0 @@ -17,6 +27,16 @@ | ^ no implementation for `f64 + {integer}` | = help: the trait `Add<{integer}>` is not implemented for `f64` + = help: the following other types implement trait `Add<Rhs>`: + <&'a f32 as Add<f32>> + <&'a f64 as Add<f64>> + <&'a i128 as Add<i128>> + <&'a i16 as Add<i16>> + <&'a i32 as Add<i32>> + <&'a i64 as Add<i64>> + <&'a i8 as Add<i8>> + <&'a isize as Add<isize>> + and 48 others help: consider using a floating-point literal by writing it with `.0` | LL | x + 100.0 @@ -29,6 +49,16 @@ | ^ no implementation for `f32 - {integer}` | = help: the trait `Sub<{integer}>` is not implemented for `f32` + = help: the following other types implement trait `Sub<Rhs>`: + <&'a f32 as Sub<f32>> + <&'a f64 as Sub<f64>> + <&'a i128 as Sub<i128>> + <&'a i16 as Sub<i16>> + <&'a i32 as Sub<i32>> + <&'a i64 as Sub<i64>> + <&'a i8 as Sub<i8>> + <&'a isize as Sub<isize>> + and 48 others help: consider using a floating-point literal by writing it with `.0` | LL | x - 100.0 @@ -41,6 +71,16 @@ | ^ no implementation for `f64 - {integer}` | = help: the trait `Sub<{integer}>` is not implemented for `f64` + = help: the following other types implement trait `Sub<Rhs>`: + <&'a f32 as Sub<f32>> + <&'a f64 as Sub<f64>> + <&'a i128 as Sub<i128>> + <&'a i16 as Sub<i16>> + <&'a i32 as Sub<i32>> + <&'a i64 as Sub<i64>> + <&'a i8 as Sub<i8>> + <&'a isize as Sub<isize>> + and 48 others help: consider using a floating-point literal by writing it with `.0` | LL | x - 100.0 @@ -53,6 +93,16 @@ | ^ no implementation for `f32 * {integer}` | = help: the trait `Mul<{integer}>` is not implemented for `f32` + = help: the following other types implement trait `Mul<Rhs>`: + <&'a f32 as Mul<f32>> + <&'a f64 as Mul<f64>> + <&'a i128 as Mul<i128>> + <&'a i16 as Mul<i16>> + <&'a i32 as Mul<i32>> + <&'a i64 as Mul<i64>> + <&'a i8 as Mul<i8>> + <&'a isize as Mul<isize>> + and 49 others help: consider using a floating-point literal by writing it with `.0` | LL | x * 100.0 @@ -65,6 +115,16 @@ | ^ no implementation for `f64 * {integer}` | = help: the trait `Mul<{integer}>` is not implemented for `f64` + = help: the following other types implement trait `Mul<Rhs>`: + <&'a f32 as Mul<f32>> + <&'a f64 as Mul<f64>> + <&'a i128 as Mul<i128>> + <&'a i16 as Mul<i16>> + <&'a i32 as Mul<i32>> + <&'a i64 as Mul<i64>> + <&'a i8 as Mul<i8>> + <&'a isize as Mul<isize>> + and 49 others help: consider using a floating-point literal by writing it with `.0` | LL | x * 100.0 @@ -77,6 +137,16 @@ | ^ no implementation for `f32 / {integer}` | = help: the trait `Div<{integer}>` is not implemented for `f32` + = help: the following other types implement trait `Div<Rhs>`: + <&'a f32 as Div<f32>> + <&'a f64 as Div<f64>> + <&'a i128 as Div<i128>> + <&'a i16 as Div<i16>> + <&'a i32 as Div<i32>> + <&'a i64 as Div<i64>> + <&'a i8 as Div<i8>> + <&'a isize as Div<isize>> + and 54 others help: consider using a floating-point literal by writing it with `.0` | LL | x / 100.0 @@ -89,6 +159,16 @@ | ^ no implementation for `f64 / {integer}` | = help: the trait `Div<{integer}>` is not implemented for `f64` + = help: the following other types implement trait `Div<Rhs>`: + <&'a f32 as Div<f32>> + <&'a f64 as Div<f64>> + <&'a i128 as Div<i128>> + <&'a i16 as Div<i16>> + <&'a i32 as Div<i32>> + <&'a i64 as Div<i64>> + <&'a i8 as Div<i8>> + <&'a isize as Div<isize>> + and 54 others help: consider using a floating-point literal by writing it with `.0` | LL | x / 100.0
diff --git a/src/test/ui/on-unimplemented/impl-substs.stderr b/src/test/ui/on-unimplemented/impl-substs.stderr index db66ab0..a0fad0a 100644 --- a/src/test/ui/on-unimplemented/impl-substs.stderr +++ b/src/test/ui/on-unimplemented/impl-substs.stderr
@@ -7,6 +7,7 @@ | required by a bound introduced by this call | = help: the trait `Foo<usize>` is not implemented for `(i32, i32, i32)` + = help: the trait `Foo<A>` is implemented for `(A, B, C)` error: aborting due to previous error
diff --git a/src/test/ui/on-unimplemented/multiple-impls.stderr b/src/test/ui/on-unimplemented/multiple-impls.stderr index 76aa128..06e1a22 100644 --- a/src/test/ui/on-unimplemented/multiple-impls.stderr +++ b/src/test/ui/on-unimplemented/multiple-impls.stderr
@@ -7,6 +7,9 @@ | required by a bound introduced by this call | = help: the trait `Index<u32>` is not implemented for `[i32]` + = help: the following other types implement trait `Index<Idx>`: + <[i32] as Index<Bar<usize>>> + <[i32] as Index<Foo<usize>>> error[E0277]: the trait bound `[i32]: Index<Foo<u32>>` is not satisfied --> $DIR/multiple-impls.rs:36:18 @@ -17,6 +20,9 @@ | required by a bound introduced by this call | = help: the trait `Index<Foo<u32>>` is not implemented for `[i32]` + = help: the following other types implement trait `Index<Idx>`: + <[i32] as Index<Bar<usize>>> + <[i32] as Index<Foo<usize>>> error[E0277]: the trait bound `[i32]: Index<Bar<u32>>` is not satisfied --> $DIR/multiple-impls.rs:39:18 @@ -27,6 +33,9 @@ | required by a bound introduced by this call | = help: the trait `Index<Bar<u32>>` is not implemented for `[i32]` + = help: the following other types implement trait `Index<Idx>`: + <[i32] as Index<Bar<usize>>> + <[i32] as Index<Foo<usize>>> error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied --> $DIR/multiple-impls.rs:33:5 @@ -35,6 +44,9 @@ | ^^^^^^^^^^^^ trait message | = help: the trait `Index<u32>` is not implemented for `[i32]` + = help: the following other types implement trait `Index<Idx>`: + <[i32] as Index<Bar<usize>>> + <[i32] as Index<Foo<usize>>> error[E0277]: the trait bound `[i32]: Index<Foo<u32>>` is not satisfied --> $DIR/multiple-impls.rs:36:5 @@ -43,6 +55,9 @@ | ^^^^^^^^^^^^ on impl for Foo | = help: the trait `Index<Foo<u32>>` is not implemented for `[i32]` + = help: the following other types implement trait `Index<Idx>`: + <[i32] as Index<Bar<usize>>> + <[i32] as Index<Foo<usize>>> error[E0277]: the trait bound `[i32]: Index<Bar<u32>>` is not satisfied --> $DIR/multiple-impls.rs:39:5 @@ -51,6 +66,9 @@ | ^^^^^^^^^^^^ on impl for Bar | = help: the trait `Index<Bar<u32>>` is not implemented for `[i32]` + = help: the following other types implement trait `Index<Idx>`: + <[i32] as Index<Bar<usize>>> + <[i32] as Index<Foo<usize>>> error: aborting due to 6 previous errors
diff --git a/src/test/ui/on-unimplemented/no-debug.stderr b/src/test/ui/on-unimplemented/no-debug.stderr index b17c1d4..417e01e 100644 --- a/src/test/ui/on-unimplemented/no-debug.stderr +++ b/src/test/ui/on-unimplemented/no-debug.stderr
@@ -7,6 +7,10 @@ = help: the trait `Debug` is not implemented for `Foo` = note: add `#[derive(Debug)]` to `Foo` or manually `impl Debug for Foo` = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Foo` with `#[derive(Debug)]` + | +LL | #[derive(Debug)] + | error[E0277]: `Bar` doesn't implement `Debug` --> $DIR/no-debug.rs:10:32
diff --git a/src/test/ui/on-unimplemented/on-impl.stderr b/src/test/ui/on-unimplemented/on-impl.stderr index 940763f..769a3d7 100644 --- a/src/test/ui/on-unimplemented/on-impl.stderr +++ b/src/test/ui/on-unimplemented/on-impl.stderr
@@ -7,6 +7,7 @@ | required by a bound introduced by this call | = help: the trait `Index<u32>` is not implemented for `[i32]` + = help: the trait `Index<usize>` is implemented for `[i32]` error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied --> $DIR/on-impl.rs:22:5 @@ -15,6 +16,7 @@ | ^^^^^^^^^^^^^^^^^^^ a usize is required to index into a slice | = help: the trait `Index<u32>` is not implemented for `[i32]` + = help: the trait `Index<usize>` is implemented for `[i32]` error: aborting due to 2 previous errors
diff --git a/src/test/ui/on-unimplemented/slice-index.stderr b/src/test/ui/on-unimplemented/slice-index.stderr index 44b8b0d..ae7d2e1 100644 --- a/src/test/ui/on-unimplemented/slice-index.stderr +++ b/src/test/ui/on-unimplemented/slice-index.stderr
@@ -5,6 +5,7 @@ | ^^^^^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[i32]>` is not implemented for `i32` + = help: the trait `SliceIndex<[T]>` is implemented for `usize` = note: required because of the requirements on the impl of `Index<i32>` for `[i32]` error[E0277]: the type `[i32]` cannot be indexed by `RangeTo<i32>` @@ -14,6 +15,9 @@ | ^^^^^^^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[i32]>` is not implemented for `RangeTo<i32>` + = help: the following other types implement trait `SliceIndex<T>`: + <RangeTo<usize> as SliceIndex<[T]>> + <RangeTo<usize> as SliceIndex<str>> = note: required because of the requirements on the impl of `Index<RangeTo<i32>>` for `[i32]` error: aborting due to 2 previous errors
diff --git a/src/test/ui/parser/attr.rs b/src/test/ui/parser/attr.rs index 91a4abb..42b2dfd 100644 --- a/src/test/ui/parser/attr.rs +++ b/src/test/ui/parser/attr.rs
@@ -3,5 +3,4 @@ fn main() {} #![lang = "foo"] //~ ERROR an inner attribute is not permitted in this context - //~| ERROR definition of an unknown language item: `foo` fn foo() {}
diff --git a/src/test/ui/parser/attr.stderr b/src/test/ui/parser/attr.stderr index 3cec61f..3527274 100644 --- a/src/test/ui/parser/attr.stderr +++ b/src/test/ui/parser/attr.stderr
@@ -3,7 +3,6 @@ | LL | #![lang = "foo"] | ^^^^^^^^^^^^^^^^ -LL | LL | fn foo() {} | ----------- the inner attribute doesn't annotate this function | @@ -14,12 +13,5 @@ LL + #[lang = "foo"] | -error[E0522]: definition of an unknown language item: `foo` - --> $DIR/attr.rs:5:1 - | -LL | #![lang = "foo"] - | ^^^^^^^^^^^^^^^^ definition of unknown language item `foo` +error: aborting due to previous error -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0522`.
diff --git a/src/test/ui/parser/issues/auxiliary/issue-94340-inc.rs b/src/test/ui/parser/issues/auxiliary/issue-94340-inc.rs new file mode 100644 index 0000000..9429e51 --- /dev/null +++ b/src/test/ui/parser/issues/auxiliary/issue-94340-inc.rs
@@ -0,0 +1,3 @@ +// include file for issue-94340.rs +#![deny(rust_2018_idioms)] +#![deny(unused_must_use)]
diff --git a/src/test/ui/parser/issues/issue-94340.rs b/src/test/ui/parser/issues/issue-94340.rs new file mode 100644 index 0000000..d0fb84a --- /dev/null +++ b/src/test/ui/parser/issues/issue-94340.rs
@@ -0,0 +1,8 @@ +// Make sure that unexpected inner attributes are not labeled as outer ones in diagnostics when +// trying to parse an item and that they are subsequently ignored not triggering confusing extra +// diagnostics like "expected item after attributes" which is not true for `include!` which can +// include empty files. + +include!("auxiliary/issue-94340-inc.rs"); + +fn main() {}
diff --git a/src/test/ui/parser/issues/issue-94340.stderr b/src/test/ui/parser/issues/issue-94340.stderr new file mode 100644 index 0000000..9fd7c38 --- /dev/null +++ b/src/test/ui/parser/issues/issue-94340.stderr
@@ -0,0 +1,20 @@ +error: an inner attribute is not permitted in this context + --> $DIR/auxiliary/issue-94340-inc.rs:2:1 + | +LL | #![deny(rust_2018_idioms)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them + +error: an inner attribute is not permitted in this context + --> $DIR/auxiliary/issue-94340-inc.rs:3:1 + | +LL | #![deny(unused_must_use)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them + +error: aborting due to 2 previous errors +
diff --git a/src/test/ui/polymorphization/const_parameters/closures.stderr b/src/test/ui/polymorphization/const_parameters/closures.stderr index d0ee893..f174215 100644 --- a/src/test/ui/polymorphization/const_parameters/closures.stderr +++ b/src/test/ui/polymorphization/const_parameters/closures.stderr
@@ -11,7 +11,7 @@ --> $DIR/closures.rs:19:19 | LL | pub fn unused<const T: usize>() -> usize { - | - generic parameter `T` is unused + | -------------- generic parameter `T` is unused LL | LL | let add_one = |x: usize| x + 1; | ^^^^^^^^^^^^^^^^ @@ -20,13 +20,13 @@ --> $DIR/closures.rs:17:8 | LL | pub fn unused<const T: usize>() -> usize { - | ^^^^^^ - generic parameter `T` is unused + | ^^^^^^ -------------- generic parameter `T` is unused error: item has unused generic parameters --> $DIR/closures.rs:28:19 | LL | pub fn used_parent<const T: usize>() -> usize { - | - generic parameter `T` is unused + | -------------- generic parameter `T` is unused LL | let x: usize = T; LL | let add_one = |x: usize| x + 1; | ^^^^^^^^^^^^^^^^ @@ -35,7 +35,7 @@ --> $DIR/closures.rs:48:13 | LL | pub fn unused_upvar<const T: usize>() -> usize { - | - generic parameter `T` is unused + | -------------- generic parameter `T` is unused LL | let x: usize = T; LL | let y = || x; | ^^^^
diff --git a/src/test/ui/polymorphization/const_parameters/functions.stderr b/src/test/ui/polymorphization/const_parameters/functions.stderr index 03d0bbb..f2b5a73 100644 --- a/src/test/ui/polymorphization/const_parameters/functions.stderr +++ b/src/test/ui/polymorphization/const_parameters/functions.stderr
@@ -11,7 +11,7 @@ --> $DIR/functions.rs:15:8 | LL | pub fn unused<const T: usize>() { - | ^^^^^^ - generic parameter `T` is unused + | ^^^^^^ -------------- generic parameter `T` is unused error: aborting due to previous error; 1 warning emitted
diff --git a/src/test/ui/polymorphization/generators.stderr b/src/test/ui/polymorphization/generators.stderr index 1152bcb..9cabb21 100644 --- a/src/test/ui/polymorphization/generators.stderr +++ b/src/test/ui/polymorphization/generators.stderr
@@ -23,7 +23,7 @@ --> $DIR/generators.rs:60:5 | LL | pub fn unused_const<const T: u32>() -> impl Generator<(), Yield = u32, Return = u32> + Unpin { - | - generic parameter `T` is unused + | ------------ generic parameter `T` is unused LL | / || { LL | | LL | | yield 1;
diff --git a/src/test/ui/proc-macro/auxiliary/api/parse.rs b/src/test/ui/proc-macro/auxiliary/api/parse.rs index 6186b94..27391f8 100644 --- a/src/test/ui/proc-macro/auxiliary/api/parse.rs +++ b/src/test/ui/proc-macro/auxiliary/api/parse.rs
@@ -18,6 +18,17 @@ fn test_display_literal() { Literal::f64_unsuffixed(1e100).to_string(), "10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0", ); + + assert_eq!( + Literal::string("a \t ❤ ' \" \u{1}").to_string(), + "\"a \\t ❤ ' \\\" \\u{1}\"", + ); + assert_eq!(Literal::character('a').to_string(), "'a'"); + assert_eq!(Literal::character('\t').to_string(), "'\\t'"); + assert_eq!(Literal::character('❤').to_string(), "'❤'"); + assert_eq!(Literal::character('\'').to_string(), "'\\''"); + assert_eq!(Literal::character('"').to_string(), "'\"'"); + assert_eq!(Literal::character('\u{1}').to_string(), "'\\u{1}'"); } fn test_parse_literal() {
diff --git a/src/test/ui/proc-macro/quote-debug.stdout b/src/test/ui/proc-macro/quote-debug.stdout index ec54851..d2cc5c6 100644 --- a/src/test/ui/proc-macro/quote-debug.stdout +++ b/src/test/ui/proc-macro/quote-debug.stdout
@@ -22,7 +22,7 @@ crate::Span::recover_proc_macro_span(0)))), crate::TokenStream::from(crate::TokenTree::Ident(crate::Ident::new("hello", crate::Span::recover_proc_macro_span(1)))), - crate::TokenStream::from(crate::TokenTree::Punct(crate::Punct::new('\u{3d}', + crate::TokenStream::from(crate::TokenTree::Punct(crate::Punct::new('=', crate::Spacing::Alone))), crate::TokenStream::from(crate::TokenTree::Literal({ let mut iter = @@ -35,7 +35,7 @@ ::core::panicking::panic("internal error: entered unreachable code") } })), - crate::TokenStream::from(crate::TokenTree::Punct(crate::Punct::new('\u{3b}', + crate::TokenStream::from(crate::TokenTree::Punct(crate::Punct::new(';', crate::Spacing::Alone)))].iter().cloned().collect::<crate::TokenStream>() } const _: () =
diff --git a/src/test/ui/range/range-1.stderr b/src/test/ui/range/range-1.stderr index 2ce4e15..0bbed87 100644 --- a/src/test/ui/range/range-1.stderr +++ b/src/test/ui/range/range-1.stderr
@@ -10,6 +10,16 @@ LL | for i in false..true {} | ^^^^^^^^^^^ the trait `Step` is not implemented for `bool` | + = help: the following other types implement trait `Step`: + char + i128 + i16 + i32 + i64 + i8 + isize + u128 + and 5 others = note: required because of the requirements on the impl of `Iterator` for `std::ops::Range<bool>` = note: required because of the requirements on the impl of `IntoIterator` for `std::ops::Range<bool>`
diff --git a/src/test/ui/regions/region-invariant-static-error-reporting.nll.stderr b/src/test/ui/regions/region-invariant-static-error-reporting.nll.stderr index 376534b..6e7eb73 100644 --- a/src/test/ui/regions/region-invariant-static-error-reporting.nll.stderr +++ b/src/test/ui/regions/region-invariant-static-error-reporting.nll.stderr
@@ -12,8 +12,8 @@ | `x` escapes the function body here | argument requires that `'a` must outlive `'static` | - = note: requirement occurs because of the type Invariant<'_>, which makes the generic argument '_ invariant - = note: the struct Invariant<'a> is invariant over the parameter 'a + = note: requirement occurs because of the type `Invariant<'_>`, which makes the generic argument `'_` invariant + = note: the struct `Invariant<'a>` is invariant over the parameter `'a` = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance error: aborting due to previous error
diff --git a/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.nll.stderr b/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.nll.stderr index a64ad46..233a040 100644 --- a/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.nll.stderr +++ b/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.nll.stderr
@@ -23,7 +23,7 @@ | ^^^^^^^ argument requires that `'b` must outlive `'a` | = help: consider adding the following bound: `'b: 'a` - = note: requirement occurs because of a mutable reference to &isize + = note: requirement occurs because of a mutable reference to `&isize` = note: mutable references are invariant over their type parameter = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
diff --git a/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.nll.stderr b/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.nll.stderr index ce5e7d0..0011974 100644 --- a/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.nll.stderr +++ b/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.nll.stderr
@@ -23,7 +23,7 @@ | ^^^^^^^^^^ argument requires that `'b` must outlive `'a` | = help: consider adding the following bound: `'b: 'a` - = note: requirement occurs because of a mutable reference to &isize + = note: requirement occurs because of a mutable reference to `&isize` = note: mutable references are invariant over their type parameter = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
diff --git a/src/test/ui/regions/regions-bounded-method-type-parameters-cross-crate.nll.stderr b/src/test/ui/regions/regions-bounded-method-type-parameters-cross-crate.nll.stderr index 32f3080..6193bf0 100644 --- a/src/test/ui/regions/regions-bounded-method-type-parameters-cross-crate.nll.stderr +++ b/src/test/ui/regions/regions-bounded-method-type-parameters-cross-crate.nll.stderr
@@ -10,8 +10,8 @@ | ^^^^^^^^^^^^^^^^^^ argument requires that `'y` must outlive `'x` | = help: consider adding the following bound: `'y: 'x` - = note: requirement occurs because of the type Inv<'_>, which makes the generic argument '_ invariant - = note: the struct Inv<'a> is invariant over the parameter 'a + = note: requirement occurs because of the type `Inv<'_>`, which makes the generic argument `'_` invariant + = note: the struct `Inv<'a>` is invariant over the parameter `'a` = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance error: aborting due to previous error
diff --git a/src/test/ui/regions/regions-bounded-method-type-parameters-trait-bound.nll.stderr b/src/test/ui/regions/regions-bounded-method-type-parameters-trait-bound.nll.stderr index 246b648..0e0086b 100644 --- a/src/test/ui/regions/regions-bounded-method-type-parameters-trait-bound.nll.stderr +++ b/src/test/ui/regions/regions-bounded-method-type-parameters-trait-bound.nll.stderr
@@ -10,8 +10,8 @@ | ^^^^^^^^^^^ argument requires that `'b` must outlive `'a` | = help: consider adding the following bound: `'b: 'a` - = note: requirement occurs because of the type Inv<'_>, which makes the generic argument '_ invariant - = note: the struct Inv<'a> is invariant over the parameter 'a + = note: requirement occurs because of the type `Inv<'_>`, which makes the generic argument `'_` invariant + = note: the struct `Inv<'a>` is invariant over the parameter `'a` = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance error: aborting due to previous error
diff --git a/src/test/ui/regions/regions-infer-invariance-due-to-decl.nll.stderr b/src/test/ui/regions/regions-infer-invariance-due-to-decl.nll.stderr index fede5f2..c8c7808 100644 --- a/src/test/ui/regions/regions-infer-invariance-due-to-decl.nll.stderr +++ b/src/test/ui/regions/regions-infer-invariance-due-to-decl.nll.stderr
@@ -6,8 +6,8 @@ LL | b_isize | ^^^^^^^ returning this value requires that `'r` must outlive `'static` | - = note: requirement occurs because of the type Invariant<'_>, which makes the generic argument '_ invariant - = note: the struct Invariant<'a> is invariant over the parameter 'a + = note: requirement occurs because of the type `Invariant<'_>`, which makes the generic argument `'_` invariant + = note: the struct `Invariant<'a>` is invariant over the parameter `'a` = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance error: aborting due to previous error
diff --git a/src/test/ui/regions/regions-infer-invariance-due-to-mutability-3.nll.stderr b/src/test/ui/regions/regions-infer-invariance-due-to-mutability-3.nll.stderr index 8f5f366..1165011 100644 --- a/src/test/ui/regions/regions-infer-invariance-due-to-mutability-3.nll.stderr +++ b/src/test/ui/regions/regions-infer-invariance-due-to-mutability-3.nll.stderr
@@ -6,8 +6,8 @@ LL | b_isize | ^^^^^^^ returning this value requires that `'r` must outlive `'static` | - = note: requirement occurs because of the type Invariant<'_>, which makes the generic argument '_ invariant - = note: the struct Invariant<'a> is invariant over the parameter 'a + = note: requirement occurs because of the type `Invariant<'_>`, which makes the generic argument `'_` invariant + = note: the struct `Invariant<'a>` is invariant over the parameter `'a` = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance error: aborting due to previous error
diff --git a/src/test/ui/regions/regions-infer-invariance-due-to-mutability-4.nll.stderr b/src/test/ui/regions/regions-infer-invariance-due-to-mutability-4.nll.stderr index 8079fb0..f3973a9 100644 --- a/src/test/ui/regions/regions-infer-invariance-due-to-mutability-4.nll.stderr +++ b/src/test/ui/regions/regions-infer-invariance-due-to-mutability-4.nll.stderr
@@ -6,8 +6,8 @@ LL | b_isize | ^^^^^^^ returning this value requires that `'r` must outlive `'static` | - = note: requirement occurs because of the type Invariant<'_>, which makes the generic argument '_ invariant - = note: the struct Invariant<'a> is invariant over the parameter 'a + = note: requirement occurs because of the type `Invariant<'_>`, which makes the generic argument `'_` invariant + = note: the struct `Invariant<'a>` is invariant over the parameter `'a` = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance error: aborting due to previous error
diff --git a/src/test/ui/regions/regions-infer-not-param.nll.stderr b/src/test/ui/regions/regions-infer-not-param.nll.stderr index 3183aee..f4875e4 100644 --- a/src/test/ui/regions/regions-infer-not-param.nll.stderr +++ b/src/test/ui/regions/regions-infer-not-param.nll.stderr
@@ -17,8 +17,8 @@ | lifetime `'a` defined here | = help: consider adding the following bound: `'b: 'a` - = note: requirement occurs because of the type Indirect2<'_>, which makes the generic argument '_ invariant - = note: the struct Indirect2<'a> is invariant over the parameter 'a + = note: requirement occurs because of the type `Indirect2<'_>`, which makes the generic argument `'_` invariant + = note: the struct `Indirect2<'a>` is invariant over the parameter `'a` = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance error: lifetime may not live long enough @@ -30,8 +30,8 @@ | lifetime `'a` defined here | = help: consider adding the following bound: `'a: 'b` - = note: requirement occurs because of the type Indirect2<'_>, which makes the generic argument '_ invariant - = note: the struct Indirect2<'a> is invariant over the parameter 'a + = note: requirement occurs because of the type `Indirect2<'_>`, which makes the generic argument `'_` invariant + = note: the struct `Indirect2<'a>` is invariant over the parameter `'a` = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance help: `'b` and `'a` must be the same: replace one with the other
diff --git a/src/test/ui/regions/regions-lifetime-bounds-on-fns.nll.stderr b/src/test/ui/regions/regions-lifetime-bounds-on-fns.nll.stderr index cae692a..ee3dcef 100644 --- a/src/test/ui/regions/regions-lifetime-bounds-on-fns.nll.stderr +++ b/src/test/ui/regions/regions-lifetime-bounds-on-fns.nll.stderr
@@ -23,7 +23,7 @@ | ^^^^^^^ argument requires that `'b` must outlive `'a` | = help: consider adding the following bound: `'b: 'a` - = note: requirement occurs because of a mutable reference to &isize + = note: requirement occurs because of a mutable reference to `&isize` = note: mutable references are invariant over their type parameter = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
diff --git a/src/test/ui/regions/regions-trait-object-subtyping.nll.stderr b/src/test/ui/regions/regions-trait-object-subtyping.nll.stderr index 26f0fca..1b3a116 100644 --- a/src/test/ui/regions/regions-trait-object-subtyping.nll.stderr +++ b/src/test/ui/regions/regions-trait-object-subtyping.nll.stderr
@@ -10,7 +10,7 @@ | ^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` | = help: consider adding the following bound: `'a: 'b` - = note: requirement occurs because of a mutable reference to dyn Dummy + = note: requirement occurs because of a mutable reference to `dyn Dummy` = note: mutable references are invariant over their type parameter = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance @@ -26,7 +26,7 @@ | ^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` | = help: consider adding the following bound: `'b: 'a` - = note: requirement occurs because of a mutable reference to dyn Dummy + = note: requirement occurs because of a mutable reference to `dyn Dummy` = note: mutable references are invariant over their type parameter = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
diff --git a/src/test/ui/regions/regions-variance-invariant-use-contravariant.nll.stderr b/src/test/ui/regions/regions-variance-invariant-use-contravariant.nll.stderr index 8e8ca8e..b35a2cb 100644 --- a/src/test/ui/regions/regions-variance-invariant-use-contravariant.nll.stderr +++ b/src/test/ui/regions/regions-variance-invariant-use-contravariant.nll.stderr
@@ -10,8 +10,8 @@ | ^^^^^^^^^^^^^^^^^ type annotation requires that `'short` must outlive `'long` | = help: consider adding the following bound: `'short: 'long` - = note: requirement occurs because of the type Invariant<'_>, which makes the generic argument '_ invariant - = note: the struct Invariant<'a> is invariant over the parameter 'a + = note: requirement occurs because of the type `Invariant<'_>`, which makes the generic argument `'_` invariant + = note: the struct `Invariant<'a>` is invariant over the parameter `'a` = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance error: aborting due to previous error
diff --git a/src/test/ui/regions/regions-variance-invariant-use-covariant.nll.stderr b/src/test/ui/regions/regions-variance-invariant-use-covariant.nll.stderr index f9a3d72..761e78d 100644 --- a/src/test/ui/regions/regions-variance-invariant-use-covariant.nll.stderr +++ b/src/test/ui/regions/regions-variance-invariant-use-covariant.nll.stderr
@@ -7,8 +7,8 @@ LL | let _: Invariant<'static> = c; | ^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'static` | - = note: requirement occurs because of the type Invariant<'_>, which makes the generic argument '_ invariant - = note: the struct Invariant<'a> is invariant over the parameter 'a + = note: requirement occurs because of the type `Invariant<'_>`, which makes the generic argument `'_` invariant + = note: the struct `Invariant<'a>` is invariant over the parameter `'a` = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance error: aborting due to previous error
diff --git a/src/test/ui/repeat-to-run-dtor-twice.stderr b/src/test/ui/repeat-to-run-dtor-twice.stderr index f07bbe3..9044137 100644 --- a/src/test/ui/repeat-to-run-dtor-twice.stderr +++ b/src/test/ui/repeat-to-run-dtor-twice.stderr
@@ -5,6 +5,10 @@ | ^^^^^^^^ the trait `Copy` is not implemented for `Foo` | = note: the `Copy` trait is required because the repeated element will be copied +help: consider annotating `Foo` with `#[derive(Copy)]` + | +LL | #[derive(Copy)] + | error: aborting due to previous error
diff --git a/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr b/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr index f8eaf61..96a899e 100644 --- a/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr +++ b/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr
@@ -9,6 +9,10 @@ | |_^ `main` can only return types that implement `Termination` | = help: the trait `Termination` is not implemented for `Result<f32, ParseFloatError>` + = help: the following other types implement trait `Termination`: + Result<!, E> + Result<(), E> + Result<Infallible, E> note: required by a bound in `assert_test_result` --> $SRC_DIR/test/src/lib.rs:LL:COL |
diff --git a/src/test/ui/rfc-2361-dbg-macro/dbg-macro-requires-debug.stderr b/src/test/ui/rfc-2361-dbg-macro/dbg-macro-requires-debug.stderr index 3cdab65..ea1f66d 100644 --- a/src/test/ui/rfc-2361-dbg-macro/dbg-macro-requires-debug.stderr +++ b/src/test/ui/rfc-2361-dbg-macro/dbg-macro-requires-debug.stderr
@@ -7,6 +7,10 @@ = help: the trait `Debug` is not implemented for `NotDebug` = note: add `#[derive(Debug)]` to `NotDebug` or manually `impl Debug for NotDebug` = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `NotDebug` with `#[derive(Debug)]` + | +LL | #[derive(Debug)] + | error: aborting due to previous error
diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr index b0af45a..0a2a5f0 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr
@@ -17,6 +17,10 @@ | LL | const fn equals_self<T: ~const PartialEq>(t: &T) -> bool { | ^^^^^^^^^^^^^^^^ required by this bound in `equals_self` +help: consider annotating `S` with `#[derive(PartialEq)]` + | +LL | #[derive(PartialEq)] + | error: aborting due to previous error
diff --git a/src/test/ui/rfc1623.stderr b/src/test/ui/rfc1623.base.stderr similarity index 93% rename from src/test/ui/rfc1623.stderr rename to src/test/ui/rfc1623.base.stderr index 16829b5..6d389a1 100644 --- a/src/test/ui/rfc1623.stderr +++ b/src/test/ui/rfc1623.base.stderr
@@ -1,5 +1,5 @@ error: implementation of `FnOnce` is not general enough - --> $DIR/rfc1623.rs:28:8 + --> $DIR/rfc1623.rs:36:8 | LL | f: &id, | ^^^ implementation of `FnOnce` is not general enough
diff --git a/src/test/ui/rfc1623.nll.stderr b/src/test/ui/rfc1623.nll.stderr index 86513b6..f85b6ff 100644 --- a/src/test/ui/rfc1623.nll.stderr +++ b/src/test/ui/rfc1623.nll.stderr
@@ -1,11 +1,12 @@ error[E0308]: mismatched types - --> $DIR/rfc1623.rs:25:35 + --> $DIR/rfc1623.rs:29:35 | LL | static SOME_STRUCT: &SomeStruct = &SomeStruct { | ___________________________________^ -LL | | foo: &Foo { bools: &[false, true] }, -LL | | bar: &Bar { bools: &[true, true] }, -LL | | f: &id, +LL | | +LL | | +LL | | +... | LL | | LL | | }; | |_^ one type is more general than the other @@ -14,13 +15,14 @@ found type `Fn<(&Foo<'_>,)>` error[E0308]: mismatched types - --> $DIR/rfc1623.rs:25:35 + --> $DIR/rfc1623.rs:29:35 | LL | static SOME_STRUCT: &SomeStruct = &SomeStruct { | ___________________________________^ -LL | | foo: &Foo { bools: &[false, true] }, -LL | | bar: &Bar { bools: &[true, true] }, -LL | | f: &id, +LL | | +LL | | +LL | | +... | LL | | LL | | }; | |_^ one type is more general than the other @@ -29,13 +31,14 @@ found type `Fn<(&Foo<'_>,)>` error: implementation of `FnOnce` is not general enough - --> $DIR/rfc1623.rs:25:35 + --> $DIR/rfc1623.rs:29:35 | LL | static SOME_STRUCT: &SomeStruct = &SomeStruct { | ___________________________________^ -LL | | foo: &Foo { bools: &[false, true] }, -LL | | bar: &Bar { bools: &[true, true] }, -LL | | f: &id, +LL | | +LL | | +LL | | +... | LL | | LL | | }; | |_^ implementation of `FnOnce` is not general enough @@ -44,13 +47,14 @@ = note: ...but it actually implements `FnOnce<(&'2 Foo<'_>,)>`, for some specific lifetime `'2` error: implementation of `FnOnce` is not general enough - --> $DIR/rfc1623.rs:25:35 + --> $DIR/rfc1623.rs:29:35 | LL | static SOME_STRUCT: &SomeStruct = &SomeStruct { | ___________________________________^ -LL | | foo: &Foo { bools: &[false, true] }, -LL | | bar: &Bar { bools: &[true, true] }, -LL | | f: &id, +LL | | +LL | | +LL | | +... | LL | | LL | | }; | |_^ implementation of `FnOnce` is not general enough
diff --git a/src/test/ui/rfc1623.rs b/src/test/ui/rfc1623.rs index 32e00f9..0e9d214 100644 --- a/src/test/ui/rfc1623.rs +++ b/src/test/ui/rfc1623.rs
@@ -1,3 +1,7 @@ +// revisions: base nll +// ignore-compare-mode-nll +//[nll] compile-flags: -Z borrowck=mir + #![allow(dead_code)] fn non_elidable<'a, 'b>(a: &'a u8, b: &'b u8) -> &'a u8 { @@ -23,10 +27,14 @@ fn id<T>(t: T) -> T { } static SOME_STRUCT: &SomeStruct = &SomeStruct { + //[nll]~^ ERROR mismatched types + //[nll]~| ERROR mismatched types + //[nll]~| ERROR implementation of `FnOnce` is not general enough + //[nll]~| ERROR implementation of `FnOnce` is not general enough foo: &Foo { bools: &[false, true] }, bar: &Bar { bools: &[true, true] }, f: &id, - //~^ ERROR implementation of `FnOnce` is not general enough + //[base]~^ ERROR implementation of `FnOnce` is not general enough }; // very simple test for a 'static static with default lifetime
diff --git a/src/test/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr b/src/test/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr index ea22d1c..94a90a5 100644 --- a/src/test/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr +++ b/src/test/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr
@@ -53,7 +53,7 @@ --> $DIR/fn-traits.rs:28:10 | LL | call(foo_unsafe); - | ---- ^^^^^^^^^^ expected an `Fn<()>` closure, found `unsafe fn() {foo_unsafe}` + | ---- ^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }` | | | required by a bound introduced by this call | @@ -70,7 +70,7 @@ --> $DIR/fn-traits.rs:30:14 | LL | call_mut(foo_unsafe); - | -------- ^^^^^^^^^^ expected an `FnMut<()>` closure, found `unsafe fn() {foo_unsafe}` + | -------- ^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }` | | | required by a bound introduced by this call | @@ -87,7 +87,7 @@ --> $DIR/fn-traits.rs:32:15 | LL | call_once(foo_unsafe); - | --------- ^^^^^^^^^^ expected an `FnOnce<()>` closure, found `unsafe fn() {foo_unsafe}` + | --------- ^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }` | | | required by a bound introduced by this call |
diff --git a/src/test/ui/rust-2018/trait-import-suggestions.stderr b/src/test/ui/rust-2018/trait-import-suggestions.stderr index eb4e43aa..6454b60 100644 --- a/src/test/ui/rust-2018/trait-import-suggestions.stderr +++ b/src/test/ui/rust-2018/trait-import-suggestions.stderr
@@ -45,6 +45,10 @@ | LL | use std::str::FromStr; | +help: there is an associated function with a similar name + | +LL | let y = u32::from_str_radix("33"); + | ~~~~~~~~~~~~~~ error: aborting due to 4 previous errors
diff --git a/src/test/ui/save-analysis/issue-89066.stderr b/src/test/ui/save-analysis/issue-89066.stderr index a3ff1c0..5ef0493 100644 --- a/src/test/ui/save-analysis/issue-89066.stderr +++ b/src/test/ui/save-analysis/issue-89066.stderr
@@ -31,7 +31,7 @@ --> $DIR/issue-89066.rs:8:8 | LL | struct All<'a, T, const N: usize> { - | ^^^ - - + | ^^^ - -------------- error: aborting due to 4 previous errors
diff --git a/src/test/ui/span/multiline-span-simple.stderr b/src/test/ui/span/multiline-span-simple.stderr index 13ef0d1..c0d9a86 100644 --- a/src/test/ui/span/multiline-span-simple.stderr +++ b/src/test/ui/span/multiline-span-simple.stderr
@@ -5,6 +5,16 @@ | ^ no implementation for `u32 + ()` | = help: the trait `Add<()>` is not implemented for `u32` + = help: the following other types implement trait `Add<Rhs>`: + <&'a f32 as Add<f32>> + <&'a f64 as Add<f64>> + <&'a i128 as Add<i128>> + <&'a i16 as Add<i16>> + <&'a i32 as Add<i32>> + <&'a i64 as Add<i64>> + <&'a i8 as Add<i8>> + <&'a isize as Add<isize>> + and 48 others error: aborting due to previous error
diff --git a/src/test/ui/specialization/default-associated-type-bound-1.stderr b/src/test/ui/specialization/default-associated-type-bound-1.stderr index f88acfb..af9f2f7 100644 --- a/src/test/ui/specialization/default-associated-type-bound-1.stderr +++ b/src/test/ui/specialization/default-associated-type-bound-1.stderr
@@ -14,8 +14,7 @@ LL | default type U = str; | ^^^ the trait `Clone` is not implemented for `str` | - = help: the following implementations were found: - <String as Clone> + = help: the trait `Clone` is implemented for `String` note: required by a bound in `X::U` --> $DIR/default-associated-type-bound-1.rs:8:13 |
diff --git a/src/test/ui/specialization/issue-59435.stderr b/src/test/ui/specialization/issue-59435.stderr index bb5d90f..2114594 100644 --- a/src/test/ui/specialization/issue-59435.stderr +++ b/src/test/ui/specialization/issue-59435.stderr
@@ -9,6 +9,10 @@ | LL | type MyType: Default; | ^^^^^^^ required by this bound in `MyTrait::MyType` +help: consider annotating `MyStruct` with `#[derive(Default)]` + | +LL | #[derive(Default)] + | error: aborting due to previous error
diff --git a/src/test/ui/str/str-idx.stderr b/src/test/ui/str/str-idx.stderr index 9ab409b..4545078 100644 --- a/src/test/ui/str/str-idx.stderr +++ b/src/test/ui/str/str-idx.stderr
@@ -7,6 +7,7 @@ = help: the trait `SliceIndex<str>` is not implemented for `{integer}` = note: you can use `.chars().nth()` or `.bytes().nth()` for more information, see chapter 8 in The Book: <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings> + = help: the trait `SliceIndex<[T]>` is implemented for `usize` = note: required because of the requirements on the impl of `Index<{integer}>` for `str` error[E0277]: the type `str` cannot be indexed by `{integer}` @@ -20,6 +21,7 @@ = help: the trait `SliceIndex<str>` is not implemented for `{integer}` = note: you can use `.chars().nth()` or `.bytes().nth()` for more information, see chapter 8 in The Book: <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings> + = help: the trait `SliceIndex<[T]>` is implemented for `usize` note: required by a bound in `core::str::<impl str>::get` --> $SRC_DIR/core/src/str/mod.rs:LL:COL | @@ -37,6 +39,7 @@ = help: the trait `SliceIndex<str>` is not implemented for `{integer}` = note: you can use `.chars().nth()` or `.bytes().nth()` for more information, see chapter 8 in The Book: <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings> + = help: the trait `SliceIndex<[T]>` is implemented for `usize` note: required by a bound in `core::str::<impl str>::get_unchecked` --> $SRC_DIR/core/src/str/mod.rs:LL:COL |
diff --git a/src/test/ui/str/str-mut-idx.stderr b/src/test/ui/str/str-mut-idx.stderr index 5956e36..9ae0856 100644 --- a/src/test/ui/str/str-mut-idx.stderr +++ b/src/test/ui/str/str-mut-idx.stderr
@@ -31,6 +31,7 @@ | ^^^^^^^^^ string indices are ranges of `usize` | = help: the trait `SliceIndex<str>` is not implemented for `usize` + = help: the trait `SliceIndex<[T]>` is implemented for `usize` = note: required because of the requirements on the impl of `Index<usize>` for `str` error[E0277]: the type `str` cannot be indexed by `{integer}` @@ -44,6 +45,7 @@ = help: the trait `SliceIndex<str>` is not implemented for `{integer}` = note: you can use `.chars().nth()` or `.bytes().nth()` for more information, see chapter 8 in The Book: <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings> + = help: the trait `SliceIndex<[T]>` is implemented for `usize` note: required by a bound in `core::str::<impl str>::get_mut` --> $SRC_DIR/core/src/str/mod.rs:LL:COL | @@ -61,6 +63,7 @@ = help: the trait `SliceIndex<str>` is not implemented for `{integer}` = note: you can use `.chars().nth()` or `.bytes().nth()` for more information, see chapter 8 in The Book: <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings> + = help: the trait `SliceIndex<[T]>` is implemented for `usize` note: required by a bound in `core::str::<impl str>::get_unchecked_mut` --> $SRC_DIR/core/src/str/mod.rs:LL:COL |
diff --git a/src/test/ui/structs/struct-path-alias-bounds.stderr b/src/test/ui/structs/struct-path-alias-bounds.stderr index 7a80e72..266291f 100644 --- a/src/test/ui/structs/struct-path-alias-bounds.stderr +++ b/src/test/ui/structs/struct-path-alias-bounds.stderr
@@ -9,6 +9,10 @@ | LL | struct S<T: Clone> { a: T } | ^^^^^ required by this bound in `S` +help: consider annotating `NoClone` with `#[derive(Clone)]` + | +LL | #[derive(Clone)] + | error: aborting due to previous error
diff --git a/src/test/ui/suggestions/derive-macro-missing-bounds.stderr b/src/test/ui/suggestions/derive-macro-missing-bounds.stderr index 7a4f7e2..75658f5 100644 --- a/src/test/ui/suggestions/derive-macro-missing-bounds.stderr +++ b/src/test/ui/suggestions/derive-macro-missing-bounds.stderr
@@ -9,6 +9,10 @@ = help: the trait `Debug` is not implemented for `a::Inner<T>` = note: add `#[derive(Debug)]` to `a::Inner<T>` or manually `impl Debug for a::Inner<T>` = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `a::Inner<T>` with `#[derive(Debug)]` + | +LL | #[derive(Debug)] + | help: consider introducing a `where` bound, but there might be an alternative better way to express this requirement | LL | struct Outer<T>(Inner<T>) where a::Inner<T>: Debug;
diff --git a/src/test/ui/suggestions/imm-ref-trait-object-literal-bound-regions.stderr b/src/test/ui/suggestions/imm-ref-trait-object-literal-bound-regions.stderr index 64a6252..0783f04 100644 --- a/src/test/ui/suggestions/imm-ref-trait-object-literal-bound-regions.stderr +++ b/src/test/ui/suggestions/imm-ref-trait-object-literal-bound-regions.stderr
@@ -4,8 +4,7 @@ LL | foo::<S>(s); | ^^^^^^^^ the trait `for<'b> Trait` is not implemented for `&'b S` | - = help: the following implementations were found: - <&'a mut S as Trait> + = help: the trait `Trait` is implemented for `&'a mut S` note: required by a bound in `foo` --> $DIR/imm-ref-trait-object-literal-bound-regions.rs:11:20 |
diff --git a/src/test/ui/suggestions/imm-ref-trait-object-literal.stderr b/src/test/ui/suggestions/imm-ref-trait-object-literal.stderr index 001af27..5f3f62a 100644 --- a/src/test/ui/suggestions/imm-ref-trait-object-literal.stderr +++ b/src/test/ui/suggestions/imm-ref-trait-object-literal.stderr
@@ -6,8 +6,7 @@ | | | required by a bound introduced by this call | - = help: the following implementations were found: - <&'a mut S as Trait> + = help: the trait `Trait` is implemented for `&'a mut S` note: required by a bound in `foo` --> $DIR/imm-ref-trait-object-literal.rs:7:11 |
diff --git a/src/test/ui/suggestions/impl-trait-return-trailing-semicolon.stderr b/src/test/ui/suggestions/impl-trait-return-trailing-semicolon.stderr index ba6967e..0de7655 100644 --- a/src/test/ui/suggestions/impl-trait-return-trailing-semicolon.stderr +++ b/src/test/ui/suggestions/impl-trait-return-trailing-semicolon.stderr
@@ -15,6 +15,8 @@ LL | | LL | | } | |_^ the trait `Bar` is not implemented for `()` + | + = help: the trait `Bar` is implemented for `u8` error: aborting due to 2 previous errors
diff --git a/src/test/ui/suggestions/into-str.stderr b/src/test/ui/suggestions/into-str.stderr index 470c0bf..8ae5c84 100644 --- a/src/test/ui/suggestions/into-str.stderr +++ b/src/test/ui/suggestions/into-str.stderr
@@ -7,12 +7,13 @@ | required by a bound introduced by this call | = note: to coerce a `String` into a `&str`, use `&*` as a prefix - = help: the following implementations were found: + = help: the following other types implement trait `From<T>`: <String as From<&String>> <String as From<&mut str>> <String as From<&str>> <String as From<Box<str>>> - and 2 others + <String as From<Cow<'a, str>>> + <String as From<char>> = note: required because of the requirements on the impl of `Into<&str>` for `String` note: required by a bound in `foo` --> $DIR/into-str.rs:1:31
diff --git a/src/test/ui/suggestions/issue-71394-no-from-impl.stderr b/src/test/ui/suggestions/issue-71394-no-from-impl.stderr index 7972437..383f40d 100644 --- a/src/test/ui/suggestions/issue-71394-no-from-impl.stderr +++ b/src/test/ui/suggestions/issue-71394-no-from-impl.stderr
@@ -4,7 +4,7 @@ LL | let _: &[i8] = data.into(); | ^^^^ the trait `From<&[u8]>` is not implemented for `&[i8]` | - = help: the following implementations were found: + = help: the following other types implement trait `From<T>`: <[T; LANES] as From<Simd<T, LANES>>> <[bool; LANES] as From<Mask<T, LANES>>> = note: required because of the requirements on the impl of `Into<&[i8]>` for `&[u8]`
diff --git a/src/test/ui/suggestions/issue-84973-blacklist.stderr b/src/test/ui/suggestions/issue-84973-blacklist.stderr index ae55c96..5d8d688 100644 --- a/src/test/ui/suggestions/issue-84973-blacklist.stderr +++ b/src/test/ui/suggestions/issue-84973-blacklist.stderr
@@ -25,6 +25,10 @@ | LL | fn f_clone<T: Clone>(t: T) {} | ^^^^^ required by this bound in `f_clone` +help: consider annotating `S` with `#[derive(Clone)]` + | +LL | #[derive(Clone)] + | error[E0277]: `[static generator@$DIR/issue-84973-blacklist.rs:17:13: 17:33]` cannot be unpinned --> $DIR/issue-84973-blacklist.rs:17:5
diff --git a/src/test/ui/suggestions/issue-84973-negative.stderr b/src/test/ui/suggestions/issue-84973-negative.stderr index bacab64..15559d4 100644 --- a/src/test/ui/suggestions/issue-84973-negative.stderr +++ b/src/test/ui/suggestions/issue-84973-negative.stderr
@@ -6,8 +6,7 @@ | | | required by a bound introduced by this call | - = help: the following implementations were found: - <&f32 as Tr> + = help: the trait `Tr` is implemented for `&f32` note: required by a bound in `bar` --> $DIR/issue-84973-negative.rs:5:11 |
diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-before-const.fixed b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-before-const.fixed new file mode 100644 index 0000000..3c06f4f --- /dev/null +++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-before-const.fixed
@@ -0,0 +1,10 @@ +// run-rustfix +// https://github.com/rust-lang/rust/issues/95616 + +fn buggy_const<'a, const N: usize>(_a: &'a Option<[u8; N]>, _f: &'a str) -> &'a str { //~ERROR [E0106] + return ""; +} + +fn main() { + buggy_const(&Some([69,69,69,69,0]), "test"); +}
diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-before-const.rs b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-before-const.rs new file mode 100644 index 0000000..110468c --- /dev/null +++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-before-const.rs
@@ -0,0 +1,10 @@ +// run-rustfix +// https://github.com/rust-lang/rust/issues/95616 + +fn buggy_const<const N: usize>(_a: &Option<[u8; N]>, _f: &str) -> &str { //~ERROR [E0106] + return ""; +} + +fn main() { + buggy_const(&Some([69,69,69,69,0]), "test"); +}
diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-before-const.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-before-const.stderr new file mode 100644 index 0000000..7b126c9 --- /dev/null +++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-before-const.stderr
@@ -0,0 +1,15 @@ +error[E0106]: missing lifetime specifier + --> $DIR/missing-lifetimes-in-signature-before-const.rs:4:67 + | +LL | fn buggy_const<const N: usize>(_a: &Option<[u8; N]>, _f: &str) -> &str { + | ---------------- ---- ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `_a` or `_f` +help: consider introducing a named lifetime parameter + | +LL | fn buggy_const<'a, const N: usize>(_a: &'a Option<[u8; N]>, _f: &'a str) -> &'a str { + | +++ ++ ++ ++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0106`.
diff --git a/src/test/ui/suggestions/suggest-methods.stderr b/src/test/ui/suggestions/suggest-methods.stderr index 535841e..9079e8f 100644 --- a/src/test/ui/suggestions/suggest-methods.stderr +++ b/src/test/ui/suggestions/suggest-methods.stderr
@@ -23,7 +23,7 @@ --> $DIR/suggest-methods.rs:28:19 | LL | let _ = 63u32.count_o(); - | ^^^^^^^ method not found in `u32` + | ^^^^^^^ help: there is an associated function with a similar name: `count_ones` error: aborting due to 4 previous errors
diff --git a/src/test/ui/target-feature/tied-features.rs b/src/test/ui/target-feature/tied-features.rs index 048777c..15f0150 100644 --- a/src/test/ui/target-feature/tied-features.rs +++ b/src/test/ui/target-feature/tied-features.rs
@@ -1,7 +1,6 @@ // build-fail // compile-flags: --crate-type=rlib --target=aarch64-unknown-linux-gnu // needs-llvm-components: aarch64 -#![cfg_attr(bootstrap, feature(aarch64_target_feature))] #![feature(no_core, lang_items)] #![no_core]
diff --git a/src/test/ui/target-feature/tied-features.stderr b/src/test/ui/target-feature/tied-features.stderr index 6362c7a..525c908 100644 --- a/src/test/ui/target-feature/tied-features.stderr +++ b/src/test/ui/target-feature/tied-features.stderr
@@ -1,5 +1,5 @@ error: the target features paca, pacg must all be either enabled or disabled together - --> $DIR/tied-features.rs:13:5 + --> $DIR/tied-features.rs:12:5 | LL | #[target_feature(enable = "pacg")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ = help: add the missing features in a `target_feature` attribute error: the target features paca, pacg must all be either enabled or disabled together - --> $DIR/tied-features.rs:25:1 + --> $DIR/tied-features.rs:24:1 | LL | #[target_feature(enable = "paca")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/traits/associated_type_bound/check-trait-object-bounds-1.stderr b/src/test/ui/traits/associated_type_bound/check-trait-object-bounds-1.stderr index 907a1bd..bfbbe7f 100644 --- a/src/test/ui/traits/associated_type_bound/check-trait-object-bounds-1.stderr +++ b/src/test/ui/traits/associated_type_bound/check-trait-object-bounds-1.stderr
@@ -4,8 +4,7 @@ LL | f::<dyn X<Y = str>>(); | ^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `str` | - = help: the following implementations were found: - <String as Clone> + = help: the trait `Clone` is implemented for `String` note: required by a bound in `f` --> $DIR/check-trait-object-bounds-1.rs:7:9 |
diff --git a/src/test/ui/traits/associated_type_bound/check-trait-object-bounds-4.stderr b/src/test/ui/traits/associated_type_bound/check-trait-object-bounds-4.stderr index b27f8d7..3ca36d5 100644 --- a/src/test/ui/traits/associated_type_bound/check-trait-object-bounds-4.stderr +++ b/src/test/ui/traits/associated_type_bound/check-trait-object-bounds-4.stderr
@@ -4,8 +4,7 @@ LL | f::<dyn X<Y = str>>(); | ^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `str` | - = help: the following implementations were found: - <String as Clone> + = help: the trait `Clone` is implemented for `String` note: required by a bound in `f` --> $DIR/check-trait-object-bounds-4.rs:10:9 |
diff --git a/src/test/ui/traits/bound/assoc-fn-bound-root-obligation.rs b/src/test/ui/traits/bound/assoc-fn-bound-root-obligation.rs new file mode 100644 index 0000000..1d23451 --- /dev/null +++ b/src/test/ui/traits/bound/assoc-fn-bound-root-obligation.rs
@@ -0,0 +1,12 @@ +fn strip_lf(s: &str) -> &str { + s.strip_suffix(b'\n').unwrap_or(s) + //~^ ERROR expected a `FnMut<(char,)>` closure, found `u8` + //~| NOTE expected an `FnMut<(char,)>` closure, found `u8` + //~| NOTE required by a bound introduced by this call + //~| HELP the trait `FnMut<(char,)>` is not implemented for `u8` + //~| HELP the following other types implement trait `Pattern<'a>`: + //~| NOTE required because of the requirements on the impl of `Pattern<'_>` for `u8` + +} + +fn main() {}
diff --git a/src/test/ui/traits/bound/assoc-fn-bound-root-obligation.stderr b/src/test/ui/traits/bound/assoc-fn-bound-root-obligation.stderr new file mode 100644 index 0000000..115539a --- /dev/null +++ b/src/test/ui/traits/bound/assoc-fn-bound-root-obligation.stderr
@@ -0,0 +1,23 @@ +error[E0277]: expected a `FnMut<(char,)>` closure, found `u8` + --> $DIR/assoc-fn-bound-root-obligation.rs:2:20 + | +LL | s.strip_suffix(b'\n').unwrap_or(s) + | ------------ ^^^^^ expected an `FnMut<(char,)>` closure, found `u8` + | | + | required by a bound introduced by this call + | + = help: the trait `FnMut<(char,)>` is not implemented for `u8` + = help: the following other types implement trait `Pattern<'a>`: + &'b String + &'b [char; N] + &'b [char] + &'b str + &'c &'b str + [char; N] + char + pattern::MultiCharEqPattern<C> + = note: required because of the requirements on the impl of `Pattern<'_>` for `u8` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/traits/bound/same-crate-name.rs b/src/test/ui/traits/bound/same-crate-name.rs index 1012edb..8d646a4 100644 --- a/src/test/ui/traits/bound/same-crate-name.rs +++ b/src/test/ui/traits/bound/same-crate-name.rs
@@ -50,6 +50,6 @@ fn main() { // impls for the correct trait where the path is not misleading. a::try_foo(other_variant_implements_correct_trait); //~^ ERROR E0277 - //~| the following implementations were found: + //~| the trait `main::a::Bar` is implemented for `ImplementsTraitForUsize<usize>` } }
diff --git a/src/test/ui/traits/bound/same-crate-name.stderr b/src/test/ui/traits/bound/same-crate-name.stderr index 81e5589..ef39a70 100644 --- a/src/test/ui/traits/bound/same-crate-name.stderr +++ b/src/test/ui/traits/bound/same-crate-name.stderr
@@ -12,6 +12,7 @@ LL | impl Bar for Foo {} | ^^^^^^^^^^^^^^^^^^^ = note: perhaps two different versions of crate `crate_a2` are being used? + = help: the trait `main::a::Bar` is implemented for `ImplementsTraitForUsize<usize>` note: required by a bound in `try_foo` --> $DIR/auxiliary/crate_a1.rs:3:24 | @@ -26,6 +27,7 @@ | | | required by a bound introduced by this call | + = help: the trait `main::a::Bar` is implemented for `ImplementsTraitForUsize<usize>` note: required by a bound in `try_foo` --> $DIR/auxiliary/crate_a1.rs:3:24 | @@ -46,6 +48,7 @@ LL | impl Bar for ImplementsWrongTraitConditionally<isize> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: perhaps two different versions of crate `crate_a2` are being used? + = help: the trait `main::a::Bar` is implemented for `ImplementsTraitForUsize<usize>` note: required by a bound in `try_foo` --> $DIR/auxiliary/crate_a1.rs:3:24 | @@ -60,8 +63,7 @@ | | | required by a bound introduced by this call | - = help: the following implementations were found: - <ImplementsTraitForUsize<usize> as main::a::Bar> + = help: the trait `main::a::Bar` is implemented for `ImplementsTraitForUsize<usize>` note: required by a bound in `try_foo` --> $DIR/auxiliary/crate_a1.rs:3:24 |
diff --git a/src/test/ui/traits/coercion-generic-bad.stderr b/src/test/ui/traits/coercion-generic-bad.stderr index f367d39..b213ee6 100644 --- a/src/test/ui/traits/coercion-generic-bad.stderr +++ b/src/test/ui/traits/coercion-generic-bad.stderr
@@ -4,8 +4,7 @@ LL | let s: Box<dyn Trait<isize>> = Box::new(Struct { person: "Fred" }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait<isize>` is not implemented for `Struct` | - = help: the following implementations were found: - <Struct as Trait<&'static str>> + = help: the trait `Trait<&'static str>` is implemented for `Struct` = note: required for the cast to the object type `dyn Trait<isize>` error: aborting due to previous error
diff --git a/src/test/ui/traits/inductive-overflow/supertrait-auto-trait.stderr b/src/test/ui/traits/inductive-overflow/supertrait-auto-trait.stderr index 9ceeea4..d7697dc 100644 --- a/src/test/ui/traits/inductive-overflow/supertrait-auto-trait.stderr +++ b/src/test/ui/traits/inductive-overflow/supertrait-auto-trait.stderr
@@ -24,6 +24,10 @@ | LL | fn copy<T: Magic>(x: T) -> (T, T) { (x, x) } | ^^^^^ required by this bound in `copy` +help: consider annotating `NoClone` with `#[derive(Copy)]` + | +LL | #[derive(Copy)] + | error: aborting due to 2 previous errors
diff --git a/src/test/ui/traits/inheritance/repeated-supertrait-ambig.stderr b/src/test/ui/traits/inheritance/repeated-supertrait-ambig.stderr index 2bff843..cab0ccd 100644 --- a/src/test/ui/traits/inheritance/repeated-supertrait-ambig.stderr +++ b/src/test/ui/traits/inheritance/repeated-supertrait-ambig.stderr
@@ -3,6 +3,10 @@ | LL | c.same_as(22) | ^^^^^^^ the trait `CompareTo<i32>` is not implemented for `dyn CompareToInts` + | + = help: the following other types implement trait `CompareTo<T>`: + <i64 as CompareTo<i64>> + <i64 as CompareTo<u64>> error[E0277]: the trait bound `C: CompareTo<i32>` is not satisfied --> $DIR/repeated-supertrait-ambig.rs:30:7 @@ -20,6 +24,10 @@ | LL | <dyn CompareToInts>::same_as(c, 22) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `CompareTo<i32>` is not implemented for `dyn CompareToInts` + | + = help: the following other types implement trait `CompareTo<T>`: + <i64 as CompareTo<i64>> + <i64 as CompareTo<u64>> error[E0277]: the trait bound `C: CompareTo<i32>` is not satisfied --> $DIR/repeated-supertrait-ambig.rs:38:5 @@ -38,7 +46,7 @@ LL | assert_eq!(22_i64.same_as(22), true); | ^^^^^^^ the trait `CompareTo<i32>` is not implemented for `i64` | - = help: the following implementations were found: + = help: the following other types implement trait `CompareTo<T>`: <i64 as CompareTo<i64>> <i64 as CompareTo<u64>>
diff --git a/src/test/ui/traits/issue-71136.stderr b/src/test/ui/traits/issue-71136.stderr index 45b1e10..62a2a64 100644 --- a/src/test/ui/traits/issue-71136.stderr +++ b/src/test/ui/traits/issue-71136.stderr
@@ -9,6 +9,10 @@ | = note: required because of the requirements on the impl of `Clone` for `Vec<Foo>` = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Foo` with `#[derive(Clone)]` + | +LL | #[derive(Clone)] + | error: aborting due to previous error
diff --git a/src/test/ui/traits/issue-79458.stderr b/src/test/ui/traits/issue-79458.stderr index b970012..cf2e4ed 100644 --- a/src/test/ui/traits/issue-79458.stderr +++ b/src/test/ui/traits/issue-79458.stderr
@@ -7,10 +7,10 @@ LL | bar: &'a mut T | ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `&mut T` | - = help: the following implementations were found: - <&T as Clone> - <*const T as Clone> - <*mut T as Clone> + = help: the following other types implement trait `Clone`: + &T + *const T + *mut T = note: `Clone` is implemented for `&T`, but not for `&mut T` = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/src/test/ui/traits/issue-91594.stderr b/src/test/ui/traits/issue-91594.stderr index 10298a0..f2b3de1 100644 --- a/src/test/ui/traits/issue-91594.stderr +++ b/src/test/ui/traits/issue-91594.stderr
@@ -4,8 +4,7 @@ LL | impl HasComponent<<Foo as Component<Foo>>::Interface> for Foo {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HasComponent<()>` is not implemented for `Foo` | - = help: the following implementations were found: - <Foo as HasComponent<<Foo as Component<Foo>>::Interface>> + = help: the trait `HasComponent<<Foo as Component<Foo>>::Interface>` is implemented for `Foo` note: required because of the requirements on the impl of `Component<Foo>` for `Foo` --> $DIR/issue-91594.rs:13:27 |
diff --git a/src/test/ui/traits/map-types.stderr b/src/test/ui/traits/map-types.stderr index 71006e1..a4686ed 100644 --- a/src/test/ui/traits/map-types.stderr +++ b/src/test/ui/traits/map-types.stderr
@@ -4,6 +4,7 @@ LL | let y: Box<dyn Map<usize, isize>> = Box::new(x); | ^^^^^^^^^^^ the trait `Map<usize, isize>` is not implemented for `Box<dyn Map<isize, isize>>` | + = help: the trait `Map<K, V>` is implemented for `HashMap<K, V>` = note: required for the cast to the object type `dyn Map<usize, isize>` error: aborting due to previous error
diff --git a/src/test/ui/traits/reservation-impl/no-use.stderr b/src/test/ui/traits/reservation-impl/no-use.stderr index 3d5bf34..cefb2a8 100644 --- a/src/test/ui/traits/reservation-impl/no-use.stderr +++ b/src/test/ui/traits/reservation-impl/no-use.stderr
@@ -6,8 +6,7 @@ | | | required by a bound introduced by this call | - = help: the following implementations were found: - <() as MyTrait> + = help: the trait `MyTrait` is implemented for `()` error: aborting due to previous error
diff --git a/src/test/ui/traits/suggest-deferences/issue-39029.stderr b/src/test/ui/traits/suggest-deferences/issue-39029.stderr index 2c225f4..5c324cd 100644 --- a/src/test/ui/traits/suggest-deferences/issue-39029.stderr +++ b/src/test/ui/traits/suggest-deferences/issue-39029.stderr
@@ -5,7 +5,7 @@ | ----------------- ^^^^ | | | | | the trait `ToSocketAddrs` is not implemented for `NoToSocketAddrs` - | | help: consider adding dereference here: `&*bad` + | | help: consider dereferencing here: `&*bad` | required by a bound introduced by this call | = note: required because of the requirements on the impl of `ToSocketAddrs` for `&NoToSocketAddrs`
diff --git a/src/test/ui/traits/suggest-deferences/issue-62530.stderr b/src/test/ui/traits/suggest-deferences/issue-62530.stderr index 2992194..d129328 100644 --- a/src/test/ui/traits/suggest-deferences/issue-62530.stderr +++ b/src/test/ui/traits/suggest-deferences/issue-62530.stderr
@@ -5,11 +5,9 @@ | -------------------- ^^^^^^^ | | | | | the trait `SomeTrait` is not implemented for `&String` - | | help: consider adding dereference here: `&*string` + | | help: consider dereferencing here: `&*string` | required by a bound introduced by this call | - = help: the following implementations were found: - <&str as SomeTrait> note: required by a bound in `takes_type_parameter` --> $DIR/issue-62530.rs:4:44 |
diff --git a/src/test/ui/traits/suggest-deferences/multiple-0.stderr b/src/test/ui/traits/suggest-deferences/multiple-0.stderr index bf9f85f..efb3c7d 100644 --- a/src/test/ui/traits/suggest-deferences/multiple-0.stderr +++ b/src/test/ui/traits/suggest-deferences/multiple-0.stderr
@@ -5,7 +5,7 @@ | --- ^^^^ | | | | | the trait `Happy` is not implemented for `&Baz` - | | help: consider adding dereference here: `&***baz` + | | help: consider dereferencing here: `&***baz` | required by a bound introduced by this call | note: required by a bound in `foo`
diff --git a/src/test/ui/traits/suggest-deferences/multiple-1.stderr b/src/test/ui/traits/suggest-deferences/multiple-1.stderr index 040fbb3..6e12321 100644 --- a/src/test/ui/traits/suggest-deferences/multiple-1.stderr +++ b/src/test/ui/traits/suggest-deferences/multiple-1.stderr
@@ -6,6 +6,7 @@ | | | required by a bound introduced by this call | + = help: the trait `Happy` is implemented for `&mut LDM` note: required by a bound in `foo` --> $DIR/multiple-1.rs:45:26 |
diff --git a/src/test/ui/traits/suggest-deferences/root-obligation.fixed b/src/test/ui/traits/suggest-deferences/root-obligation.fixed new file mode 100644 index 0000000..7a8433f --- /dev/null +++ b/src/test/ui/traits/suggest-deferences/root-obligation.fixed
@@ -0,0 +1,13 @@ +// run-rustfix + +fn get_vowel_count(string: &str) -> usize { + string + .chars() + .filter(|c| "aeiou".contains(*c)) + //~^ ERROR expected a `Fn<(char,)>` closure, found `char` + .count() +} + +fn main() { + let _ = get_vowel_count("asdf"); +}
diff --git a/src/test/ui/traits/suggest-deferences/root-obligation.rs b/src/test/ui/traits/suggest-deferences/root-obligation.rs new file mode 100644 index 0000000..51bac21 --- /dev/null +++ b/src/test/ui/traits/suggest-deferences/root-obligation.rs
@@ -0,0 +1,13 @@ +// run-rustfix + +fn get_vowel_count(string: &str) -> usize { + string + .chars() + .filter(|c| "aeiou".contains(c)) + //~^ ERROR expected a `Fn<(char,)>` closure, found `char` + .count() +} + +fn main() { + let _ = get_vowel_count("asdf"); +}
diff --git a/src/test/ui/traits/suggest-deferences/root-obligation.stderr b/src/test/ui/traits/suggest-deferences/root-obligation.stderr new file mode 100644 index 0000000..16e03e7 --- /dev/null +++ b/src/test/ui/traits/suggest-deferences/root-obligation.stderr
@@ -0,0 +1,24 @@ +error[E0277]: expected a `Fn<(char,)>` closure, found `char` + --> $DIR/root-obligation.rs:6:38 + | +LL | .filter(|c| "aeiou".contains(c)) + | -------- ^ expected an `Fn<(char,)>` closure, found `char` + | | + | required by a bound introduced by this call + | + = help: the trait `Fn<(char,)>` is not implemented for `char` + = note: required because of the requirements on the impl of `FnOnce<(char,)>` for `&char` + = note: required because of the requirements on the impl of `Pattern<'_>` for `&char` +note: required by a bound in `core::str::<impl str>::contains` + --> $SRC_DIR/core/src/str/mod.rs:LL:COL + | +LL | pub fn contains<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool { + | ^^^^^^^^^^^ required by this bound in `core::str::<impl str>::contains` +help: consider dereferencing here + | +LL | .filter(|c| "aeiou".contains(*c)) + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/try-block/try-block-bad-type.stderr b/src/test/ui/try-block/try-block-bad-type.stderr index cf3a078..f990671 100644 --- a/src/test/ui/try-block/try-block-bad-type.stderr +++ b/src/test/ui/try-block/try-block-bad-type.stderr
@@ -5,8 +5,7 @@ | ^ the trait `From<&str>` is not implemented for `TryFromSliceError` | = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait - = help: the following implementations were found: - <TryFromSliceError as From<Infallible>> + = help: the trait `From<Infallible>` is implemented for `TryFromSliceError` = note: required because of the requirements on the impl of `FromResidual<Result<Infallible, &str>>` for `Result<u32, TryFromSliceError>` error[E0271]: type mismatch resolving `<Result<i32, i32> as Try>::Output == &str`
diff --git a/src/test/ui/try-trait/bad-interconversion.stderr b/src/test/ui/try-trait/bad-interconversion.stderr index 1710511..1a41052 100644 --- a/src/test/ui/try-trait/bad-interconversion.stderr +++ b/src/test/ui/try-trait/bad-interconversion.stderr
@@ -7,12 +7,16 @@ | ^ the trait `From<i32>` is not implemented for `u8` | = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait - = help: the following implementations were found: - <u8 as From<NonZeroU8>> - <u8 as From<bool>> + = help: the following other types implement trait `From<T>`: <f32 as From<i16>> <f32 as From<i8>> - and 71 others + <f32 as From<u16>> + <f32 as From<u8>> + <f64 as From<f32>> + <f64 as From<i16>> + <f64 as From<i32>> + <f64 as From<i8>> + and 67 others = note: required because of the requirements on the impl of `FromResidual<Result<Infallible, i32>>` for `Result<u64, u8>` error[E0277]: the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result` @@ -27,6 +31,7 @@ | |_- this function returns a `Result` | = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `Result<u64, String>` + = help: the trait `FromResidual<Result<Infallible, E>>` is implemented for `Result<T, F>` error[E0277]: the `?` operator can only be used on `Result`s in a function that returns `Result` --> $DIR/bad-interconversion.rs:17:31 @@ -39,6 +44,7 @@ | |_- this function returns a `Result` | = help: the trait `FromResidual<ControlFlow<{integer}, Infallible>>` is not implemented for `Result<u64, String>` + = help: the trait `FromResidual<Result<Infallible, E>>` is implemented for `Result<T, F>` error[E0277]: the `?` operator can only be used on `Option`s, not `Result`s, in a function that returns `Option` --> $DIR/bad-interconversion.rs:22:22 @@ -51,6 +57,7 @@ | |_- this function returns an `Option` | = help: the trait `FromResidual<Result<Infallible, &str>>` is not implemented for `Option<u16>` + = help: the trait `FromResidual` is implemented for `Option<T>` error[E0277]: the `?` operator can only be used on `Option`s in a function that returns `Option` --> $DIR/bad-interconversion.rs:27:33 @@ -63,6 +70,7 @@ | |_- this function returns an `Option` | = help: the trait `FromResidual<ControlFlow<{integer}, Infallible>>` is not implemented for `Option<u64>` + = help: the trait `FromResidual` is implemented for `Option<T>` error[E0277]: the `?` operator can only be used on `ControlFlow`s in a function that returns `ControlFlow` --> $DIR/bad-interconversion.rs:32:39 @@ -75,6 +83,7 @@ | |_- this function returns a `ControlFlow` | = help: the trait `FromResidual<Result<Infallible, &str>>` is not implemented for `ControlFlow<String>` + = help: the trait `FromResidual` is implemented for `ControlFlow<B, C>` error[E0277]: the `?` operator can only be used on `ControlFlow`s in a function that returns `ControlFlow` --> $DIR/bad-interconversion.rs:37:12 @@ -88,6 +97,7 @@ | |_- this function returns a `ControlFlow` | = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `ControlFlow<u64>` + = help: the trait `FromResidual` is implemented for `ControlFlow<B, C>` error[E0277]: the `?` operator in a function that returns `ControlFlow<B, _>` can only be used on other `ControlFlow<B, _>`s (with the same Break type) --> $DIR/bad-interconversion.rs:43:29 @@ -102,6 +112,7 @@ | = help: the trait `FromResidual<ControlFlow<u8, Infallible>>` is not implemented for `ControlFlow<i64>` = note: unlike `Result`, there's no `From`-conversion performed for `ControlFlow` + = help: the trait `FromResidual` is implemented for `ControlFlow<B, C>` error: aborting due to 8 previous errors
diff --git a/src/test/ui/try-trait/option-to-result.stderr b/src/test/ui/try-trait/option-to-result.stderr index aadfbf6..b0e4de8 100644 --- a/src/test/ui/try-trait/option-to-result.stderr +++ b/src/test/ui/try-trait/option-to-result.stderr
@@ -10,6 +10,7 @@ | |_- this function returns a `Result` | = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `Result<(), ()>` + = help: the trait `FromResidual<Result<Infallible, E>>` is implemented for `Result<T, F>` error[E0277]: the `?` operator can only be used on `Option`s, not `Result`s, in a function that returns `Option` --> $DIR/option-to-result.rs:11:6 @@ -23,6 +24,7 @@ | |_- this function returns an `Option` | = help: the trait `FromResidual<Result<Infallible, i32>>` is not implemented for `Option<i32>` + = help: the trait `FromResidual` is implemented for `Option<T>` error: aborting due to 2 previous errors
diff --git a/src/test/ui/try-trait/try-on-option.stderr b/src/test/ui/try-trait/try-on-option.stderr index 24db9f5..7b2a9a1 100644 --- a/src/test/ui/try-trait/try-on-option.stderr +++ b/src/test/ui/try-trait/try-on-option.stderr
@@ -10,6 +10,7 @@ | |_- this function returns a `Result` | = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `Result<u32, ()>` + = help: the trait `FromResidual<Result<Infallible, E>>` is implemented for `Result<T, F>` error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) --> $DIR/try-on-option.rs:11:6
diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr index 922e41e..b2edcc5 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr
@@ -29,10 +29,10 @@ | ^ | note: constant used multiple times - --> $DIR/generic_duplicate_param_use.rs:12:22 + --> $DIR/generic_duplicate_param_use.rs:12:16 | LL | type TwoConsts<const X: usize, const Y: usize> = impl Debug; - | ^ ^ + | ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^ error: aborting due to 3 previous errors
diff --git a/src/test/ui/type-alias-impl-trait/generic_nondefining_use.stderr b/src/test/ui/type-alias-impl-trait/generic_nondefining_use.stderr index 3669490..6c82d31 100644 --- a/src/test/ui/type-alias-impl-trait/generic_nondefining_use.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_nondefining_use.stderr
@@ -26,10 +26,10 @@ | ^^^^ | note: used non-generic constant `123_usize` for generic parameter - --> $DIR/generic_nondefining_use.rs:11:21 + --> $DIR/generic_nondefining_use.rs:11:15 | LL | type OneConst<const X: usize> = impl Debug; - | ^ + | ^^^^^^^^^^^^^^ error: aborting due to 3 previous errors
diff --git a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.base.stderr similarity index 76% rename from src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr rename to src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.base.stderr index 15ec2ee..a3b410c 100644 --- a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.base.stderr
@@ -1,23 +1,23 @@ error: at least one trait must be specified - --> $DIR/generic_type_does_not_live_long_enough.rs:10:24 + --> $DIR/generic_type_does_not_live_long_enough.rs:14:24 | LL | type WrongGeneric<T> = impl 'static; | ^^^^^^^^^^^^ error: non-defining opaque type use in defining scope - --> $DIR/generic_type_does_not_live_long_enough.rs:6:18 + --> $DIR/generic_type_does_not_live_long_enough.rs:10:18 | LL | let z: i32 = x; | ^ | note: used non-generic type `&'static i32` for generic parameter - --> $DIR/generic_type_does_not_live_long_enough.rs:10:19 + --> $DIR/generic_type_does_not_live_long_enough.rs:14:19 | LL | type WrongGeneric<T> = impl 'static; | ^ error[E0310]: the parameter type `T` may not live long enough - --> $DIR/generic_type_does_not_live_long_enough.rs:14:5 + --> $DIR/generic_type_does_not_live_long_enough.rs:18:5 | LL | fn wrong_generic<T>(t: T) -> WrongGeneric<T> { | - help: consider adding an explicit lifetime bound...: `T: 'static`
diff --git a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.nll.stderr b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.nll.stderr index dc85db6..db771d2 100644 --- a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.nll.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.nll.stderr
@@ -1,23 +1,23 @@ error: at least one trait must be specified - --> $DIR/generic_type_does_not_live_long_enough.rs:10:24 + --> $DIR/generic_type_does_not_live_long_enough.rs:14:24 | LL | type WrongGeneric<T> = impl 'static; | ^^^^^^^^^^^^ error: non-defining opaque type use in defining scope - --> $DIR/generic_type_does_not_live_long_enough.rs:6:18 + --> $DIR/generic_type_does_not_live_long_enough.rs:10:18 | LL | let z: i32 = x; | ^ | note: used non-generic type `&'static i32` for generic parameter - --> $DIR/generic_type_does_not_live_long_enough.rs:10:19 + --> $DIR/generic_type_does_not_live_long_enough.rs:14:19 | LL | type WrongGeneric<T> = impl 'static; | ^ error[E0310]: the parameter type `T` may not live long enough - --> $DIR/generic_type_does_not_live_long_enough.rs:14:5 + --> $DIR/generic_type_does_not_live_long_enough.rs:18:5 | LL | t | ^
diff --git a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs index cb90776..2ad7e61 100644 --- a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs +++ b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs
@@ -1,5 +1,9 @@ #![feature(type_alias_impl_trait)] +// revisions: base nll +// ignore-compare-mode-nll +//[nll] compile-flags: -Z borrowck=mir + fn main() { let y = 42; let x = wrong_generic(&y);
diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.base.stderr similarity index 89% rename from src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr rename to src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.base.stderr index 45329ea..be77b60 100644 --- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.base.stderr
@@ -1,5 +1,5 @@ error: implementation of `FnOnce` is not general enough - --> $DIR/issue-57611-trait-alias.rs:20:9 + --> $DIR/issue-57611-trait-alias.rs:25:9 | LL | |x| x | ^^^^^ implementation of `FnOnce` is not general enough
diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr index 91daa65..f5b9156 100644 --- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr
@@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/issue-57611-trait-alias.rs:20:9 + --> $DIR/issue-57611-trait-alias.rs:25:9 | LL | |x| x | ^^^^^ one type is more general than the other @@ -7,13 +7,13 @@ = note: expected type `for<'r> Fn<(&'r X,)>` found type `Fn<(&X,)>` note: this closure does not fulfill the lifetime requirements - --> $DIR/issue-57611-trait-alias.rs:20:9 + --> $DIR/issue-57611-trait-alias.rs:25:9 | LL | |x| x | ^^^^^ error: implementation of `FnOnce` is not general enough - --> $DIR/issue-57611-trait-alias.rs:20:9 + --> $DIR/issue-57611-trait-alias.rs:25:9 | LL | |x| x | ^^^^^ implementation of `FnOnce` is not general enough
diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs index 7c6e764..e95ddab 100644 --- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs +++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs
@@ -1,6 +1,11 @@ // Regression test for issue #57611 // Ensures that we don't ICE // FIXME: This should compile, but it currently doesn't +// known-bug + +// revisions: base nll +// ignore-compare-mode-nll +//[nll] compile-flags: -Z borrowck=mir #![feature(trait_alias)] #![feature(type_alias_impl_trait)] @@ -18,7 +23,6 @@ impl Foo for X { fn bar(&self) -> Self::Bar { |x| x - //~^ ERROR implementation of `FnOnce` is not general enough } }
diff --git a/src/test/ui/type-alias-impl-trait/issue-60371.stderr b/src/test/ui/type-alias-impl-trait/issue-60371.stderr index 5fec078..d0c0437 100644 --- a/src/test/ui/type-alias-impl-trait/issue-60371.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-60371.stderr
@@ -13,8 +13,7 @@ LL | const FUN: fn() -> Self::Item = || (); | ^^ the trait `Bug` is not implemented for `()` | - = help: the following implementations were found: - <&() as Bug> + = help: the trait `Bug` is implemented for `&()` error: aborting due to 2 previous errors
diff --git a/src/test/ui/type-alias-impl-trait/multiple_definitions.rs b/src/test/ui/type-alias-impl-trait/multiple_definitions.rs new file mode 100644 index 0000000..9e6268e --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/multiple_definitions.rs
@@ -0,0 +1,30 @@ +// check-pass + +use std::marker::PhantomData; + +pub struct ConcreteError {} +pub trait IoBase {} +struct X {} +impl IoBase for X {} + +pub struct ClusterIterator<B, E, S = B> { + pub fat: B, + phantom_s: PhantomData<S>, + phantom_e: PhantomData<E>, +} + +pub struct FileSystem<IO: IoBase> { + pub disk: IO, +} + +impl<IO: IoBase> FileSystem<IO> { + pub fn cluster_iter(&self) -> ClusterIterator<impl IoBase + '_, ConcreteError> { + ClusterIterator { + fat: X {}, + phantom_s: PhantomData::default(), + phantom_e: PhantomData::default(), + } + } +} + +fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/nested-tait-inference.stderr b/src/test/ui/type-alias-impl-trait/nested-tait-inference.stderr index eb72e88..0df2b57 100644 --- a/src/test/ui/type-alias-impl-trait/nested-tait-inference.stderr +++ b/src/test/ui/type-alias-impl-trait/nested-tait-inference.stderr
@@ -4,8 +4,7 @@ LL | fn foo() -> impl Foo<FooX> { | ^^^^^^^^^^^^^^ the trait `Foo<FooX>` is not implemented for `()` | - = help: the following implementations were found: - <() as Foo<()>> + = help: the trait `Foo<()>` is implemented for `()` error[E0277]: the trait bound `(): Foo<FooX>` is not satisfied --> $DIR/nested-tait-inference.rs:12:28 @@ -19,8 +18,7 @@ LL | | } | |_^ the trait `Foo<FooX>` is not implemented for `()` | - = help: the following implementations were found: - <() as Foo<()>> + = help: the trait `Foo<()>` is implemented for `()` error: aborting due to 2 previous errors
diff --git a/src/test/ui/type-alias-impl-trait/nested-tait-inference2.stderr b/src/test/ui/type-alias-impl-trait/nested-tait-inference2.stderr index 1372a01..264e802 100644 --- a/src/test/ui/type-alias-impl-trait/nested-tait-inference2.stderr +++ b/src/test/ui/type-alias-impl-trait/nested-tait-inference2.stderr
@@ -4,7 +4,7 @@ LL | fn foo() -> impl Foo<FooX> { | ^^^^^^^^^^^^^^ the trait `Foo<FooX>` is not implemented for `()` | - = help: the following implementations were found: + = help: the following other types implement trait `Foo<A>`: <() as Foo<()>> <() as Foo<u32>> @@ -19,7 +19,7 @@ LL | | } | |_^ the trait `Foo<FooX>` is not implemented for `()` | - = help: the following implementations were found: + = help: the following other types implement trait `Foo<A>`: <() as Foo<()>> <() as Foo<u32>>
diff --git a/src/test/ui/type-alias-impl-trait/self-referential-2.stderr b/src/test/ui/type-alias-impl-trait/self-referential-2.stderr index 6997676..348696f 100644 --- a/src/test/ui/type-alias-impl-trait/self-referential-2.stderr +++ b/src/test/ui/type-alias-impl-trait/self-referential-2.stderr
@@ -5,6 +5,16 @@ | ^^^^^^ no implementation for `i32 == Foo` | = help: the trait `PartialEq<Foo>` is not implemented for `i32` + = help: the following other types implement trait `PartialEq<Rhs>`: + f32 + f64 + i128 + i16 + i32 + i64 + i8 + isize + and 6 others error: aborting due to previous error
diff --git a/src/test/ui/type-alias-impl-trait/self-referential-4.stderr b/src/test/ui/type-alias-impl-trait/self-referential-4.stderr index 4a6ee2f..8382647 100644 --- a/src/test/ui/type-alias-impl-trait/self-referential-4.stderr +++ b/src/test/ui/type-alias-impl-trait/self-referential-4.stderr
@@ -5,6 +5,16 @@ | ^ no implementation for `&i32 == Bar<'b, 'static>` | = help: the trait `PartialEq<Bar<'b, 'static>>` is not implemented for `&i32` + = help: the following other types implement trait `PartialEq<Rhs>`: + f32 + f64 + i128 + i16 + i32 + i64 + i8 + isize + and 6 others error[E0277]: can't compare `&i32` with `Foo<'static, 'b>` --> $DIR/self-referential-4.rs:12:5 @@ -13,6 +23,16 @@ | ^ no implementation for `&i32 == Foo<'static, 'b>` | = help: the trait `PartialEq<Foo<'static, 'b>>` is not implemented for `&i32` + = help: the following other types implement trait `PartialEq<Rhs>`: + f32 + f64 + i128 + i16 + i32 + i64 + i8 + isize + and 6 others error[E0277]: can't compare `&i32` with `Moo<'static, 'a>` --> $DIR/self-referential-4.rs:18:5 @@ -21,6 +41,16 @@ | ^ no implementation for `&i32 == Moo<'static, 'a>` | = help: the trait `PartialEq<Moo<'static, 'a>>` is not implemented for `&i32` + = help: the following other types implement trait `PartialEq<Rhs>`: + f32 + f64 + i128 + i16 + i32 + i64 + i8 + isize + and 6 others error: aborting due to 3 previous errors
diff --git a/src/test/ui/type-alias-impl-trait/self-referential.stderr b/src/test/ui/type-alias-impl-trait/self-referential.stderr index 0626e6b..2ebb15b 100644 --- a/src/test/ui/type-alias-impl-trait/self-referential.stderr +++ b/src/test/ui/type-alias-impl-trait/self-referential.stderr
@@ -5,6 +5,16 @@ | ^ no implementation for `&i32 == Bar<'b, 'a>` | = help: the trait `PartialEq<Bar<'b, 'a>>` is not implemented for `&i32` + = help: the following other types implement trait `PartialEq<Rhs>`: + f32 + f64 + i128 + i16 + i32 + i64 + i8 + isize + and 6 others error[E0277]: can't compare `&i32` with `(i32, &i32)` --> $DIR/self-referential.rs:12:10 @@ -13,6 +23,16 @@ | ^ no implementation for `&i32 == (i32, &i32)` | = help: the trait `PartialEq<(i32, &i32)>` is not implemented for `&i32` + = help: the following other types implement trait `PartialEq<Rhs>`: + f32 + f64 + i128 + i16 + i32 + i64 + i8 + isize + and 6 others error[E0277]: can't compare `&i32` with `(i32, Moo<'b, 'a>::{opaque#0})` --> $DIR/self-referential.rs:18:10 @@ -21,6 +41,16 @@ | ^ no implementation for `&i32 == (i32, Moo<'b, 'a>::{opaque#0})` | = help: the trait `PartialEq<(i32, Moo<'b, 'a>::{opaque#0})>` is not implemented for `&i32` + = help: the following other types implement trait `PartialEq<Rhs>`: + f32 + f64 + i128 + i16 + i32 + i64 + i8 + isize + and 6 others error: aborting due to 3 previous errors
diff --git a/src/test/ui/type/type-check-defaults.stderr b/src/test/ui/type/type-check-defaults.stderr index 2a61547..56a9b53 100644 --- a/src/test/ui/type/type-check-defaults.stderr +++ b/src/test/ui/type/type-check-defaults.stderr
@@ -2,7 +2,7 @@ --> $DIR/type-check-defaults.rs:6:19 | LL | struct WellFormed<Z = Foo<i32, i32>>(Z); - | ^ value of type `i32` cannot be built from `std::iter::Iterator<Item=i32>` + | ^^^^^^^^^^^^^^^^^ value of type `i32` cannot be built from `std::iter::Iterator<Item=i32>` | = help: the trait `FromIterator<i32>` is not implemented for `i32` note: required by a bound in `Foo` @@ -15,7 +15,7 @@ --> $DIR/type-check-defaults.rs:8:27 | LL | struct WellFormedNoBounds<Z:?Sized = Foo<i32, i32>>(Z); - | ^ value of type `i32` cannot be built from `std::iter::Iterator<Item=i32>` + | ^^^^^^^^^^^^^^^^^^^^^^^^ value of type `i32` cannot be built from `std::iter::Iterator<Item=i32>` | = help: the trait `FromIterator<i32>` is not implemented for `i32` note: required by a bound in `Foo` @@ -65,6 +65,16 @@ | ^^^^^^^ no implementation for `i32 + u8` | = help: the trait `Add<u8>` is not implemented for `i32` + = help: the following other types implement trait `Add<Rhs>`: + <&'a f32 as Add<f32>> + <&'a f64 as Add<f64>> + <&'a i128 as Add<i128>> + <&'a i16 as Add<i16>> + <&'a i32 as Add<i32>> + <&'a i64 as Add<i64>> + <&'a i8 as Add<i8>> + <&'a isize as Add<isize>> + and 48 others error: aborting due to 7 previous errors
diff --git a/src/test/ui/typeck/explain_clone_autoref.rs b/src/test/ui/typeck/explain_clone_autoref.rs new file mode 100644 index 0000000..9279e4c --- /dev/null +++ b/src/test/ui/typeck/explain_clone_autoref.rs
@@ -0,0 +1,13 @@ +struct NotClone; + +fn main() { + clone_thing(&NotClone); +} + +fn clone_thing(nc: &NotClone) -> NotClone { + //~^ NOTE expected `NotClone` because of return type + nc.clone() + //~^ ERROR mismatched type + //~| NOTE `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead + //~| NOTE expected struct `NotClone`, found `&NotClone` +}
diff --git a/src/test/ui/typeck/explain_clone_autoref.stderr b/src/test/ui/typeck/explain_clone_autoref.stderr new file mode 100644 index 0000000..faac680 --- /dev/null +++ b/src/test/ui/typeck/explain_clone_autoref.stderr
@@ -0,0 +1,18 @@ +error[E0308]: mismatched types + --> $DIR/explain_clone_autoref.rs:9:5 + | +LL | fn clone_thing(nc: &NotClone) -> NotClone { + | -------- expected `NotClone` because of return type +LL | +LL | nc.clone() + | ^^^^^^^^^^ expected struct `NotClone`, found `&NotClone` + | +note: `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead + --> $DIR/explain_clone_autoref.rs:9:5 + | +LL | nc.clone() + | ^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/typeck/issue-81293.stderr b/src/test/ui/typeck/issue-81293.stderr index c545a56..9658288 100644 --- a/src/test/ui/typeck/issue-81293.stderr +++ b/src/test/ui/typeck/issue-81293.stderr
@@ -20,6 +20,16 @@ | ^ no implementation for `usize + u16` | = help: the trait `Add<u16>` is not implemented for `usize` + = help: the following other types implement trait `Add<Rhs>`: + <&'a f32 as Add<f32>> + <&'a f64 as Add<f64>> + <&'a i128 as Add<i128>> + <&'a i16 as Add<i16>> + <&'a i32 as Add<i32>> + <&'a i64 as Add<i64>> + <&'a i8 as Add<i8>> + <&'a isize as Add<isize>> + and 48 others error: aborting due to 3 previous errors
diff --git a/src/test/ui/typeck/issue-90101.stderr b/src/test/ui/typeck/issue-90101.stderr index 998b636..ab9a72e 100644 --- a/src/test/ui/typeck/issue-90101.stderr +++ b/src/test/ui/typeck/issue-90101.stderr
@@ -6,7 +6,7 @@ | | | required by a bound introduced by this call | - = help: the following implementations were found: + = help: the following other types implement trait `From<T>`: <PathBuf as From<&T>> <PathBuf as From<Box<Path>>> <PathBuf as From<Cow<'a, Path>>>
diff --git a/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr b/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr index d0bc432..74766d9 100644 --- a/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr +++ b/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr
@@ -5,6 +5,16 @@ | ^^^^^^^^^^^^^^^^^^^^^^ no implementation for `i32 + u32` | = help: the trait `Add<u32>` is not implemented for `i32` + = help: the following other types implement trait `Add<Rhs>`: + <&'a f32 as Add<f32>> + <&'a f64 as Add<f64>> + <&'a i128 as Add<i128>> + <&'a i16 as Add<i16>> + <&'a i32 as Add<i32>> + <&'a i64 as Add<i64>> + <&'a i8 as Add<i8>> + <&'a isize as Add<isize>> + and 48 others error[E0308]: mismatched types --> $DIR/ufcs-qpath-self-mismatch.rs:6:28
diff --git a/src/test/ui/unboxed-closures/issue-30906.stderr b/src/test/ui/unboxed-closures/issue-30906.base.stderr similarity index 92% rename from src/test/ui/unboxed-closures/issue-30906.stderr rename to src/test/ui/unboxed-closures/issue-30906.base.stderr index 35b1e45..5d555a9 100644 --- a/src/test/ui/unboxed-closures/issue-30906.stderr +++ b/src/test/ui/unboxed-closures/issue-30906.base.stderr
@@ -1,5 +1,5 @@ error: implementation of `FnOnce` is not general enough - --> $DIR/issue-30906.rs:18:5 + --> $DIR/issue-30906.rs:22:5 | LL | test(Compose(f, |_| {})); | ^^^^ implementation of `FnOnce` is not general enough
diff --git a/src/test/ui/unboxed-closures/issue-30906.nll.stderr b/src/test/ui/unboxed-closures/issue-30906.nll.stderr index 147a209..333e8e1 100644 --- a/src/test/ui/unboxed-closures/issue-30906.nll.stderr +++ b/src/test/ui/unboxed-closures/issue-30906.nll.stderr
@@ -1,5 +1,5 @@ error: implementation of `FnOnce` is not general enough - --> $DIR/issue-30906.rs:18:5 + --> $DIR/issue-30906.rs:22:5 | LL | test(Compose(f, |_| {})); | ^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
diff --git a/src/test/ui/unboxed-closures/issue-30906.rs b/src/test/ui/unboxed-closures/issue-30906.rs index e2d219e..1fd3a7f 100644 --- a/src/test/ui/unboxed-closures/issue-30906.rs +++ b/src/test/ui/unboxed-closures/issue-30906.rs
@@ -1,5 +1,9 @@ #![feature(fn_traits, unboxed_closures)] +// revisions: base nll +// ignore-compare-mode-nll +//[nll] compile-flags: -Z borrowck=mir + fn test<F: for<'x> FnOnce<(&'x str,)>>(_: F) {} struct Compose<F, G>(F, G);
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-infer-argument-types-two-region-pointers.stderr b/src/test/ui/unboxed-closures/unboxed-closures-infer-argument-types-two-region-pointers.base.stderr similarity index 91% rename from src/test/ui/unboxed-closures/unboxed-closures-infer-argument-types-two-region-pointers.stderr rename to src/test/ui/unboxed-closures/unboxed-closures-infer-argument-types-two-region-pointers.base.stderr index d781333..ebd14c6 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-infer-argument-types-two-region-pointers.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-infer-argument-types-two-region-pointers.base.stderr
@@ -1,23 +1,27 @@ error[E0312]: lifetime of reference outlives lifetime of borrowed content... - --> $DIR/unboxed-closures-infer-argument-types-two-region-pointers.rs:17:15 + --> $DIR/unboxed-closures-infer-argument-types-two-region-pointers.rs:21:15 | LL | x.set(y); | ^ | note: ...the reference is valid for the anonymous lifetime #2 defined here... - --> $DIR/unboxed-closures-infer-argument-types-two-region-pointers.rs:16:14 + --> $DIR/unboxed-closures-infer-argument-types-two-region-pointers.rs:20:14 | LL | doit(0, &|x, y| { | ______________^ LL | | x.set(y); +LL | | +LL | | LL | | }); | |_____^ note: ...but the borrowed content is only valid for the anonymous lifetime #3 defined here - --> $DIR/unboxed-closures-infer-argument-types-two-region-pointers.rs:16:14 + --> $DIR/unboxed-closures-infer-argument-types-two-region-pointers.rs:20:14 | LL | doit(0, &|x, y| { | ______________^ LL | | x.set(y); +LL | | +LL | | LL | | }); | |_____^
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-infer-argument-types-two-region-pointers.nll.stderr b/src/test/ui/unboxed-closures/unboxed-closures-infer-argument-types-two-region-pointers.nll.stderr index e97157b..aeeee6e 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-infer-argument-types-two-region-pointers.nll.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-infer-argument-types-two-region-pointers.nll.stderr
@@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/unboxed-closures-infer-argument-types-two-region-pointers.rs:17:9 + --> $DIR/unboxed-closures-infer-argument-types-two-region-pointers.rs:21:9 | LL | doit(0, &|x, y| { | - - has type `&'1 i32`
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-infer-argument-types-two-region-pointers.rs b/src/test/ui/unboxed-closures/unboxed-closures-infer-argument-types-two-region-pointers.rs index a1364b9..288349e 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-infer-argument-types-two-region-pointers.rs +++ b/src/test/ui/unboxed-closures/unboxed-closures-infer-argument-types-two-region-pointers.rs
@@ -3,6 +3,10 @@ // That a closure whose expected argument types include two distinct // bound regions. +// revisions: base nll +// ignore-compare-mode-nll +//[nll] compile-flags: -Z borrowck=mir + use std::cell::Cell; fn doit<T,F>(val: T, f: &F) @@ -14,6 +18,8 @@ fn doit<T,F>(val: T, f: &F) pub fn main() { doit(0, &|x, y| { - x.set(y); //~ ERROR E0312 + x.set(y); + //[base]~^ ERROR E0312 + //[nll]~^^ lifetime may not live long enough }); }
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr b/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr index c9a2023..18e1339 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr
@@ -2,11 +2,12 @@ --> $DIR/unboxed-closures-unsafe-extern-fn.rs:20:21 | LL | let x = call_it(&square, 22); - | ------- ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` + | ------- ^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }` | | | required by a bound introduced by this call | = help: the trait `for<'r> Fn<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}` + = note: unsafe function cannot be called generically without an unsafe block note: required by a bound in `call_it` --> $DIR/unboxed-closures-unsafe-extern-fn.rs:9:15 | @@ -17,11 +18,12 @@ --> $DIR/unboxed-closures-unsafe-extern-fn.rs:25:25 | LL | let y = call_it_mut(&mut square, 22); - | ----------- ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` + | ----------- ^^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }` | | | required by a bound introduced by this call | = help: the trait `for<'r> FnMut<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}` + = note: unsafe function cannot be called generically without an unsafe block note: required by a bound in `call_it_mut` --> $DIR/unboxed-closures-unsafe-extern-fn.rs:12:19 | @@ -32,11 +34,12 @@ --> $DIR/unboxed-closures-unsafe-extern-fn.rs:30:26 | LL | let z = call_it_once(square, 22); - | ------------ ^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` + | ------------ ^^^^^^ call the function in a closure: `|| unsafe { /* code */ }` | | | required by a bound introduced by this call | = help: the trait `for<'r> FnOnce<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}` + = note: unsafe function cannot be called generically without an unsafe block note: required by a bound in `call_it_once` --> $DIR/unboxed-closures-unsafe-extern-fn.rs:15:20 |
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr b/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr index 64d5777..c826af3 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr
@@ -2,11 +2,12 @@ --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:21:21 | LL | let x = call_it(&square, 22); - | ------- ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` + | ------- ^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }` | | | required by a bound introduced by this call | = help: the trait `for<'r> Fn<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}` + = note: unsafe function cannot be called generically without an unsafe block note: required by a bound in `call_it` --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:10:15 | @@ -17,11 +18,12 @@ --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:26:25 | LL | let y = call_it_mut(&mut square, 22); - | ----------- ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` + | ----------- ^^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }` | | | required by a bound introduced by this call | = help: the trait `for<'r> FnMut<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}` + = note: unsafe function cannot be called generically without an unsafe block note: required by a bound in `call_it_mut` --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:13:19 | @@ -32,11 +34,12 @@ --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:31:26 | LL | let z = call_it_once(square, 22); - | ------------ ^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` + | ------------ ^^^^^^ call the function in a closure: `|| unsafe { /* code */ }` | | | required by a bound introduced by this call | = help: the trait `for<'r> FnOnce<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}` + = note: unsafe function cannot be called generically without an unsafe block note: required by a bound in `call_it_once` --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:16:20 |
diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore.base.stderr similarity index 93% rename from src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr rename to src/test/ui/underscore-lifetime/dyn-trait-underscore.base.stderr index f4285a0..0735779 100644 --- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr +++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.base.stderr
@@ -1,5 +1,5 @@ error[E0759]: `items` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement - --> $DIR/dyn-trait-underscore.rs:8:20 + --> $DIR/dyn-trait-underscore.rs:12:20 | LL | fn a<T>(items: &[T]) -> Box<dyn Iterator<Item=&T>> { | ---- this data with an anonymous lifetime `'_`... @@ -10,7 +10,7 @@ | ...is used and required to live as long as `'static` here | note: `'static` lifetime requirement introduced by the return type - --> $DIR/dyn-trait-underscore.rs:6:29 + --> $DIR/dyn-trait-underscore.rs:10:29 | LL | fn a<T>(items: &[T]) -> Box<dyn Iterator<Item=&T>> { | ^^^^^^^^^^^^^^^^^^^^^ `'static` requirement introduced here
diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr index 8ed48bd..53d45f6 100644 --- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr +++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr
@@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/dyn-trait-underscore.rs:8:5 + --> $DIR/dyn-trait-underscore.rs:12:5 | LL | fn a<T>(items: &[T]) -> Box<dyn Iterator<Item=&T>> { | - let's call the lifetime of this reference `'1`
diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.rs b/src/test/ui/underscore-lifetime/dyn-trait-underscore.rs index e951adf0..7110d43 100644 --- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.rs +++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.rs
@@ -3,9 +3,15 @@ // // cc #48468 +// revisions: base nll +// ignore-compare-mode-nll +//[nll] compile-flags: -Z borrowck=mir + fn a<T>(items: &[T]) -> Box<dyn Iterator<Item=&T>> { // ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static` - Box::new(items.iter()) //~ ERROR E0759 + Box::new(items.iter()) + //[base]~^ ERROR E0759 + //[nll]~^^ ERROR lifetime may not live long enough } fn b<T>(items: &[T]) -> Box<dyn Iterator<Item=&T> + '_> {
diff --git a/src/test/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.stderr b/src/test/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.base.stderr similarity index 92% rename from src/test/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.stderr rename to src/test/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.base.stderr index 8976da0..2581911 100644 --- a/src/test/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.stderr +++ b/src/test/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.base.stderr
@@ -1,5 +1,5 @@ error[E0623]: lifetime mismatch - --> $DIR/underscore-lifetime-elison-mismatch.rs:1:49 + --> $DIR/underscore-lifetime-elison-mismatch.rs:5:49 | LL | fn foo(x: &mut Vec<&'_ u8>, y: &'_ u8) { x.push(y); } | ------ ------ ^ ...but data from `y` flows into `x` here
diff --git a/src/test/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.nll.stderr b/src/test/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.nll.stderr index e1d57b8..8e10242 100644 --- a/src/test/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.nll.stderr +++ b/src/test/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.nll.stderr
@@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/underscore-lifetime-elison-mismatch.rs:1:42 + --> $DIR/underscore-lifetime-elison-mismatch.rs:5:42 | LL | fn foo(x: &mut Vec<&'_ u8>, y: &'_ u8) { x.push(y); } | - - ^^^^^^^^^ argument requires that `'1` must outlive `'2`
diff --git a/src/test/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.rs b/src/test/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.rs index f465a80..6d49513 100644 --- a/src/test/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.rs +++ b/src/test/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.rs
@@ -1,3 +1,9 @@ -fn foo(x: &mut Vec<&'_ u8>, y: &'_ u8) { x.push(y); } //~ ERROR lifetime mismatch +// revisions: base nll +// ignore-compare-mode-nll +//[nll] compile-flags: -Z borrowck=mir + +fn foo(x: &mut Vec<&'_ u8>, y: &'_ u8) { x.push(y); } +//[base]~^ ERROR lifetime mismatch +//[nll]~^^ ERROR lifetime may not live long enough fn main() {}
diff --git a/src/test/ui/unevaluated_fixed_size_array_len.stderr b/src/test/ui/unevaluated_fixed_size_array_len.stderr index 03932d5..5e67b2c 100644 --- a/src/test/ui/unevaluated_fixed_size_array_len.stderr +++ b/src/test/ui/unevaluated_fixed_size_array_len.stderr
@@ -4,8 +4,7 @@ LL | <[(); 0] as Foo>::foo() | ^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `[(); 0]` | - = help: the following implementations were found: - <[(); 1] as Foo> + = help: the trait `Foo` is implemented for `[(); 1]` error: aborting due to previous error
diff --git a/src/test/ui/union/union-derive-clone.mirunsafeck.stderr b/src/test/ui/union/union-derive-clone.mirunsafeck.stderr index de0bc78..c242a7d 100644 --- a/src/test/ui/union/union-derive-clone.mirunsafeck.stderr +++ b/src/test/ui/union/union-derive-clone.mirunsafeck.stderr
@@ -38,6 +38,10 @@ LL | pub struct AssertParamIsCopy<T: Copy + ?Sized> { | ^^^^ required by this bound in `AssertParamIsCopy` = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `U1` with `#[derive(Copy)]` + | +LL | #[derive(Copy)] + | error: aborting due to 2 previous errors
diff --git a/src/test/ui/union/union-derive-clone.thirunsafeck.stderr b/src/test/ui/union/union-derive-clone.thirunsafeck.stderr index de0bc78..c242a7d 100644 --- a/src/test/ui/union/union-derive-clone.thirunsafeck.stderr +++ b/src/test/ui/union/union-derive-clone.thirunsafeck.stderr
@@ -38,6 +38,10 @@ LL | pub struct AssertParamIsCopy<T: Copy + ?Sized> { | ^^^^ required by this bound in `AssertParamIsCopy` = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `U1` with `#[derive(Copy)]` + | +LL | #[derive(Copy)] + | error: aborting due to 2 previous errors
diff --git a/src/test/ui/union/union-derive-eq.mirunsafeck.stderr b/src/test/ui/union/union-derive-eq.mirunsafeck.stderr index ff4dfcd..99505f3 100644 --- a/src/test/ui/union/union-derive-eq.mirunsafeck.stderr +++ b/src/test/ui/union/union-derive-eq.mirunsafeck.stderr
@@ -13,6 +13,10 @@ LL | pub struct AssertParamIsEq<T: Eq + ?Sized> { | ^^ required by this bound in `AssertParamIsEq` = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `PartialEqNotEq` with `#[derive(Eq)]` + | +LL | #[derive(Eq)] + | error: aborting due to previous error
diff --git a/src/test/ui/union/union-derive-eq.thirunsafeck.stderr b/src/test/ui/union/union-derive-eq.thirunsafeck.stderr index ff4dfcd..99505f3 100644 --- a/src/test/ui/union/union-derive-eq.thirunsafeck.stderr +++ b/src/test/ui/union/union-derive-eq.thirunsafeck.stderr
@@ -13,6 +13,10 @@ LL | pub struct AssertParamIsEq<T: Eq + ?Sized> { | ^^ required by this bound in `AssertParamIsEq` = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `PartialEqNotEq` with `#[derive(Eq)]` + | +LL | #[derive(Eq)] + | error: aborting due to previous error
diff --git a/src/test/ui/unsized/box-instead-of-dyn-fn.rs b/src/test/ui/unsized/box-instead-of-dyn-fn.rs new file mode 100644 index 0000000..2fa741b --- /dev/null +++ b/src/test/ui/unsized/box-instead-of-dyn-fn.rs
@@ -0,0 +1,15 @@ +use std::fmt::Debug; + +// Test to suggest boxing the return type, and the closure branch of the `if` + +fn print_on_or_the_other<'a>(a: i32, b: &'a String) -> dyn Fn() + 'a { + //~^ ERROR return type cannot have an unboxed trait object + if a % 2 == 0 { + move || println!("{a}") + } else { + Box::new(move || println!("{}", b)) + //~^ ERROR `if` and `else` have incompatible types + } +} + +fn main() {}
diff --git a/src/test/ui/unsized/box-instead-of-dyn-fn.stderr b/src/test/ui/unsized/box-instead-of-dyn-fn.stderr new file mode 100644 index 0000000..80f61cb --- /dev/null +++ b/src/test/ui/unsized/box-instead-of-dyn-fn.stderr
@@ -0,0 +1,39 @@ +error[E0308]: `if` and `else` have incompatible types + --> $DIR/box-instead-of-dyn-fn.rs:10:9 + | +LL | / if a % 2 == 0 { +LL | | move || println!("{a}") + | | ----------------------- expected because of this +LL | | } else { +LL | | Box::new(move || println!("{}", b)) + | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected closure, found struct `Box` +LL | | +LL | | } + | |_____- `if` and `else` have incompatible types + | + = note: expected type `[closure@$DIR/box-instead-of-dyn-fn.rs:8:9: 8:32]` + found struct `Box<[closure@$DIR/box-instead-of-dyn-fn.rs:10:18: 10:43]>` + +error[E0746]: return type cannot have an unboxed trait object + --> $DIR/box-instead-of-dyn-fn.rs:5:56 + | +LL | fn print_on_or_the_other<'a>(a: i32, b: &'a String) -> dyn Fn() + 'a { + | ^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types> + = note: if all the returned values were of the same type you could use `impl Fn() + 'a` as the return type + = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits> + = note: you can create a new `enum` with a variant for each returned type +help: return a boxed trait object instead + | +LL | fn print_on_or_the_other<'a>(a: i32, b: &'a String) -> Box<dyn Fn() + 'a> { + | ++++ + +help: ... and box this value + | +LL | Box::new(move || println!("{a}")) + | +++++++++ + + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0308, E0746. +For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/unsized/issue-91801.rs b/src/test/ui/unsized/issue-91801.rs new file mode 100644 index 0000000..096b1a9 --- /dev/null +++ b/src/test/ui/unsized/issue-91801.rs
@@ -0,0 +1,19 @@ +pub struct Something; + +type Validator<'a> = dyn 'a + Send + Sync + Fn(&'a Something) -> Result<(), ()>; + +pub static ALL_VALIDATORS: &[(&'static str, &'static Validator)] = + &[("validate that credits and debits balance", &validate_something)]; + +fn or<'a>(first: &'static Validator<'a>, second: &'static Validator<'a>) -> Validator<'a> { + //~^ ERROR return type cannot have an unboxed trait object + return Box::new(move |something: &'_ Something| -> Result<(), ()> { + first(something).or_else(|_| second(something)) + }); +} + +fn validate_something(_: &Something) -> Result<(), ()> { + Ok(()) +} + +fn main() {}
diff --git a/src/test/ui/unsized/issue-91801.stderr b/src/test/ui/unsized/issue-91801.stderr new file mode 100644 index 0000000..e854514 --- /dev/null +++ b/src/test/ui/unsized/issue-91801.stderr
@@ -0,0 +1,15 @@ +error[E0746]: return type cannot have an unboxed trait object + --> $DIR/issue-91801.rs:8:77 + | +LL | fn or<'a>(first: &'static Validator<'a>, second: &'static Validator<'a>) -> Validator<'a> { + | ^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits> +help: use `impl Fn(&'a Something) -> Result<(), ()> + Send + Sync + 'a` as the return type, as all return paths are of type `Box<[closure@$DIR/issue-91801.rs:10:21: 12:6]>`, which implements `Fn(&'a Something) -> Result<(), ()> + Send + Sync + 'a` + | +LL | fn or<'a>(first: &'static Validator<'a>, second: &'static Validator<'a>) -> impl Fn(&'a Something) -> Result<(), ()> + Send + Sync + 'a { + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0746`.
diff --git a/src/test/ui/unsized/issue-91803.rs b/src/test/ui/unsized/issue-91803.rs new file mode 100644 index 0000000..c74897c --- /dev/null +++ b/src/test/ui/unsized/issue-91803.rs
@@ -0,0 +1,8 @@ +trait Foo<'a> {} + +fn or<'a>(first: &'static dyn Foo<'a>) -> dyn Foo<'a> { + //~^ ERROR return type cannot have an unboxed trait object + return Box::new(panic!()); +} + +fn main() {}
diff --git a/src/test/ui/unsized/issue-91803.stderr b/src/test/ui/unsized/issue-91803.stderr new file mode 100644 index 0000000..2dad9e8 --- /dev/null +++ b/src/test/ui/unsized/issue-91803.stderr
@@ -0,0 +1,15 @@ +error[E0746]: return type cannot have an unboxed trait object + --> $DIR/issue-91803.rs:3:43 + | +LL | fn or<'a>(first: &'static dyn Foo<'a>) -> dyn Foo<'a> { + | ^^^^^^^^^^^ doesn't have a size known at compile-time + | + = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits> +help: use `impl Foo<'a>` as the return type, as all return paths are of type `Box<_>`, which implements `Foo<'a>` + | +LL | fn or<'a>(first: &'static dyn Foo<'a>) -> impl Foo<'a> { + | ~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0746`.
diff --git a/src/test/ui/unsized/unsized-fn-param.stderr b/src/test/ui/unsized/unsized-fn-param.stderr index b498259..3eecca0 100644 --- a/src/test/ui/unsized/unsized-fn-param.stderr +++ b/src/test/ui/unsized/unsized-fn-param.stderr
@@ -6,6 +6,10 @@ | = help: the trait `Sized` is not implemented for `str` = note: required for the cast to the object type `dyn AsRef<Path>` +help: consider borrowing the value, since `&str` can be coerced into `dyn AsRef<Path>` + | +LL | foo11(&"bar", &"baz"); + | + error[E0277]: the size for values of type `str` cannot be known at compilation time --> $DIR/unsized-fn-param.rs:13:19 @@ -15,6 +19,10 @@ | = help: the trait `Sized` is not implemented for `str` = note: required for the cast to the object type `dyn AsRef<Path>` +help: consider borrowing the value, since `&str` can be coerced into `dyn AsRef<Path>` + | +LL | foo12(&"bar", &"baz"); + | + error[E0277]: the size for values of type `str` cannot be known at compilation time --> $DIR/unsized-fn-param.rs:16:11 @@ -24,6 +32,10 @@ | = help: the trait `Sized` is not implemented for `str` = note: required for the cast to the object type `dyn AsRef<str>` +help: consider borrowing the value, since `&str` can be coerced into `dyn AsRef<str>` + | +LL | foo21(&"bar", &"baz"); + | + error[E0277]: the size for values of type `str` cannot be known at compilation time --> $DIR/unsized-fn-param.rs:18:19 @@ -33,6 +45,10 @@ | = help: the trait `Sized` is not implemented for `str` = note: required for the cast to the object type `dyn AsRef<str>` +help: consider borrowing the value, since `&str` can be coerced into `dyn AsRef<str>` + | +LL | foo22(&"bar", &"baz"); + | + error: aborting due to 4 previous errors
diff --git a/src/test/ui/variance/variance-associated-types2.stderr b/src/test/ui/variance/variance-associated-types2.base.stderr similarity index 85% rename from src/test/ui/variance/variance-associated-types2.stderr rename to src/test/ui/variance/variance-associated-types2.base.stderr index af4f2a7..c8ace08 100644 --- a/src/test/ui/variance/variance-associated-types2.stderr +++ b/src/test/ui/variance/variance-associated-types2.base.stderr
@@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/variance-associated-types2.rs:13:42 + --> $DIR/variance-associated-types2.rs:17:42 | LL | let _: Box<dyn Foo<Bar = &'a u32>> = make(); | ^^^^^^ lifetime mismatch @@ -7,7 +7,7 @@ = note: expected trait object `dyn Foo<Bar = &'a u32>` found trait object `dyn Foo<Bar = &'static u32>` note: the lifetime `'a` as defined here... - --> $DIR/variance-associated-types2.rs:12:9 + --> $DIR/variance-associated-types2.rs:16:9 | LL | fn take<'a>(_: &'a u32) { | ^^
diff --git a/src/test/ui/variance/variance-associated-types2.nll.stderr b/src/test/ui/variance/variance-associated-types2.nll.stderr index 35871c1..b74c400 100644 --- a/src/test/ui/variance/variance-associated-types2.nll.stderr +++ b/src/test/ui/variance/variance-associated-types2.nll.stderr
@@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/variance-associated-types2.rs:13:12 + --> $DIR/variance-associated-types2.rs:17:12 | LL | fn take<'a>(_: &'a u32) { | -- lifetime `'a` defined here
diff --git a/src/test/ui/variance/variance-associated-types2.rs b/src/test/ui/variance/variance-associated-types2.rs index 6a095fc..e3c8e6d 100644 --- a/src/test/ui/variance/variance-associated-types2.rs +++ b/src/test/ui/variance/variance-associated-types2.rs
@@ -1,6 +1,10 @@ // Test that dyn Foo<Bar = T> is invariant with respect to T. // Failure to enforce invariance here can be weaponized, see #71550 for details. +// revisions: base nll +// ignore-compare-mode-nll +//[nll] compile-flags: -Z borrowck=mir + trait Foo { type Bar; } @@ -11,7 +15,8 @@ fn make() -> Box<dyn Foo<Bar = &'static u32>> { fn take<'a>(_: &'a u32) { let _: Box<dyn Foo<Bar = &'a u32>> = make(); - //~^ ERROR mismatched types [E0308] + //[base]~^ ERROR mismatched types [E0308] + //[nll]~^^ ERROR lifetime may not live long enough } fn main() {}
diff --git a/src/test/ui/variance/variance-btree-invariant-types.stderr b/src/test/ui/variance/variance-btree-invariant-types.base.stderr similarity index 83% rename from src/test/ui/variance/variance-btree-invariant-types.stderr rename to src/test/ui/variance/variance-btree-invariant-types.base.stderr index df519e2..5b78f42 100644 --- a/src/test/ui/variance/variance-btree-invariant-types.stderr +++ b/src/test/ui/variance/variance-btree-invariant-types.base.stderr
@@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/variance-btree-invariant-types.rs:4:5 + --> $DIR/variance-btree-invariant-types.rs:8:5 | LL | v | ^ lifetime mismatch @@ -7,145 +7,85 @@ = note: expected struct `std::collections::btree_map::IterMut<'_, &'new (), _>` found struct `std::collections::btree_map::IterMut<'_, &'static (), _>` note: the lifetime `'new` as defined here... - --> $DIR/variance-btree-invariant-types.rs:3:21 + --> $DIR/variance-btree-invariant-types.rs:7:21 | LL | fn iter_cov_key<'a, 'new>(v: IterMut<'a, &'static (), ()>) -> IterMut<'a, &'new (), ()> { | ^^^^ = note: ...does not necessarily outlive the static lifetime error[E0308]: mismatched types - --> $DIR/variance-btree-invariant-types.rs:7:5 - | -LL | v - | ^ lifetime mismatch - | - = note: expected struct `std::collections::btree_map::IterMut<'_, _, &'new ()>` - found struct `std::collections::btree_map::IterMut<'_, _, &'static ()>` -note: the lifetime `'new` as defined here... - --> $DIR/variance-btree-invariant-types.rs:6:21 - | -LL | fn iter_cov_val<'a, 'new>(v: IterMut<'a, (), &'static ()>) -> IterMut<'a, (), &'new ()> { - | ^^^^ - = note: ...does not necessarily outlive the static lifetime - -error[E0308]: mismatched types - --> $DIR/variance-btree-invariant-types.rs:10:5 - | -LL | v - | ^ lifetime mismatch - | - = note: expected struct `std::collections::btree_map::IterMut<'_, &'static (), _>` - found struct `std::collections::btree_map::IterMut<'_, &'new (), _>` -note: the lifetime `'new` as defined here... - --> $DIR/variance-btree-invariant-types.rs:9:24 - | -LL | fn iter_contra_key<'a, 'new>(v: IterMut<'a, &'new (), ()>) -> IterMut<'a, &'static (), ()> { - | ^^^^ - = note: ...does not necessarily outlive the static lifetime - -error[E0308]: mismatched types --> $DIR/variance-btree-invariant-types.rs:13:5 | LL | v | ^ lifetime mismatch | - = note: expected struct `std::collections::btree_map::IterMut<'_, _, &'static ()>` - found struct `std::collections::btree_map::IterMut<'_, _, &'new ()>` + = note: expected struct `std::collections::btree_map::IterMut<'_, _, &'new ()>` + found struct `std::collections::btree_map::IterMut<'_, _, &'static ()>` note: the lifetime `'new` as defined here... - --> $DIR/variance-btree-invariant-types.rs:12:24 + --> $DIR/variance-btree-invariant-types.rs:12:21 | -LL | fn iter_contra_val<'a, 'new>(v: IterMut<'a, (), &'new ()>) -> IterMut<'a, (), &'static ()> { +LL | fn iter_cov_val<'a, 'new>(v: IterMut<'a, (), &'static ()>) -> IterMut<'a, (), &'new ()> { + | ^^^^ + = note: ...does not necessarily outlive the static lifetime + +error[E0308]: mismatched types + --> $DIR/variance-btree-invariant-types.rs:18:5 + | +LL | v + | ^ lifetime mismatch + | + = note: expected struct `std::collections::btree_map::IterMut<'_, &'static (), _>` + found struct `std::collections::btree_map::IterMut<'_, &'new (), _>` +note: the lifetime `'new` as defined here... + --> $DIR/variance-btree-invariant-types.rs:17:24 + | +LL | fn iter_contra_key<'a, 'new>(v: IterMut<'a, &'new (), ()>) -> IterMut<'a, &'static (), ()> { | ^^^^ = note: ...does not necessarily outlive the static lifetime error[E0308]: mismatched types - --> $DIR/variance-btree-invariant-types.rs:17:5 - | -LL | v - | ^ lifetime mismatch - | - = note: expected struct `RangeMut<'_, &'new (), _>` - found struct `RangeMut<'_, &'static (), _>` -note: the lifetime `'new` as defined here... - --> $DIR/variance-btree-invariant-types.rs:16:22 - | -LL | fn range_cov_key<'a, 'new>(v: RangeMut<'a, &'static (), ()>) -> RangeMut<'a, &'new (), ()> { - | ^^^^ - = note: ...does not necessarily outlive the static lifetime - -error[E0308]: mismatched types - --> $DIR/variance-btree-invariant-types.rs:20:5 - | -LL | v - | ^ lifetime mismatch - | - = note: expected struct `RangeMut<'_, _, &'new ()>` - found struct `RangeMut<'_, _, &'static ()>` -note: the lifetime `'new` as defined here... - --> $DIR/variance-btree-invariant-types.rs:19:22 - | -LL | fn range_cov_val<'a, 'new>(v: RangeMut<'a, (), &'static ()>) -> RangeMut<'a, (), &'new ()> { - | ^^^^ - = note: ...does not necessarily outlive the static lifetime - -error[E0308]: mismatched types --> $DIR/variance-btree-invariant-types.rs:23:5 | LL | v | ^ lifetime mismatch | - = note: expected struct `RangeMut<'_, &'static (), _>` - found struct `RangeMut<'_, &'new (), _>` + = note: expected struct `std::collections::btree_map::IterMut<'_, _, &'static ()>` + found struct `std::collections::btree_map::IterMut<'_, _, &'new ()>` note: the lifetime `'new` as defined here... - --> $DIR/variance-btree-invariant-types.rs:22:25 + --> $DIR/variance-btree-invariant-types.rs:22:24 | -LL | fn range_contra_key<'a, 'new>(v: RangeMut<'a, &'new (), ()>) -> RangeMut<'a, &'static (), ()> { - | ^^^^ +LL | fn iter_contra_val<'a, 'new>(v: IterMut<'a, (), &'new ()>) -> IterMut<'a, (), &'static ()> { + | ^^^^ = note: ...does not necessarily outlive the static lifetime error[E0308]: mismatched types - --> $DIR/variance-btree-invariant-types.rs:26:5 + --> $DIR/variance-btree-invariant-types.rs:29:5 | LL | v | ^ lifetime mismatch | - = note: expected struct `RangeMut<'_, _, &'static ()>` - found struct `RangeMut<'_, _, &'new ()>` + = note: expected struct `RangeMut<'_, &'new (), _>` + found struct `RangeMut<'_, &'static (), _>` note: the lifetime `'new` as defined here... - --> $DIR/variance-btree-invariant-types.rs:25:25 + --> $DIR/variance-btree-invariant-types.rs:28:22 | -LL | fn range_contra_val<'a, 'new>(v: RangeMut<'a, (), &'new ()>) -> RangeMut<'a, (), &'static ()> { - | ^^^^ +LL | fn range_cov_key<'a, 'new>(v: RangeMut<'a, &'static (), ()>) -> RangeMut<'a, &'new (), ()> { + | ^^^^ = note: ...does not necessarily outlive the static lifetime error[E0308]: mismatched types - --> $DIR/variance-btree-invariant-types.rs:31:5 + --> $DIR/variance-btree-invariant-types.rs:34:5 | LL | v | ^ lifetime mismatch | - = note: expected struct `std::collections::btree_map::OccupiedEntry<'_, &'new (), _>` - found struct `std::collections::btree_map::OccupiedEntry<'_, &'static (), _>` + = note: expected struct `RangeMut<'_, _, &'new ()>` + found struct `RangeMut<'_, _, &'static ()>` note: the lifetime `'new` as defined here... - --> $DIR/variance-btree-invariant-types.rs:29:20 + --> $DIR/variance-btree-invariant-types.rs:33:22 | -LL | fn occ_cov_key<'a, 'new>(v: OccupiedEntry<'a, &'static (), ()>) - | ^^^^ - = note: ...does not necessarily outlive the static lifetime - -error[E0308]: mismatched types - --> $DIR/variance-btree-invariant-types.rs:35:5 - | -LL | v - | ^ lifetime mismatch - | - = note: expected struct `std::collections::btree_map::OccupiedEntry<'_, _, &'new ()>` - found struct `std::collections::btree_map::OccupiedEntry<'_, _, &'static ()>` -note: the lifetime `'new` as defined here... - --> $DIR/variance-btree-invariant-types.rs:33:20 - | -LL | fn occ_cov_val<'a, 'new>(v: OccupiedEntry<'a, (), &'static ()>) - | ^^^^ +LL | fn range_cov_val<'a, 'new>(v: RangeMut<'a, (), &'static ()>) -> RangeMut<'a, (), &'new ()> { + | ^^^^ = note: ...does not necessarily outlive the static lifetime error[E0308]: mismatched types @@ -154,17 +94,77 @@ LL | v | ^ lifetime mismatch | + = note: expected struct `RangeMut<'_, &'static (), _>` + found struct `RangeMut<'_, &'new (), _>` +note: the lifetime `'new` as defined here... + --> $DIR/variance-btree-invariant-types.rs:38:25 + | +LL | fn range_contra_key<'a, 'new>(v: RangeMut<'a, &'new (), ()>) -> RangeMut<'a, &'static (), ()> { + | ^^^^ + = note: ...does not necessarily outlive the static lifetime + +error[E0308]: mismatched types + --> $DIR/variance-btree-invariant-types.rs:44:5 + | +LL | v + | ^ lifetime mismatch + | + = note: expected struct `RangeMut<'_, _, &'static ()>` + found struct `RangeMut<'_, _, &'new ()>` +note: the lifetime `'new` as defined here... + --> $DIR/variance-btree-invariant-types.rs:43:25 + | +LL | fn range_contra_val<'a, 'new>(v: RangeMut<'a, (), &'new ()>) -> RangeMut<'a, (), &'static ()> { + | ^^^^ + = note: ...does not necessarily outlive the static lifetime + +error[E0308]: mismatched types + --> $DIR/variance-btree-invariant-types.rs:51:5 + | +LL | v + | ^ lifetime mismatch + | + = note: expected struct `std::collections::btree_map::OccupiedEntry<'_, &'new (), _>` + found struct `std::collections::btree_map::OccupiedEntry<'_, &'static (), _>` +note: the lifetime `'new` as defined here... + --> $DIR/variance-btree-invariant-types.rs:49:20 + | +LL | fn occ_cov_key<'a, 'new>(v: OccupiedEntry<'a, &'static (), ()>) + | ^^^^ + = note: ...does not necessarily outlive the static lifetime + +error[E0308]: mismatched types + --> $DIR/variance-btree-invariant-types.rs:57:5 + | +LL | v + | ^ lifetime mismatch + | + = note: expected struct `std::collections::btree_map::OccupiedEntry<'_, _, &'new ()>` + found struct `std::collections::btree_map::OccupiedEntry<'_, _, &'static ()>` +note: the lifetime `'new` as defined here... + --> $DIR/variance-btree-invariant-types.rs:55:20 + | +LL | fn occ_cov_val<'a, 'new>(v: OccupiedEntry<'a, (), &'static ()>) + | ^^^^ + = note: ...does not necessarily outlive the static lifetime + +error[E0308]: mismatched types + --> $DIR/variance-btree-invariant-types.rs:63:5 + | +LL | v + | ^ lifetime mismatch + | = note: expected struct `std::collections::btree_map::OccupiedEntry<'_, &'static (), _>` found struct `std::collections::btree_map::OccupiedEntry<'_, &'new (), _>` note: the lifetime `'new` as defined here... - --> $DIR/variance-btree-invariant-types.rs:37:23 + --> $DIR/variance-btree-invariant-types.rs:61:23 | LL | fn occ_contra_key<'a, 'new>(v: OccupiedEntry<'a, &'new (), ()>) | ^^^^ = note: ...does not necessarily outlive the static lifetime error[E0308]: mismatched types - --> $DIR/variance-btree-invariant-types.rs:43:5 + --> $DIR/variance-btree-invariant-types.rs:69:5 | LL | v | ^ lifetime mismatch @@ -172,14 +172,14 @@ = note: expected struct `std::collections::btree_map::OccupiedEntry<'_, _, &'static ()>` found struct `std::collections::btree_map::OccupiedEntry<'_, _, &'new ()>` note: the lifetime `'new` as defined here... - --> $DIR/variance-btree-invariant-types.rs:41:23 + --> $DIR/variance-btree-invariant-types.rs:67:23 | LL | fn occ_contra_val<'a, 'new>(v: OccupiedEntry<'a, (), &'new ()>) | ^^^^ = note: ...does not necessarily outlive the static lifetime error[E0308]: mismatched types - --> $DIR/variance-btree-invariant-types.rs:48:5 + --> $DIR/variance-btree-invariant-types.rs:76:5 | LL | v | ^ lifetime mismatch @@ -187,14 +187,14 @@ = note: expected struct `std::collections::btree_map::VacantEntry<'_, &'new (), _>` found struct `std::collections::btree_map::VacantEntry<'_, &'static (), _>` note: the lifetime `'new` as defined here... - --> $DIR/variance-btree-invariant-types.rs:46:20 + --> $DIR/variance-btree-invariant-types.rs:74:20 | LL | fn vac_cov_key<'a, 'new>(v: VacantEntry<'a, &'static (), ()>) | ^^^^ = note: ...does not necessarily outlive the static lifetime error[E0308]: mismatched types - --> $DIR/variance-btree-invariant-types.rs:52:5 + --> $DIR/variance-btree-invariant-types.rs:82:5 | LL | v | ^ lifetime mismatch @@ -202,14 +202,14 @@ = note: expected struct `std::collections::btree_map::VacantEntry<'_, _, &'new ()>` found struct `std::collections::btree_map::VacantEntry<'_, _, &'static ()>` note: the lifetime `'new` as defined here... - --> $DIR/variance-btree-invariant-types.rs:50:20 + --> $DIR/variance-btree-invariant-types.rs:80:20 | LL | fn vac_cov_val<'a, 'new>(v: VacantEntry<'a, (), &'static ()>) | ^^^^ = note: ...does not necessarily outlive the static lifetime error[E0308]: mismatched types - --> $DIR/variance-btree-invariant-types.rs:56:5 + --> $DIR/variance-btree-invariant-types.rs:88:5 | LL | v | ^ lifetime mismatch @@ -217,14 +217,14 @@ = note: expected struct `std::collections::btree_map::VacantEntry<'_, &'static (), _>` found struct `std::collections::btree_map::VacantEntry<'_, &'new (), _>` note: the lifetime `'new` as defined here... - --> $DIR/variance-btree-invariant-types.rs:54:23 + --> $DIR/variance-btree-invariant-types.rs:86:23 | LL | fn vac_contra_key<'a, 'new>(v: VacantEntry<'a, &'new (), ()>) | ^^^^ = note: ...does not necessarily outlive the static lifetime error[E0308]: mismatched types - --> $DIR/variance-btree-invariant-types.rs:60:5 + --> $DIR/variance-btree-invariant-types.rs:94:5 | LL | v | ^ lifetime mismatch @@ -232,7 +232,7 @@ = note: expected struct `std::collections::btree_map::VacantEntry<'_, _, &'static ()>` found struct `std::collections::btree_map::VacantEntry<'_, _, &'new ()>` note: the lifetime `'new` as defined here... - --> $DIR/variance-btree-invariant-types.rs:58:23 + --> $DIR/variance-btree-invariant-types.rs:92:23 | LL | fn vac_contra_val<'a, 'new>(v: VacantEntry<'a, (), &'new ()>) | ^^^^
diff --git a/src/test/ui/variance/variance-btree-invariant-types.nll.stderr b/src/test/ui/variance/variance-btree-invariant-types.nll.stderr index 867d9f8..991a7b0 100644 --- a/src/test/ui/variance/variance-btree-invariant-types.nll.stderr +++ b/src/test/ui/variance/variance-btree-invariant-types.nll.stderr
@@ -1,101 +1,101 @@ error: lifetime may not live long enough - --> $DIR/variance-btree-invariant-types.rs:4:5 + --> $DIR/variance-btree-invariant-types.rs:8:5 | LL | fn iter_cov_key<'a, 'new>(v: IterMut<'a, &'static (), ()>) -> IterMut<'a, &'new (), ()> { | ---- lifetime `'new` defined here LL | v | ^ returning this value requires that `'new` must outlive `'static` | - = note: requirement occurs because of the type std::collections::btree_map::IterMut<'_, &(), ()>, which makes the generic argument &() invariant - = note: the struct std::collections::btree_map::IterMut<'a, K, V> is invariant over the parameter K + = note: requirement occurs because of the type `std::collections::btree_map::IterMut<'_, &(), ()>`, which makes the generic argument `&()` invariant + = note: the struct `std::collections::btree_map::IterMut<'a, K, V>` is invariant over the parameter `K` = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance error: lifetime may not live long enough - --> $DIR/variance-btree-invariant-types.rs:7:5 + --> $DIR/variance-btree-invariant-types.rs:13:5 | LL | fn iter_cov_val<'a, 'new>(v: IterMut<'a, (), &'static ()>) -> IterMut<'a, (), &'new ()> { | ---- lifetime `'new` defined here LL | v | ^ returning this value requires that `'new` must outlive `'static` | - = note: requirement occurs because of the type std::collections::btree_map::IterMut<'_, (), &()>, which makes the generic argument () invariant - = note: the struct std::collections::btree_map::IterMut<'a, K, V> is invariant over the parameter K + = note: requirement occurs because of the type `std::collections::btree_map::IterMut<'_, (), &()>`, which makes the generic argument `()` invariant + = note: the struct `std::collections::btree_map::IterMut<'a, K, V>` is invariant over the parameter `K` = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance error: lifetime may not live long enough - --> $DIR/variance-btree-invariant-types.rs:10:5 + --> $DIR/variance-btree-invariant-types.rs:18:5 | LL | fn iter_contra_key<'a, 'new>(v: IterMut<'a, &'new (), ()>) -> IterMut<'a, &'static (), ()> { | ---- lifetime `'new` defined here LL | v | ^ returning this value requires that `'new` must outlive `'static` | - = note: requirement occurs because of the type std::collections::btree_map::IterMut<'_, &(), ()>, which makes the generic argument &() invariant - = note: the struct std::collections::btree_map::IterMut<'a, K, V> is invariant over the parameter K + = note: requirement occurs because of the type `std::collections::btree_map::IterMut<'_, &(), ()>`, which makes the generic argument `&()` invariant + = note: the struct `std::collections::btree_map::IterMut<'a, K, V>` is invariant over the parameter `K` = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance error: lifetime may not live long enough - --> $DIR/variance-btree-invariant-types.rs:13:5 + --> $DIR/variance-btree-invariant-types.rs:23:5 | LL | fn iter_contra_val<'a, 'new>(v: IterMut<'a, (), &'new ()>) -> IterMut<'a, (), &'static ()> { | ---- lifetime `'new` defined here LL | v | ^ returning this value requires that `'new` must outlive `'static` | - = note: requirement occurs because of the type std::collections::btree_map::IterMut<'_, (), &()>, which makes the generic argument () invariant - = note: the struct std::collections::btree_map::IterMut<'a, K, V> is invariant over the parameter K + = note: requirement occurs because of the type `std::collections::btree_map::IterMut<'_, (), &()>`, which makes the generic argument `()` invariant + = note: the struct `std::collections::btree_map::IterMut<'a, K, V>` is invariant over the parameter `K` = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance error: lifetime may not live long enough - --> $DIR/variance-btree-invariant-types.rs:17:5 + --> $DIR/variance-btree-invariant-types.rs:29:5 | LL | fn range_cov_key<'a, 'new>(v: RangeMut<'a, &'static (), ()>) -> RangeMut<'a, &'new (), ()> { | ---- lifetime `'new` defined here LL | v | ^ returning this value requires that `'new` must outlive `'static` | - = note: requirement occurs because of the type RangeMut<'_, &(), ()>, which makes the generic argument &() invariant - = note: the struct RangeMut<'a, K, V> is invariant over the parameter K + = note: requirement occurs because of the type `RangeMut<'_, &(), ()>`, which makes the generic argument `&()` invariant + = note: the struct `RangeMut<'a, K, V>` is invariant over the parameter `K` = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance error: lifetime may not live long enough - --> $DIR/variance-btree-invariant-types.rs:20:5 + --> $DIR/variance-btree-invariant-types.rs:34:5 | LL | fn range_cov_val<'a, 'new>(v: RangeMut<'a, (), &'static ()>) -> RangeMut<'a, (), &'new ()> { | ---- lifetime `'new` defined here LL | v | ^ returning this value requires that `'new` must outlive `'static` | - = note: requirement occurs because of the type RangeMut<'_, (), &()>, which makes the generic argument () invariant - = note: the struct RangeMut<'a, K, V> is invariant over the parameter K + = note: requirement occurs because of the type `RangeMut<'_, (), &()>`, which makes the generic argument `()` invariant + = note: the struct `RangeMut<'a, K, V>` is invariant over the parameter `K` = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance error: lifetime may not live long enough - --> $DIR/variance-btree-invariant-types.rs:23:5 + --> $DIR/variance-btree-invariant-types.rs:39:5 | LL | fn range_contra_key<'a, 'new>(v: RangeMut<'a, &'new (), ()>) -> RangeMut<'a, &'static (), ()> { | ---- lifetime `'new` defined here LL | v | ^ returning this value requires that `'new` must outlive `'static` | - = note: requirement occurs because of the type RangeMut<'_, &(), ()>, which makes the generic argument &() invariant - = note: the struct RangeMut<'a, K, V> is invariant over the parameter K + = note: requirement occurs because of the type `RangeMut<'_, &(), ()>`, which makes the generic argument `&()` invariant + = note: the struct `RangeMut<'a, K, V>` is invariant over the parameter `K` = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance error: lifetime may not live long enough - --> $DIR/variance-btree-invariant-types.rs:26:5 + --> $DIR/variance-btree-invariant-types.rs:44:5 | LL | fn range_contra_val<'a, 'new>(v: RangeMut<'a, (), &'new ()>) -> RangeMut<'a, (), &'static ()> { | ---- lifetime `'new` defined here LL | v | ^ returning this value requires that `'new` must outlive `'static` | - = note: requirement occurs because of the type RangeMut<'_, (), &()>, which makes the generic argument () invariant - = note: the struct RangeMut<'a, K, V> is invariant over the parameter K + = note: requirement occurs because of the type `RangeMut<'_, (), &()>`, which makes the generic argument `()` invariant + = note: the struct `RangeMut<'a, K, V>` is invariant over the parameter `K` = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance error: lifetime may not live long enough - --> $DIR/variance-btree-invariant-types.rs:31:5 + --> $DIR/variance-btree-invariant-types.rs:51:5 | LL | fn occ_cov_key<'a, 'new>(v: OccupiedEntry<'a, &'static (), ()>) | ---- lifetime `'new` defined here @@ -103,12 +103,12 @@ LL | v | ^ returning this value requires that `'new` must outlive `'static` | - = note: requirement occurs because of the type std::collections::btree_map::OccupiedEntry<'_, &(), ()>, which makes the generic argument &() invariant - = note: the struct std::collections::btree_map::OccupiedEntry<'a, K, V> is invariant over the parameter K + = note: requirement occurs because of the type `std::collections::btree_map::OccupiedEntry<'_, &(), ()>`, which makes the generic argument `&()` invariant + = note: the struct `std::collections::btree_map::OccupiedEntry<'a, K, V>` is invariant over the parameter `K` = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance error: lifetime may not live long enough - --> $DIR/variance-btree-invariant-types.rs:35:5 + --> $DIR/variance-btree-invariant-types.rs:57:5 | LL | fn occ_cov_val<'a, 'new>(v: OccupiedEntry<'a, (), &'static ()>) | ---- lifetime `'new` defined here @@ -116,12 +116,12 @@ LL | v | ^ returning this value requires that `'new` must outlive `'static` | - = note: requirement occurs because of the type std::collections::btree_map::OccupiedEntry<'_, (), &()>, which makes the generic argument () invariant - = note: the struct std::collections::btree_map::OccupiedEntry<'a, K, V> is invariant over the parameter K + = note: requirement occurs because of the type `std::collections::btree_map::OccupiedEntry<'_, (), &()>`, which makes the generic argument `()` invariant + = note: the struct `std::collections::btree_map::OccupiedEntry<'a, K, V>` is invariant over the parameter `K` = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance error: lifetime may not live long enough - --> $DIR/variance-btree-invariant-types.rs:39:5 + --> $DIR/variance-btree-invariant-types.rs:63:5 | LL | fn occ_contra_key<'a, 'new>(v: OccupiedEntry<'a, &'new (), ()>) | ---- lifetime `'new` defined here @@ -129,12 +129,12 @@ LL | v | ^ returning this value requires that `'new` must outlive `'static` | - = note: requirement occurs because of the type std::collections::btree_map::OccupiedEntry<'_, &(), ()>, which makes the generic argument &() invariant - = note: the struct std::collections::btree_map::OccupiedEntry<'a, K, V> is invariant over the parameter K + = note: requirement occurs because of the type `std::collections::btree_map::OccupiedEntry<'_, &(), ()>`, which makes the generic argument `&()` invariant + = note: the struct `std::collections::btree_map::OccupiedEntry<'a, K, V>` is invariant over the parameter `K` = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance error: lifetime may not live long enough - --> $DIR/variance-btree-invariant-types.rs:43:5 + --> $DIR/variance-btree-invariant-types.rs:69:5 | LL | fn occ_contra_val<'a, 'new>(v: OccupiedEntry<'a, (), &'new ()>) | ---- lifetime `'new` defined here @@ -142,12 +142,12 @@ LL | v | ^ returning this value requires that `'new` must outlive `'static` | - = note: requirement occurs because of the type std::collections::btree_map::OccupiedEntry<'_, (), &()>, which makes the generic argument () invariant - = note: the struct std::collections::btree_map::OccupiedEntry<'a, K, V> is invariant over the parameter K + = note: requirement occurs because of the type `std::collections::btree_map::OccupiedEntry<'_, (), &()>`, which makes the generic argument `()` invariant + = note: the struct `std::collections::btree_map::OccupiedEntry<'a, K, V>` is invariant over the parameter `K` = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance error: lifetime may not live long enough - --> $DIR/variance-btree-invariant-types.rs:48:5 + --> $DIR/variance-btree-invariant-types.rs:76:5 | LL | fn vac_cov_key<'a, 'new>(v: VacantEntry<'a, &'static (), ()>) | ---- lifetime `'new` defined here @@ -155,12 +155,12 @@ LL | v | ^ returning this value requires that `'new` must outlive `'static` | - = note: requirement occurs because of the type std::collections::btree_map::VacantEntry<'_, &(), ()>, which makes the generic argument &() invariant - = note: the struct std::collections::btree_map::VacantEntry<'a, K, V> is invariant over the parameter K + = note: requirement occurs because of the type `std::collections::btree_map::VacantEntry<'_, &(), ()>`, which makes the generic argument `&()` invariant + = note: the struct `std::collections::btree_map::VacantEntry<'a, K, V>` is invariant over the parameter `K` = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance error: lifetime may not live long enough - --> $DIR/variance-btree-invariant-types.rs:52:5 + --> $DIR/variance-btree-invariant-types.rs:82:5 | LL | fn vac_cov_val<'a, 'new>(v: VacantEntry<'a, (), &'static ()>) | ---- lifetime `'new` defined here @@ -168,12 +168,12 @@ LL | v | ^ returning this value requires that `'new` must outlive `'static` | - = note: requirement occurs because of the type std::collections::btree_map::VacantEntry<'_, (), &()>, which makes the generic argument () invariant - = note: the struct std::collections::btree_map::VacantEntry<'a, K, V> is invariant over the parameter K + = note: requirement occurs because of the type `std::collections::btree_map::VacantEntry<'_, (), &()>`, which makes the generic argument `()` invariant + = note: the struct `std::collections::btree_map::VacantEntry<'a, K, V>` is invariant over the parameter `K` = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance error: lifetime may not live long enough - --> $DIR/variance-btree-invariant-types.rs:56:5 + --> $DIR/variance-btree-invariant-types.rs:88:5 | LL | fn vac_contra_key<'a, 'new>(v: VacantEntry<'a, &'new (), ()>) | ---- lifetime `'new` defined here @@ -181,12 +181,12 @@ LL | v | ^ returning this value requires that `'new` must outlive `'static` | - = note: requirement occurs because of the type std::collections::btree_map::VacantEntry<'_, &(), ()>, which makes the generic argument &() invariant - = note: the struct std::collections::btree_map::VacantEntry<'a, K, V> is invariant over the parameter K + = note: requirement occurs because of the type `std::collections::btree_map::VacantEntry<'_, &(), ()>`, which makes the generic argument `&()` invariant + = note: the struct `std::collections::btree_map::VacantEntry<'a, K, V>` is invariant over the parameter `K` = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance error: lifetime may not live long enough - --> $DIR/variance-btree-invariant-types.rs:60:5 + --> $DIR/variance-btree-invariant-types.rs:94:5 | LL | fn vac_contra_val<'a, 'new>(v: VacantEntry<'a, (), &'new ()>) | ---- lifetime `'new` defined here @@ -194,8 +194,8 @@ LL | v | ^ returning this value requires that `'new` must outlive `'static` | - = note: requirement occurs because of the type std::collections::btree_map::VacantEntry<'_, (), &()>, which makes the generic argument () invariant - = note: the struct std::collections::btree_map::VacantEntry<'a, K, V> is invariant over the parameter K + = note: requirement occurs because of the type `std::collections::btree_map::VacantEntry<'_, (), &()>`, which makes the generic argument `()` invariant + = note: the struct `std::collections::btree_map::VacantEntry<'a, K, V>` is invariant over the parameter `K` = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance error: aborting due to 16 previous errors
diff --git a/src/test/ui/variance/variance-btree-invariant-types.rs b/src/test/ui/variance/variance-btree-invariant-types.rs index 4549622..7ddf6b2 100644 --- a/src/test/ui/variance/variance-btree-invariant-types.rs +++ b/src/test/ui/variance/variance-btree-invariant-types.rs
@@ -1,63 +1,99 @@ use std::collections::btree_map::{IterMut, OccupiedEntry, RangeMut, VacantEntry}; +// revisions: base nll +// ignore-compare-mode-nll +//[nll] compile-flags: -Z borrowck=mir + fn iter_cov_key<'a, 'new>(v: IterMut<'a, &'static (), ()>) -> IterMut<'a, &'new (), ()> { - v //~ ERROR mismatched types + v + //[base]~^ ERROR mismatched types + //[nll]~^^ lifetime may not live long enough } fn iter_cov_val<'a, 'new>(v: IterMut<'a, (), &'static ()>) -> IterMut<'a, (), &'new ()> { - v //~ ERROR mismatched types + v + //[base]~^ ERROR mismatched types + //[nll]~^^ lifetime may not live long enough } fn iter_contra_key<'a, 'new>(v: IterMut<'a, &'new (), ()>) -> IterMut<'a, &'static (), ()> { - v //~ ERROR mismatched types + v + //[base]~^ ERROR mismatched types + //[nll]~^^ lifetime may not live long enough } fn iter_contra_val<'a, 'new>(v: IterMut<'a, (), &'new ()>) -> IterMut<'a, (), &'static ()> { - v //~ ERROR mismatched types + v + //[base]~^ ERROR mismatched types + //[nll]~^^ lifetime may not live long enough } fn range_cov_key<'a, 'new>(v: RangeMut<'a, &'static (), ()>) -> RangeMut<'a, &'new (), ()> { - v //~ ERROR mismatched types + v + //[base]~^ ERROR mismatched types + //[nll]~^^ lifetime may not live long enough } fn range_cov_val<'a, 'new>(v: RangeMut<'a, (), &'static ()>) -> RangeMut<'a, (), &'new ()> { - v //~ ERROR mismatched types + v + //[base]~^ ERROR mismatched types + //[nll]~^^ lifetime may not live long enough } fn range_contra_key<'a, 'new>(v: RangeMut<'a, &'new (), ()>) -> RangeMut<'a, &'static (), ()> { - v //~ ERROR mismatched types + v + //[base]~^ ERROR mismatched types + //[nll]~^^ lifetime may not live long enough } fn range_contra_val<'a, 'new>(v: RangeMut<'a, (), &'new ()>) -> RangeMut<'a, (), &'static ()> { - v //~ ERROR mismatched types + v + //[base]~^ ERROR mismatched types + //[nll]~^^ lifetime may not live long enough } fn occ_cov_key<'a, 'new>(v: OccupiedEntry<'a, &'static (), ()>) -> OccupiedEntry<'a, &'new (), ()> { - v //~ ERROR mismatched types + v + //[base]~^ ERROR mismatched types + //[nll]~^^ lifetime may not live long enough } fn occ_cov_val<'a, 'new>(v: OccupiedEntry<'a, (), &'static ()>) -> OccupiedEntry<'a, (), &'new ()> { - v //~ ERROR mismatched types + v + //[base]~^ ERROR mismatched types + //[nll]~^^ lifetime may not live long enough } fn occ_contra_key<'a, 'new>(v: OccupiedEntry<'a, &'new (), ()>) -> OccupiedEntry<'a, &'static (), ()> { - v //~ ERROR mismatched types + v + //[base]~^ ERROR mismatched types + //[nll]~^^ lifetime may not live long enough } fn occ_contra_val<'a, 'new>(v: OccupiedEntry<'a, (), &'new ()>) -> OccupiedEntry<'a, (), &'static ()> { - v //~ ERROR mismatched types + v + //[base]~^ ERROR mismatched types + //[nll]~^^ lifetime may not live long enough } fn vac_cov_key<'a, 'new>(v: VacantEntry<'a, &'static (), ()>) -> VacantEntry<'a, &'new (), ()> { - v //~ ERROR mismatched types + v + //[base]~^ ERROR mismatched types + //[nll]~^^ lifetime may not live long enough } fn vac_cov_val<'a, 'new>(v: VacantEntry<'a, (), &'static ()>) -> VacantEntry<'a, (), &'new ()> { - v //~ ERROR mismatched types + v + //[base]~^ ERROR mismatched types + //[nll]~^^ lifetime may not live long enough } fn vac_contra_key<'a, 'new>(v: VacantEntry<'a, &'new (), ()>) -> VacantEntry<'a, &'static (), ()> { - v //~ ERROR mismatched types + v + //[base]~^ ERROR mismatched types + //[nll]~^^ lifetime may not live long enough } fn vac_contra_val<'a, 'new>(v: VacantEntry<'a, (), &'new ()>) -> VacantEntry<'a, (), &'static ()> { - v //~ ERROR mismatched types + v + //[base]~^ ERROR mismatched types + //[nll]~^^ lifetime may not live long enough }
diff --git a/src/test/ui/variance/variance-cell-is-invariant.stderr b/src/test/ui/variance/variance-cell-is-invariant.base.stderr similarity index 92% rename from src/test/ui/variance/variance-cell-is-invariant.stderr rename to src/test/ui/variance/variance-cell-is-invariant.base.stderr index 6fcd646..e3180b6 100644 --- a/src/test/ui/variance/variance-cell-is-invariant.stderr +++ b/src/test/ui/variance/variance-cell-is-invariant.base.stderr
@@ -1,5 +1,5 @@ error[E0623]: lifetime mismatch - --> $DIR/variance-cell-is-invariant.rs:14:25 + --> $DIR/variance-cell-is-invariant.rs:18:25 | LL | fn use_<'short,'long>(c: Foo<'short>, | ----------- these two types are declared with different lifetimes...
diff --git a/src/test/ui/variance/variance-cell-is-invariant.nll.stderr b/src/test/ui/variance/variance-cell-is-invariant.nll.stderr index d6a8568..c2e93d9 100644 --- a/src/test/ui/variance/variance-cell-is-invariant.nll.stderr +++ b/src/test/ui/variance/variance-cell-is-invariant.nll.stderr
@@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/variance-cell-is-invariant.rs:14:12 + --> $DIR/variance-cell-is-invariant.rs:18:12 | LL | fn use_<'short,'long>(c: Foo<'short>, | ------ ----- lifetime `'long` defined here @@ -10,8 +10,8 @@ | ^^^^^^^^^^ type annotation requires that `'short` must outlive `'long` | = help: consider adding the following bound: `'short: 'long` - = note: requirement occurs because of the type Foo<'_>, which makes the generic argument '_ invariant - = note: the struct Foo<'a> is invariant over the parameter 'a + = note: requirement occurs because of the type `Foo<'_>`, which makes the generic argument `'_` invariant + = note: the struct `Foo<'a>` is invariant over the parameter `'a` = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance error: aborting due to previous error
diff --git a/src/test/ui/variance/variance-cell-is-invariant.rs b/src/test/ui/variance/variance-cell-is-invariant.rs index ff9ad66..b8b7314 100644 --- a/src/test/ui/variance/variance-cell-is-invariant.rs +++ b/src/test/ui/variance/variance-cell-is-invariant.rs
@@ -1,6 +1,10 @@ // Test that Cell is considered invariant with respect to its // type. +// revisions: base nll +// ignore-compare-mode-nll +//[nll] compile-flags: -Z borrowck=mir + use std::cell::Cell; struct Foo<'a> { @@ -11,7 +15,9 @@ fn use_<'short,'long>(c: Foo<'short>, s: &'short isize, l: &'long isize, _where:Option<&'short &'long ()>) { - let _: Foo<'long> = c; //~ ERROR E0623 + let _: Foo<'long> = c; + //[base]~^ ERROR E0623 + //[nll]~^^ ERROR lifetime may not live long enough } fn main() {
diff --git a/src/test/ui/variance/variance-covariant-arg-object.stderr b/src/test/ui/variance/variance-contravariant-arg-object.base.stderr similarity index 77% copy from src/test/ui/variance/variance-covariant-arg-object.stderr copy to src/test/ui/variance/variance-contravariant-arg-object.base.stderr index d590a4d..19b8b9d 100644 --- a/src/test/ui/variance/variance-covariant-arg-object.stderr +++ b/src/test/ui/variance/variance-contravariant-arg-object.base.stderr
@@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/variance-covariant-arg-object.rs:15:5 + --> $DIR/variance-contravariant-arg-object.rs:18:5 | LL | v | ^ lifetime mismatch @@ -7,18 +7,18 @@ = note: expected trait object `dyn Get<&'min i32>` found trait object `dyn Get<&'max i32>` note: the lifetime `'min` as defined here... - --> $DIR/variance-covariant-arg-object.rs:10:21 + --> $DIR/variance-contravariant-arg-object.rs:14:21 | LL | fn get_min_from_max<'min, 'max>(v: Box<dyn Get<&'max i32>>) | ^^^^ note: ...does not necessarily outlive the lifetime `'max` as defined here - --> $DIR/variance-covariant-arg-object.rs:10:27 + --> $DIR/variance-contravariant-arg-object.rs:14:27 | LL | fn get_min_from_max<'min, 'max>(v: Box<dyn Get<&'max i32>>) | ^^^^ error[E0308]: mismatched types - --> $DIR/variance-covariant-arg-object.rs:22:5 + --> $DIR/variance-contravariant-arg-object.rs:28:5 | LL | v | ^ lifetime mismatch @@ -26,12 +26,12 @@ = note: expected trait object `dyn Get<&'max i32>` found trait object `dyn Get<&'min i32>` note: the lifetime `'min` as defined here... - --> $DIR/variance-covariant-arg-object.rs:18:21 + --> $DIR/variance-contravariant-arg-object.rs:23:21 | LL | fn get_max_from_min<'min, 'max, G>(v: Box<dyn Get<&'min i32>>) | ^^^^ note: ...does not necessarily outlive the lifetime `'max` as defined here - --> $DIR/variance-covariant-arg-object.rs:18:27 + --> $DIR/variance-contravariant-arg-object.rs:23:27 | LL | fn get_max_from_min<'min, 'max, G>(v: Box<dyn Get<&'min i32>>) | ^^^^
diff --git a/src/test/ui/variance/variance-contravariant-arg-object.nll.stderr b/src/test/ui/variance/variance-contravariant-arg-object.nll.stderr index 3315eaa..4071a41 100644 --- a/src/test/ui/variance/variance-contravariant-arg-object.nll.stderr +++ b/src/test/ui/variance/variance-contravariant-arg-object.nll.stderr
@@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/variance-contravariant-arg-object.rs:14:5 + --> $DIR/variance-contravariant-arg-object.rs:18:5 | LL | fn get_min_from_max<'min, 'max>(v: Box<dyn Get<&'max i32>>) | ---- ---- lifetime `'max` defined here @@ -12,7 +12,7 @@ = help: consider adding the following bound: `'min: 'max` error: lifetime may not live long enough - --> $DIR/variance-contravariant-arg-object.rs:22:5 + --> $DIR/variance-contravariant-arg-object.rs:28:5 | LL | fn get_max_from_min<'min, 'max, G>(v: Box<dyn Get<&'min i32>>) | ---- ---- lifetime `'max` defined here
diff --git a/src/test/ui/variance/variance-contravariant-arg-object.rs b/src/test/ui/variance/variance-contravariant-arg-object.rs index 947f4cd..dab42c3 100644 --- a/src/test/ui/variance/variance-contravariant-arg-object.rs +++ b/src/test/ui/variance/variance-contravariant-arg-object.rs
@@ -3,6 +3,10 @@ // Test that even when `T` is only used in contravariant position, it // is treated as invariant. +// revisions: base nll +// ignore-compare-mode-nll +//[nll] compile-flags: -Z borrowck=mir + trait Get<T> : 'static { fn get(&self, t: T); } @@ -11,7 +15,9 @@ fn get_min_from_max<'min, 'max>(v: Box<dyn Get<&'max i32>>) -> Box<dyn Get<&'min i32>> where 'max : 'min { - v //~ ERROR mismatched types + v + //[base]~^ ERROR mismatched types + //[nll]~^^ ERROR lifetime may not live long enough } fn get_max_from_min<'min, 'max, G>(v: Box<dyn Get<&'min i32>>) @@ -19,7 +25,9 @@ fn get_max_from_min<'min, 'max, G>(v: Box<dyn Get<&'min i32>>) where 'max : 'min { // Previously OK: - v //~ ERROR mismatched types + v + //[base]~^ ERROR mismatched types + //[nll]~^^ ERROR lifetime may not live long enough } fn main() { }
diff --git a/src/test/ui/variance/variance-contravariant-arg-object.stderr b/src/test/ui/variance/variance-contravariant-arg-object.stderr deleted file mode 100644 index 16583fa..0000000 --- a/src/test/ui/variance/variance-contravariant-arg-object.stderr +++ /dev/null
@@ -1,41 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/variance-contravariant-arg-object.rs:14:5 - | -LL | v - | ^ lifetime mismatch - | - = note: expected trait object `dyn Get<&'min i32>` - found trait object `dyn Get<&'max i32>` -note: the lifetime `'min` as defined here... - --> $DIR/variance-contravariant-arg-object.rs:10:21 - | -LL | fn get_min_from_max<'min, 'max>(v: Box<dyn Get<&'max i32>>) - | ^^^^ -note: ...does not necessarily outlive the lifetime `'max` as defined here - --> $DIR/variance-contravariant-arg-object.rs:10:27 - | -LL | fn get_min_from_max<'min, 'max>(v: Box<dyn Get<&'max i32>>) - | ^^^^ - -error[E0308]: mismatched types - --> $DIR/variance-contravariant-arg-object.rs:22:5 - | -LL | v - | ^ lifetime mismatch - | - = note: expected trait object `dyn Get<&'max i32>` - found trait object `dyn Get<&'min i32>` -note: the lifetime `'min` as defined here... - --> $DIR/variance-contravariant-arg-object.rs:17:21 - | -LL | fn get_max_from_min<'min, 'max, G>(v: Box<dyn Get<&'min i32>>) - | ^^^^ -note: ...does not necessarily outlive the lifetime `'max` as defined here - --> $DIR/variance-contravariant-arg-object.rs:17:27 - | -LL | fn get_max_from_min<'min, 'max, G>(v: Box<dyn Get<&'min i32>>) - | ^^^^ - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/variance/variance-invariant-arg-trait-match.stderr b/src/test/ui/variance/variance-contravariant-arg-trait-match.base.stderr similarity index 75% copy from src/test/ui/variance/variance-invariant-arg-trait-match.stderr copy to src/test/ui/variance/variance-contravariant-arg-trait-match.base.stderr index 0328496..56cf845 100644 --- a/src/test/ui/variance/variance-invariant-arg-trait-match.stderr +++ b/src/test/ui/variance/variance-contravariant-arg-trait-match.base.stderr
@@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/variance-invariant-arg-trait-match.rs:10:5 + --> $DIR/variance-contravariant-arg-trait-match.rs:17:5 | LL | impls_get::<G,&'min i32>() | ^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch @@ -7,18 +7,18 @@ = note: expected type `Get<&'min i32>` found type `Get<&'max i32>` note: the lifetime `'min` as defined here... - --> $DIR/variance-invariant-arg-trait-match.rs:7:21 + --> $DIR/variance-contravariant-arg-trait-match.rs:14:21 | LL | fn get_min_from_max<'min, 'max, G>() | ^^^^ note: ...does not necessarily outlive the lifetime `'max` as defined here - --> $DIR/variance-invariant-arg-trait-match.rs:7:27 + --> $DIR/variance-contravariant-arg-trait-match.rs:14:27 | LL | fn get_min_from_max<'min, 'max, G>() | ^^^^ error[E0308]: mismatched types - --> $DIR/variance-invariant-arg-trait-match.rs:16:5 + --> $DIR/variance-contravariant-arg-trait-match.rs:27:5 | LL | impls_get::<G,&'max i32>() | ^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch @@ -26,12 +26,12 @@ = note: expected type `Get<&'max i32>` found type `Get<&'min i32>` note: the lifetime `'min` as defined here... - --> $DIR/variance-invariant-arg-trait-match.rs:13:21 + --> $DIR/variance-contravariant-arg-trait-match.rs:22:21 | LL | fn get_max_from_min<'min, 'max, G>() | ^^^^ note: ...does not necessarily outlive the lifetime `'max` as defined here - --> $DIR/variance-invariant-arg-trait-match.rs:13:27 + --> $DIR/variance-contravariant-arg-trait-match.rs:22:27 | LL | fn get_max_from_min<'min, 'max, G>() | ^^^^
diff --git a/src/test/ui/variance/variance-contravariant-arg-trait-match.nll.stderr b/src/test/ui/variance/variance-contravariant-arg-trait-match.nll.stderr index 6f13675..6ca8f5e 100644 --- a/src/test/ui/variance/variance-contravariant-arg-trait-match.nll.stderr +++ b/src/test/ui/variance/variance-contravariant-arg-trait-match.nll.stderr
@@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/variance-contravariant-arg-trait-match.rs:13:5 + --> $DIR/variance-contravariant-arg-trait-match.rs:17:5 | LL | fn get_min_from_max<'min, 'max, G>() | ---- ---- lifetime `'max` defined here @@ -12,7 +12,7 @@ = help: consider adding the following bound: `'min: 'max` error: lifetime may not live long enough - --> $DIR/variance-contravariant-arg-trait-match.rs:21:5 + --> $DIR/variance-contravariant-arg-trait-match.rs:27:5 | LL | fn get_max_from_min<'min, 'max, G>() | ---- ---- lifetime `'max` defined here
diff --git a/src/test/ui/variance/variance-contravariant-arg-trait-match.rs b/src/test/ui/variance/variance-contravariant-arg-trait-match.rs index 904d931..11513d5 100644 --- a/src/test/ui/variance/variance-contravariant-arg-trait-match.rs +++ b/src/test/ui/variance/variance-contravariant-arg-trait-match.rs
@@ -3,6 +3,10 @@ // Test that even when `T` is only used in contravariant position, it // is treated as invariant. +// revisions: base nll +// ignore-compare-mode-nll +//[nll] compile-flags: -Z borrowck=mir + trait Get<T> { fn get(&self, t: T); } @@ -10,7 +14,9 @@ trait Get<T> { fn get_min_from_max<'min, 'max, G>() where 'max : 'min, G : Get<&'max i32> { - impls_get::<G,&'min i32>() //~ ERROR mismatched types + impls_get::<G,&'min i32>() + //[base]~^ ERROR mismatched types + //[nll]~^^ ERROR lifetime may not live long enough } fn get_max_from_min<'min, 'max, G>() @@ -18,7 +24,9 @@ fn get_max_from_min<'min, 'max, G>() { // Previously OK, but now an error because traits are invariant: - impls_get::<G,&'max i32>() //~ ERROR mismatched types + impls_get::<G,&'max i32>() + //[base]~^ ERROR mismatched types + //[nll]~^^ ERROR lifetime may not live long enough } fn impls_get<G,T>() where G : Get<T> { }
diff --git a/src/test/ui/variance/variance-contravariant-arg-trait-match.stderr b/src/test/ui/variance/variance-contravariant-arg-trait-match.stderr deleted file mode 100644 index 370e57f..0000000 --- a/src/test/ui/variance/variance-contravariant-arg-trait-match.stderr +++ /dev/null
@@ -1,41 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/variance-contravariant-arg-trait-match.rs:13:5 - | -LL | impls_get::<G,&'min i32>() - | ^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch - | - = note: expected type `Get<&'min i32>` - found type `Get<&'max i32>` -note: the lifetime `'min` as defined here... - --> $DIR/variance-contravariant-arg-trait-match.rs:10:21 - | -LL | fn get_min_from_max<'min, 'max, G>() - | ^^^^ -note: ...does not necessarily outlive the lifetime `'max` as defined here - --> $DIR/variance-contravariant-arg-trait-match.rs:10:27 - | -LL | fn get_min_from_max<'min, 'max, G>() - | ^^^^ - -error[E0308]: mismatched types - --> $DIR/variance-contravariant-arg-trait-match.rs:21:5 - | -LL | impls_get::<G,&'max i32>() - | ^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch - | - = note: expected type `Get<&'max i32>` - found type `Get<&'min i32>` -note: the lifetime `'min` as defined here... - --> $DIR/variance-contravariant-arg-trait-match.rs:16:21 - | -LL | fn get_max_from_min<'min, 'max, G>() - | ^^^^ -note: ...does not necessarily outlive the lifetime `'max` as defined here - --> $DIR/variance-contravariant-arg-trait-match.rs:16:27 - | -LL | fn get_max_from_min<'min, 'max, G>() - | ^^^^ - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/variance/variance-invariant-self-trait-match.stderr b/src/test/ui/variance/variance-contravariant-self-trait-match.base.stderr similarity index 75% copy from src/test/ui/variance/variance-invariant-self-trait-match.stderr copy to src/test/ui/variance/variance-contravariant-self-trait-match.base.stderr index c553581..2ccab2e 100644 --- a/src/test/ui/variance/variance-invariant-self-trait-match.stderr +++ b/src/test/ui/variance/variance-contravariant-self-trait-match.base.stderr
@@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/variance-invariant-self-trait-match.rs:10:5 + --> $DIR/variance-contravariant-self-trait-match.rs:17:5 | LL | impls_get::<&'min G>(); | ^^^^^^^^^^^^^^^^^^^^ lifetime mismatch @@ -7,18 +7,18 @@ = note: expected type `<&'min G as Get>` found type `<&'max G as Get>` note: the lifetime `'min` as defined here... - --> $DIR/variance-invariant-self-trait-match.rs:7:21 + --> $DIR/variance-contravariant-self-trait-match.rs:14:21 | LL | fn get_min_from_max<'min, 'max, G>() | ^^^^ note: ...does not necessarily outlive the lifetime `'max` as defined here - --> $DIR/variance-invariant-self-trait-match.rs:7:27 + --> $DIR/variance-contravariant-self-trait-match.rs:14:27 | LL | fn get_min_from_max<'min, 'max, G>() | ^^^^ error[E0308]: mismatched types - --> $DIR/variance-invariant-self-trait-match.rs:16:5 + --> $DIR/variance-contravariant-self-trait-match.rs:28:5 | LL | impls_get::<&'max G>(); | ^^^^^^^^^^^^^^^^^^^^ lifetime mismatch @@ -26,12 +26,12 @@ = note: expected type `<&'max G as Get>` found type `<&'min G as Get>` note: the lifetime `'min` as defined here... - --> $DIR/variance-invariant-self-trait-match.rs:13:21 + --> $DIR/variance-contravariant-self-trait-match.rs:22:21 | LL | fn get_max_from_min<'min, 'max, G>() | ^^^^ note: ...does not necessarily outlive the lifetime `'max` as defined here - --> $DIR/variance-invariant-self-trait-match.rs:13:27 + --> $DIR/variance-contravariant-self-trait-match.rs:22:27 | LL | fn get_max_from_min<'min, 'max, G>() | ^^^^
diff --git a/src/test/ui/variance/variance-contravariant-self-trait-match.nll.stderr b/src/test/ui/variance/variance-contravariant-self-trait-match.nll.stderr index fe08ce0..d2c549b 100644 --- a/src/test/ui/variance/variance-contravariant-self-trait-match.nll.stderr +++ b/src/test/ui/variance/variance-contravariant-self-trait-match.nll.stderr
@@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/variance-contravariant-self-trait-match.rs:13:5 + --> $DIR/variance-contravariant-self-trait-match.rs:17:5 | LL | fn get_min_from_max<'min, 'max, G>() | ---- ---- lifetime `'max` defined here @@ -12,7 +12,7 @@ = help: consider adding the following bound: `'min: 'max` error: lifetime may not live long enough - --> $DIR/variance-contravariant-self-trait-match.rs:22:5 + --> $DIR/variance-contravariant-self-trait-match.rs:28:5 | LL | fn get_max_from_min<'min, 'max, G>() | ---- ---- lifetime `'max` defined here
diff --git a/src/test/ui/variance/variance-contravariant-self-trait-match.rs b/src/test/ui/variance/variance-contravariant-self-trait-match.rs index e173758..f8d7c68 100644 --- a/src/test/ui/variance/variance-contravariant-self-trait-match.rs +++ b/src/test/ui/variance/variance-contravariant-self-trait-match.rs
@@ -3,6 +3,10 @@ // Test that even when `Self` is only used in contravariant position, it // is treated as invariant. +// revisions: base nll +// ignore-compare-mode-nll +//[nll] compile-flags: -Z borrowck=mir + trait Get { fn get(&self); } @@ -10,7 +14,9 @@ trait Get { fn get_min_from_max<'min, 'max, G>() where 'max : 'min, G : 'max, &'max G : Get { - impls_get::<&'min G>(); //~ ERROR mismatched types + impls_get::<&'min G>(); + //[base]~^ ERROR mismatched types + //[nll]~^^ ERROR lifetime may not live long enough } fn get_max_from_min<'min, 'max, G>() @@ -19,7 +25,9 @@ fn get_max_from_min<'min, 'max, G>() // Previously OK, but now error because traits are invariant with // respect to all inputs. - impls_get::<&'max G>(); //~ ERROR mismatched types + impls_get::<&'max G>(); + //[base]~^ ERROR mismatched types + //[nll]~^^ ERROR lifetime may not live long enough } fn impls_get<G>() where G : Get { }
diff --git a/src/test/ui/variance/variance-contravariant-self-trait-match.stderr b/src/test/ui/variance/variance-contravariant-self-trait-match.stderr deleted file mode 100644 index ab14faa..0000000 --- a/src/test/ui/variance/variance-contravariant-self-trait-match.stderr +++ /dev/null
@@ -1,41 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/variance-contravariant-self-trait-match.rs:13:5 - | -LL | impls_get::<&'min G>(); - | ^^^^^^^^^^^^^^^^^^^^ lifetime mismatch - | - = note: expected type `<&'min G as Get>` - found type `<&'max G as Get>` -note: the lifetime `'min` as defined here... - --> $DIR/variance-contravariant-self-trait-match.rs:10:21 - | -LL | fn get_min_from_max<'min, 'max, G>() - | ^^^^ -note: ...does not necessarily outlive the lifetime `'max` as defined here - --> $DIR/variance-contravariant-self-trait-match.rs:10:27 - | -LL | fn get_min_from_max<'min, 'max, G>() - | ^^^^ - -error[E0308]: mismatched types - --> $DIR/variance-contravariant-self-trait-match.rs:22:5 - | -LL | impls_get::<&'max G>(); - | ^^^^^^^^^^^^^^^^^^^^ lifetime mismatch - | - = note: expected type `<&'max G as Get>` - found type `<&'min G as Get>` -note: the lifetime `'min` as defined here... - --> $DIR/variance-contravariant-self-trait-match.rs:16:21 - | -LL | fn get_max_from_min<'min, 'max, G>() - | ^^^^ -note: ...does not necessarily outlive the lifetime `'max` as defined here - --> $DIR/variance-contravariant-self-trait-match.rs:16:27 - | -LL | fn get_max_from_min<'min, 'max, G>() - | ^^^^ - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/variance/variance-covariant-arg-object.stderr b/src/test/ui/variance/variance-covariant-arg-object.base.stderr similarity index 79% rename from src/test/ui/variance/variance-covariant-arg-object.stderr rename to src/test/ui/variance/variance-covariant-arg-object.base.stderr index d590a4d..3a97875 100644 --- a/src/test/ui/variance/variance-covariant-arg-object.stderr +++ b/src/test/ui/variance/variance-covariant-arg-object.base.stderr
@@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/variance-covariant-arg-object.rs:15:5 + --> $DIR/variance-covariant-arg-object.rs:19:5 | LL | v | ^ lifetime mismatch @@ -7,18 +7,18 @@ = note: expected trait object `dyn Get<&'min i32>` found trait object `dyn Get<&'max i32>` note: the lifetime `'min` as defined here... - --> $DIR/variance-covariant-arg-object.rs:10:21 + --> $DIR/variance-covariant-arg-object.rs:14:21 | LL | fn get_min_from_max<'min, 'max>(v: Box<dyn Get<&'max i32>>) | ^^^^ note: ...does not necessarily outlive the lifetime `'max` as defined here - --> $DIR/variance-covariant-arg-object.rs:10:27 + --> $DIR/variance-covariant-arg-object.rs:14:27 | LL | fn get_min_from_max<'min, 'max>(v: Box<dyn Get<&'max i32>>) | ^^^^ error[E0308]: mismatched types - --> $DIR/variance-covariant-arg-object.rs:22:5 + --> $DIR/variance-covariant-arg-object.rs:28:5 | LL | v | ^ lifetime mismatch @@ -26,12 +26,12 @@ = note: expected trait object `dyn Get<&'max i32>` found trait object `dyn Get<&'min i32>` note: the lifetime `'min` as defined here... - --> $DIR/variance-covariant-arg-object.rs:18:21 + --> $DIR/variance-covariant-arg-object.rs:24:21 | LL | fn get_max_from_min<'min, 'max, G>(v: Box<dyn Get<&'min i32>>) | ^^^^ note: ...does not necessarily outlive the lifetime `'max` as defined here - --> $DIR/variance-covariant-arg-object.rs:18:27 + --> $DIR/variance-covariant-arg-object.rs:24:27 | LL | fn get_max_from_min<'min, 'max, G>(v: Box<dyn Get<&'min i32>>) | ^^^^
diff --git a/src/test/ui/variance/variance-covariant-arg-object.nll.stderr b/src/test/ui/variance/variance-covariant-arg-object.nll.stderr index b116b8e..1b2ec61 100644 --- a/src/test/ui/variance/variance-covariant-arg-object.nll.stderr +++ b/src/test/ui/variance/variance-covariant-arg-object.nll.stderr
@@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/variance-covariant-arg-object.rs:15:5 + --> $DIR/variance-covariant-arg-object.rs:19:5 | LL | fn get_min_from_max<'min, 'max>(v: Box<dyn Get<&'max i32>>) | ---- ---- lifetime `'max` defined here @@ -12,7 +12,7 @@ = help: consider adding the following bound: `'min: 'max` error: lifetime may not live long enough - --> $DIR/variance-covariant-arg-object.rs:22:5 + --> $DIR/variance-covariant-arg-object.rs:28:5 | LL | fn get_max_from_min<'min, 'max, G>(v: Box<dyn Get<&'min i32>>) | ---- ---- lifetime `'max` defined here
diff --git a/src/test/ui/variance/variance-covariant-arg-object.rs b/src/test/ui/variance/variance-covariant-arg-object.rs index 7cbf65a..20f74a3 100644 --- a/src/test/ui/variance/variance-covariant-arg-object.rs +++ b/src/test/ui/variance/variance-covariant-arg-object.rs
@@ -3,6 +3,10 @@ // Test that even when `T` is only used in covariant position, it // is treated as invariant. +// revisions: base nll +// ignore-compare-mode-nll +//[nll] compile-flags: -Z borrowck=mir + trait Get<T> : 'static { fn get(&self) -> T; } @@ -12,14 +16,18 @@ fn get_min_from_max<'min, 'max>(v: Box<dyn Get<&'max i32>>) where 'max : 'min { // Previously OK, now an error as traits are invariant. - v //~ ERROR mismatched types + v + //[base]~^ ERROR mismatched types + //[nll]~^^ ERROR lifetime may not live long enough } fn get_max_from_min<'min, 'max, G>(v: Box<dyn Get<&'min i32>>) -> Box<dyn Get<&'max i32>> where 'max : 'min { - v //~ ERROR mismatched types + v + //[base]~^ ERROR mismatched types + //[nll]~^^ ERROR lifetime may not live long enough } fn main() { }
diff --git a/src/test/ui/variance/variance-invariant-arg-trait-match.stderr b/src/test/ui/variance/variance-covariant-arg-trait-match.base.stderr similarity index 76% copy from src/test/ui/variance/variance-invariant-arg-trait-match.stderr copy to src/test/ui/variance/variance-covariant-arg-trait-match.base.stderr index 0328496..1749a87 100644 --- a/src/test/ui/variance/variance-invariant-arg-trait-match.stderr +++ b/src/test/ui/variance/variance-covariant-arg-trait-match.base.stderr
@@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/variance-invariant-arg-trait-match.rs:10:5 + --> $DIR/variance-covariant-arg-trait-match.rs:18:5 | LL | impls_get::<G,&'min i32>() | ^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch @@ -7,18 +7,18 @@ = note: expected type `Get<&'min i32>` found type `Get<&'max i32>` note: the lifetime `'min` as defined here... - --> $DIR/variance-invariant-arg-trait-match.rs:7:21 + --> $DIR/variance-covariant-arg-trait-match.rs:14:21 | LL | fn get_min_from_max<'min, 'max, G>() | ^^^^ note: ...does not necessarily outlive the lifetime `'max` as defined here - --> $DIR/variance-invariant-arg-trait-match.rs:7:27 + --> $DIR/variance-covariant-arg-trait-match.rs:14:27 | LL | fn get_min_from_max<'min, 'max, G>() | ^^^^ error[E0308]: mismatched types - --> $DIR/variance-invariant-arg-trait-match.rs:16:5 + --> $DIR/variance-covariant-arg-trait-match.rs:26:5 | LL | impls_get::<G,&'max i32>() | ^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch @@ -26,12 +26,12 @@ = note: expected type `Get<&'max i32>` found type `Get<&'min i32>` note: the lifetime `'min` as defined here... - --> $DIR/variance-invariant-arg-trait-match.rs:13:21 + --> $DIR/variance-covariant-arg-trait-match.rs:23:21 | LL | fn get_max_from_min<'min, 'max, G>() | ^^^^ note: ...does not necessarily outlive the lifetime `'max` as defined here - --> $DIR/variance-invariant-arg-trait-match.rs:13:27 + --> $DIR/variance-covariant-arg-trait-match.rs:23:27 | LL | fn get_max_from_min<'min, 'max, G>() | ^^^^
diff --git a/src/test/ui/variance/variance-covariant-arg-trait-match.nll.stderr b/src/test/ui/variance/variance-covariant-arg-trait-match.nll.stderr index a982a29..870af48 100644 --- a/src/test/ui/variance/variance-covariant-arg-trait-match.nll.stderr +++ b/src/test/ui/variance/variance-covariant-arg-trait-match.nll.stderr
@@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/variance-covariant-arg-trait-match.rs:14:5 + --> $DIR/variance-covariant-arg-trait-match.rs:18:5 | LL | fn get_min_from_max<'min, 'max, G>() | ---- ---- lifetime `'max` defined here @@ -12,7 +12,7 @@ = help: consider adding the following bound: `'min: 'max` error: lifetime may not live long enough - --> $DIR/variance-covariant-arg-trait-match.rs:20:5 + --> $DIR/variance-covariant-arg-trait-match.rs:26:5 | LL | fn get_max_from_min<'min, 'max, G>() | ---- ---- lifetime `'max` defined here
diff --git a/src/test/ui/variance/variance-covariant-arg-trait-match.rs b/src/test/ui/variance/variance-covariant-arg-trait-match.rs index 2d4f0ea..d3d66d3 100644 --- a/src/test/ui/variance/variance-covariant-arg-trait-match.rs +++ b/src/test/ui/variance/variance-covariant-arg-trait-match.rs
@@ -3,6 +3,10 @@ // Test that even when `T` is only used in covariant position, it // is treated as invariant. +// revisions: base nll +// ignore-compare-mode-nll +//[nll] compile-flags: -Z borrowck=mir + trait Get<T> { fn get(&self) -> T; } @@ -11,13 +15,17 @@ fn get_min_from_max<'min, 'max, G>() where 'max : 'min, G : Get<&'max i32> { // Previously OK, now an error as traits are invariant. - impls_get::<G,&'min i32>() //~ ERROR mismatched types + impls_get::<G,&'min i32>() + //[base]~^ ERROR mismatched types + //[nll]~^^ ERROR lifetime may not live long enough } fn get_max_from_min<'min, 'max, G>() where 'max : 'min, G : Get<&'min i32> { - impls_get::<G,&'max i32>() //~ ERROR mismatched types + impls_get::<G,&'max i32>() + //[base]~^ ERROR mismatched types + //[nll]~^^ ERROR lifetime may not live long enough } fn impls_get<G,T>() where G : Get<T> { }
diff --git a/src/test/ui/variance/variance-covariant-arg-trait-match.stderr b/src/test/ui/variance/variance-covariant-arg-trait-match.stderr deleted file mode 100644 index eb1766b..0000000 --- a/src/test/ui/variance/variance-covariant-arg-trait-match.stderr +++ /dev/null
@@ -1,41 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/variance-covariant-arg-trait-match.rs:14:5 - | -LL | impls_get::<G,&'min i32>() - | ^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch - | - = note: expected type `Get<&'min i32>` - found type `Get<&'max i32>` -note: the lifetime `'min` as defined here... - --> $DIR/variance-covariant-arg-trait-match.rs:10:21 - | -LL | fn get_min_from_max<'min, 'max, G>() - | ^^^^ -note: ...does not necessarily outlive the lifetime `'max` as defined here - --> $DIR/variance-covariant-arg-trait-match.rs:10:27 - | -LL | fn get_min_from_max<'min, 'max, G>() - | ^^^^ - -error[E0308]: mismatched types - --> $DIR/variance-covariant-arg-trait-match.rs:20:5 - | -LL | impls_get::<G,&'max i32>() - | ^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch - | - = note: expected type `Get<&'max i32>` - found type `Get<&'min i32>` -note: the lifetime `'min` as defined here... - --> $DIR/variance-covariant-arg-trait-match.rs:17:21 - | -LL | fn get_max_from_min<'min, 'max, G>() - | ^^^^ -note: ...does not necessarily outlive the lifetime `'max` as defined here - --> $DIR/variance-covariant-arg-trait-match.rs:17:27 - | -LL | fn get_max_from_min<'min, 'max, G>() - | ^^^^ - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/variance/variance-invariant-self-trait-match.stderr b/src/test/ui/variance/variance-covariant-self-trait-match.base.stderr similarity index 76% rename from src/test/ui/variance/variance-invariant-self-trait-match.stderr rename to src/test/ui/variance/variance-covariant-self-trait-match.base.stderr index c553581..94afc01 100644 --- a/src/test/ui/variance/variance-invariant-self-trait-match.stderr +++ b/src/test/ui/variance/variance-covariant-self-trait-match.base.stderr
@@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/variance-invariant-self-trait-match.rs:10:5 + --> $DIR/variance-covariant-self-trait-match.rs:18:5 | LL | impls_get::<&'min G>(); | ^^^^^^^^^^^^^^^^^^^^ lifetime mismatch @@ -7,18 +7,18 @@ = note: expected type `<&'min G as Get>` found type `<&'max G as Get>` note: the lifetime `'min` as defined here... - --> $DIR/variance-invariant-self-trait-match.rs:7:21 + --> $DIR/variance-covariant-self-trait-match.rs:14:21 | LL | fn get_min_from_max<'min, 'max, G>() | ^^^^ note: ...does not necessarily outlive the lifetime `'max` as defined here - --> $DIR/variance-invariant-self-trait-match.rs:7:27 + --> $DIR/variance-covariant-self-trait-match.rs:14:27 | LL | fn get_min_from_max<'min, 'max, G>() | ^^^^ error[E0308]: mismatched types - --> $DIR/variance-invariant-self-trait-match.rs:16:5 + --> $DIR/variance-covariant-self-trait-match.rs:26:5 | LL | impls_get::<&'max G>(); | ^^^^^^^^^^^^^^^^^^^^ lifetime mismatch @@ -26,12 +26,12 @@ = note: expected type `<&'max G as Get>` found type `<&'min G as Get>` note: the lifetime `'min` as defined here... - --> $DIR/variance-invariant-self-trait-match.rs:13:21 + --> $DIR/variance-covariant-self-trait-match.rs:23:21 | LL | fn get_max_from_min<'min, 'max, G>() | ^^^^ note: ...does not necessarily outlive the lifetime `'max` as defined here - --> $DIR/variance-invariant-self-trait-match.rs:13:27 + --> $DIR/variance-covariant-self-trait-match.rs:23:27 | LL | fn get_max_from_min<'min, 'max, G>() | ^^^^
diff --git a/src/test/ui/variance/variance-covariant-self-trait-match.nll.stderr b/src/test/ui/variance/variance-covariant-self-trait-match.nll.stderr index 81b25e3..14da2d2 100644 --- a/src/test/ui/variance/variance-covariant-self-trait-match.nll.stderr +++ b/src/test/ui/variance/variance-covariant-self-trait-match.nll.stderr
@@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/variance-covariant-self-trait-match.rs:14:5 + --> $DIR/variance-covariant-self-trait-match.rs:18:5 | LL | fn get_min_from_max<'min, 'max, G>() | ---- ---- lifetime `'max` defined here @@ -12,7 +12,7 @@ = help: consider adding the following bound: `'min: 'max` error: lifetime may not live long enough - --> $DIR/variance-covariant-self-trait-match.rs:20:5 + --> $DIR/variance-covariant-self-trait-match.rs:26:5 | LL | fn get_max_from_min<'min, 'max, G>() | ---- ---- lifetime `'max` defined here
diff --git a/src/test/ui/variance/variance-covariant-self-trait-match.rs b/src/test/ui/variance/variance-covariant-self-trait-match.rs index e86a5fc..ece4501 100644 --- a/src/test/ui/variance/variance-covariant-self-trait-match.rs +++ b/src/test/ui/variance/variance-covariant-self-trait-match.rs
@@ -3,6 +3,10 @@ // Test that even when `Self` is only used in covariant position, it // is treated as invariant. +// revisions: base nll +// ignore-compare-mode-nll +//[nll] compile-flags: -Z borrowck=mir + trait Get { fn get() -> Self; } @@ -11,13 +15,17 @@ fn get_min_from_max<'min, 'max, G>() where 'max : 'min, G : 'max, &'max G : Get { // Previously OK, now an error as traits are invariant. - impls_get::<&'min G>(); //~ ERROR mismatched types + impls_get::<&'min G>(); + //[base]~^ ERROR mismatched types + //[nll]~^^ ERROR lifetime may not live long enough } fn get_max_from_min<'min, 'max, G>() where 'max : 'min, G : 'max, &'min G : Get { - impls_get::<&'max G>(); //~ ERROR mismatched types + impls_get::<&'max G>(); + //[base]~^ ERROR mismatched types + //[nll]~^^ ERROR lifetime may not live long enough } fn impls_get<G>() where G : Get { }
diff --git a/src/test/ui/variance/variance-covariant-self-trait-match.stderr b/src/test/ui/variance/variance-covariant-self-trait-match.stderr deleted file mode 100644 index b0bcb2e..0000000 --- a/src/test/ui/variance/variance-covariant-self-trait-match.stderr +++ /dev/null
@@ -1,41 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/variance-covariant-self-trait-match.rs:14:5 - | -LL | impls_get::<&'min G>(); - | ^^^^^^^^^^^^^^^^^^^^ lifetime mismatch - | - = note: expected type `<&'min G as Get>` - found type `<&'max G as Get>` -note: the lifetime `'min` as defined here... - --> $DIR/variance-covariant-self-trait-match.rs:10:21 - | -LL | fn get_min_from_max<'min, 'max, G>() - | ^^^^ -note: ...does not necessarily outlive the lifetime `'max` as defined here - --> $DIR/variance-covariant-self-trait-match.rs:10:27 - | -LL | fn get_min_from_max<'min, 'max, G>() - | ^^^^ - -error[E0308]: mismatched types - --> $DIR/variance-covariant-self-trait-match.rs:20:5 - | -LL | impls_get::<&'max G>(); - | ^^^^^^^^^^^^^^^^^^^^ lifetime mismatch - | - = note: expected type `<&'max G as Get>` - found type `<&'min G as Get>` -note: the lifetime `'min` as defined here... - --> $DIR/variance-covariant-self-trait-match.rs:17:21 - | -LL | fn get_max_from_min<'min, 'max, G>() - | ^^^^ -note: ...does not necessarily outlive the lifetime `'max` as defined here - --> $DIR/variance-covariant-self-trait-match.rs:17:27 - | -LL | fn get_max_from_min<'min, 'max, G>() - | ^^^^ - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/variance/variance-covariant-arg-object.stderr b/src/test/ui/variance/variance-invariant-arg-object.base.stderr similarity index 79% copy from src/test/ui/variance/variance-covariant-arg-object.stderr copy to src/test/ui/variance/variance-invariant-arg-object.base.stderr index d590a4d..ec9271e 100644 --- a/src/test/ui/variance/variance-covariant-arg-object.stderr +++ b/src/test/ui/variance/variance-invariant-arg-object.base.stderr
@@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/variance-covariant-arg-object.rs:15:5 + --> $DIR/variance-invariant-arg-object.rs:15:5 | LL | v | ^ lifetime mismatch @@ -7,18 +7,18 @@ = note: expected trait object `dyn Get<&'min i32>` found trait object `dyn Get<&'max i32>` note: the lifetime `'min` as defined here... - --> $DIR/variance-covariant-arg-object.rs:10:21 + --> $DIR/variance-invariant-arg-object.rs:11:21 | LL | fn get_min_from_max<'min, 'max>(v: Box<dyn Get<&'max i32>>) | ^^^^ note: ...does not necessarily outlive the lifetime `'max` as defined here - --> $DIR/variance-covariant-arg-object.rs:10:27 + --> $DIR/variance-invariant-arg-object.rs:11:27 | LL | fn get_min_from_max<'min, 'max>(v: Box<dyn Get<&'max i32>>) | ^^^^ error[E0308]: mismatched types - --> $DIR/variance-covariant-arg-object.rs:22:5 + --> $DIR/variance-invariant-arg-object.rs:24:5 | LL | v | ^ lifetime mismatch @@ -26,12 +26,12 @@ = note: expected trait object `dyn Get<&'max i32>` found trait object `dyn Get<&'min i32>` note: the lifetime `'min` as defined here... - --> $DIR/variance-covariant-arg-object.rs:18:21 + --> $DIR/variance-invariant-arg-object.rs:20:21 | LL | fn get_max_from_min<'min, 'max, G>(v: Box<dyn Get<&'min i32>>) | ^^^^ note: ...does not necessarily outlive the lifetime `'max` as defined here - --> $DIR/variance-covariant-arg-object.rs:18:27 + --> $DIR/variance-invariant-arg-object.rs:20:27 | LL | fn get_max_from_min<'min, 'max, G>(v: Box<dyn Get<&'min i32>>) | ^^^^
diff --git a/src/test/ui/variance/variance-invariant-arg-object.nll.stderr b/src/test/ui/variance/variance-invariant-arg-object.nll.stderr index 303c7f3..47364f4 100644 --- a/src/test/ui/variance/variance-invariant-arg-object.nll.stderr +++ b/src/test/ui/variance/variance-invariant-arg-object.nll.stderr
@@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/variance-invariant-arg-object.rs:11:5 + --> $DIR/variance-invariant-arg-object.rs:15:5 | LL | fn get_min_from_max<'min, 'max>(v: Box<dyn Get<&'max i32>>) | ---- ---- lifetime `'max` defined here @@ -12,7 +12,7 @@ = help: consider adding the following bound: `'min: 'max` error: lifetime may not live long enough - --> $DIR/variance-invariant-arg-object.rs:18:5 + --> $DIR/variance-invariant-arg-object.rs:24:5 | LL | fn get_max_from_min<'min, 'max, G>(v: Box<dyn Get<&'min i32>>) | ---- ---- lifetime `'max` defined here
diff --git a/src/test/ui/variance/variance-invariant-arg-object.rs b/src/test/ui/variance/variance-invariant-arg-object.rs index 886d263..cc8820f 100644 --- a/src/test/ui/variance/variance-invariant-arg-object.rs +++ b/src/test/ui/variance/variance-invariant-arg-object.rs
@@ -1,5 +1,9 @@ #![allow(dead_code)] +// revisions: base nll +// ignore-compare-mode-nll +//[nll] compile-flags: -Z borrowck=mir + trait Get<T> : 'static { fn get(&self, t: T) -> T; } @@ -8,14 +12,18 @@ fn get_min_from_max<'min, 'max>(v: Box<dyn Get<&'max i32>>) -> Box<dyn Get<&'min i32>> where 'max : 'min { - v //~ ERROR mismatched types + v + //[base]~^ ERROR mismatched types + //[nll]~^^ ERROR lifetime may not live long enough } fn get_max_from_min<'min, 'max, G>(v: Box<dyn Get<&'min i32>>) -> Box<dyn Get<&'max i32>> where 'max : 'min { - v //~ ERROR mismatched types + v + //[base]~^ ERROR mismatched types + //[nll]~^^ ERROR lifetime may not live long enough } fn main() { }
diff --git a/src/test/ui/variance/variance-invariant-arg-object.stderr b/src/test/ui/variance/variance-invariant-arg-object.stderr deleted file mode 100644 index 6c1b07e..0000000 --- a/src/test/ui/variance/variance-invariant-arg-object.stderr +++ /dev/null
@@ -1,41 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/variance-invariant-arg-object.rs:11:5 - | -LL | v - | ^ lifetime mismatch - | - = note: expected trait object `dyn Get<&'min i32>` - found trait object `dyn Get<&'max i32>` -note: the lifetime `'min` as defined here... - --> $DIR/variance-invariant-arg-object.rs:7:21 - | -LL | fn get_min_from_max<'min, 'max>(v: Box<dyn Get<&'max i32>>) - | ^^^^ -note: ...does not necessarily outlive the lifetime `'max` as defined here - --> $DIR/variance-invariant-arg-object.rs:7:27 - | -LL | fn get_min_from_max<'min, 'max>(v: Box<dyn Get<&'max i32>>) - | ^^^^ - -error[E0308]: mismatched types - --> $DIR/variance-invariant-arg-object.rs:18:5 - | -LL | v - | ^ lifetime mismatch - | - = note: expected trait object `dyn Get<&'max i32>` - found trait object `dyn Get<&'min i32>` -note: the lifetime `'min` as defined here... - --> $DIR/variance-invariant-arg-object.rs:14:21 - | -LL | fn get_max_from_min<'min, 'max, G>(v: Box<dyn Get<&'min i32>>) - | ^^^^ -note: ...does not necessarily outlive the lifetime `'max` as defined here - --> $DIR/variance-invariant-arg-object.rs:14:27 - | -LL | fn get_max_from_min<'min, 'max, G>(v: Box<dyn Get<&'min i32>>) - | ^^^^ - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/variance/variance-invariant-arg-trait-match.stderr b/src/test/ui/variance/variance-invariant-arg-trait-match.base.stderr similarity index 76% rename from src/test/ui/variance/variance-invariant-arg-trait-match.stderr rename to src/test/ui/variance/variance-invariant-arg-trait-match.base.stderr index 0328496..fe28468 100644 --- a/src/test/ui/variance/variance-invariant-arg-trait-match.stderr +++ b/src/test/ui/variance/variance-invariant-arg-trait-match.base.stderr
@@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/variance-invariant-arg-trait-match.rs:10:5 + --> $DIR/variance-invariant-arg-trait-match.rs:14:5 | LL | impls_get::<G,&'min i32>() | ^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch @@ -7,18 +7,18 @@ = note: expected type `Get<&'min i32>` found type `Get<&'max i32>` note: the lifetime `'min` as defined here... - --> $DIR/variance-invariant-arg-trait-match.rs:7:21 + --> $DIR/variance-invariant-arg-trait-match.rs:11:21 | LL | fn get_min_from_max<'min, 'max, G>() | ^^^^ note: ...does not necessarily outlive the lifetime `'max` as defined here - --> $DIR/variance-invariant-arg-trait-match.rs:7:27 + --> $DIR/variance-invariant-arg-trait-match.rs:11:27 | LL | fn get_min_from_max<'min, 'max, G>() | ^^^^ error[E0308]: mismatched types - --> $DIR/variance-invariant-arg-trait-match.rs:16:5 + --> $DIR/variance-invariant-arg-trait-match.rs:22:5 | LL | impls_get::<G,&'max i32>() | ^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch @@ -26,12 +26,12 @@ = note: expected type `Get<&'max i32>` found type `Get<&'min i32>` note: the lifetime `'min` as defined here... - --> $DIR/variance-invariant-arg-trait-match.rs:13:21 + --> $DIR/variance-invariant-arg-trait-match.rs:19:21 | LL | fn get_max_from_min<'min, 'max, G>() | ^^^^ note: ...does not necessarily outlive the lifetime `'max` as defined here - --> $DIR/variance-invariant-arg-trait-match.rs:13:27 + --> $DIR/variance-invariant-arg-trait-match.rs:19:27 | LL | fn get_max_from_min<'min, 'max, G>() | ^^^^
diff --git a/src/test/ui/variance/variance-invariant-arg-trait-match.nll.stderr b/src/test/ui/variance/variance-invariant-arg-trait-match.nll.stderr index 2909e81..74d2745 100644 --- a/src/test/ui/variance/variance-invariant-arg-trait-match.nll.stderr +++ b/src/test/ui/variance/variance-invariant-arg-trait-match.nll.stderr
@@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/variance-invariant-arg-trait-match.rs:10:5 + --> $DIR/variance-invariant-arg-trait-match.rs:14:5 | LL | fn get_min_from_max<'min, 'max, G>() | ---- ---- lifetime `'max` defined here @@ -12,7 +12,7 @@ = help: consider adding the following bound: `'min: 'max` error: lifetime may not live long enough - --> $DIR/variance-invariant-arg-trait-match.rs:16:5 + --> $DIR/variance-invariant-arg-trait-match.rs:22:5 | LL | fn get_max_from_min<'min, 'max, G>() | ---- ---- lifetime `'max` defined here
diff --git a/src/test/ui/variance/variance-invariant-arg-trait-match.rs b/src/test/ui/variance/variance-invariant-arg-trait-match.rs index 97d0fdd..498dd57 100644 --- a/src/test/ui/variance/variance-invariant-arg-trait-match.rs +++ b/src/test/ui/variance/variance-invariant-arg-trait-match.rs
@@ -1,5 +1,9 @@ #![allow(dead_code)] +// revisions: base nll +// ignore-compare-mode-nll +//[nll] compile-flags: -Z borrowck=mir + trait Get<T> { fn get(&self, t: T) -> T; } @@ -7,13 +11,17 @@ trait Get<T> { fn get_min_from_max<'min, 'max, G>() where 'max : 'min, G : Get<&'max i32> { - impls_get::<G,&'min i32>() //~ ERROR mismatched types + impls_get::<G,&'min i32>() + //[base]~^ ERROR mismatched types + //[nll]~^^ ERROR lifetime may not live long enough } fn get_max_from_min<'min, 'max, G>() where 'max : 'min, G : Get<&'min i32> { - impls_get::<G,&'max i32>() //~ ERROR mismatched types + impls_get::<G,&'max i32>() + //[base]~^ ERROR mismatched types + //[nll]~^^ ERROR lifetime may not live long enough } fn impls_get<G,T>() where G : Get<T> { }
diff --git a/src/test/ui/variance/variance-invariant-self-trait-match.stderr b/src/test/ui/variance/variance-invariant-self-trait-match.base.stderr similarity index 76% copy from src/test/ui/variance/variance-invariant-self-trait-match.stderr copy to src/test/ui/variance/variance-invariant-self-trait-match.base.stderr index c553581..a2589f0 100644 --- a/src/test/ui/variance/variance-invariant-self-trait-match.stderr +++ b/src/test/ui/variance/variance-invariant-self-trait-match.base.stderr
@@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/variance-invariant-self-trait-match.rs:10:5 + --> $DIR/variance-invariant-self-trait-match.rs:14:5 | LL | impls_get::<&'min G>(); | ^^^^^^^^^^^^^^^^^^^^ lifetime mismatch @@ -7,18 +7,18 @@ = note: expected type `<&'min G as Get>` found type `<&'max G as Get>` note: the lifetime `'min` as defined here... - --> $DIR/variance-invariant-self-trait-match.rs:7:21 + --> $DIR/variance-invariant-self-trait-match.rs:11:21 | LL | fn get_min_from_max<'min, 'max, G>() | ^^^^ note: ...does not necessarily outlive the lifetime `'max` as defined here - --> $DIR/variance-invariant-self-trait-match.rs:7:27 + --> $DIR/variance-invariant-self-trait-match.rs:11:27 | LL | fn get_min_from_max<'min, 'max, G>() | ^^^^ error[E0308]: mismatched types - --> $DIR/variance-invariant-self-trait-match.rs:16:5 + --> $DIR/variance-invariant-self-trait-match.rs:22:5 | LL | impls_get::<&'max G>(); | ^^^^^^^^^^^^^^^^^^^^ lifetime mismatch @@ -26,12 +26,12 @@ = note: expected type `<&'max G as Get>` found type `<&'min G as Get>` note: the lifetime `'min` as defined here... - --> $DIR/variance-invariant-self-trait-match.rs:13:21 + --> $DIR/variance-invariant-self-trait-match.rs:19:21 | LL | fn get_max_from_min<'min, 'max, G>() | ^^^^ note: ...does not necessarily outlive the lifetime `'max` as defined here - --> $DIR/variance-invariant-self-trait-match.rs:13:27 + --> $DIR/variance-invariant-self-trait-match.rs:19:27 | LL | fn get_max_from_min<'min, 'max, G>() | ^^^^
diff --git a/src/test/ui/variance/variance-invariant-self-trait-match.nll.stderr b/src/test/ui/variance/variance-invariant-self-trait-match.nll.stderr index 01b2c88..9d16e89 100644 --- a/src/test/ui/variance/variance-invariant-self-trait-match.nll.stderr +++ b/src/test/ui/variance/variance-invariant-self-trait-match.nll.stderr
@@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/variance-invariant-self-trait-match.rs:10:5 + --> $DIR/variance-invariant-self-trait-match.rs:14:5 | LL | fn get_min_from_max<'min, 'max, G>() | ---- ---- lifetime `'max` defined here @@ -12,7 +12,7 @@ = help: consider adding the following bound: `'min: 'max` error: lifetime may not live long enough - --> $DIR/variance-invariant-self-trait-match.rs:16:5 + --> $DIR/variance-invariant-self-trait-match.rs:22:5 | LL | fn get_max_from_min<'min, 'max, G>() | ---- ---- lifetime `'max` defined here
diff --git a/src/test/ui/variance/variance-invariant-self-trait-match.rs b/src/test/ui/variance/variance-invariant-self-trait-match.rs index 678eefa..0f3176b 100644 --- a/src/test/ui/variance/variance-invariant-self-trait-match.rs +++ b/src/test/ui/variance/variance-invariant-self-trait-match.rs
@@ -1,5 +1,9 @@ #![allow(dead_code)] +// revisions: base nll +// ignore-compare-mode-nll +//[nll] compile-flags: -Z borrowck=mir + trait Get { fn get(&self) -> Self; } @@ -7,13 +11,17 @@ trait Get { fn get_min_from_max<'min, 'max, G>() where 'max : 'min, &'max G : Get, G : 'max { - impls_get::<&'min G>(); //~ ERROR mismatched types + impls_get::<&'min G>(); + //[base]~^ ERROR mismatched types + //[nll]~^^ ERROR lifetime may not live long enough } fn get_max_from_min<'min, 'max, G>() where 'max : 'min, &'min G : Get, G : 'min { - impls_get::<&'max G>(); //~ ERROR mismatched types + impls_get::<&'max G>(); + //[base]~^ ERROR mismatched types + //[nll]~^^ ERROR lifetime may not live long enough } fn impls_get<G>() where G : Get { }
diff --git a/src/test/ui/variance/variance-trait-matching.stderr b/src/test/ui/variance/variance-trait-matching.base.stderr similarity index 89% rename from src/test/ui/variance/variance-trait-matching.stderr rename to src/test/ui/variance/variance-trait-matching.base.stderr index 5141531..8872620 100644 --- a/src/test/ui/variance/variance-trait-matching.stderr +++ b/src/test/ui/variance/variance-trait-matching.base.stderr
@@ -1,5 +1,5 @@ error[E0621]: explicit lifetime required in the type of `get` - --> $DIR/variance-trait-matching.rs:24:5 + --> $DIR/variance-trait-matching.rs:28:5 | LL | fn get<'a, G>(get: &G) -> i32 | -- help: add explicit lifetime `'a` to the type of `get`: `&'a G`
diff --git a/src/test/ui/variance/variance-trait-matching.nll.stderr b/src/test/ui/variance/variance-trait-matching.nll.stderr index 3308cc6..52c5eed 100644 --- a/src/test/ui/variance/variance-trait-matching.nll.stderr +++ b/src/test/ui/variance/variance-trait-matching.nll.stderr
@@ -1,5 +1,5 @@ error[E0621]: explicit lifetime required in the type of `get` - --> $DIR/variance-trait-matching.rs:24:5 + --> $DIR/variance-trait-matching.rs:28:5 | LL | fn get<'a, G>(get: &G) -> i32 | -- help: add explicit lifetime `'a` to the type of `get`: `&'a G`
diff --git a/src/test/ui/variance/variance-trait-matching.rs b/src/test/ui/variance/variance-trait-matching.rs index b4efee7..993db93 100644 --- a/src/test/ui/variance/variance-trait-matching.rs +++ b/src/test/ui/variance/variance-trait-matching.rs
@@ -1,5 +1,9 @@ #![allow(dead_code)] +// revisions: base nll +// ignore-compare-mode-nll +//[nll] compile-flags: -Z borrowck=mir + // Get<T> is covariant in T trait Get<T> { fn get(&self) -> T;
diff --git a/src/test/ui/variance/variance-use-contravariant-struct-1.stderr b/src/test/ui/variance/variance-use-contravariant-struct-1.base.stderr similarity index 76% rename from src/test/ui/variance/variance-use-contravariant-struct-1.stderr rename to src/test/ui/variance/variance-use-contravariant-struct-1.base.stderr index ec0cb22..a354aa5 100644 --- a/src/test/ui/variance/variance-use-contravariant-struct-1.stderr +++ b/src/test/ui/variance/variance-use-contravariant-struct-1.base.stderr
@@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/variance-use-contravariant-struct-1.rs:12:5 + --> $DIR/variance-use-contravariant-struct-1.rs:14:5 | LL | v | ^ lifetime mismatch @@ -7,12 +7,12 @@ = note: expected struct `SomeStruct<&'min ()>` found struct `SomeStruct<&'max ()>` note: the lifetime `'min` as defined here... - --> $DIR/variance-use-contravariant-struct-1.rs:8:8 + --> $DIR/variance-use-contravariant-struct-1.rs:10:8 | LL | fn foo<'min,'max>(v: SomeStruct<&'max ()>) | ^^^^ note: ...does not necessarily outlive the lifetime `'max` as defined here - --> $DIR/variance-use-contravariant-struct-1.rs:8:13 + --> $DIR/variance-use-contravariant-struct-1.rs:10:13 | LL | fn foo<'min,'max>(v: SomeStruct<&'max ()>) | ^^^^
diff --git a/src/test/ui/variance/variance-use-contravariant-struct-1.nll.stderr b/src/test/ui/variance/variance-use-contravariant-struct-1.nll.stderr index 837c70ca..9549a8c 100644 --- a/src/test/ui/variance/variance-use-contravariant-struct-1.nll.stderr +++ b/src/test/ui/variance/variance-use-contravariant-struct-1.nll.stderr
@@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/variance-use-contravariant-struct-1.rs:12:5 + --> $DIR/variance-use-contravariant-struct-1.rs:14:5 | LL | fn foo<'min,'max>(v: SomeStruct<&'max ()>) | ---- ---- lifetime `'max` defined here
diff --git a/src/test/ui/variance/variance-use-contravariant-struct-1.rs b/src/test/ui/variance/variance-use-contravariant-struct-1.rs index 8a02ef4..b55f5e7 100644 --- a/src/test/ui/variance/variance-use-contravariant-struct-1.rs +++ b/src/test/ui/variance/variance-use-contravariant-struct-1.rs
@@ -1,7 +1,9 @@ // Test various uses of structs with distint variances to make sure // they permit lifetimes to be approximated as expected. - +// revisions: base nll +// ignore-compare-mode-nll +//[nll] compile-flags: -Z borrowck=mir struct SomeStruct<T>(fn(T)); @@ -9,7 +11,9 @@ fn foo<'min,'max>(v: SomeStruct<&'max ()>) -> SomeStruct<&'min ()> where 'max : 'min { - v //~ ERROR mismatched types + v + //[base]~^ ERROR mismatched types + //[nll]~^^ ERROR lifetime may not live long enough }
diff --git a/src/test/ui/variance/variance-use-covariant-struct-1.stderr b/src/test/ui/variance/variance-use-covariant-struct-1.base.stderr similarity index 78% rename from src/test/ui/variance/variance-use-covariant-struct-1.stderr rename to src/test/ui/variance/variance-use-covariant-struct-1.base.stderr index 0c0071c..542d44c 100644 --- a/src/test/ui/variance/variance-use-covariant-struct-1.stderr +++ b/src/test/ui/variance/variance-use-covariant-struct-1.base.stderr
@@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/variance-use-covariant-struct-1.rs:10:5 + --> $DIR/variance-use-covariant-struct-1.rs:14:5 | LL | v | ^ lifetime mismatch @@ -7,12 +7,12 @@ = note: expected struct `SomeStruct<&'max ()>` found struct `SomeStruct<&'min ()>` note: the lifetime `'min` as defined here... - --> $DIR/variance-use-covariant-struct-1.rs:6:8 + --> $DIR/variance-use-covariant-struct-1.rs:10:8 | LL | fn foo<'min,'max>(v: SomeStruct<&'min ()>) | ^^^^ note: ...does not necessarily outlive the lifetime `'max` as defined here - --> $DIR/variance-use-covariant-struct-1.rs:6:13 + --> $DIR/variance-use-covariant-struct-1.rs:10:13 | LL | fn foo<'min,'max>(v: SomeStruct<&'min ()>) | ^^^^
diff --git a/src/test/ui/variance/variance-use-covariant-struct-1.nll.stderr b/src/test/ui/variance/variance-use-covariant-struct-1.nll.stderr index bab858c..2fac827 100644 --- a/src/test/ui/variance/variance-use-covariant-struct-1.nll.stderr +++ b/src/test/ui/variance/variance-use-covariant-struct-1.nll.stderr
@@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/variance-use-covariant-struct-1.rs:10:5 + --> $DIR/variance-use-covariant-struct-1.rs:14:5 | LL | fn foo<'min,'max>(v: SomeStruct<&'min ()>) | ---- ---- lifetime `'max` defined here
diff --git a/src/test/ui/variance/variance-use-covariant-struct-1.rs b/src/test/ui/variance/variance-use-covariant-struct-1.rs index e19a35b..3e3e76d 100644 --- a/src/test/ui/variance/variance-use-covariant-struct-1.rs +++ b/src/test/ui/variance/variance-use-covariant-struct-1.rs
@@ -1,13 +1,19 @@ // Test that a covariant struct does not permit the lifetime of a // reference to be enlarged. +// revisions: base nll +// ignore-compare-mode-nll +//[nll] compile-flags: -Z borrowck=mir + struct SomeStruct<T>(T); fn foo<'min,'max>(v: SomeStruct<&'min ()>) -> SomeStruct<&'max ()> where 'max : 'min { - v //~ ERROR mismatched types + v + //[base]~^ ERROR mismatched types + //[nll]~^^ ERROR lifetime may not live long enough } fn main() { }
diff --git a/src/test/ui/variance/variance-use-invariant-struct-1.stderr b/src/test/ui/variance/variance-use-invariant-struct-1.base.stderr similarity index 76% rename from src/test/ui/variance/variance-use-invariant-struct-1.stderr rename to src/test/ui/variance/variance-use-invariant-struct-1.base.stderr index 76e4bd7..02b4e91 100644 --- a/src/test/ui/variance/variance-use-invariant-struct-1.stderr +++ b/src/test/ui/variance/variance-use-invariant-struct-1.base.stderr
@@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/variance-use-invariant-struct-1.rs:12:5 + --> $DIR/variance-use-invariant-struct-1.rs:14:5 | LL | v | ^ lifetime mismatch @@ -7,18 +7,18 @@ = note: expected struct `SomeStruct<&'min ()>` found struct `SomeStruct<&'max ()>` note: the lifetime `'min` as defined here... - --> $DIR/variance-use-invariant-struct-1.rs:8:8 + --> $DIR/variance-use-invariant-struct-1.rs:10:8 | LL | fn foo<'min,'max>(v: SomeStruct<&'max ()>) | ^^^^ note: ...does not necessarily outlive the lifetime `'max` as defined here - --> $DIR/variance-use-invariant-struct-1.rs:8:13 + --> $DIR/variance-use-invariant-struct-1.rs:10:13 | LL | fn foo<'min,'max>(v: SomeStruct<&'max ()>) | ^^^^ error[E0308]: mismatched types - --> $DIR/variance-use-invariant-struct-1.rs:19:5 + --> $DIR/variance-use-invariant-struct-1.rs:23:5 | LL | v | ^ lifetime mismatch @@ -26,12 +26,12 @@ = note: expected struct `SomeStruct<&'max ()>` found struct `SomeStruct<&'min ()>` note: the lifetime `'min` as defined here... - --> $DIR/variance-use-invariant-struct-1.rs:15:8 + --> $DIR/variance-use-invariant-struct-1.rs:19:8 | LL | fn bar<'min,'max>(v: SomeStruct<&'min ()>) | ^^^^ note: ...does not necessarily outlive the lifetime `'max` as defined here - --> $DIR/variance-use-invariant-struct-1.rs:15:13 + --> $DIR/variance-use-invariant-struct-1.rs:19:13 | LL | fn bar<'min,'max>(v: SomeStruct<&'min ()>) | ^^^^
diff --git a/src/test/ui/variance/variance-use-invariant-struct-1.nll.stderr b/src/test/ui/variance/variance-use-invariant-struct-1.nll.stderr index f1df2a8..e8460a3 100644 --- a/src/test/ui/variance/variance-use-invariant-struct-1.nll.stderr +++ b/src/test/ui/variance/variance-use-invariant-struct-1.nll.stderr
@@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/variance-use-invariant-struct-1.rs:12:5 + --> $DIR/variance-use-invariant-struct-1.rs:14:5 | LL | fn foo<'min,'max>(v: SomeStruct<&'max ()>) | ---- ---- lifetime `'max` defined here @@ -10,12 +10,12 @@ | ^ function was supposed to return data with lifetime `'max` but it is returning data with lifetime `'min` | = help: consider adding the following bound: `'min: 'max` - = note: requirement occurs because of the type SomeStruct<&()>, which makes the generic argument &() invariant - = note: the struct SomeStruct<T> is invariant over the parameter T + = note: requirement occurs because of the type `SomeStruct<&()>`, which makes the generic argument `&()` invariant + = note: the struct `SomeStruct<T>` is invariant over the parameter `T` = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance error: lifetime may not live long enough - --> $DIR/variance-use-invariant-struct-1.rs:19:5 + --> $DIR/variance-use-invariant-struct-1.rs:23:5 | LL | fn bar<'min,'max>(v: SomeStruct<&'min ()>) | ---- ---- lifetime `'max` defined here @@ -26,8 +26,8 @@ | ^ function was supposed to return data with lifetime `'max` but it is returning data with lifetime `'min` | = help: consider adding the following bound: `'min: 'max` - = note: requirement occurs because of the type SomeStruct<&()>, which makes the generic argument &() invariant - = note: the struct SomeStruct<T> is invariant over the parameter T + = note: requirement occurs because of the type `SomeStruct<&()>`, which makes the generic argument `&()` invariant + = note: the struct `SomeStruct<T>` is invariant over the parameter `T` = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance error: aborting due to 2 previous errors
diff --git a/src/test/ui/variance/variance-use-invariant-struct-1.rs b/src/test/ui/variance/variance-use-invariant-struct-1.rs index 4772a9f..7be0351 100644 --- a/src/test/ui/variance/variance-use-invariant-struct-1.rs +++ b/src/test/ui/variance/variance-use-invariant-struct-1.rs
@@ -1,7 +1,9 @@ // Test various uses of structs with distint variances to make sure // they permit lifetimes to be approximated as expected. - +// revisions: base nll +// ignore-compare-mode-nll +//[nll] compile-flags: -Z borrowck=mir struct SomeStruct<T>(*mut T); @@ -9,14 +11,18 @@ fn foo<'min,'max>(v: SomeStruct<&'max ()>) -> SomeStruct<&'min ()> where 'max : 'min { - v //~ ERROR mismatched types + v + //[base]~^ ERROR mismatched types + //[nll]~^^ ERROR lifetime may not live long enough } fn bar<'min,'max>(v: SomeStruct<&'min ()>) -> SomeStruct<&'max ()> where 'max : 'min { - v //~ ERROR mismatched types + v + //[base]~^ ERROR mismatched types + //[nll]~^^ ERROR lifetime may not live long enough }
diff --git a/src/test/ui/wf/hir-wf-check-erase-regions.stderr b/src/test/ui/wf/hir-wf-check-erase-regions.stderr index 0d9b962..037f8b9 100644 --- a/src/test/ui/wf/hir-wf-check-erase-regions.stderr +++ b/src/test/ui/wf/hir-wf-check-erase-regions.stderr
@@ -5,6 +5,7 @@ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&T` is not an iterator | = help: the trait `Iterator` is not implemented for `&T` + = help: the trait `Iterator` is implemented for `&mut I` = note: required because of the requirements on the impl of `IntoIterator` for `&T` note: required by a bound in `Flatten` --> $SRC_DIR/core/src/iter/adapters/flatten.rs:LL:COL @@ -19,6 +20,7 @@ | ^^^^^^^^^^^^^^ `&T` is not an iterator | = help: the trait `Iterator` is not implemented for `&T` + = help: the trait `Iterator` is implemented for `&mut I` = note: required because of the requirements on the impl of `IntoIterator` for `&T` note: required by a bound in `Flatten` --> $SRC_DIR/core/src/iter/adapters/flatten.rs:LL:COL
diff --git a/src/test/ui/wf/wf-const-type.stderr b/src/test/ui/wf/wf-const-type.stderr index 5a6d66e..e47920d 100644 --- a/src/test/ui/wf/wf-const-type.stderr +++ b/src/test/ui/wf/wf-const-type.stderr
@@ -10,6 +10,10 @@ | LL | struct IsCopy<T:Copy> { t: T } | ^^^^ required by this bound in `IsCopy` +help: consider annotating `NotCopy` with `#[derive(Copy)]` + | +LL | #[derive(Copy)] + | error: aborting due to previous error
diff --git a/src/test/ui/wf/wf-static-method.stderr b/src/test/ui/wf/wf-static-method.base.stderr similarity index 80% rename from src/test/ui/wf/wf-static-method.stderr rename to src/test/ui/wf/wf-static-method.base.stderr index c663931..186ab27 100644 --- a/src/test/ui/wf/wf-static-method.stderr +++ b/src/test/ui/wf/wf-static-method.base.stderr
@@ -1,131 +1,131 @@ error[E0312]: lifetime of reference outlives lifetime of borrowed content... - --> $DIR/wf-static-method.rs:17:9 + --> $DIR/wf-static-method.rs:21:9 | LL | u | ^ | note: ...the reference is valid for the lifetime `'a` as defined here... - --> $DIR/wf-static-method.rs:14:6 + --> $DIR/wf-static-method.rs:18:6 | LL | impl<'a, 'b> Foo<'a, 'b, Evil<'a, 'b>> for () { | ^^ note: ...but the borrowed content is only valid for the lifetime `'b` as defined here - --> $DIR/wf-static-method.rs:14:10 + --> $DIR/wf-static-method.rs:18:10 | LL | impl<'a, 'b> Foo<'a, 'b, Evil<'a, 'b>> for () { | ^^ error[E0478]: lifetime bound not satisfied - --> $DIR/wf-static-method.rs:26:18 + --> $DIR/wf-static-method.rs:32:18 | LL | let me = Self::make_me(); | ^^^^ | note: lifetime parameter instantiated with the lifetime `'b` as defined here - --> $DIR/wf-static-method.rs:23:10 + --> $DIR/wf-static-method.rs:29:10 | LL | impl<'a, 'b> Foo<'a, 'b, ()> for IndirectEvil<'a, 'b> { | ^^ note: but lifetime parameter must outlive the lifetime `'a` as defined here - --> $DIR/wf-static-method.rs:23:6 + --> $DIR/wf-static-method.rs:29:6 | LL | impl<'a, 'b> Foo<'a, 'b, ()> for IndirectEvil<'a, 'b> { | ^^ error[E0312]: lifetime of reference outlives lifetime of borrowed content... - --> $DIR/wf-static-method.rs:33:9 + --> $DIR/wf-static-method.rs:41:9 | LL | u | ^ | note: ...the reference is valid for the lifetime `'a` as defined here... - --> $DIR/wf-static-method.rs:31:6 + --> $DIR/wf-static-method.rs:39:6 | LL | impl<'a, 'b> Evil<'a, 'b> { | ^^ note: ...but the borrowed content is only valid for the lifetime `'b` as defined here - --> $DIR/wf-static-method.rs:31:10 + --> $DIR/wf-static-method.rs:39:10 | LL | impl<'a, 'b> Evil<'a, 'b> { | ^^ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'b` due to conflicting requirements - --> $DIR/wf-static-method.rs:41:5 + --> $DIR/wf-static-method.rs:51:5 | LL | <()>::static_evil(b) | ^^^^^^^^^^^^^^^^^ | note: first, the lifetime cannot outlive the lifetime `'b` as defined here... - --> $DIR/wf-static-method.rs:40:13 + --> $DIR/wf-static-method.rs:50:13 | LL | fn evil<'a, 'b>(b: &'b u32) -> &'a u32 { | ^^ note: ...so that reference does not outlive borrowed content - --> $DIR/wf-static-method.rs:41:23 + --> $DIR/wf-static-method.rs:51:23 | LL | <()>::static_evil(b) | ^ note: but, the lifetime must be valid for the lifetime `'a` as defined here... - --> $DIR/wf-static-method.rs:40:9 + --> $DIR/wf-static-method.rs:50:9 | LL | fn evil<'a, 'b>(b: &'b u32) -> &'a u32 { | ^^ note: ...so that reference does not outlive borrowed content - --> $DIR/wf-static-method.rs:41:5 + --> $DIR/wf-static-method.rs:51:5 | LL | <()>::static_evil(b) | ^^^^^^^^^^^^^^^^^^^^ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'b` due to conflicting requirements - --> $DIR/wf-static-method.rs:45:5 + --> $DIR/wf-static-method.rs:57:5 | LL | <IndirectEvil>::static_evil(b) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first, the lifetime cannot outlive the lifetime `'b` as defined here... - --> $DIR/wf-static-method.rs:44:22 + --> $DIR/wf-static-method.rs:56:22 | LL | fn indirect_evil<'a, 'b>(b: &'b u32) -> &'a u32 { | ^^ note: ...so that reference does not outlive borrowed content - --> $DIR/wf-static-method.rs:45:33 + --> $DIR/wf-static-method.rs:57:33 | LL | <IndirectEvil>::static_evil(b) | ^ note: but, the lifetime must be valid for the lifetime `'a` as defined here... - --> $DIR/wf-static-method.rs:44:18 + --> $DIR/wf-static-method.rs:56:18 | LL | fn indirect_evil<'a, 'b>(b: &'b u32) -> &'a u32 { | ^^ note: ...so that reference does not outlive borrowed content - --> $DIR/wf-static-method.rs:45:5 + --> $DIR/wf-static-method.rs:57:5 | LL | <IndirectEvil>::static_evil(b) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'b` due to conflicting requirements - --> $DIR/wf-static-method.rs:50:5 + --> $DIR/wf-static-method.rs:63:5 | LL | <Evil>::inherent_evil(b) | ^^^^^^^^^^^^^^^^^^^^^ | note: first, the lifetime cannot outlive the lifetime `'b` as defined here... - --> $DIR/wf-static-method.rs:49:22 + --> $DIR/wf-static-method.rs:62:22 | LL | fn inherent_evil<'a, 'b>(b: &'b u32) -> &'a u32 { | ^^ note: ...so that reference does not outlive borrowed content - --> $DIR/wf-static-method.rs:50:27 + --> $DIR/wf-static-method.rs:63:27 | LL | <Evil>::inherent_evil(b) | ^ note: but, the lifetime must be valid for the lifetime `'a` as defined here... - --> $DIR/wf-static-method.rs:49:18 + --> $DIR/wf-static-method.rs:62:18 | LL | fn inherent_evil<'a, 'b>(b: &'b u32) -> &'a u32 { | ^^ note: ...so that reference does not outlive borrowed content - --> $DIR/wf-static-method.rs:50:5 + --> $DIR/wf-static-method.rs:63:5 | LL | <Evil>::inherent_evil(b) | ^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/wf/wf-static-method.nll.stderr b/src/test/ui/wf/wf-static-method.nll.stderr index 2650431..7556d8e 100644 --- a/src/test/ui/wf/wf-static-method.nll.stderr +++ b/src/test/ui/wf/wf-static-method.nll.stderr
@@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/wf-static-method.rs:17:9 + --> $DIR/wf-static-method.rs:21:9 | LL | impl<'a, 'b> Foo<'a, 'b, Evil<'a, 'b>> for () { | -- -- lifetime `'b` defined here @@ -12,7 +12,7 @@ = help: consider adding the following bound: `'b: 'a` error: lifetime may not live long enough - --> $DIR/wf-static-method.rs:26:18 + --> $DIR/wf-static-method.rs:32:18 | LL | impl<'a, 'b> Foo<'a, 'b, ()> for IndirectEvil<'a, 'b> { | -- -- lifetime `'b` defined here @@ -25,7 +25,7 @@ = help: consider adding the following bound: `'b: 'a` error: lifetime may not live long enough - --> $DIR/wf-static-method.rs:33:9 + --> $DIR/wf-static-method.rs:41:9 | LL | impl<'a, 'b> Evil<'a, 'b> { | -- -- lifetime `'b` defined here @@ -38,7 +38,7 @@ = help: consider adding the following bound: `'b: 'a` error: lifetime may not live long enough - --> $DIR/wf-static-method.rs:41:5 + --> $DIR/wf-static-method.rs:51:5 | LL | fn evil<'a, 'b>(b: &'b u32) -> &'a u32 { | -- -- lifetime `'b` defined here @@ -50,7 +50,7 @@ = help: consider adding the following bound: `'b: 'a` error: lifetime may not live long enough - --> $DIR/wf-static-method.rs:45:5 + --> $DIR/wf-static-method.rs:57:5 | LL | fn indirect_evil<'a, 'b>(b: &'b u32) -> &'a u32 { | -- -- lifetime `'b` defined here @@ -62,7 +62,7 @@ = help: consider adding the following bound: `'b: 'a` error: lifetime may not live long enough - --> $DIR/wf-static-method.rs:50:5 + --> $DIR/wf-static-method.rs:63:5 | LL | fn inherent_evil<'a, 'b>(b: &'b u32) -> &'a u32 { | -- -- lifetime `'b` defined here
diff --git a/src/test/ui/wf/wf-static-method.rs b/src/test/ui/wf/wf-static-method.rs index 6e805d6..83557ce 100644 --- a/src/test/ui/wf/wf-static-method.rs +++ b/src/test/ui/wf/wf-static-method.rs
@@ -4,6 +4,10 @@ // static inherent methods isn't quite working - need to // fix that before removing the check. +// revisions: base nll +// ignore-compare-mode-nll +//[nll] compile-flags: -Z borrowck=mir + trait Foo<'a, 'b, T>: Sized { fn make_me() -> Self { loop {} } fn static_evil(u: &'b u32) -> &'a u32; @@ -14,7 +18,9 @@ fn make_me() -> Self { loop {} } impl<'a, 'b> Foo<'a, 'b, Evil<'a, 'b>> for () { fn make_me() -> Self { } fn static_evil(u: &'b u32) -> &'a u32 { - u //~ ERROR E0312 + u + //[base]~^ ERROR E0312 + //[nll]~^^ ERROR lifetime may not live long enough } } @@ -23,14 +29,18 @@ fn static_evil(u: &'b u32) -> &'a u32 { impl<'a, 'b> Foo<'a, 'b, ()> for IndirectEvil<'a, 'b> { fn make_me() -> Self { IndirectEvil(None) } fn static_evil(u: &'b u32) -> &'a u32 { - let me = Self::make_me(); //~ ERROR lifetime bound not satisfied + let me = Self::make_me(); + //[base]~^ ERROR lifetime bound not satisfied + //[nll]~^^ ERROR lifetime may not live long enough loop {} // (`me` could be used for the lifetime transmute). } } impl<'a, 'b> Evil<'a, 'b> { fn inherent_evil(u: &'b u32) -> &'a u32 { - u //~ ERROR E0312 + u + //[base]~^ ERROR E0312 + //[nll]~^^ ERROR lifetime may not live long enough } } @@ -38,17 +48,21 @@ fn inherent_evil(u: &'b u32) -> &'a u32 { // *check* that they hold. fn evil<'a, 'b>(b: &'b u32) -> &'a u32 { - <()>::static_evil(b) //~ ERROR cannot infer an appropriate lifetime + <()>::static_evil(b) + //[base]~^ ERROR cannot infer an appropriate lifetime + //[nll]~^^ ERROR lifetime may not live long enough } fn indirect_evil<'a, 'b>(b: &'b u32) -> &'a u32 { <IndirectEvil>::static_evil(b) - //~^ ERROR cannot infer an appropriate lifetime + //[base]~^ ERROR cannot infer an appropriate lifetime + //[nll]~^^ ERROR lifetime may not live long enough } fn inherent_evil<'a, 'b>(b: &'b u32) -> &'a u32 { <Evil>::inherent_evil(b) - //~^ ERROR cannot infer an appropriate lifetime + //[base]~^ ERROR cannot infer an appropriate lifetime + //[nll]~^^ ERROR lifetime may not live long enough }
diff --git a/src/test/ui/wf/wf-static-type.stderr b/src/test/ui/wf/wf-static-type.stderr index c45bd57..4ae69cf 100644 --- a/src/test/ui/wf/wf-static-type.stderr +++ b/src/test/ui/wf/wf-static-type.stderr
@@ -10,6 +10,10 @@ | LL | struct IsCopy<T:Copy> { t: T } | ^^^^ required by this bound in `IsCopy` +help: consider annotating `NotCopy` with `#[derive(Copy)]` + | +LL | #[derive(Copy)] + | error: aborting due to previous error
diff --git a/src/test/ui/where-clauses/where-clauses-method-unsatisfied.stderr b/src/test/ui/where-clauses/where-clauses-method-unsatisfied.stderr index 3a4cbb6..c13552b 100644 --- a/src/test/ui/where-clauses/where-clauses-method-unsatisfied.stderr +++ b/src/test/ui/where-clauses/where-clauses-method-unsatisfied.stderr
@@ -11,6 +11,10 @@ | LL | fn equals(&self, u: &Foo<T>) -> bool where T : Eq { | ^^ required by this bound in `Foo::<T>::equals` +help: consider annotating `Bar` with `#[derive(Eq)]` + | +LL | #[derive(Eq)] + | error: aborting due to previous error
diff --git a/src/test/ui/where-clauses/where-clauses-unsatisfied.stderr b/src/test/ui/where-clauses/where-clauses-unsatisfied.stderr index ba18119..b1805a4 100644 --- a/src/test/ui/where-clauses/where-clauses-unsatisfied.stderr +++ b/src/test/ui/where-clauses/where-clauses-unsatisfied.stderr
@@ -9,6 +9,10 @@ | LL | fn equal<T>(a: &T, b: &T) -> bool where T : Eq { a == b } | ^^ required by this bound in `equal` +help: consider annotating `Struct` with `#[derive(Eq)]` + | +LL | #[derive(Eq)] + | error: aborting due to previous error
diff --git a/src/test/ui/where-clauses/where-for-self-2.stderr b/src/test/ui/where-clauses/where-for-self-2.base.stderr similarity index 89% rename from src/test/ui/where-clauses/where-for-self-2.stderr rename to src/test/ui/where-clauses/where-for-self-2.base.stderr index 6da46e2..c09610c 100644 --- a/src/test/ui/where-clauses/where-for-self-2.stderr +++ b/src/test/ui/where-clauses/where-for-self-2.base.stderr
@@ -1,5 +1,5 @@ error: implementation of `Bar` is not general enough - --> $DIR/where-for-self-2.rs:23:5 + --> $DIR/where-for-self-2.rs:27:5 | LL | foo(&X); | ^^^ implementation of `Bar` is not general enough
diff --git a/src/test/ui/where-clauses/where-for-self-2.nll.stderr b/src/test/ui/where-clauses/where-for-self-2.nll.stderr index f65db78..92d1b21 100644 --- a/src/test/ui/where-clauses/where-for-self-2.nll.stderr +++ b/src/test/ui/where-clauses/where-for-self-2.nll.stderr
@@ -1,5 +1,5 @@ error: implementation of `Bar` is not general enough - --> $DIR/where-for-self-2.rs:23:5 + --> $DIR/where-for-self-2.rs:27:5 | LL | foo(&X); | ^^^^^^^ implementation of `Bar` is not general enough
diff --git a/src/test/ui/where-clauses/where-for-self-2.rs b/src/test/ui/where-clauses/where-for-self-2.rs index 37c6954..4e4e0ec 100644 --- a/src/test/ui/where-clauses/where-for-self-2.rs +++ b/src/test/ui/where-clauses/where-for-self-2.rs
@@ -3,6 +3,10 @@ // specific lifetime is not enough to satisfy the `for<'a> ...` constraint, which // should require *all* lifetimes. +// revisions: base nll +// ignore-compare-mode-nll +//[nll] compile-flags: -Z borrowck=mir + static X: &'static u32 = &42; trait Bar {
diff --git a/src/tools/cargo b/src/tools/cargo index 1ef1e0a..e2e2ddd 160000 --- a/src/tools/cargo +++ b/src/tools/cargo
@@ -1 +1 @@ -Subproject commit 1ef1e0a12723ce9548d7da2b63119de9002bead8 +Subproject commit e2e2dddebe66dfc1403a312653557e332445308b
diff --git a/src/tools/clippy/clippy_lints/src/collapsible_match.rs b/src/tools/clippy/clippy_lints/src/collapsible_match.rs index c71e9f1..cc354b5 100644 --- a/src/tools/clippy/clippy_lints/src/collapsible_match.rs +++ b/src/tools/clippy/clippy_lints/src/collapsible_match.rs
@@ -3,11 +3,12 @@ use clippy_utils::visitors::is_local_used; use clippy_utils::{is_lang_ctor, is_unit_expr, path_to_local, peel_blocks_with_stmt, peel_ref_operators, SpanlessEq}; use if_chain::if_chain; +use rustc_errors::MultiSpan; use rustc_hir::LangItem::OptionNone; use rustc_hir::{Arm, Expr, Guard, HirId, Pat, PatKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::{MultiSpan, Span}; +use rustc_span::Span; declare_clippy_lint! { /// ### What it does @@ -129,8 +130,8 @@ fn check_arm<'tcx>( &msg, |diag| { let mut help_span = MultiSpan::from_spans(vec![binding_span, inner_then_pat.span]); - help_span.push_span_label(binding_span, "replace this binding".into()); - help_span.push_span_label(inner_then_pat.span, "with this pattern".into()); + help_span.push_span_label(binding_span, "replace this binding"); + help_span.push_span_label(inner_then_pat.span, "with this pattern"); diag.span_help(help_span, "the outer pattern can be modified to include the inner pattern"); }, );
diff --git a/src/tools/clippy/clippy_lints/src/doc.rs b/src/tools/clippy/clippy_lints/src/doc.rs index 703aa45..92cf82b 100644 --- a/src/tools/clippy/clippy_lints/src/doc.rs +++ b/src/tools/clippy/clippy_lints/src/doc.rs
@@ -11,7 +11,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sync::Lrc; use rustc_errors::emitter::EmitterWriter; -use rustc_errors::{Applicability, Handler, SuggestionStyle}; +use rustc_errors::{Applicability, Handler, MultiSpan, SuggestionStyle}; use rustc_hir as hir; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{AnonConst, Expr}; @@ -25,7 +25,7 @@ use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::def_id::LocalDefId; use rustc_span::edition::Edition; -use rustc_span::source_map::{BytePos, FilePathMapping, MultiSpan, SourceMap, Span}; +use rustc_span::source_map::{BytePos, FilePathMapping, SourceMap, Span}; use rustc_span::{sym, FileName, Pos}; use std::io; use std::ops::Range; @@ -621,7 +621,19 @@ fn has_needless_main(code: String, edition: Edition) -> bool { let filename = FileName::anon_source_code(&code); let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); - let emitter = EmitterWriter::new(Box::new(io::sink()), None, false, false, false, None, false); + let fallback_bundle = rustc_errors::fallback_fluent_bundle(false) + .expect("failed to load fallback fluent bundle"); + let emitter = EmitterWriter::new( + Box::new(io::sink()), + None, + None, + fallback_bundle, + false, + false, + false, + None, + false, + ); let handler = Handler::with_emitter(false, None, Box::new(emitter)); let sess = ParseSess::with_span_handler(handler, sm);
diff --git a/src/tools/clippy/clippy_lints/src/loops/needless_collect.rs b/src/tools/clippy/clippy_lints/src/loops/needless_collect.rs index 0619085..ddaffc7 100644 --- a/src/tools/clippy/clippy_lints/src/loops/needless_collect.rs +++ b/src/tools/clippy/clippy_lints/src/loops/needless_collect.rs
@@ -6,7 +6,7 @@ use clippy_utils::{can_move_expr_to_closure, is_trait_method, path_to_local, path_to_local_id, CaptureKind}; use if_chain::if_chain; use rustc_data_structures::fx::FxHashMap; -use rustc_errors::Applicability; +use rustc_errors::{Applicability, MultiSpan}; use rustc_hir::intravisit::{walk_block, walk_expr, Visitor}; use rustc_hir::{Block, Expr, ExprKind, HirId, HirIdSet, Local, Mutability, Node, PatKind, Stmt, StmtKind}; use rustc_lint::LateContext; @@ -14,7 +14,7 @@ use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::{self, Ty}; use rustc_span::sym; -use rustc_span::{MultiSpan, Span}; +use rustc_span::Span; const NEEDLESS_COLLECT_MSG: &str = "avoid using `collect()` when not needed"; @@ -102,7 +102,7 @@ fn check_needless_collect_indirect_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateCo // Suggest replacing iter_call with iter_replacement, and removing stmt let mut span = MultiSpan::from_span(method_name.ident.span); - span.push_span_label(iter_call.span, "the iterator could be used here instead".into()); + span.push_span_label(iter_call.span, "the iterator could be used here instead"); span_lint_hir_and_then( cx, super::NEEDLESS_COLLECT,
diff --git a/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs b/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs index ecc9acf..06209bf 100644 --- a/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs +++ b/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs
@@ -148,7 +148,7 @@ fn check_fn( if let Err((span, err)) = is_min_const_fn(cx.tcx, mir, self.msrv.as_ref()) { if cx.tcx.is_const_fn_raw(def_id.to_def_id()) { - cx.tcx.sess.span_err(span, &err); + cx.tcx.sess.span_err(span, err.as_ref()); } } else { span_lint(cx, MISSING_CONST_FOR_FN, span, "this could be a `const fn`");
diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs index 5eb7b0f..d29d07d 100644 --- a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs +++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
@@ -235,11 +235,12 @@ fn check_fn( for (span, suggestion) in clone_spans { diag.span_suggestion( span, - &snippet_opt(cx, span) + snippet_opt(cx, span) .map_or( "change the call to".into(), |x| Cow::from(format!("change `{}` to", x)), - ), + ) + .as_ref(), suggestion.into(), Applicability::Unspecified, ); @@ -264,11 +265,12 @@ fn check_fn( for (span, suggestion) in clone_spans { diag.span_suggestion( span, - &snippet_opt(cx, span) + snippet_opt(cx, span) .map_or( "change the call to".into(), |x| Cow::from(format!("change `{}` to", x)) - ), + ) + .as_ref(), suggestion.into(), Applicability::Unspecified, );
diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs index 9d43138..5f453dc 100644 --- a/src/tools/clippy/clippy_lints/src/ptr.rs +++ b/src/tools/clippy/clippy_lints/src/ptr.rs
@@ -5,7 +5,7 @@ use clippy_utils::ty::expr_sig; use clippy_utils::{get_expr_use_or_unification_node, is_lint_allowed, path_def_id, path_to_local, paths}; use if_chain::if_chain; -use rustc_errors::Applicability; +use rustc_errors::{Applicability, MultiSpan}; use rustc_hir::def_id::DefId; use rustc_hir::hir_id::HirIdMap; use rustc_hir::intravisit::{walk_expr, Visitor}; @@ -19,8 +19,8 @@ use rustc_middle::ty::{self, Ty}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; +use rustc_span::sym; use rustc_span::symbol::Symbol; -use rustc_span::{sym, MultiSpan}; use std::fmt; use std::iter;
diff --git a/src/tools/clippy/clippy_utils/src/diagnostics.rs b/src/tools/clippy/clippy_utils/src/diagnostics.rs index 625a538..b142397 100644 --- a/src/tools/clippy/clippy_utils/src/diagnostics.rs +++ b/src/tools/clippy/clippy_utils/src/diagnostics.rs
@@ -8,10 +8,10 @@ //! Thank you! //! ~The `INTERNAL_METADATA_COLLECTOR` lint -use rustc_errors::{emitter::MAX_SUGGESTION_HIGHLIGHT_LINES, Applicability, Diagnostic}; +use rustc_errors::{emitter::MAX_SUGGESTION_HIGHLIGHT_LINES, Applicability, Diagnostic, MultiSpan}; use rustc_hir::HirId; use rustc_lint::{LateContext, Lint, LintContext}; -use rustc_span::source_map::{MultiSpan, Span}; +use rustc_span::source_map::Span; use std::env; fn docs_link(diag: &mut Diagnostic, lint: &'static Lint) { @@ -155,7 +155,13 @@ pub fn span_lint_and_then<C, S, F>(cx: &C, lint: &'static Lint, sp: S, msg: &str }); } -pub fn span_lint_hir(cx: &LateContext<'_>, lint: &'static Lint, hir_id: HirId, sp: Span, msg: &str) { +pub fn span_lint_hir( + cx: &LateContext<'_>, + lint: &'static Lint, + hir_id: HirId, + sp: Span, + msg: &str, +) { cx.tcx.struct_span_lint_hir(lint, hir_id, sp, |diag| { let mut diag = diag.build(msg); docs_link(&mut diag, lint); @@ -272,9 +278,14 @@ pub fn span_lint_and_sugg_for_edges( let sugg_lines_count = sugg.lines().count(); if sugg_lines_count > MAX_SUGGESTION_HIGHLIGHT_LINES { let sm = cx.sess().source_map(); - if let (Ok(line_upper), Ok(line_bottom)) = (sm.lookup_line(sp.lo()), sm.lookup_line(sp.hi())) { + if let (Ok(line_upper), Ok(line_bottom)) = + (sm.lookup_line(sp.lo()), sm.lookup_line(sp.hi())) + { let split_idx = MAX_SUGGESTION_HIGHLIGHT_LINES / 2; - let span_upper = sm.span_until_char(sp.with_hi(line_upper.sf.lines[line_upper.line + split_idx]), '\n'); + let span_upper = sm.span_until_char( + sp.with_hi(line_upper.sf.lines[line_upper.line + split_idx]), + '\n', + ); let span_bottom = sp.with_lo(line_bottom.sf.lines[line_bottom.line - split_idx]); let sugg_lines_vec = sugg.lines().collect::<Vec<&str>>();
diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs index 855a6a6..bc1b0d7 100644 --- a/src/tools/clippy/src/driver.rs +++ b/src/tools/clippy/src/driver.rs
@@ -165,9 +165,13 @@ fn report_clippy_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) { // Separate the output with an empty line eprintln!(); + let fallback_bundle = rustc_errors::fallback_fluent_bundle(false) + .expect("failed to load fallback fluent bundle"); let emitter = Box::new(rustc_errors::emitter::EmitterWriter::stderr( rustc_errors::ColorConfig::Auto, None, + None, + fallback_bundle, false, false, None, @@ -191,7 +195,7 @@ fn report_clippy_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) { ]; for note in &xs { - handler.note_without_error(note); + handler.note_without_error(note.as_ref()); } // If backtraces are enabled, also print the query stack
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 1bdea33..8a72b44 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs
@@ -806,8 +806,7 @@ pub fn make_test_description<R: Read>( cfg: Option<&str>, ) -> test::TestDesc { let mut ignore = false; - #[cfg(not(bootstrap))] - let ignore_message: Option<String> = None; + let ignore_message = None; let mut should_fail = false; let rustc_has_profiler_support = env::var_os("RUSTC_PROFILER_SUPPORT").is_some(); @@ -879,7 +878,6 @@ pub fn make_test_description<R: Read>( test::TestDesc { name, ignore, - #[cfg(not(bootstrap))] ignore_message, should_panic, compile_fail: false,
diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index 503b624..8c1f28f 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs
@@ -744,12 +744,10 @@ fn make_test_name( testpaths: &TestPaths, revision: Option<&String>, ) -> test::TestName { - // Convert a complete path to something like - // - // ui/foo/bar/baz.rs - let path = PathBuf::from(config.src_base.file_name().unwrap()) - .join(&testpaths.relative_dir) - .join(&testpaths.file.file_name().unwrap()); + // Print the name of the file, relative to the repository root. + // `src_base` looks like `/path/to/rust/src/test/ui` + let root_directory = config.src_base.parent().unwrap().parent().unwrap().parent().unwrap(); + let path = testpaths.file.strip_prefix(root_directory).unwrap(); let debugger = match config.debugger { Some(d) => format!("-{}", d), None => String::new(),
diff --git a/src/tools/error_index_generator/build.rs b/src/tools/error_index_generator/build.rs index caae8c6..70b00b3 100644 --- a/src/tools/error_index_generator/build.rs +++ b/src/tools/error_index_generator/build.rs
@@ -7,7 +7,6 @@ fn main() { // Note that we could skip one of the .. but this ensures we at least loosely find the right // directory. let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); - let dest = out_dir.join("error_codes.rs"); let error_codes_path = "../../../compiler/rustc_error_codes/src/error_codes.rs"; @@ -29,35 +28,4 @@ fn main() { let md_content = fs::read_to_string(entry.path()).unwrap(); fs::write(&out_dir.join(entry.file_name()), &md_content).unwrap(); } - - let mut all = String::new(); - all.push_str( - r###" -fn register_all() -> Vec<(&'static str, Option<&'static str>)> { - let mut long_codes: Vec<(&'static str, Option<&'static str>)> = Vec::new(); - macro_rules! register_diagnostics { - ($($ecode:ident: $message:expr,)*) => ( - register_diagnostics!{$($ecode:$message,)* ;} - ); - - ($($ecode:ident: $message:expr,)* ; $($code:ident,)*) => ( - $( - {long_codes.extend([ - (stringify!($ecode), Some($message)), - ].iter());} - )* - $( - {long_codes.extend([ - stringify!($code), - ].iter().cloned().map(|s| (s, None)).collect::<Vec<_>>());} - )* - ) - } -"###, - ); - all.push_str(r#"include!(concat!(env!("OUT_DIR"), "/all_error_codes.rs"));"#); - all.push_str("\nlong_codes\n"); - all.push_str("}\n"); - - fs::write(&dest, all).unwrap(); }
diff --git a/src/tools/error_index_generator/main.rs b/src/tools/error_index_generator/main.rs index 39498c9..51ed1b5 100644 --- a/src/tools/error_index_generator/main.rs +++ b/src/tools/error_index_generator/main.rs
@@ -277,4 +277,26 @@ fn main() { } } -include!(concat!(env!("OUT_DIR"), "/error_codes.rs")); +fn register_all() -> Vec<(&'static str, Option<&'static str>)> { + let mut long_codes: Vec<(&'static str, Option<&'static str>)> = Vec::new(); + macro_rules! register_diagnostics { + ($($ecode:ident: $message:expr,)*) => ( + register_diagnostics!{$($ecode:$message,)* ;} + ); + + ($($ecode:ident: $message:expr,)* ; $($code:ident,)*) => ( + $( + {long_codes.extend([ + (stringify!($ecode), Some($message)), + ].iter());} + )* + $( + {long_codes.extend([ + stringify!($code), + ].iter().cloned().map(|s| (s, None)).collect::<Vec<_>>());} + )* + ) + } + include!(concat!(env!("OUT_DIR"), "/all_error_codes.rs")); + long_codes +}
diff --git a/src/tools/rust-analyzer b/src/tools/rust-analyzer index bc08b8e..46d7ee6 160000 --- a/src/tools/rust-analyzer +++ b/src/tools/rust-analyzer
@@ -1 +1 @@ -Subproject commit bc08b8eff3f8e4da7c448d7b7f6461938c817a60 +Subproject commit 46d7ee68f26285db26b2640f2c07d6332380c756
diff --git a/src/tools/rustfmt/src/parse/session.rs b/src/tools/rustfmt/src/parse/session.rs index 7571e6d..7125b2e 100644 --- a/src/tools/rustfmt/src/parse/session.rs +++ b/src/tools/rustfmt/src/parse/session.rs
@@ -33,6 +33,12 @@ fn source_map(&self) -> Option<&Lrc<SourceMap>> { None } fn emit_diagnostic(&mut self, _db: &Diagnostic) {} + fn fluent_bundle(&self) -> Option<&Lrc<rustc_errors::FluentBundle>> { + None + } + fn fallback_fluent_bundle(&self) -> &Lrc<rustc_errors::FluentBundle> { + panic!("silent emitter attempted to translate a diagnostic"); + } } fn silent_emitter() -> Box<dyn Emitter + Send> { @@ -82,6 +88,14 @@ fn emit_diagnostic(&mut self, db: &Diagnostic) { } self.handle_non_ignoreable_error(db); } + + fn fluent_bundle(&self) -> Option<&Lrc<rustc_errors::FluentBundle>> { + self.emitter.fluent_bundle() + } + + fn fallback_fluent_bundle(&self) -> &Lrc<rustc_errors::FluentBundle> { + self.emitter.fallback_fluent_bundle() + } } fn default_handler( @@ -100,9 +114,13 @@ fn default_handler( let emitter = if hide_parse_errors { silent_emitter() } else { + let fallback_bundle = rustc_errors::fallback_fluent_bundle(false) + .expect("failed to load fallback fluent bundle"); Box::new(EmitterWriter::stderr( color_cfg, Some(source_map.clone()), + None, + fallback_bundle, false, false, None, @@ -313,7 +331,8 @@ mod emitter { use super::*; use crate::config::IgnoreList; use crate::utils::mk_sp; - use rustc_span::{FileName as SourceMapFileName, MultiSpan, RealFileName}; + use rustc_errors::MultiSpan; + use rustc_span::{FileName as SourceMapFileName, RealFileName}; use std::path::PathBuf; use std::sync::atomic::AtomicU32; @@ -328,6 +347,12 @@ fn source_map(&self) -> Option<&Lrc<SourceMap>> { fn emit_diagnostic(&mut self, _db: &Diagnostic) { self.num_emitted_errors.fetch_add(1, Ordering::Release); } + fn fluent_bundle(&self) -> Option<&Lrc<rustc_errors::FluentBundle>> { + None + } + fn fallback_fluent_bundle(&self) -> &Lrc<rustc_errors::FluentBundle> { + panic!("test emitter attempted to translate a diagnostic"); + } } fn build_diagnostic(level: DiagnosticLevel, span: Option<MultiSpan>) -> Diagnostic {
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index ab4be43..ea6e01e 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs
@@ -38,6 +38,8 @@ ("bitmaps", "MPL-2.0+"), // cargo via im-rc ("instant", "BSD-3-Clause"), // rustc_driver/tracing-subscriber/parking_lot ("snap", "BSD-3-Clause"), // rustc + ("fluent-langneg", "Apache-2.0"), // rustc (fluent translations) + ("self_cell", "Apache-2.0"), // rustc (fluent translations) // FIXME: this dependency violates the documentation comment above: ("fortanix-sgx-abi", "MPL-2.0"), // libstd but only for `sgx` target ]; @@ -113,6 +115,9 @@ "filetime", "fixedbitset", "flate2", + "fluent-bundle", + "fluent-langneg", + "fluent-syntax", "fortanix-sgx-abi", "generic-array", "getopts", @@ -125,6 +130,8 @@ "if_chain", "indexmap", "instant", + "intl-memoizer", + "intl_pluralrules", "itertools", "itoa", "jobserver", @@ -157,6 +164,7 @@ "pkg-config", "polonius-engine", "ppv-lite86", + "proc-macro-hack", "proc-macro2", "psm", "punycode", @@ -184,6 +192,7 @@ "ryu", "scoped-tls", "scopeguard", + "self_cell", "semver", "serde", "serde_derive", @@ -200,9 +209,12 @@ "tempfile", "termcolor", "termize", + "thiserror", + "thiserror-impl", "thorin-dwp", "thread_local", "time", + "tinystr", "tinyvec", "tracing", "tracing-attributes", @@ -210,11 +222,16 @@ "tracing-log", "tracing-subscriber", "tracing-tree", + "type-map", "typenum", "unic-char-property", "unic-char-range", "unic-common", "unic-emoji-char", + "unic-langid", + "unic-langid-impl", + "unic-langid-macros", + "unic-langid-macros-impl", "unic-ucd-version", "unicode-normalization", "unicode-script", @@ -228,7 +245,8 @@ "winapi-i686-pc-windows-gnu", "winapi-util", "winapi-x86_64-pc-windows-gnu", - // this is a false-positive: it's only used by rustfmt, but because it's enabled through a feature, tidy thinks it's used by rustc as well. + // this is a false-positive: it's only used by rustfmt, but because it's enabled through a + // feature, tidy thinks it's used by rustc as well. "yansi-term", ];
diff --git a/src/version b/src/version index 91951fd..76d0536 100644 --- a/src/version +++ b/src/version
@@ -1 +1 @@ -1.61.0 +1.62.0