| author | bors <bors@rust-lang.org> 2026-04-13 18:32:47 UTC |
| committer | bors <bors@rust-lang.org> 2026-04-13 18:32:47 UTC |
| log | 17584a181979f04f2aaad867332c22db1caa511a |
| tree | 740d16a404e0af53ad474216d9e824ac8e54472c |
| parent | a72e2a71d8fbcbc46cdd18784e2ab2c32cbd9c93 |
| parent | 9f11d53cd30e38a02e85c0f046a3f76b2ef6fe96 |
Rollup of 19 pull requests
Successful merges:
- rust-lang/rust#155162 (relnotes for 1.95)
- rust-lang/rust#140763 (Change codegen of LLVM intrinsics to be name-based, and add llvm linkage support for `bf16(xN)` and `i1xN`)
- rust-lang/rust#153604 (Fix thread::available_parallelism on WASI targets with threads)
- rust-lang/rust#154193 (Implement EII for statics)
- rust-lang/rust#154389 (Add more robust handling of nested query cycles)
- rust-lang/rust#154435 (resolve: Some import resolution cleanups)
- rust-lang/rust#155236 (Normalize individual predicate of `InstantiatedPredicates` inside `predicates_for_generics`)
- rust-lang/rust#155243 (cg_ssa: transmute between scalable vectors)
- rust-lang/rust#153941 (tests/debuginfo/basic-stepping.rs: Explain why all lines are not steppable)
- rust-lang/rust#154587 (Add --verbose-run-make-subprocess-output flag to suppress verbose run-make output for passing tests)
- rust-lang/rust#154624 (Make `DerefPure` dyn-incompatible)
- rust-lang/rust#154929 (Add `const Default` impls for `LazyCell` and `LazyLock`)
- rust-lang/rust#154944 (Small refactor of `arena_cache` query values)
- rust-lang/rust#155055 (UI automation)
- rust-lang/rust#155062 (Move tests from `tests/ui/issues/` to appropriate directories)
- rust-lang/rust#155131 (Stabilize feature `uint_bit_width`)
- rust-lang/rust#155147 (Stabilize feature `int_lowest_highest_one`)
- rust-lang/rust#155174 (Improve emission of `UnknownDiagnosticAttribute` lint)
- rust-lang/rust#155194 (Fix manpage version replacement and use verbose version)188 files changed, 2658 insertions(+), 782 deletions(-)
RELEASES.md+131| ... | ... | @@ -1,3 +1,134 @@ |
| 1 | Version 1.95 (2026-04-16) | |
| 2 | ========================== | |
| 3 | ||
| 4 | <a id="1.95-Language"></a> | |
| 5 | ||
| 6 | Language | |
| 7 | -------- | |
| 8 | - [Stabilize `if let` guards on match arms](https://github.com/rust-lang/rust/pull/141295) | |
| 9 | - [`irrefutable_let_patterns` lint no longer lints on let chains](https://github.com/rust-lang/rust/pull/146832) | |
| 10 | - [Support importing path-segment keywords with renaming](https://github.com/rust-lang/rust/pull/146972) | |
| 11 | - [Stabilize inline assembly for PowerPC and PowerPC64](https://github.com/rust-lang/rust/pull/147996) | |
| 12 | - [const-eval: be more consistent in the behavior of padding during typed copies](https://github.com/rust-lang/rust/pull/148967) | |
| 13 | - [Const blocks are no longer evaluated to determine if expressions involving fallible operations can implicitly be constant-promoted.](https://github.com/rust-lang/rust/pull/150557). Expressions whose ability to implicitly be promoted would depend on the result of a const block are no longer implicitly promoted. | |
| 14 | - [Make operational semantics of pattern matching independent of crate and module](https://github.com/rust-lang/rust/pull/150681) | |
| 15 | ||
| 16 | ||
| 17 | <a id="1.95-Compiler"></a> | |
| 18 | ||
| 19 | Compiler | |
| 20 | -------- | |
| 21 | - [Stabilize `--remap-path-scope` for controlling the scoping of how paths get remapped in the resulting binary](https://github.com/rust-lang/rust/pull/147611) | |
| 22 | ||
| 23 | ||
| 24 | <a id="1.95-Platform-Support"></a> | |
| 25 | ||
| 26 | Platform Support | |
| 27 | ---------------- | |
| 28 | - [Promote `powerpc64-unknown-linux-musl` to Tier 2 with host tools](https://github.com/rust-lang/rust/pull/149962) | |
| 29 | - [Promote `aarch64-apple-tvos` to Tier 2](https://github.com/rust-lang/rust/pull/152021) | |
| 30 | - [Promote `aarch64-apple-tvos-sim` to Tier 2](https://github.com/rust-lang/rust/pull/152021) | |
| 31 | - [Promote `aarch64-apple-watchos` to Tier 2](https://github.com/rust-lang/rust/pull/152021) | |
| 32 | - [Promote `aarch64-apple-watchos-sim` to Tier 2](https://github.com/rust-lang/rust/pull/152021) | |
| 33 | - [Promote `aarch64-apple-visionos` to Tier 2](https://github.com/rust-lang/rust/pull/152021) | |
| 34 | - [Promote `aarch64-apple-visionos-sim` to Tier 2](https://github.com/rust-lang/rust/pull/152021) | |
| 35 | ||
| 36 | ||
| 37 | Refer to Rust's [platform support page][platform-support-doc] | |
| 38 | for more information on Rust's tiered platform support. | |
| 39 | ||
| 40 | [platform-support-doc]: https://doc.rust-lang.org/rustc/platform-support.html | |
| 41 | ||
| 42 | <a id="1.95-Libraries"></a> | |
| 43 | ||
| 44 | Libraries | |
| 45 | --------- | |
| 46 | - [`thread::scope`: document how join interacts with TLS destructors](https://github.com/rust-lang/rust/pull/149482) | |
| 47 | - [Speed up `str::contains` on aarch64 targets with `neon` target feature enabled by default](https://github.com/rust-lang/rust/pull/152176) | |
| 48 | ||
| 49 | ||
| 50 | <a id="1.95-Stabilized-APIs"></a> | |
| 51 | ||
| 52 | Stabilized APIs | |
| 53 | --------------- | |
| 54 | ||
| 55 | - [`MaybeUninit<[T; N]>: From<[MaybeUninit<T>; N]>`](https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#impl-From%3CMaybeUninit%3C%5BT;+N%5D%3E%3E-for-%5BMaybeUninit%3CT%3E;+N%5D) | |
| 56 | - [`MaybeUninit<[T; N]>: AsRef<[MaybeUninit<T>; N]>`](https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#impl-AsRef%3C%5BMaybeUninit%3CT%3E;+N%5D%3E-for-MaybeUninit%3C%5BT;+N%5D%3E) | |
| 57 | - [`MaybeUninit<[T; N]>: AsRef<[MaybeUninit<T>]>`](https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#impl-AsRef%3C%5BMaybeUninit%3CT%3E%5D%3E-for-MaybeUninit%3C%5BT;+N%5D%3E) | |
| 58 | - [`MaybeUninit<[T; N]>: AsMut<[MaybeUninit<T>; N]>`](https://doc.rust-lang.org/beta/std/mem/union.MaybeUninit.html#impl-AsMut%3C%5BMaybeUninit%3CT%3E;+N%5D%3E-for-MaybeUninit%3C%5BT;+N%5D%3E) | |
| 59 | - [`MaybeUninit<[T; N]>: AsMut<[MaybeUninit<T>]>`](https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#impl-AsMut%3C%5BMaybeUninit%3CT%3E%5D%3E-for-MaybeUninit%3C%5BT;+N%5D%3E) | |
| 60 | - [`[MaybeUninit<T>; N]: From<MaybeUninit<[T; N]>>`](https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#impl-From%3C%5BMaybeUninit%3CT%3E;+N%5D%3E-for-MaybeUninit%3C%5BT;+N%5D%3E) | |
| 61 | - [`Cell<[T; N]>: AsRef<[Cell<T>; N]>`](https://doc.rust-lang.org/stable/std/cell/struct.Cell.html#impl-AsRef%3C%5BCell%3CT%3E;+N%5D%3E-for-Cell%3C%5BT;+N%5D%3E) | |
| 62 | - [`Cell<[T; N]>: AsRef<[Cell<T>]>`](https://doc.rust-lang.org/stable/std/cell/struct.Cell.html#impl-AsRef%3C%5BCell%3CT%3E%5D%3E-for-Cell%3C%5BT;+N%5D%3E) | |
| 63 | - [`Cell<[T]>: AsRef<[Cell<T>]>`](https://doc.rust-lang.org/stable/std/cell/struct.Cell.html#impl-AsRef%3C%5BCell%3CT%3E%5D%3E-for-Cell%3C%5BT%5D%3E) | |
| 64 | - [`bool: TryFrom<{integer}>`](https://doc.rust-lang.org/stable/std/primitive.bool.html#impl-TryFrom%3Cu128%3E-for-bool) | |
| 65 | - [`AtomicPtr::update`](https://doc.rust-lang.org/stable/std/sync/atomic/struct.AtomicPtr.html#method.update) | |
| 66 | - [`AtomicPtr::try_update`](https://doc.rust-lang.org/stable/std/sync/atomic/struct.AtomicPtr.html#method.try_update) | |
| 67 | - [`AtomicBool::update`](https://doc.rust-lang.org/stable/std/sync/atomic/struct.AtomicBool.html#method.update) | |
| 68 | - [`AtomicBool::try_update`](https://doc.rust-lang.org/stable/std/sync/atomic/struct.AtomicBool.html#method.try_update) | |
| 69 | - [`AtomicIn::update`](https://doc.rust-lang.org/stable/std/sync/atomic/struct.AtomicIsize.html#method.update) | |
| 70 | - [`AtomicIn::try_update`](https://doc.rust-lang.org/stable/std/sync/atomic/struct.AtomicIsize.html#method.try_update) | |
| 71 | - [`AtomicUn::update`](https://doc.rust-lang.org/stable/std/sync/atomic/struct.AtomicUsize.html#method.update) | |
| 72 | - [`AtomicUn::try_update`](https://doc.rust-lang.org/stable/std/sync/atomic/struct.AtomicUsize.html#method.try_update) | |
| 73 | - [`cfg_select!`](https://doc.rust-lang.org/stable/std/macro.cfg_select.html) | |
| 74 | - [`mod core::range`](https://doc.rust-lang.org/stable/core/range/index.html) | |
| 75 | - [`core::range::RangeInclusive`](https://doc.rust-lang.org/stable/core/range/struct.RangeInclusive.html) | |
| 76 | - [`core::range::RangeInclusiveIter`](https://doc.rust-lang.org/stable/core/range/struct.RangeInclusiveIter.html) | |
| 77 | - [`core::hint::cold_path`](https://doc.rust-lang.org/stable/core/hint/fn.cold_path.html) | |
| 78 | - [`<*const T>::as_ref_unchecked`](https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.as_ref_unchecked) | |
| 79 | - [`<*mut T>::as_ref_unchecked`](https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.as_ref_unchecked-1) | |
| 80 | - [`<*mut T>::as_mut_unchecked`](https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.as_mut_unchecked) | |
| 81 | ||
| 82 | ||
| 83 | These previously stable APIs are now stable in const contexts: | |
| 84 | ||
| 85 | - [`fmt::from_fn`](https://doc.rust-lang.org/stable/std/fmt/fn.from_fn.html) | |
| 86 | - [`ControlFlow::is_break`](https://doc.rust-lang.org/stable/core/ops/enum.ControlFlow.html#method.is_break) | |
| 87 | - [`ControlFlow::is_continue`](https://doc.rust-lang.org/stable/core/ops/enum.ControlFlow.html#method.is_continue) | |
| 88 | ||
| 89 | ||
| 90 | <a id="1.95-Cargo"></a> | |
| 91 | ||
| 92 | Cargo | |
| 93 | ----- | |
| 94 | - [docs(report): enhance man pages for `cargo report *`](https://github.com/rust-lang/cargo/pull/16430/)<a id="1.95-Rustdoc"></a> | |
| 95 | ||
| 96 | Rustdoc | |
| 97 | ----- | |
| 98 | - [In search results, rank unstable items lower](https://github.com/rust-lang/rust/pull/149460) | |
| 99 | - [Add new "hide deprecated items" setting in rustdoc](https://github.com/rust-lang/rust/pull/151091) | |
| 100 | <a id="1.95-Compatibility-Notes"></a> | |
| 101 | ||
| 102 | Compatibility Notes | |
| 103 | ------------------- | |
| 104 | - [Array coercions may now result in less inference constraints than before](https://github.com/rust-lang/rust/pull/140283) | |
| 105 | - Importing `$crate` without renaming, i.e. `use $crate::{self};`, is now no longer permitted due to stricter error checking for `self` imports. | |
| 106 | - [const-eval: be more consistent in the behavior of padding during typed copies.](https://github.com/rust-lang/rust/pull/148967) | |
| 107 | In very rare cases, this may cause compilation errors due to bytes from parts of a pointer ending up in the padding bytes of a `const` or `static`. | |
| 108 | - [A future-incompatibility warning lint `ambiguous_glob_imported_traits` is now reported when using an ambiguously glob imported trait](https://github.com/rust-lang/rust/pull/149058) | |
| 109 | - [Check lifetime bounds of types mentioning only type parameters](https://github.com/rust-lang/rust/pull/149389) | |
| 110 | - [Report more visibility-related ambiguous import errors](https://github.com/rust-lang/rust/pull/149596) | |
| 111 | - [Deprecate `Eq::assert_receiver_is_total_eq` and emit future compatibility warnings on manual impls](https://github.com/rust-lang/rust/pull/149978) | |
| 112 | - [powerpc64: Use the ELF ABI version set in target spec instead of guessing](https://github.com/rust-lang/rust/pull/150468) (fixes the ELF ABI used by the OpenBSD target) | |
| 113 | - Matching on a `#[non_exhaustive]` enum [now reads the discriminant, even if the enum has only one variant](https://github.com/rust-lang/rust/pull/150681). This can cause closures to capture values that they previously wouldn't. | |
| 114 | - `mut ref` and `mut ref mut` patterns, part of the unstable [Match Ergonomics 2024 RFC](https://github.com/rust-lang/rust/issues/123076), were accidentally allowed on stable within struct pattern field shorthand. These patterns are now correctly feature-gated as unstable in this position. | |
| 115 | - [Add future-compatibility warning for derive helper attributes which conflict with built-in attributes](https://github.com/rust-lang/rust/pull/151152) | |
| 116 | - [JSON target specs](https://doc.rust-lang.org/rustc/targets/custom.html) have been destabilized and now require `-Z unstable-options` to use. Previously, they could not be used without the standard library, which has no stable build mechanism. In preparation for the `build-std` project adding that support, JSON target specs are being proactively gated to ensure they remain unstable even if `build-std` is stabilized. Cargo now includes the `-Z json-target-spec` CLI flag to automatically pass `-Z unstable-options` to the compiler when needed. See [#150151](https://github.com/rust-lang/rust/pull/150151), [#151534](https://github.com/rust-lang/rust/pull/150151), and [rust-lang/cargo#16557](https://github.com/rust-lang/cargo/pull/16557). | |
| 117 | - [The arguments of `#[feature]` attributes on invalid targets are now checked](https://github.com/rust-lang/rust/issues/153764) | |
| 118 | ||
| 119 | ||
| 120 | <a id="1.95-Internal-Changes"></a> | |
| 121 | ||
| 122 | Internal Changes | |
| 123 | ---------------- | |
| 124 | ||
| 125 | These changes do not affect any public interfaces of Rust, but they represent | |
| 126 | significant improvements to the performance or internals of rustc and related | |
| 127 | tools. | |
| 128 | ||
| 129 | - [Update to LLVM 22](https://github.com/rust-lang/rust/pull/150722) | |
| 130 | ||
| 131 | ||
| 1 | 132 | Version 1.94.1 (2026-03-26) |
| 2 | 133 | =========================== |
| 3 | 134 |
compiler/rustc_ast/src/ast.rs+7| ... | ... | @@ -3918,6 +3918,13 @@ pub struct StaticItem { |
| 3918 | 3918 | pub mutability: Mutability, |
| 3919 | 3919 | pub expr: Option<Box<Expr>>, |
| 3920 | 3920 | pub define_opaque: Option<ThinVec<(NodeId, Path)>>, |
| 3921 | ||
| 3922 | /// This static is an implementation of an externally implementable item (EII). | |
| 3923 | /// This means, there was an EII declared somewhere and this static is the | |
| 3924 | /// implementation that should be used for the declaration. | |
| 3925 | /// | |
| 3926 | /// For statics, there may be at most one `EiiImpl`, but this is a `ThinVec` to make usages of this field nicer. | |
| 3927 | pub eii_impls: ThinVec<EiiImpl>, | |
| 3921 | 3928 | } |
| 3922 | 3929 | |
| 3923 | 3930 | #[derive(Clone, Encodable, Decodable, Debug, Walkable)] |
compiler/rustc_ast_lowering/src/item.rs+10-3| ... | ... | @@ -213,8 +213,14 @@ impl<'hir, R: ResolverAstLoweringExt<'hir>> LoweringContext<'_, 'hir, R> { |
| 213 | 213 | i: &ItemKind, |
| 214 | 214 | ) -> Vec<hir::Attribute> { |
| 215 | 215 | match i { |
| 216 | ItemKind::Fn(box Fn { eii_impls, .. }) if eii_impls.is_empty() => Vec::new(), | |
| 217 | ItemKind::Fn(box Fn { eii_impls, .. }) => { | |
| 216 | ItemKind::Fn(box Fn { eii_impls, .. }) | |
| 217 | | ItemKind::Static(box StaticItem { eii_impls, .. }) | |
| 218 | if eii_impls.is_empty() => | |
| 219 | { | |
| 220 | Vec::new() | |
| 221 | } | |
| 222 | ItemKind::Fn(box Fn { eii_impls, .. }) | |
| 223 | | ItemKind::Static(box StaticItem { eii_impls, .. }) => { | |
| 218 | 224 | vec![hir::Attribute::Parsed(AttributeKind::EiiImpls( |
| 219 | 225 | eii_impls.iter().map(|i| self.lower_eii_impl(i)).collect(), |
| 220 | 226 | ))] |
| ... | ... | @@ -226,7 +232,6 @@ impl<'hir, R: ResolverAstLoweringExt<'hir>> LoweringContext<'_, 'hir, R> { |
| 226 | 232 | |
| 227 | 233 | ItemKind::ExternCrate(..) |
| 228 | 234 | | ItemKind::Use(..) |
| 229 | | ItemKind::Static(..) | |
| 230 | 235 | | ItemKind::Const(..) |
| 231 | 236 | | ItemKind::ConstBlock(..) |
| 232 | 237 | | ItemKind::Mod(..) |
| ... | ... | @@ -302,6 +307,7 @@ impl<'hir, R: ResolverAstLoweringExt<'hir>> LoweringContext<'_, 'hir, R> { |
| 302 | 307 | mutability: m, |
| 303 | 308 | expr: e, |
| 304 | 309 | define_opaque, |
| 310 | eii_impls: _, | |
| 305 | 311 | }) => { |
| 306 | 312 | let ident = self.lower_ident(*ident); |
| 307 | 313 | let ty = self |
| ... | ... | @@ -826,6 +832,7 @@ impl<'hir, R: ResolverAstLoweringExt<'hir>> LoweringContext<'_, 'hir, R> { |
| 826 | 832 | expr: _, |
| 827 | 833 | safety, |
| 828 | 834 | define_opaque, |
| 835 | eii_impls: _, | |
| 829 | 836 | }) => { |
| 830 | 837 | let ty = self |
| 831 | 838 | .lower_ty_alloc(ty, ImplTraitContext::Disallowed(ImplTraitPosition::StaticTy)); |
compiler/rustc_ast_pretty/src/pprust/state/item.rs+26-12| ... | ... | @@ -43,6 +43,7 @@ impl<'a> State<'a> { |
| 43 | 43 | expr, |
| 44 | 44 | safety, |
| 45 | 45 | define_opaque, |
| 46 | eii_impls, | |
| 46 | 47 | }) => self.print_item_const( |
| 47 | 48 | *ident, |
| 48 | 49 | Some(*mutability), |
| ... | ... | @@ -53,6 +54,7 @@ impl<'a> State<'a> { |
| 53 | 54 | *safety, |
| 54 | 55 | ast::Defaultness::Implicit, |
| 55 | 56 | define_opaque.as_deref(), |
| 57 | eii_impls, | |
| 56 | 58 | ), |
| 57 | 59 | ast::ForeignItemKind::TyAlias(box ast::TyAlias { |
| 58 | 60 | defaultness, |
| ... | ... | @@ -93,8 +95,12 @@ impl<'a> State<'a> { |
| 93 | 95 | safety: ast::Safety, |
| 94 | 96 | defaultness: ast::Defaultness, |
| 95 | 97 | define_opaque: Option<&[(ast::NodeId, ast::Path)]>, |
| 98 | eii_impls: &[EiiImpl], | |
| 96 | 99 | ) { |
| 97 | 100 | self.print_define_opaques(define_opaque); |
| 101 | for eii_impl in eii_impls { | |
| 102 | self.print_eii_impl(eii_impl); | |
| 103 | } | |
| 98 | 104 | let (cb, ib) = self.head(""); |
| 99 | 105 | self.print_visibility(vis); |
| 100 | 106 | self.print_safety(safety); |
| ... | ... | @@ -191,6 +197,7 @@ impl<'a> State<'a> { |
| 191 | 197 | mutability: mutbl, |
| 192 | 198 | expr: body, |
| 193 | 199 | define_opaque, |
| 200 | eii_impls, | |
| 194 | 201 | }) => { |
| 195 | 202 | self.print_safety(*safety); |
| 196 | 203 | self.print_item_const( |
| ... | ... | @@ -203,6 +210,7 @@ impl<'a> State<'a> { |
| 203 | 210 | ast::Safety::Default, |
| 204 | 211 | ast::Defaultness::Implicit, |
| 205 | 212 | define_opaque.as_deref(), |
| 213 | eii_impls, | |
| 206 | 214 | ); |
| 207 | 215 | } |
| 208 | 216 | ast::ItemKind::ConstBlock(ast::ConstBlockItem { id: _, span: _, block }) => { |
| ... | ... | @@ -234,6 +242,7 @@ impl<'a> State<'a> { |
| 234 | 242 | ast::Safety::Default, |
| 235 | 243 | *defaultness, |
| 236 | 244 | define_opaque.as_deref(), |
| 245 | &[], | |
| 237 | 246 | ); |
| 238 | 247 | } |
| 239 | 248 | ast::ItemKind::Fn(func) => { |
| ... | ... | @@ -602,6 +611,7 @@ impl<'a> State<'a> { |
| 602 | 611 | ast::Safety::Default, |
| 603 | 612 | *defaultness, |
| 604 | 613 | define_opaque.as_deref(), |
| 614 | &[], | |
| 605 | 615 | ); |
| 606 | 616 | } |
| 607 | 617 | ast::AssocItemKind::Type(box ast::TyAlias { |
| ... | ... | @@ -703,18 +713,8 @@ impl<'a> State<'a> { |
| 703 | 713 | |
| 704 | 714 | self.print_define_opaques(define_opaque.as_deref()); |
| 705 | 715 | |
| 706 | for EiiImpl { eii_macro_path, impl_safety, .. } in eii_impls { | |
| 707 | self.word("#["); | |
| 708 | if let Safety::Unsafe(..) = impl_safety { | |
| 709 | self.word("unsafe"); | |
| 710 | self.popen(); | |
| 711 | } | |
| 712 | self.print_path(eii_macro_path, false, 0); | |
| 713 | if let Safety::Unsafe(..) = impl_safety { | |
| 714 | self.pclose(); | |
| 715 | } | |
| 716 | self.word("]"); | |
| 717 | self.hardbreak(); | |
| 716 | for eii_impl in eii_impls { | |
| 717 | self.print_eii_impl(eii_impl); | |
| 718 | 718 | } |
| 719 | 719 | |
| 720 | 720 | let body_cb_ib = body.as_ref().map(|body| (body, self.head(""))); |
| ... | ... | @@ -741,6 +741,20 @@ impl<'a> State<'a> { |
| 741 | 741 | } |
| 742 | 742 | } |
| 743 | 743 | |
| 744 | fn print_eii_impl(&mut self, eii: &ast::EiiImpl) { | |
| 745 | self.word("#["); | |
| 746 | if let Safety::Unsafe(..) = eii.impl_safety { | |
| 747 | self.word("unsafe"); | |
| 748 | self.popen(); | |
| 749 | } | |
| 750 | self.print_path(&eii.eii_macro_path, false, 0); | |
| 751 | if let Safety::Unsafe(..) = eii.impl_safety { | |
| 752 | self.pclose(); | |
| 753 | } | |
| 754 | self.word("]"); | |
| 755 | self.hardbreak(); | |
| 756 | } | |
| 757 | ||
| 744 | 758 | fn print_define_opaques(&mut self, define_opaque: Option<&[(ast::NodeId, ast::Path)]>) { |
| 745 | 759 | if let Some(define_opaque) = define_opaque { |
| 746 | 760 | self.word("#[define_opaque("); |
compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs+2-1| ... | ... | @@ -709,7 +709,8 @@ pub(crate) struct RustcEiiForeignItemParser; |
| 709 | 709 | impl<S: Stage> NoArgsAttributeParser<S> for RustcEiiForeignItemParser { |
| 710 | 710 | const PATH: &[Symbol] = &[sym::rustc_eii_foreign_item]; |
| 711 | 711 | const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error; |
| 712 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::ForeignFn)]); | |
| 712 | const ALLOWED_TARGETS: AllowedTargets = | |
| 713 | AllowedTargets::AllowList(&[Allow(Target::ForeignFn), Allow(Target::ForeignStatic)]); | |
| 713 | 714 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcEiiForeignItem; |
| 714 | 715 | } |
| 715 | 716 |
compiler/rustc_attr_parsing/src/attributes/diagnostic/on_const.rs+1| ... | ... | @@ -17,6 +17,7 @@ impl<S: Stage> AttributeParser<S> for OnConstParser { |
| 17 | 17 | template!(List: &[r#"/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...""#]), |
| 18 | 18 | |this, cx, args| { |
| 19 | 19 | if !cx.features().diagnostic_on_const() { |
| 20 | // `UnknownDiagnosticAttribute` is emitted in rustc_resolve/macros.rs | |
| 20 | 21 | return; |
| 21 | 22 | } |
| 22 | 23 |
compiler/rustc_attr_parsing/src/attributes/diagnostic/on_move.rs+1| ... | ... | @@ -24,6 +24,7 @@ impl OnMoveParser { |
| 24 | 24 | mode: Mode, |
| 25 | 25 | ) { |
| 26 | 26 | if !cx.features().diagnostic_on_move() { |
| 27 | // `UnknownDiagnosticAttribute` is emitted in rustc_resolve/macros.rs | |
| 27 | 28 | return; |
| 28 | 29 | } |
| 29 | 30 |
compiler/rustc_attr_parsing/src/attributes/diagnostic/on_unknown.rs+1| ... | ... | @@ -18,6 +18,7 @@ impl OnUnknownParser { |
| 18 | 18 | mode: Mode, |
| 19 | 19 | ) { |
| 20 | 20 | if !cx.features().diagnostic_on_unknown() { |
| 21 | // `UnknownDiagnosticAttribute` is emitted in rustc_resolve/macros.rs | |
| 21 | 22 | return; |
| 22 | 23 | } |
| 23 | 24 | let span = cx.attr_span; |
compiler/rustc_builtin_macros/src/eii.rs+119-59| ... | ... | @@ -1,7 +1,8 @@ |
| 1 | 1 | use rustc_ast::token::{Delimiter, TokenKind}; |
| 2 | 2 | use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree}; |
| 3 | 3 | use rustc_ast::{ |
| 4 | Attribute, DUMMY_NODE_ID, EiiDecl, EiiImpl, ItemKind, MetaItem, Path, StmtKind, Visibility, ast, | |
| 4 | Attribute, DUMMY_NODE_ID, EiiDecl, EiiImpl, ItemKind, MetaItem, Mutability, Path, StmtKind, | |
| 5 | Visibility, ast, | |
| 5 | 6 | }; |
| 6 | 7 | use rustc_ast_pretty::pprust::path_to_string; |
| 7 | 8 | use rustc_expand::base::{Annotatable, ExtCtxt}; |
| ... | ... | @@ -10,8 +11,9 @@ use thin_vec::{ThinVec, thin_vec}; |
| 10 | 11 | |
| 11 | 12 | use crate::errors::{ |
| 12 | 13 | EiiExternTargetExpectedList, EiiExternTargetExpectedMacro, EiiExternTargetExpectedUnsafe, |
| 13 | EiiMacroExpectedMaxOneArgument, EiiOnlyOnce, EiiSharedMacroExpectedFunction, | |
| 14 | EiiSharedMacroInStatementPosition, | |
| 14 | EiiMacroExpectedMaxOneArgument, EiiOnlyOnce, EiiSharedMacroInStatementPosition, | |
| 15 | EiiSharedMacroTarget, EiiStaticArgumentRequired, EiiStaticDefault, | |
| 16 | EiiStaticMultipleImplementations, EiiStaticMutable, | |
| 15 | 17 | }; |
| 16 | 18 | |
| 17 | 19 | /// ```rust |
| ... | ... | @@ -73,44 +75,72 @@ fn eii_( |
| 73 | 75 | }); |
| 74 | 76 | return vec![orig_item]; |
| 75 | 77 | } else { |
| 76 | ecx.dcx().emit_err(EiiSharedMacroExpectedFunction { | |
| 78 | ecx.dcx().emit_err(EiiSharedMacroTarget { | |
| 77 | 79 | span: eii_attr_span, |
| 78 | 80 | name: path_to_string(&meta_item.path), |
| 79 | 81 | }); |
| 80 | 82 | return vec![orig_item]; |
| 81 | 83 | }; |
| 82 | 84 | |
| 83 | let ast::Item { attrs, id: _, span: _, vis, kind: ItemKind::Fn(func), tokens: _ } = | |
| 84 | item.as_ref() | |
| 85 | else { | |
| 86 | ecx.dcx().emit_err(EiiSharedMacroExpectedFunction { | |
| 87 | span: eii_attr_span, | |
| 88 | name: path_to_string(&meta_item.path), | |
| 89 | }); | |
| 90 | return vec![Annotatable::Item(item)]; | |
| 85 | let ast::Item { attrs, id: _, span: _, vis, kind, tokens: _ } = item.as_ref(); | |
| 86 | let (item_span, foreign_item_name) = match kind { | |
| 87 | ItemKind::Fn(func) => (func.sig.span, func.ident), | |
| 88 | ItemKind::Static(stat) => { | |
| 89 | // Statics with a default are not supported yet | |
| 90 | if let Some(stat_body) = &stat.expr { | |
| 91 | ecx.dcx().emit_err(EiiStaticDefault { | |
| 92 | span: stat_body.span, | |
| 93 | name: path_to_string(&meta_item.path), | |
| 94 | }); | |
| 95 | return vec![]; | |
| 96 | } | |
| 97 | // Statics must have an explicit name for the eii | |
| 98 | if meta_item.is_word() { | |
| 99 | ecx.dcx().emit_err(EiiStaticArgumentRequired { | |
| 100 | span: eii_attr_span, | |
| 101 | name: path_to_string(&meta_item.path), | |
| 102 | }); | |
| 103 | return vec![]; | |
| 104 | } | |
| 105 | ||
| 106 | // Mut statics are currently not supported | |
| 107 | if stat.mutability == Mutability::Mut { | |
| 108 | ecx.dcx().emit_err(EiiStaticMutable { | |
| 109 | span: eii_attr_span, | |
| 110 | name: path_to_string(&meta_item.path), | |
| 111 | }); | |
| 112 | } | |
| 113 | ||
| 114 | (item.span, stat.ident) | |
| 115 | } | |
| 116 | _ => { | |
| 117 | ecx.dcx().emit_err(EiiSharedMacroTarget { | |
| 118 | span: eii_attr_span, | |
| 119 | name: path_to_string(&meta_item.path), | |
| 120 | }); | |
| 121 | return vec![Annotatable::Item(item)]; | |
| 122 | } | |
| 91 | 123 | }; |
| 124 | ||
| 92 | 125 | // only clone what we need |
| 93 | 126 | let attrs = attrs.clone(); |
| 94 | let func = (**func).clone(); | |
| 95 | 127 | let vis = vis.clone(); |
| 96 | 128 | |
| 97 | 129 | let attrs_from_decl = |
| 98 | 130 | filter_attrs_for_multiple_eii_attr(ecx, attrs, eii_attr_span, &meta_item.path); |
| 99 | 131 | |
| 100 | let Ok(macro_name) = name_for_impl_macro(ecx, &func, &meta_item) else { | |
| 132 | let Ok(macro_name) = name_for_impl_macro(ecx, foreign_item_name, &meta_item) else { | |
| 101 | 133 | // we don't need to wrap in Annotatable::Stmt conditionally since |
| 102 | 134 | // EII can't be used on items in statement position |
| 103 | 135 | return vec![Annotatable::Item(item)]; |
| 104 | 136 | }; |
| 105 | 137 | |
| 106 | // span of the declaring item without attributes | |
| 107 | let item_span = func.sig.span; | |
| 108 | let foreign_item_name = func.ident; | |
| 109 | ||
| 110 | 138 | let mut module_items = Vec::new(); |
| 111 | 139 | |
| 112 | if func.body.is_some() { | |
| 113 | module_items.push(generate_default_impl( | |
| 140 | if let ItemKind::Fn(func) = kind | |
| 141 | && func.body.is_some() | |
| 142 | { | |
| 143 | module_items.push(generate_default_func_impl( | |
| 114 | 144 | ecx, |
| 115 | 145 | &func, |
| 116 | 146 | impl_unsafe, |
| ... | ... | @@ -125,7 +155,7 @@ fn eii_( |
| 125 | 155 | ecx, |
| 126 | 156 | eii_attr_span, |
| 127 | 157 | item_span, |
| 128 | func, | |
| 158 | kind, | |
| 129 | 159 | vis, |
| 130 | 160 | &attrs_from_decl, |
| 131 | 161 | )); |
| ... | ... | @@ -148,11 +178,11 @@ fn eii_( |
| 148 | 178 | /// declaration of the EII. |
| 149 | 179 | fn name_for_impl_macro( |
| 150 | 180 | ecx: &mut ExtCtxt<'_>, |
| 151 | func: &ast::Fn, | |
| 181 | item_ident: Ident, | |
| 152 | 182 | meta_item: &MetaItem, |
| 153 | 183 | ) -> Result<Ident, ErrorGuaranteed> { |
| 154 | 184 | if meta_item.is_word() { |
| 155 | Ok(func.ident) | |
| 185 | Ok(item_ident) | |
| 156 | 186 | } else if let Some([first]) = meta_item.meta_item_list() |
| 157 | 187 | && let Some(m) = first.meta_item() |
| 158 | 188 | && m.path.segments.len() == 1 |
| ... | ... | @@ -190,7 +220,7 @@ fn filter_attrs_for_multiple_eii_attr( |
| 190 | 220 | .collect() |
| 191 | 221 | } |
| 192 | 222 | |
| 193 | fn generate_default_impl( | |
| 223 | fn generate_default_func_impl( | |
| 194 | 224 | ecx: &mut ExtCtxt<'_>, |
| 195 | 225 | func: &ast::Fn, |
| 196 | 226 | impl_unsafe: bool, |
| ... | ... | @@ -257,7 +287,7 @@ fn generate_foreign_item( |
| 257 | 287 | ecx: &mut ExtCtxt<'_>, |
| 258 | 288 | eii_attr_span: Span, |
| 259 | 289 | item_span: Span, |
| 260 | mut func: ast::Fn, | |
| 290 | item_kind: &ItemKind, | |
| 261 | 291 | vis: Visibility, |
| 262 | 292 | attrs_from_decl: &[Attribute], |
| 263 | 293 | ) -> Box<ast::Item> { |
| ... | ... | @@ -268,30 +298,21 @@ fn generate_foreign_item( |
| 268 | 298 | // This attribute makes sure that we later know that this foreign item's symbol should not be. |
| 269 | 299 | foreign_item_attrs.push(ecx.attr_word(sym::rustc_eii_foreign_item, eii_attr_span)); |
| 270 | 300 | |
| 271 | let abi = match func.sig.header.ext { | |
| 272 | // extern "X" fn => extern "X" {} | |
| 273 | ast::Extern::Explicit(lit, _) => Some(lit), | |
| 274 | // extern fn => extern {} | |
| 275 | ast::Extern::Implicit(_) => None, | |
| 276 | // fn => extern "Rust" {} | |
| 277 | ast::Extern::None => Some(ast::StrLit { | |
| 278 | symbol: sym::Rust, | |
| 279 | suffix: None, | |
| 280 | symbol_unescaped: sym::Rust, | |
| 281 | style: ast::StrStyle::Cooked, | |
| 282 | span: eii_attr_span, | |
| 283 | }), | |
| 301 | // We set the abi to the default "rust" abi, which can be overridden by `generate_foreign_func`, | |
| 302 | // if a specific abi was specified on the EII function | |
| 303 | let mut abi = Some(ast::StrLit { | |
| 304 | symbol: sym::Rust, | |
| 305 | suffix: None, | |
| 306 | symbol_unescaped: sym::Rust, | |
| 307 | style: ast::StrStyle::Cooked, | |
| 308 | span: eii_attr_span, | |
| 309 | }); | |
| 310 | let foreign_kind = match item_kind { | |
| 311 | ItemKind::Fn(func) => generate_foreign_func(func.clone(), &mut abi), | |
| 312 | ItemKind::Static(stat) => generate_foreign_static(stat.clone()), | |
| 313 | _ => unreachable!("Target was checked earlier"), | |
| 284 | 314 | }; |
| 285 | 315 | |
| 286 | // ABI has been moved to the extern {} block, so we remove it from the fn item. | |
| 287 | func.sig.header.ext = ast::Extern::None; | |
| 288 | func.body = None; | |
| 289 | ||
| 290 | // And mark safe functions explicitly as `safe fn`. | |
| 291 | if func.sig.header.safety == ast::Safety::Default { | |
| 292 | func.sig.header.safety = ast::Safety::Safe(func.sig.span); | |
| 293 | } | |
| 294 | ||
| 295 | 316 | ecx.item( |
| 296 | 317 | eii_attr_span, |
| 297 | 318 | ThinVec::new(), |
| ... | ... | @@ -304,13 +325,46 @@ fn generate_foreign_item( |
| 304 | 325 | id: ast::DUMMY_NODE_ID, |
| 305 | 326 | span: item_span, |
| 306 | 327 | vis, |
| 307 | kind: ast::ForeignItemKind::Fn(Box::new(func.clone())), | |
| 328 | kind: foreign_kind, | |
| 308 | 329 | tokens: None, |
| 309 | 330 | })]), |
| 310 | 331 | }), |
| 311 | 332 | ) |
| 312 | 333 | } |
| 313 | 334 | |
| 335 | fn generate_foreign_func( | |
| 336 | mut func: Box<ast::Fn>, | |
| 337 | abi: &mut Option<ast::StrLit>, | |
| 338 | ) -> ast::ForeignItemKind { | |
| 339 | match func.sig.header.ext { | |
| 340 | // extern "X" fn => extern "X" {} | |
| 341 | ast::Extern::Explicit(lit, _) => *abi = Some(lit), | |
| 342 | // extern fn => extern {} | |
| 343 | ast::Extern::Implicit(_) => *abi = None, | |
| 344 | // no abi was specified, so we keep the default | |
| 345 | ast::Extern::None => {} | |
| 346 | }; | |
| 347 | ||
| 348 | // ABI has been moved to the extern {} block, so we remove it from the fn item. | |
| 349 | func.sig.header.ext = ast::Extern::None; | |
| 350 | func.body = None; | |
| 351 | ||
| 352 | // And mark safe functions explicitly as `safe fn`. | |
| 353 | if func.sig.header.safety == ast::Safety::Default { | |
| 354 | func.sig.header.safety = ast::Safety::Safe(func.sig.span); | |
| 355 | } | |
| 356 | ||
| 357 | ast::ForeignItemKind::Fn(func) | |
| 358 | } | |
| 359 | ||
| 360 | fn generate_foreign_static(mut stat: Box<ast::StaticItem>) -> ast::ForeignItemKind { | |
| 361 | if stat.safety == ast::Safety::Default { | |
| 362 | stat.safety = ast::Safety::Safe(stat.ident.span); | |
| 363 | } | |
| 364 | ||
| 365 | ast::ForeignItemKind::Static(stat) | |
| 366 | } | |
| 367 | ||
| 314 | 368 | /// Generate a stub macro (a bit like in core) that will roughly look like: |
| 315 | 369 | /// |
| 316 | 370 | /// ```rust, ignore, example |
| ... | ... | @@ -453,19 +507,25 @@ pub(crate) fn eii_shared_macro( |
| 453 | 507 | { |
| 454 | 508 | item |
| 455 | 509 | } else { |
| 456 | ecx.dcx().emit_err(EiiSharedMacroExpectedFunction { | |
| 457 | span, | |
| 458 | name: path_to_string(&meta_item.path), | |
| 459 | }); | |
| 510 | ecx.dcx().emit_err(EiiSharedMacroTarget { span, name: path_to_string(&meta_item.path) }); | |
| 460 | 511 | return vec![item]; |
| 461 | 512 | }; |
| 462 | 513 | |
| 463 | let ItemKind::Fn(f) = &mut i.kind else { | |
| 464 | ecx.dcx().emit_err(EiiSharedMacroExpectedFunction { | |
| 465 | span, | |
| 466 | name: path_to_string(&meta_item.path), | |
| 467 | }); | |
| 468 | return vec![item]; | |
| 514 | let eii_impls = match &mut i.kind { | |
| 515 | ItemKind::Fn(func) => &mut func.eii_impls, | |
| 516 | ItemKind::Static(stat) => { | |
| 517 | if !stat.eii_impls.is_empty() { | |
| 518 | // Reject multiple implementations on one static item | |
| 519 | // because it might be unintuitive for libraries defining statics the defined statics may alias | |
| 520 | ecx.dcx().emit_err(EiiStaticMultipleImplementations { span }); | |
| 521 | } | |
| 522 | &mut stat.eii_impls | |
| 523 | } | |
| 524 | _ => { | |
| 525 | ecx.dcx() | |
| 526 | .emit_err(EiiSharedMacroTarget { span, name: path_to_string(&meta_item.path) }); | |
| 527 | return vec![item]; | |
| 528 | } | |
| 469 | 529 | }; |
| 470 | 530 | |
| 471 | 531 | let is_default = if meta_item.is_word() { |
| ... | ... | @@ -483,7 +543,7 @@ pub(crate) fn eii_shared_macro( |
| 483 | 543 | return vec![item]; |
| 484 | 544 | }; |
| 485 | 545 | |
| 486 | f.eii_impls.push(EiiImpl { | |
| 546 | eii_impls.push(EiiImpl { | |
| 487 | 547 | node_id: DUMMY_NODE_ID, |
| 488 | 548 | inner_span: meta_item.path.span, |
| 489 | 549 | eii_macro_path: meta_item.path.clone(), |
compiler/rustc_builtin_macros/src/errors.rs+36-2| ... | ... | @@ -1117,8 +1117,42 @@ pub(crate) struct EiiExternTargetExpectedUnsafe { |
| 1117 | 1117 | } |
| 1118 | 1118 | |
| 1119 | 1119 | #[derive(Diagnostic)] |
| 1120 | #[diag("`#[{$name}]` is only valid on functions")] | |
| 1121 | pub(crate) struct EiiSharedMacroExpectedFunction { | |
| 1120 | #[diag("`#[{$name}]` is only valid on functions and statics")] | |
| 1121 | pub(crate) struct EiiSharedMacroTarget { | |
| 1122 | #[primary_span] | |
| 1123 | pub span: Span, | |
| 1124 | pub name: String, | |
| 1125 | } | |
| 1126 | ||
| 1127 | #[derive(Diagnostic)] | |
| 1128 | #[diag("static cannot implement multiple EIIs")] | |
| 1129 | #[note( | |
| 1130 | "this is not allowed because multiple externally implementable statics that alias may be unintuitive" | |
| 1131 | )] | |
| 1132 | pub(crate) struct EiiStaticMultipleImplementations { | |
| 1133 | #[primary_span] | |
| 1134 | pub span: Span, | |
| 1135 | } | |
| 1136 | ||
| 1137 | #[derive(Diagnostic)] | |
| 1138 | #[diag("`#[{$name}]` cannot be used on statics with a value")] | |
| 1139 | pub(crate) struct EiiStaticDefault { | |
| 1140 | #[primary_span] | |
| 1141 | pub span: Span, | |
| 1142 | pub name: String, | |
| 1143 | } | |
| 1144 | ||
| 1145 | #[derive(Diagnostic)] | |
| 1146 | #[diag("`#[{$name}]` requires the name as an explicit argument when used on a static")] | |
| 1147 | pub(crate) struct EiiStaticArgumentRequired { | |
| 1148 | #[primary_span] | |
| 1149 | pub span: Span, | |
| 1150 | pub name: String, | |
| 1151 | } | |
| 1152 | ||
| 1153 | #[derive(Diagnostic)] | |
| 1154 | #[diag("`#[{$name}]` cannot be used on mutable statics")] | |
| 1155 | pub(crate) struct EiiStaticMutable { | |
| 1122 | 1156 | #[primary_span] |
| 1123 | 1157 | pub span: Span, |
| 1124 | 1158 | pub name: String, |
compiler/rustc_codegen_llvm/src/errors.rs+29| ... | ... | @@ -211,3 +211,32 @@ pub(crate) struct FixedX18InvalidArch<'a> { |
| 211 | 211 | "enabling both `-Zpacked-stack` and the `backchain` target feature is incompatible with the default s390x ABI. Switch to s390x-unknown-none-softfloat if you need both attributes" |
| 212 | 212 | )] |
| 213 | 213 | pub(crate) struct PackedStackBackchainNeedsSoftfloat; |
| 214 | ||
| 215 | #[derive(Diagnostic)] | |
| 216 | #[diag( | |
| 217 | "intrinsic signature mismatch for `{$name}`: expected signature `{$llvm_fn_ty}`, found `{$rust_fn_ty}`" | |
| 218 | )] | |
| 219 | pub(crate) struct IntrinsicSignatureMismatch<'a> { | |
| 220 | pub name: &'a str, | |
| 221 | pub llvm_fn_ty: &'a str, | |
| 222 | pub rust_fn_ty: &'a str, | |
| 223 | #[primary_span] | |
| 224 | pub span: Span, | |
| 225 | } | |
| 226 | ||
| 227 | #[derive(Diagnostic)] | |
| 228 | #[diag("unknown LLVM intrinsic `{$name}`")] | |
| 229 | pub(crate) struct UnknownIntrinsic<'a> { | |
| 230 | pub name: &'a str, | |
| 231 | #[primary_span] | |
| 232 | pub span: Span, | |
| 233 | } | |
| 234 | ||
| 235 | #[derive(Diagnostic)] | |
| 236 | #[diag("intrinsic `{$name}` cannot be used with target arch `{$target_arch}`")] | |
| 237 | pub(crate) struct IntrinsicWrongArch<'a> { | |
| 238 | pub name: &'a str, | |
| 239 | pub target_arch: &'a str, | |
| 240 | #[primary_span] | |
| 241 | pub span: Span, | |
| 242 | } |
compiler/rustc_codegen_llvm/src/intrinsic.rs+263-27| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | use std::cmp::Ordering; |
| 2 | 2 | use std::ffi::c_uint; |
| 3 | use std::{assert_matches, ptr}; | |
| 3 | use std::{assert_matches, iter, ptr}; | |
| 4 | 4 | |
| 5 | 5 | use rustc_abi::{ |
| 6 | 6 | Align, BackendRepr, ExternAbi, Float, HasDataLayout, NumScalableVectors, Primitive, Size, |
| ... | ... | @@ -21,10 +21,11 @@ use rustc_middle::ty::offload_meta::OffloadMetadata; |
| 21 | 21 | use rustc_middle::ty::{self, GenericArgsRef, Instance, SimdAlign, Ty, TyCtxt, TypingEnv}; |
| 22 | 22 | use rustc_middle::{bug, span_bug}; |
| 23 | 23 | use rustc_session::config::CrateType; |
| 24 | use rustc_session::lint::builtin::DEPRECATED_LLVM_INTRINSIC; | |
| 24 | 25 | use rustc_span::{Span, Symbol, sym}; |
| 25 | 26 | use rustc_symbol_mangling::{mangle_internal_symbol, symbol_name_for_instance_in_crate}; |
| 26 | 27 | use rustc_target::callconv::PassMode; |
| 27 | use rustc_target::spec::Os; | |
| 28 | use rustc_target::spec::{Arch, Os}; | |
| 28 | 29 | use tracing::debug; |
| 29 | 30 | |
| 30 | 31 | use crate::abi::FnAbiLlvmExt; |
| ... | ... | @@ -36,7 +37,8 @@ use crate::builder::gpu_offload::{ |
| 36 | 37 | use crate::context::CodegenCx; |
| 37 | 38 | use crate::declare::declare_raw_fn; |
| 38 | 39 | use crate::errors::{ |
| 39 | AutoDiffWithoutEnable, AutoDiffWithoutLto, OffloadWithoutEnable, OffloadWithoutFatLTO, | |
| 40 | AutoDiffWithoutEnable, AutoDiffWithoutLto, IntrinsicSignatureMismatch, IntrinsicWrongArch, | |
| 41 | OffloadWithoutEnable, OffloadWithoutFatLTO, UnknownIntrinsic, | |
| 40 | 42 | }; |
| 41 | 43 | use crate::llvm::{self, Type, Value}; |
| 42 | 44 | use crate::type_of::LayoutLlvmExt; |
| ... | ... | @@ -797,7 +799,7 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { |
| 797 | 799 | &mut self, |
| 798 | 800 | instance: ty::Instance<'tcx>, |
| 799 | 801 | args: &[OperandRef<'tcx, Self::Value>], |
| 800 | is_cleanup: bool, | |
| 802 | _is_cleanup: bool, | |
| 801 | 803 | ) -> Self::Value { |
| 802 | 804 | let tcx = self.tcx(); |
| 803 | 805 | |
| ... | ... | @@ -826,42 +828,29 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { |
| 826 | 828 | llargument_tys.push(arg_layout.immediate_llvm_type(self)); |
| 827 | 829 | } |
| 828 | 830 | |
| 829 | let fn_ty = self.type_func(&llargument_tys, llreturn_ty); | |
| 830 | ||
| 831 | 831 | let fn_ptr = if let Some(&llfn) = self.intrinsic_instances.borrow().get(&instance) { |
| 832 | 832 | llfn |
| 833 | 833 | } else { |
| 834 | 834 | let sym = tcx.symbol_name(instance).name; |
| 835 | 835 | |
| 836 | // FIXME use get_intrinsic | |
| 837 | 836 | let llfn = if let Some(llfn) = self.get_declared_value(sym) { |
| 838 | 837 | llfn |
| 839 | 838 | } else { |
| 840 | // Function addresses in Rust are never significant, allowing functions to | |
| 841 | // be merged. | |
| 842 | let llfn = declare_raw_fn( | |
| 843 | self, | |
| 844 | sym, | |
| 845 | llvm::CCallConv, | |
| 846 | llvm::UnnamedAddr::Global, | |
| 847 | llvm::Visibility::Default, | |
| 848 | fn_ty, | |
| 849 | ); | |
| 850 | ||
| 851 | llfn | |
| 839 | intrinsic_fn(self, sym, llreturn_ty, llargument_tys, instance) | |
| 852 | 840 | }; |
| 853 | 841 | |
| 854 | 842 | self.intrinsic_instances.borrow_mut().insert(instance, llfn); |
| 855 | 843 | |
| 856 | 844 | llfn |
| 857 | 845 | }; |
| 846 | let fn_ty = self.get_type_of_global(fn_ptr); | |
| 858 | 847 | |
| 859 | 848 | let mut llargs = vec![]; |
| 860 | 849 | |
| 861 | 850 | for arg in args { |
| 862 | 851 | match arg.val { |
| 863 | 852 | OperandValue::ZeroSized => {} |
| 864 | OperandValue::Immediate(_) => llargs.push(arg.immediate()), | |
| 853 | OperandValue::Immediate(a) => llargs.push(a), | |
| 865 | 854 | OperandValue::Pair(a, b) => { |
| 866 | 855 | llargs.push(a); |
| 867 | 856 | llargs.push(b); |
| ... | ... | @@ -887,24 +876,38 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { |
| 887 | 876 | } |
| 888 | 877 | |
| 889 | 878 | debug!("call intrinsic {:?} with args ({:?})", instance, llargs); |
| 890 | let args = self.check_call("call", fn_ty, fn_ptr, &llargs); | |
| 879 | ||
| 880 | for (dest_ty, arg) in iter::zip(self.func_params_types(fn_ty), &mut llargs) { | |
| 881 | let src_ty = self.val_ty(arg); | |
| 882 | assert!( | |
| 883 | can_autocast(self, src_ty, dest_ty), | |
| 884 | "Cannot match `{dest_ty:?}` (expected) with {src_ty:?} (found) in `{fn_ptr:?}" | |
| 885 | ); | |
| 886 | ||
| 887 | *arg = autocast(self, arg, src_ty, dest_ty); | |
| 888 | } | |
| 889 | ||
| 891 | 890 | let llret = unsafe { |
| 892 | 891 | llvm::LLVMBuildCallWithOperandBundles( |
| 893 | 892 | self.llbuilder, |
| 894 | 893 | fn_ty, |
| 895 | 894 | fn_ptr, |
| 896 | args.as_ptr() as *const &llvm::Value, | |
| 897 | args.len() as c_uint, | |
| 895 | llargs.as_ptr(), | |
| 896 | llargs.len() as c_uint, | |
| 898 | 897 | ptr::dangling(), |
| 899 | 898 | 0, |
| 900 | 899 | c"".as_ptr(), |
| 901 | 900 | ) |
| 902 | 901 | }; |
| 903 | if is_cleanup { | |
| 904 | self.apply_attrs_to_cleanup_callsite(llret); | |
| 905 | } | |
| 906 | 902 | |
| 907 | llret | |
| 903 | let src_ty = self.val_ty(llret); | |
| 904 | let dest_ty = llreturn_ty; | |
| 905 | assert!( | |
| 906 | can_autocast(self, dest_ty, src_ty), | |
| 907 | "Cannot match `{src_ty:?}` (expected) with `{dest_ty:?}` (found) in `{fn_ptr:?}`" | |
| 908 | ); | |
| 909 | ||
| 910 | autocast(self, llret, src_ty, dest_ty) | |
| 908 | 911 | } |
| 909 | 912 | |
| 910 | 913 | fn abort(&mut self) { |
| ... | ... | @@ -955,6 +958,239 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { |
| 955 | 958 | } |
| 956 | 959 | } |
| 957 | 960 | |
| 961 | fn llvm_arch_for(rust_arch: &Arch) -> Option<&'static str> { | |
| 962 | Some(match rust_arch { | |
| 963 | Arch::AArch64 | Arch::Arm64EC => "aarch64", | |
| 964 | Arch::AmdGpu => "amdgcn", | |
| 965 | Arch::Arm => "arm", | |
| 966 | Arch::Bpf => "bpf", | |
| 967 | Arch::Hexagon => "hexagon", | |
| 968 | Arch::LoongArch32 | Arch::LoongArch64 => "loongarch", | |
| 969 | Arch::Mips | Arch::Mips32r6 | Arch::Mips64 | Arch::Mips64r6 => "mips", | |
| 970 | Arch::Nvptx64 => "nvvm", | |
| 971 | Arch::PowerPC | Arch::PowerPC64 => "ppc", | |
| 972 | Arch::RiscV32 | Arch::RiscV64 => "riscv", | |
| 973 | Arch::S390x => "s390", | |
| 974 | Arch::SpirV => "spv", | |
| 975 | Arch::Wasm32 | Arch::Wasm64 => "wasm", | |
| 976 | Arch::X86 | Arch::X86_64 => "x86", | |
| 977 | _ => return None, // fallback for unknown archs | |
| 978 | }) | |
| 979 | } | |
| 980 | ||
| 981 | fn can_autocast<'ll>(cx: &CodegenCx<'ll, '_>, rust_ty: &'ll Type, llvm_ty: &'ll Type) -> bool { | |
| 982 | if rust_ty == llvm_ty { | |
| 983 | return true; | |
| 984 | } | |
| 985 | ||
| 986 | match cx.type_kind(llvm_ty) { | |
| 987 | // Some LLVM intrinsics return **non-packed** structs, but they can't be mimicked from Rust | |
| 988 | // due to auto field-alignment in non-packed structs (packed structs are represented in LLVM | |
| 989 | // as, well, packed structs, so they won't match with those either) | |
| 990 | TypeKind::Struct if cx.type_kind(rust_ty) == TypeKind::Struct => { | |
| 991 | let rust_element_tys = cx.struct_element_types(rust_ty); | |
| 992 | let llvm_element_tys = cx.struct_element_types(llvm_ty); | |
| 993 | ||
| 994 | if rust_element_tys.len() != llvm_element_tys.len() { | |
| 995 | return false; | |
| 996 | } | |
| 997 | ||
| 998 | iter::zip(rust_element_tys, llvm_element_tys).all( | |
| 999 | |(rust_element_ty, llvm_element_ty)| { | |
| 1000 | can_autocast(cx, rust_element_ty, llvm_element_ty) | |
| 1001 | }, | |
| 1002 | ) | |
| 1003 | } | |
| 1004 | TypeKind::Vector => { | |
| 1005 | let llvm_element_ty = cx.element_type(llvm_ty); | |
| 1006 | let element_count = cx.vector_length(llvm_ty) as u64; | |
| 1007 | ||
| 1008 | if llvm_element_ty == cx.type_bf16() { | |
| 1009 | rust_ty == cx.type_vector(cx.type_i16(), element_count) | |
| 1010 | } else if llvm_element_ty == cx.type_i1() { | |
| 1011 | let int_width = element_count.next_power_of_two().max(8); | |
| 1012 | rust_ty == cx.type_ix(int_width) | |
| 1013 | } else { | |
| 1014 | false | |
| 1015 | } | |
| 1016 | } | |
| 1017 | TypeKind::BFloat => rust_ty == cx.type_i16(), | |
| 1018 | _ => false, | |
| 1019 | } | |
| 1020 | } | |
| 1021 | ||
| 1022 | fn autocast<'ll>( | |
| 1023 | bx: &mut Builder<'_, 'll, '_>, | |
| 1024 | val: &'ll Value, | |
| 1025 | src_ty: &'ll Type, | |
| 1026 | dest_ty: &'ll Type, | |
| 1027 | ) -> &'ll Value { | |
| 1028 | if src_ty == dest_ty { | |
| 1029 | return val; | |
| 1030 | } | |
| 1031 | match (bx.type_kind(src_ty), bx.type_kind(dest_ty)) { | |
| 1032 | // re-pack structs | |
| 1033 | (TypeKind::Struct, TypeKind::Struct) => { | |
| 1034 | let mut ret = bx.const_poison(dest_ty); | |
| 1035 | for (idx, (src_element_ty, dest_element_ty)) in | |
| 1036 | iter::zip(bx.struct_element_types(src_ty), bx.struct_element_types(dest_ty)) | |
| 1037 | .enumerate() | |
| 1038 | { | |
| 1039 | let elt = bx.extract_value(val, idx as u64); | |
| 1040 | let casted_elt = autocast(bx, elt, src_element_ty, dest_element_ty); | |
| 1041 | ret = bx.insert_value(ret, casted_elt, idx as u64); | |
| 1042 | } | |
| 1043 | ret | |
| 1044 | } | |
| 1045 | // cast from the i1xN vector type to the primitive type | |
| 1046 | (TypeKind::Vector, TypeKind::Integer) if bx.element_type(src_ty) == bx.type_i1() => { | |
| 1047 | let vector_length = bx.vector_length(src_ty) as u64; | |
| 1048 | let int_width = vector_length.next_power_of_two().max(8); | |
| 1049 | ||
| 1050 | let val = if vector_length == int_width { | |
| 1051 | val | |
| 1052 | } else { | |
| 1053 | // zero-extends vector | |
| 1054 | let shuffle_indices = match vector_length { | |
| 1055 | 0 => unreachable!("zero length vectors are not allowed"), | |
| 1056 | 1 => vec![0, 1, 1, 1, 1, 1, 1, 1], | |
| 1057 | 2 => vec![0, 1, 2, 2, 2, 2, 2, 2], | |
| 1058 | 3 => vec![0, 1, 2, 3, 3, 3, 3, 3], | |
| 1059 | 4.. => (0..int_width as i32).collect(), | |
| 1060 | }; | |
| 1061 | let shuffle_mask = | |
| 1062 | shuffle_indices.into_iter().map(|i| bx.const_i32(i)).collect::<Vec<_>>(); | |
| 1063 | bx.shuffle_vector(val, bx.const_null(src_ty), bx.const_vector(&shuffle_mask)) | |
| 1064 | }; | |
| 1065 | bx.bitcast(val, dest_ty) | |
| 1066 | } | |
| 1067 | // cast from the primitive type to the i1xN vector type | |
| 1068 | (TypeKind::Integer, TypeKind::Vector) if bx.element_type(dest_ty) == bx.type_i1() => { | |
| 1069 | let vector_length = bx.vector_length(dest_ty) as u64; | |
| 1070 | let int_width = vector_length.next_power_of_two().max(8); | |
| 1071 | ||
| 1072 | let intermediate_ty = bx.type_vector(bx.type_i1(), int_width); | |
| 1073 | let intermediate = bx.bitcast(val, intermediate_ty); | |
| 1074 | ||
| 1075 | if vector_length == int_width { | |
| 1076 | intermediate | |
| 1077 | } else { | |
| 1078 | let shuffle_mask: Vec<_> = | |
| 1079 | (0..vector_length).map(|i| bx.const_i32(i as i32)).collect(); | |
| 1080 | bx.shuffle_vector( | |
| 1081 | intermediate, | |
| 1082 | bx.const_poison(intermediate_ty), | |
| 1083 | bx.const_vector(&shuffle_mask), | |
| 1084 | ) | |
| 1085 | } | |
| 1086 | } | |
| 1087 | _ => bx.bitcast(val, dest_ty), // for `bf16(xN)` <-> `u16(xN)` | |
| 1088 | } | |
| 1089 | } | |
| 1090 | ||
| 1091 | fn intrinsic_fn<'ll, 'tcx>( | |
| 1092 | bx: &Builder<'_, 'll, 'tcx>, | |
| 1093 | name: &str, | |
| 1094 | rust_return_ty: &'ll Type, | |
| 1095 | rust_argument_tys: Vec<&'ll Type>, | |
| 1096 | instance: ty::Instance<'tcx>, | |
| 1097 | ) -> &'ll Value { | |
| 1098 | let tcx = bx.tcx; | |
| 1099 | ||
| 1100 | let rust_fn_ty = bx.type_func(&rust_argument_tys, rust_return_ty); | |
| 1101 | ||
| 1102 | let intrinsic = llvm::Intrinsic::lookup(name.as_bytes()); | |
| 1103 | ||
| 1104 | if let Some(intrinsic) = intrinsic | |
| 1105 | && intrinsic.is_target_specific() | |
| 1106 | { | |
| 1107 | let (llvm_arch, _) = name[5..].split_once('.').unwrap(); | |
| 1108 | let rust_arch = &tcx.sess.target.arch; | |
| 1109 | ||
| 1110 | if let Some(correct_llvm_arch) = llvm_arch_for(rust_arch) | |
| 1111 | && llvm_arch != correct_llvm_arch | |
| 1112 | { | |
| 1113 | tcx.dcx().emit_fatal(IntrinsicWrongArch { | |
| 1114 | name, | |
| 1115 | target_arch: rust_arch.desc(), | |
| 1116 | span: tcx.def_span(instance.def_id()), | |
| 1117 | }); | |
| 1118 | } | |
| 1119 | } | |
| 1120 | ||
| 1121 | if let Some(intrinsic) = intrinsic | |
| 1122 | && !intrinsic.is_overloaded() | |
| 1123 | { | |
| 1124 | // FIXME: also do this for overloaded intrinsics | |
| 1125 | let llfn = intrinsic.get_declaration(bx.llmod, &[]); | |
| 1126 | let llvm_fn_ty = bx.get_type_of_global(llfn); | |
| 1127 | ||
| 1128 | let llvm_return_ty = bx.get_return_type(llvm_fn_ty); | |
| 1129 | let llvm_argument_tys = bx.func_params_types(llvm_fn_ty); | |
| 1130 | let llvm_is_variadic = bx.func_is_variadic(llvm_fn_ty); | |
| 1131 | ||
| 1132 | let is_correct_signature = !llvm_is_variadic | |
| 1133 | && rust_argument_tys.len() == llvm_argument_tys.len() | |
| 1134 | && iter::once((rust_return_ty, llvm_return_ty)) | |
| 1135 | .chain(iter::zip(rust_argument_tys, llvm_argument_tys)) | |
| 1136 | .all(|(rust_ty, llvm_ty)| can_autocast(bx, rust_ty, llvm_ty)); | |
| 1137 | ||
| 1138 | if !is_correct_signature { | |
| 1139 | tcx.dcx().emit_fatal(IntrinsicSignatureMismatch { | |
| 1140 | name, | |
| 1141 | llvm_fn_ty: &format!("{llvm_fn_ty:?}"), | |
| 1142 | rust_fn_ty: &format!("{rust_fn_ty:?}"), | |
| 1143 | span: tcx.def_span(instance.def_id()), | |
| 1144 | }); | |
| 1145 | } | |
| 1146 | ||
| 1147 | return llfn; | |
| 1148 | } | |
| 1149 | ||
| 1150 | // Function addresses in Rust are never significant, allowing functions to be merged. | |
| 1151 | let llfn = declare_raw_fn( | |
| 1152 | bx, | |
| 1153 | name, | |
| 1154 | llvm::CCallConv, | |
| 1155 | llvm::UnnamedAddr::Global, | |
| 1156 | llvm::Visibility::Default, | |
| 1157 | rust_fn_ty, | |
| 1158 | ); | |
| 1159 | ||
| 1160 | if intrinsic.is_none() { | |
| 1161 | let mut new_llfn = None; | |
| 1162 | let can_upgrade = unsafe { llvm::LLVMRustUpgradeIntrinsicFunction(llfn, &mut new_llfn) }; | |
| 1163 | ||
| 1164 | if !can_upgrade { | |
| 1165 | // This is either plain wrong, or this can be caused by incompatible LLVM versions | |
| 1166 | tcx.dcx().emit_fatal(UnknownIntrinsic { name, span: tcx.def_span(instance.def_id()) }); | |
| 1167 | } else if let Some(def_id) = instance.def_id().as_local() { | |
| 1168 | // we can emit diagnostics only for local crates | |
| 1169 | let hir_id = tcx.local_def_id_to_hir_id(def_id); | |
| 1170 | ||
| 1171 | // not all intrinsics are upgraded to some other intrinsics, most are upgraded to instruction sequences | |
| 1172 | let msg = if let Some(new_llfn) = new_llfn { | |
| 1173 | format!( | |
| 1174 | "using deprecated intrinsic `{name}`, `{}` can be used instead", | |
| 1175 | str::from_utf8(&llvm::get_value_name(new_llfn)).unwrap() | |
| 1176 | ) | |
| 1177 | } else { | |
| 1178 | format!("using deprecated intrinsic `{name}`") | |
| 1179 | }; | |
| 1180 | ||
| 1181 | tcx.emit_node_lint( | |
| 1182 | DEPRECATED_LLVM_INTRINSIC, | |
| 1183 | hir_id, | |
| 1184 | rustc_errors::DiagDecorator(|d| { | |
| 1185 | d.primary_message(msg).span(tcx.hir_span(hir_id)); | |
| 1186 | }), | |
| 1187 | ); | |
| 1188 | } | |
| 1189 | } | |
| 1190 | ||
| 1191 | llfn | |
| 1192 | } | |
| 1193 | ||
| 958 | 1194 | fn catch_unwind_intrinsic<'ll, 'tcx>( |
| 959 | 1195 | bx: &mut Builder<'_, 'll, 'tcx>, |
| 960 | 1196 | try_func: &'ll Value, |
compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs-1| ... | ... | @@ -73,7 +73,6 @@ unsafe extern "C" { |
| 73 | 73 | pub(crate) fn LLVMDumpModule(M: &Module); |
| 74 | 74 | pub(crate) fn LLVMDumpValue(V: &Value); |
| 75 | 75 | pub(crate) fn LLVMGetFunctionCallConv(F: &Value) -> c_uint; |
| 76 | pub(crate) fn LLVMGetReturnType(T: &Type) -> &Type; | |
| 77 | 76 | pub(crate) fn LLVMGetParams(Fnc: &Value, params: *mut &Value); |
| 78 | 77 | pub(crate) fn LLVMGetNamedFunction(M: &Module, Name: *const c_char) -> Option<&Value>; |
| 79 | 78 | } |
compiler/rustc_codegen_llvm/src/llvm/ffi.rs+14| ... | ... | @@ -921,6 +921,9 @@ unsafe extern "C" { |
| 921 | 921 | pub(crate) fn LLVMDoubleTypeInContext(C: &Context) -> &Type; |
| 922 | 922 | pub(crate) fn LLVMFP128TypeInContext(C: &Context) -> &Type; |
| 923 | 923 | |
| 924 | // Operations on non-IEEE real types | |
| 925 | pub(crate) fn LLVMBFloatTypeInContext(C: &Context) -> &Type; | |
| 926 | ||
| 924 | 927 | // Operations on function types |
| 925 | 928 | pub(crate) fn LLVMFunctionType<'a>( |
| 926 | 929 | ReturnType: &'a Type, |
| ... | ... | @@ -930,6 +933,8 @@ unsafe extern "C" { |
| 930 | 933 | ) -> &'a Type; |
| 931 | 934 | pub(crate) fn LLVMCountParamTypes(FunctionTy: &Type) -> c_uint; |
| 932 | 935 | pub(crate) fn LLVMGetParamTypes<'a>(FunctionTy: &'a Type, Dest: *mut &'a Type); |
| 936 | pub(crate) fn LLVMGetReturnType(FunctionTy: &Type) -> &Type; | |
| 937 | pub(crate) fn LLVMIsFunctionVarArg(FunctionTy: &Type) -> Bool; | |
| 933 | 938 | |
| 934 | 939 | // Operations on struct types |
| 935 | 940 | pub(crate) fn LLVMStructTypeInContext<'a>( |
| ... | ... | @@ -1084,12 +1089,18 @@ unsafe extern "C" { |
| 1084 | 1089 | |
| 1085 | 1090 | // Operations about llvm intrinsics |
| 1086 | 1091 | pub(crate) fn LLVMLookupIntrinsicID(Name: *const c_char, NameLen: size_t) -> c_uint; |
| 1092 | pub(crate) fn LLVMIntrinsicIsOverloaded(ID: NonZero<c_uint>) -> Bool; | |
| 1087 | 1093 | pub(crate) fn LLVMGetIntrinsicDeclaration<'a>( |
| 1088 | 1094 | Mod: &'a Module, |
| 1089 | 1095 | ID: NonZero<c_uint>, |
| 1090 | 1096 | ParamTypes: *const &'a Type, |
| 1091 | 1097 | ParamCount: size_t, |
| 1092 | 1098 | ) -> &'a Value; |
| 1099 | pub(crate) fn LLVMRustUpgradeIntrinsicFunction<'a>( | |
| 1100 | Fn: &'a Value, | |
| 1101 | NewFn: &mut Option<&'a Value>, | |
| 1102 | ) -> bool; | |
| 1103 | pub(crate) fn LLVMRustIsTargetIntrinsic(ID: NonZero<c_uint>) -> bool; | |
| 1093 | 1104 | |
| 1094 | 1105 | // Operations on parameters |
| 1095 | 1106 | pub(crate) fn LLVMIsAArgument(Val: &Value) -> Option<&Value>; |
| ... | ... | @@ -1605,6 +1616,9 @@ unsafe extern "C" { |
| 1605 | 1616 | Packed: Bool, |
| 1606 | 1617 | ); |
| 1607 | 1618 | |
| 1619 | pub(crate) fn LLVMCountStructElementTypes(StructTy: &Type) -> c_uint; | |
| 1620 | pub(crate) fn LLVMGetStructElementTypes<'a>(StructTy: &'a Type, Dest: *mut &'a Type); | |
| 1621 | ||
| 1608 | 1622 | pub(crate) safe fn LLVMMetadataAsValue<'a>(C: &'a Context, MD: &'a Metadata) -> &'a Value; |
| 1609 | 1623 | |
| 1610 | 1624 | pub(crate) safe fn LLVMSetUnnamedAddress(Global: &Value, UnnamedAddr: UnnamedAddr); |
compiler/rustc_codegen_llvm/src/llvm/mod.rs+8| ... | ... | @@ -323,6 +323,14 @@ impl Intrinsic { |
| 323 | 323 | NonZero::new(id).map(|id| Self { id }) |
| 324 | 324 | } |
| 325 | 325 | |
| 326 | pub(crate) fn is_overloaded(self) -> bool { | |
| 327 | unsafe { LLVMIntrinsicIsOverloaded(self.id).is_true() } | |
| 328 | } | |
| 329 | ||
| 330 | pub(crate) fn is_target_specific(self) -> bool { | |
| 331 | unsafe { LLVMRustIsTargetIntrinsic(self.id) } | |
| 332 | } | |
| 333 | ||
| 326 | 334 | pub(crate) fn get_declaration<'ll>( |
| 327 | 335 | self, |
| 328 | 336 | llmod: &'ll Module, |
compiler/rustc_codegen_llvm/src/mono_item.rs+9-1| ... | ... | @@ -135,7 +135,8 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { |
| 135 | 135 | let ty = self.get_type_of_global(aliasee); |
| 136 | 136 | |
| 137 | 137 | for (alias, linkage, visibility) in aliases { |
| 138 | let symbol_name = self.tcx.symbol_name(Instance::mono(self.tcx, *alias)); | |
| 138 | let instance = Instance::mono(self.tcx, *alias); | |
| 139 | let symbol_name = self.tcx.symbol_name(instance); | |
| 139 | 140 | tracing::debug!("STATIC ALIAS: {alias:?} {linkage:?} {visibility:?}"); |
| 140 | 141 | |
| 141 | 142 | let lldecl = llvm::add_alias( |
| ... | ... | @@ -145,6 +146,13 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { |
| 145 | 146 | aliasee, |
| 146 | 147 | &CString::new(symbol_name.name).unwrap(), |
| 147 | 148 | ); |
| 149 | // Add the alias name to the set of cached items, so there is no duplicate | |
| 150 | // instance added to it during the normal `external static` codegen | |
| 151 | let prev_entry = self.instances.borrow_mut().insert(instance, lldecl); | |
| 152 | ||
| 153 | // If there already was a previous entry, then `add_static_aliases` was called multiple times for the same `alias` | |
| 154 | // which would result in incorrect codegen | |
| 155 | assert!(prev_entry.is_none(), "An instance was already present for {instance:?}"); | |
| 148 | 156 | |
| 149 | 157 | llvm::set_visibility(lldecl, base::visibility_to_llvm(*visibility)); |
| 150 | 158 | llvm::set_linkage(lldecl, base::linkage_to_llvm(*linkage)); |
compiler/rustc_codegen_llvm/src/type_.rs+22| ... | ... | @@ -77,6 +77,10 @@ impl<'ll, CX: Borrow<SCx<'ll>>> GenericCx<'ll, CX> { |
| 77 | 77 | unsafe { llvm::LLVMAddFunction(self.llmod(), name.as_ptr(), ty) } |
| 78 | 78 | } |
| 79 | 79 | |
| 80 | pub(crate) fn get_return_type(&self, ty: &'ll Type) -> &'ll Type { | |
| 81 | unsafe { llvm::LLVMGetReturnType(ty) } | |
| 82 | } | |
| 83 | ||
| 80 | 84 | pub(crate) fn func_params_types(&self, ty: &'ll Type) -> Vec<&'ll Type> { |
| 81 | 85 | unsafe { |
| 82 | 86 | let n_args = llvm::LLVMCountParamTypes(ty) as usize; |
| ... | ... | @@ -86,6 +90,20 @@ impl<'ll, CX: Borrow<SCx<'ll>>> GenericCx<'ll, CX> { |
| 86 | 90 | args |
| 87 | 91 | } |
| 88 | 92 | } |
| 93 | ||
| 94 | pub(crate) fn func_is_variadic(&self, ty: &'ll Type) -> bool { | |
| 95 | unsafe { llvm::LLVMIsFunctionVarArg(ty).is_true() } | |
| 96 | } | |
| 97 | ||
| 98 | pub(crate) fn struct_element_types(&self, ty: &'ll Type) -> Vec<&'ll Type> { | |
| 99 | unsafe { | |
| 100 | let n_args = llvm::LLVMCountStructElementTypes(ty) as usize; | |
| 101 | let mut args = Vec::with_capacity(n_args); | |
| 102 | llvm::LLVMGetStructElementTypes(ty, args.as_mut_ptr()); | |
| 103 | args.set_len(n_args); | |
| 104 | args | |
| 105 | } | |
| 106 | } | |
| 89 | 107 | } |
| 90 | 108 | impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { |
| 91 | 109 | pub(crate) fn type_bool(&self) -> &'ll Type { |
| ... | ... | @@ -165,6 +183,10 @@ impl<'ll, CX: Borrow<SCx<'ll>>> GenericCx<'ll, CX> { |
| 165 | 183 | ) |
| 166 | 184 | } |
| 167 | 185 | } |
| 186 | ||
| 187 | pub(crate) fn type_bf16(&self) -> &'ll Type { | |
| 188 | unsafe { llvm::LLVMBFloatTypeInContext(self.llcx()) } | |
| 189 | } | |
| 168 | 190 | } |
| 169 | 191 | |
| 170 | 192 | impl<'ll, CX: Borrow<SCx<'ll>>> BaseTypeCodegenMethods for GenericCx<'ll, CX> { |
compiler/rustc_codegen_ssa/src/mir/rvalue.rs+8| ... | ... | @@ -302,6 +302,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { |
| 302 | 302 | let to_backend_ty = bx.cx().immediate_backend_type(cast); |
| 303 | 303 | OperandValue::Immediate(bx.bitcast(imm, to_backend_ty)) |
| 304 | 304 | } |
| 305 | ( | |
| 306 | OperandValue::Immediate(imm), | |
| 307 | abi::BackendRepr::SimdScalableVector { element: from_scalar, .. }, | |
| 308 | abi::BackendRepr::SimdScalableVector { element: to_scalar, .. }, | |
| 309 | ) if vector_can_bitcast(from_scalar) && vector_can_bitcast(to_scalar) => { | |
| 310 | let to_backend_ty = bx.cx().immediate_backend_type(cast); | |
| 311 | OperandValue::Immediate(bx.bitcast(imm, to_backend_ty)) | |
| 312 | } | |
| 305 | 313 | ( |
| 306 | 314 | OperandValue::Pair(imm_a, imm_b), |
| 307 | 315 | abi::BackendRepr::ScalarPair(in_a, in_b), |
compiler/rustc_expand/src/build.rs+1| ... | ... | @@ -715,6 +715,7 @@ impl<'a> ExtCtxt<'a> { |
| 715 | 715 | mutability, |
| 716 | 716 | expr: Some(expr), |
| 717 | 717 | define_opaque: None, |
| 718 | eii_impls: Default::default(), | |
| 718 | 719 | } |
| 719 | 720 | .into(), |
| 720 | 721 | ), |
compiler/rustc_hir_analysis/src/check/compare_eii.rs+118-14| ... | ... | @@ -15,7 +15,7 @@ use rustc_hir::{self as hir, FnSig, HirId, ItemKind, find_attr}; |
| 15 | 15 | use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt}; |
| 16 | 16 | use rustc_infer::traits::{ObligationCause, ObligationCauseCode}; |
| 17 | 17 | use rustc_middle::ty::error::{ExpectedFound, TypeError}; |
| 18 | use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt, TypingMode}; | |
| 18 | use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, TypeVisitableExt, TypingMode}; | |
| 19 | 19 | use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol}; |
| 20 | 20 | use rustc_trait_selection::error_reporting::InferCtxtErrorExt; |
| 21 | 21 | use rustc_trait_selection::regions::InferCtxtRegionExt; |
| ... | ... | @@ -26,7 +26,10 @@ use super::potentially_plural_count; |
| 26 | 26 | use crate::check::compare_impl_item::{ |
| 27 | 27 | CheckNumberOfEarlyBoundRegionsError, check_number_of_early_bound_regions, |
| 28 | 28 | }; |
| 29 | use crate::errors::{EiiWithGenerics, LifetimesOrBoundsMismatchOnEii}; | |
| 29 | use crate::errors::{ | |
| 30 | EiiDefkindMismatch, EiiDefkindMismatchStaticMutability, EiiDefkindMismatchStaticSafety, | |
| 31 | EiiWithGenerics, LifetimesOrBoundsMismatchOnEii, | |
| 32 | }; | |
| 30 | 33 | |
| 31 | 34 | /// Checks whether the signature of some `external_impl`, matches |
| 32 | 35 | /// the signature of `declaration`, which it is supposed to be compatible |
| ... | ... | @@ -38,14 +41,7 @@ pub(crate) fn compare_eii_function_types<'tcx>( |
| 38 | 41 | eii_name: Symbol, |
| 39 | 42 | eii_attr_span: Span, |
| 40 | 43 | ) -> Result<(), ErrorGuaranteed> { |
| 41 | // Error recovery can resolve the EII target to another value item with the same name, | |
| 42 | // such as a tuple-struct constructor. Skip the comparison in that case and rely on the | |
| 43 | // earlier name-resolution error instead of ICEing while building EII diagnostics. | |
| 44 | // See <https://github.com/rust-lang/rust/issues/153502>. | |
| 45 | if !is_foreign_function(tcx, foreign_item) { | |
| 46 | return Ok(()); | |
| 47 | } | |
| 48 | ||
| 44 | check_eii_target(tcx, external_impl, foreign_item, eii_name, eii_attr_span)?; | |
| 49 | 45 | check_is_structurally_compatible(tcx, external_impl, foreign_item, eii_name, eii_attr_span)?; |
| 50 | 46 | |
| 51 | 47 | let external_impl_span = tcx.def_span(external_impl); |
| ... | ... | @@ -152,6 +148,118 @@ pub(crate) fn compare_eii_function_types<'tcx>( |
| 152 | 148 | Ok(()) |
| 153 | 149 | } |
| 154 | 150 | |
| 151 | pub(crate) fn compare_eii_statics<'tcx>( | |
| 152 | tcx: TyCtxt<'tcx>, | |
| 153 | external_impl: LocalDefId, | |
| 154 | external_impl_ty: Ty<'tcx>, | |
| 155 | foreign_item: DefId, | |
| 156 | eii_name: Symbol, | |
| 157 | eii_attr_span: Span, | |
| 158 | ) -> Result<(), ErrorGuaranteed> { | |
| 159 | check_eii_target(tcx, external_impl, foreign_item, eii_name, eii_attr_span)?; | |
| 160 | ||
| 161 | let external_impl_span = tcx.def_span(external_impl); | |
| 162 | let cause = ObligationCause::new( | |
| 163 | external_impl_span, | |
| 164 | external_impl, | |
| 165 | ObligationCauseCode::CompareEii { external_impl, declaration: foreign_item }, | |
| 166 | ); | |
| 167 | ||
| 168 | let param_env = ParamEnv::empty(); | |
| 169 | ||
| 170 | let infcx = &tcx.infer_ctxt().build(TypingMode::non_body_analysis()); | |
| 171 | let ocx = ObligationCtxt::new_with_diagnostics(infcx); | |
| 172 | ||
| 173 | let declaration_ty = tcx.type_of(foreign_item).instantiate_identity(); | |
| 174 | debug!(?declaration_ty); | |
| 175 | ||
| 176 | // FIXME: Copied over from compare impl items, same issue: | |
| 177 | // We'd want to keep more accurate spans than "the method signature" when | |
| 178 | // processing the comparison between the trait and impl fn, but we sadly lose them | |
| 179 | // and point at the whole signature when a trait bound or specific input or output | |
| 180 | // type would be more appropriate. In other places we have a `Vec<Span>` | |
| 181 | // corresponding to their `Vec<Predicate>`, but we don't have that here. | |
| 182 | // Fixing this would improve the output of test `issue-83765.rs`. | |
| 183 | let result = ocx.sup(&cause, param_env, declaration_ty, external_impl_ty); | |
| 184 | ||
| 185 | if let Err(terr) = result { | |
| 186 | debug!(?external_impl_ty, ?declaration_ty, ?terr, "sub_types failed"); | |
| 187 | ||
| 188 | let mut diag = struct_span_code_err!( | |
| 189 | tcx.dcx(), | |
| 190 | cause.span, | |
| 191 | E0806, | |
| 192 | "static `{}` has a type that is incompatible with the declaration of `#[{eii_name}]`", | |
| 193 | tcx.item_name(external_impl) | |
| 194 | ); | |
| 195 | diag.span_note(eii_attr_span, "expected this because of this attribute"); | |
| 196 | ||
| 197 | return Err(diag.emit()); | |
| 198 | } | |
| 199 | ||
| 200 | // Check that all obligations are satisfied by the implementation's | |
| 201 | // version. | |
| 202 | let errors = ocx.evaluate_obligations_error_on_ambiguity(); | |
| 203 | if !errors.is_empty() { | |
| 204 | let reported = infcx.err_ctxt().report_fulfillment_errors(errors); | |
| 205 | return Err(reported); | |
| 206 | } | |
| 207 | ||
| 208 | // Finally, resolve all regions. This catches wily misuses of | |
| 209 | // lifetime parameters. | |
| 210 | let errors = infcx.resolve_regions(external_impl, param_env, []); | |
| 211 | if !errors.is_empty() { | |
| 212 | return Err(infcx | |
| 213 | .tainted_by_errors() | |
| 214 | .unwrap_or_else(|| infcx.err_ctxt().report_region_errors(external_impl, &errors))); | |
| 215 | } | |
| 216 | ||
| 217 | Ok(()) | |
| 218 | } | |
| 219 | ||
| 220 | fn check_eii_target( | |
| 221 | tcx: TyCtxt<'_>, | |
| 222 | external_impl: LocalDefId, | |
| 223 | foreign_item: DefId, | |
| 224 | eii_name: Symbol, | |
| 225 | eii_attr_span: Span, | |
| 226 | ) -> Result<(), ErrorGuaranteed> { | |
| 227 | // Error recovery can resolve the EII target to another value item with the same name, | |
| 228 | // such as a tuple-struct constructor. Skip the comparison in that case and rely on the | |
| 229 | // earlier name-resolution error instead of ICEing while building EII diagnostics. | |
| 230 | // See <https://github.com/rust-lang/rust/issues/153502>. | |
| 231 | if !tcx.is_foreign_item(foreign_item) { | |
| 232 | return Err(tcx.dcx().delayed_bug("EII is a foreign item")); | |
| 233 | } | |
| 234 | let expected_kind = tcx.def_kind(foreign_item); | |
| 235 | let actual_kind = tcx.def_kind(external_impl); | |
| 236 | ||
| 237 | match expected_kind { | |
| 238 | // Correct target | |
| 239 | _ if expected_kind == actual_kind => Ok(()), | |
| 240 | DefKind::Static { mutability: m1, safety: s1, .. } | |
| 241 | if let DefKind::Static { mutability: m2, safety: s2, .. } = actual_kind => | |
| 242 | { | |
| 243 | Err(if s1 != s2 { | |
| 244 | tcx.dcx().emit_err(EiiDefkindMismatchStaticSafety { span: eii_attr_span, eii_name }) | |
| 245 | } else if m1 != m2 { | |
| 246 | tcx.dcx() | |
| 247 | .emit_err(EiiDefkindMismatchStaticMutability { span: eii_attr_span, eii_name }) | |
| 248 | } else { | |
| 249 | unreachable!() | |
| 250 | }) | |
| 251 | } | |
| 252 | // Not checked by attr target checking | |
| 253 | DefKind::Fn | DefKind::Static { .. } => Err(tcx.dcx().emit_err(EiiDefkindMismatch { | |
| 254 | span: eii_attr_span, | |
| 255 | eii_name, | |
| 256 | expected_kind: expected_kind.descr(foreign_item), | |
| 257 | })), | |
| 258 | // Checked by attr target checking | |
| 259 | _ => Err(tcx.dcx().delayed_bug("Attribute should not be allowed by target checking")), | |
| 260 | } | |
| 261 | } | |
| 262 | ||
| 155 | 263 | /// Checks a bunch of different properties of the impl/trait methods for |
| 156 | 264 | /// compatibility, such as asyncness, number of argument, self receiver kind, |
| 157 | 265 | /// and number of early- and late-bound generics. |
| ... | ... | @@ -451,7 +559,3 @@ fn get_declaration_sig<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Option<&' |
| 451 | 559 | let hir_id: HirId = tcx.local_def_id_to_hir_id(def_id); |
| 452 | 560 | tcx.hir_fn_sig_by_hir_id(hir_id) |
| 453 | 561 | } |
| 454 | ||
| 455 | fn is_foreign_function(tcx: TyCtxt<'_>, def_id: DefId) -> bool { | |
| 456 | tcx.is_foreign_item(def_id) && matches!(tcx.def_kind(def_id), DefKind::Fn) | |
| 457 | } |
compiler/rustc_hir_analysis/src/check/wfcheck.rs+34-3| ... | ... | @@ -41,7 +41,7 @@ use rustc_trait_selection::traits::{ |
| 41 | 41 | }; |
| 42 | 42 | use tracing::{debug, instrument}; |
| 43 | 43 | |
| 44 | use super::compare_eii::compare_eii_function_types; | |
| 44 | use super::compare_eii::{compare_eii_function_types, compare_eii_statics}; | |
| 45 | 45 | use crate::autoderef::Autoderef; |
| 46 | 46 | use crate::constrained_generic_params::{Parameter, identify_constrained_generic_params}; |
| 47 | 47 | use crate::errors; |
| ... | ... | @@ -1208,7 +1208,7 @@ fn check_item_fn( |
| 1208 | 1208 | decl: &hir::FnDecl<'_>, |
| 1209 | 1209 | ) -> Result<(), ErrorGuaranteed> { |
| 1210 | 1210 | enter_wf_checking_ctxt(tcx, def_id, |wfcx| { |
| 1211 | check_eiis(tcx, def_id); | |
| 1211 | check_eiis_fn(tcx, def_id); | |
| 1212 | 1212 | |
| 1213 | 1213 | let sig = tcx.fn_sig(def_id).instantiate_identity(); |
| 1214 | 1214 | check_fn_or_method(wfcx, sig, decl, def_id); |
| ... | ... | @@ -1216,7 +1216,7 @@ fn check_item_fn( |
| 1216 | 1216 | }) |
| 1217 | 1217 | } |
| 1218 | 1218 | |
| 1219 | fn check_eiis(tcx: TyCtxt<'_>, def_id: LocalDefId) { | |
| 1219 | fn check_eiis_fn(tcx: TyCtxt<'_>, def_id: LocalDefId) { | |
| 1220 | 1220 | // does the function have an EiiImpl attribute? that contains the defid of a *macro* |
| 1221 | 1221 | // that was used to mark the implementation. This is a two step process. |
| 1222 | 1222 | for EiiImpl { resolution, span, .. } in |
| ... | ... | @@ -1243,6 +1243,33 @@ fn check_eiis(tcx: TyCtxt<'_>, def_id: LocalDefId) { |
| 1243 | 1243 | } |
| 1244 | 1244 | } |
| 1245 | 1245 | |
| 1246 | fn check_eiis_static<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId, ty: Ty<'tcx>) { | |
| 1247 | // does the function have an EiiImpl attribute? that contains the defid of a *macro* | |
| 1248 | // that was used to mark the implementation. This is a two step process. | |
| 1249 | for EiiImpl { resolution, span, .. } in | |
| 1250 | find_attr!(tcx, def_id, EiiImpls(impls) => impls).into_iter().flatten() | |
| 1251 | { | |
| 1252 | let (foreign_item, name) = match resolution { | |
| 1253 | EiiImplResolution::Macro(def_id) => { | |
| 1254 | // we expect this macro to have the `EiiMacroFor` attribute, that points to a function | |
| 1255 | // signature that we'd like to compare the function we're currently checking with | |
| 1256 | if let Some(foreign_item) = | |
| 1257 | find_attr!(tcx, *def_id, EiiDeclaration(EiiDecl {foreign_item: t, ..}) => *t) | |
| 1258 | { | |
| 1259 | (foreign_item, tcx.item_name(*def_id)) | |
| 1260 | } else { | |
| 1261 | tcx.dcx().span_delayed_bug(*span, "resolved to something that's not an EII"); | |
| 1262 | continue; | |
| 1263 | } | |
| 1264 | } | |
| 1265 | EiiImplResolution::Known(decl) => (decl.foreign_item, decl.name.name), | |
| 1266 | EiiImplResolution::Error(_eg) => continue, | |
| 1267 | }; | |
| 1268 | ||
| 1269 | let _ = compare_eii_statics(tcx, def_id, ty, foreign_item, name, *span); | |
| 1270 | } | |
| 1271 | } | |
| 1272 | ||
| 1246 | 1273 | #[instrument(level = "debug", skip(tcx))] |
| 1247 | 1274 | pub(crate) fn check_static_item<'tcx>( |
| 1248 | 1275 | tcx: TyCtxt<'tcx>, |
| ... | ... | @@ -1251,6 +1278,10 @@ pub(crate) fn check_static_item<'tcx>( |
| 1251 | 1278 | should_check_for_sync: bool, |
| 1252 | 1279 | ) -> Result<(), ErrorGuaranteed> { |
| 1253 | 1280 | enter_wf_checking_ctxt(tcx, item_id, |wfcx| { |
| 1281 | if should_check_for_sync { | |
| 1282 | check_eiis_static(tcx, item_id, ty); | |
| 1283 | } | |
| 1284 | ||
| 1254 | 1285 | let span = tcx.ty_span(item_id); |
| 1255 | 1286 | let loc = Some(WellFormedLoc::Ty(item_id)); |
| 1256 | 1287 | let item_ty = wfcx.deeply_normalize(span, loc, ty); |
compiler/rustc_hir_analysis/src/errors.rs+25| ... | ... | @@ -1933,3 +1933,28 @@ pub(crate) struct ImplUnpinForPinProjectedType { |
| 1933 | 1933 | pub adt_span: Span, |
| 1934 | 1934 | pub adt_name: Symbol, |
| 1935 | 1935 | } |
| 1936 | ||
| 1937 | #[derive(Diagnostic)] | |
| 1938 | #[diag("`#[{$eii_name}]` must be used on a {$expected_kind}")] | |
| 1939 | pub(crate) struct EiiDefkindMismatch { | |
| 1940 | #[primary_span] | |
| 1941 | pub span: Span, | |
| 1942 | pub eii_name: Symbol, | |
| 1943 | pub expected_kind: &'static str, | |
| 1944 | } | |
| 1945 | ||
| 1946 | #[derive(Diagnostic)] | |
| 1947 | #[diag("mutability does not match with the definition of`#[{$eii_name}]`")] | |
| 1948 | pub(crate) struct EiiDefkindMismatchStaticMutability { | |
| 1949 | #[primary_span] | |
| 1950 | pub span: Span, | |
| 1951 | pub eii_name: Symbol, | |
| 1952 | } | |
| 1953 | ||
| 1954 | #[derive(Diagnostic)] | |
| 1955 | #[diag("safety does not match with the definition of`#[{$eii_name}]`")] | |
| 1956 | pub(crate) struct EiiDefkindMismatchStaticSafety { | |
| 1957 | #[primary_span] | |
| 1958 | pub span: Span, | |
| 1959 | pub eii_name: Symbol, | |
| 1960 | } |
compiler/rustc_hir_typeck/src/expr.rs+4-1| ... | ... | @@ -3557,6 +3557,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { |
| 3557 | 3557 | // Register the impl's predicates. One of these predicates |
| 3558 | 3558 | // must be unsatisfied, or else we wouldn't have gotten here |
| 3559 | 3559 | // in the first place. |
| 3560 | let unnormalized_predicates = | |
| 3561 | self.tcx.predicates_of(impl_def_id).instantiate(self.tcx, impl_args); | |
| 3560 | 3562 | ocx.register_obligations(traits::predicates_for_generics( |
| 3561 | 3563 | |idx, span| { |
| 3562 | 3564 | cause.clone().derived_cause( |
| ... | ... | @@ -3574,8 +3576,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { |
| 3574 | 3576 | }, |
| 3575 | 3577 | ) |
| 3576 | 3578 | }, |
| 3579 | |pred| ocx.normalize(&cause, self.param_env, pred), | |
| 3577 | 3580 | self.param_env, |
| 3578 | self.tcx.predicates_of(impl_def_id).instantiate(self.tcx, impl_args), | |
| 3581 | unnormalized_predicates, | |
| 3579 | 3582 | )); |
| 3580 | 3583 | |
| 3581 | 3584 | // Normalize the output type, which we can use later on as the |
compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs+2-15| ... | ... | @@ -423,20 +423,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { |
| 423 | 423 | } |
| 424 | 424 | } |
| 425 | 425 | |
| 426 | /// Instantiates and normalizes the bounds for a given item | |
| 427 | pub(crate) fn instantiate_bounds( | |
| 428 | &self, | |
| 429 | span: Span, | |
| 430 | def_id: DefId, | |
| 431 | args: GenericArgsRef<'tcx>, | |
| 432 | ) -> ty::InstantiatedPredicates<'tcx> { | |
| 433 | let bounds = self.tcx.predicates_of(def_id); | |
| 434 | let result = bounds.instantiate(self.tcx, args); | |
| 435 | let result = self.normalize(span, result); | |
| 436 | debug!("instantiate_bounds(bounds={:?}, args={:?}) = {:?}", bounds, args, result); | |
| 437 | result | |
| 438 | } | |
| 439 | ||
| 440 | 426 | pub(crate) fn normalize<T>(&self, span: Span, value: T) -> T |
| 441 | 427 | where |
| 442 | 428 | T: TypeFoldable<TyCtxt<'tcx>>, |
| ... | ... | @@ -1426,10 +1412,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { |
| 1426 | 1412 | ) { |
| 1427 | 1413 | let param_env = self.param_env; |
| 1428 | 1414 | |
| 1429 | let bounds = self.instantiate_bounds(span, def_id, args); | |
| 1415 | let bounds = self.tcx.predicates_of(def_id).instantiate(self.tcx, args); | |
| 1430 | 1416 | |
| 1431 | 1417 | for obligation in traits::predicates_for_generics( |
| 1432 | 1418 | |idx, predicate_span| self.cause(span, code(idx, predicate_span)), |
| 1419 | |pred| self.normalize(span, pred), | |
| 1433 | 1420 | param_env, |
| 1434 | 1421 | bounds, |
| 1435 | 1422 | ) { |
compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs+1-1| ... | ... | @@ -339,9 +339,9 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> { |
| 339 | 339 | |
| 340 | 340 | // Check whether the impl imposes obligations we have to worry about. |
| 341 | 341 | let impl_bounds = tcx.predicates_of(impl_).instantiate(tcx, impl_args); |
| 342 | let impl_bounds = ocx.normalize(&ObligationCause::dummy(), self.param_env, impl_bounds); | |
| 343 | 342 | let impl_obligations = traits::predicates_for_generics( |
| 344 | 343 | |_, _| ObligationCause::dummy(), |
| 344 | |pred| ocx.normalize(&ObligationCause::dummy(), self.param_env, pred), | |
| 345 | 345 | self.param_env, |
| 346 | 346 | impl_bounds, |
| 347 | 347 | ); |
compiler/rustc_hir_typeck/src/method/confirm.rs+2-2| ... | ... | @@ -144,8 +144,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { |
| 144 | 144 | ); |
| 145 | 145 | self.unify_receivers(self_ty, method_sig_rcvr, pick); |
| 146 | 146 | |
| 147 | let (method_sig, method_predicates) = | |
| 148 | self.normalize(self.span, (method_sig, method_predicates)); | |
| 147 | let method_sig = self.normalize(self.span, method_sig); | |
| 149 | 148 | |
| 150 | 149 | // Make sure nobody calls `drop()` explicitly. |
| 151 | 150 | self.check_for_illegal_method_calls(pick); |
| ... | ... | @@ -626,6 +625,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { |
| 626 | 625 | ); |
| 627 | 626 | self.cause(self.span, code) |
| 628 | 627 | }, |
| 628 | |pred| self.normalize(self.call_expr.span, pred), | |
| 629 | 629 | self.param_env, |
| 630 | 630 | method_predicates, |
| 631 | 631 | ) { |
compiler/rustc_hir_typeck/src/method/mod.rs+9-5| ... | ... | @@ -442,17 +442,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { |
| 442 | 442 | // any late-bound regions appearing in its bounds. |
| 443 | 443 | let bounds = self.tcx.predicates_of(def_id).instantiate(self.tcx, args); |
| 444 | 444 | |
| 445 | let InferOk { value: bounds, obligations: o } = | |
| 446 | self.at(&obligation.cause, self.param_env).normalize(bounds); | |
| 447 | obligations.extend(o); | |
| 448 | assert!(!bounds.has_escaping_bound_vars()); | |
| 449 | ||
| 450 | 445 | let predicates_cause = obligation.cause.clone(); |
| 446 | let mut normalization_obligations = PredicateObligations::new(); | |
| 451 | 447 | obligations.extend(traits::predicates_for_generics( |
| 452 | 448 | move |_, _| predicates_cause.clone(), |
| 449 | |pred| { | |
| 450 | let InferOk { value: pred, obligations: o } = | |
| 451 | self.at(&obligation.cause, self.param_env).normalize(pred); | |
| 452 | normalization_obligations.extend(o); | |
| 453 | assert!(!pred.has_escaping_bound_vars()); | |
| 454 | pred | |
| 455 | }, | |
| 453 | 456 | self.param_env, |
| 454 | 457 | bounds, |
| 455 | 458 | )); |
| 459 | obligations.extend(normalization_obligations); | |
| 456 | 460 | |
| 457 | 461 | // Also add an obligation for the method type being well-formed. |
| 458 | 462 | debug!( |
compiler/rustc_hir_typeck/src/method/probe.rs+1-1| ... | ... | @@ -1989,7 +1989,6 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { |
| 1989 | 1989 | let impl_def_id = probe.item.container_id(self.tcx); |
| 1990 | 1990 | let impl_bounds = |
| 1991 | 1991 | self.tcx.predicates_of(impl_def_id).instantiate(self.tcx, impl_args); |
| 1992 | let impl_bounds = ocx.normalize(cause, self.param_env, impl_bounds); | |
| 1993 | 1992 | // Convert the bounds into obligations. |
| 1994 | 1993 | ocx.register_obligations(traits::predicates_for_generics( |
| 1995 | 1994 | |idx, span| { |
| ... | ... | @@ -2001,6 +2000,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { |
| 2001 | 2000 | ); |
| 2002 | 2001 | self.cause(self.span, code) |
| 2003 | 2002 | }, |
| 2003 | |pred| ocx.normalize(cause, self.param_env, pred), | |
| 2004 | 2004 | self.param_env, |
| 2005 | 2005 | impl_bounds, |
| 2006 | 2006 | )); |
compiler/rustc_lint_defs/src/builtin.rs+46| ... | ... | @@ -37,6 +37,7 @@ declare_lint_pass! { |
| 37 | 37 | DEPENDENCY_ON_UNIT_NEVER_TYPE_FALLBACK, |
| 38 | 38 | DEPRECATED, |
| 39 | 39 | DEPRECATED_IN_FUTURE, |
| 40 | DEPRECATED_LLVM_INTRINSIC, | |
| 40 | 41 | DEPRECATED_SAFE_2024, |
| 41 | 42 | DEPRECATED_WHERE_CLAUSE_LOCATION, |
| 42 | 43 | DUPLICATE_FEATURES, |
| ... | ... | @@ -5597,3 +5598,48 @@ declare_lint! { |
| 5597 | 5598 | report_in_deps: false, |
| 5598 | 5599 | }; |
| 5599 | 5600 | } |
| 5601 | ||
| 5602 | declare_lint! { | |
| 5603 | /// The `deprecated_llvm_intrinsic` lint detects usage of deprecated LLVM intrinsics. | |
| 5604 | /// | |
| 5605 | /// ### Example | |
| 5606 | /// | |
| 5607 | /// ```rust,ignore (requires x86) | |
| 5608 | /// #![cfg(any(target_arch = "x86", target_arch = "x86_64"))] | |
| 5609 | /// #![feature(link_llvm_intrinsics, abi_unadjusted)] | |
| 5610 | /// #![deny(deprecated_llvm_intrinsic)] | |
| 5611 | /// | |
| 5612 | /// unsafe extern "unadjusted" { | |
| 5613 | /// #[link_name = "llvm.x86.addcarryx.u32"] | |
| 5614 | /// fn foo(a: u8, b: u32, c: u32, d: &mut u32) -> u8; | |
| 5615 | /// } | |
| 5616 | /// | |
| 5617 | /// #[inline(never)] | |
| 5618 | /// #[target_feature(enable = "adx")] | |
| 5619 | /// pub fn bar(a: u8, b: u32, c: u32, d: &mut u32) -> u8 { | |
| 5620 | /// unsafe { foo(a, b, c, d) } | |
| 5621 | /// } | |
| 5622 | /// ``` | |
| 5623 | /// | |
| 5624 | /// This will produce: | |
| 5625 | /// | |
| 5626 | /// ```text | |
| 5627 | /// error: Using deprecated intrinsic `llvm.x86.addcarryx.u32` | |
| 5628 | /// --> example.rs:7:5 | |
| 5629 | /// | | |
| 5630 | /// 7 | fn foo(a: u8, b: u32, c: u32, d: &mut u32) -> u8; | |
| 5631 | /// | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
| 5632 | /// | | |
| 5633 | /// ``` | |
| 5634 | /// | |
| 5635 | /// ### Explanation | |
| 5636 | /// | |
| 5637 | /// LLVM periodically updates its list of intrinsics. Deprecated intrinsics are unlikely | |
| 5638 | /// to be removed, but they may optimize less well than their new versions, so it's | |
| 5639 | /// best to use the new version. Also, some deprecated intrinsics might have buggy | |
| 5640 | /// behavior | |
| 5641 | pub DEPRECATED_LLVM_INTRINSIC, | |
| 5642 | Allow, | |
| 5643 | "detects uses of deprecated LLVM intrinsics", | |
| 5644 | @feature_gate = link_llvm_intrinsics; | |
| 5645 | } |
compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp+14| ... | ... | @@ -9,6 +9,7 @@ |
| 9 | 9 | #include "llvm/ADT/StringRef.h" |
| 10 | 10 | #include "llvm/BinaryFormat/Magic.h" |
| 11 | 11 | #include "llvm/Bitcode/BitcodeWriter.h" |
| 12 | #include "llvm/IR/AutoUpgrade.h" | |
| 12 | 13 | #include "llvm/IR/DIBuilder.h" |
| 13 | 14 | #include "llvm/IR/DebugInfoMetadata.h" |
| 14 | 15 | #include "llvm/IR/DiagnosticHandler.h" |
| ... | ... | @@ -1815,6 +1816,19 @@ extern "C" void LLVMRustSetNoSanitizeHWAddress(LLVMValueRef Global) { |
| 1815 | 1816 | GV.setSanitizerMetadata(MD); |
| 1816 | 1817 | } |
| 1817 | 1818 | |
| 1819 | extern "C" bool LLVMRustUpgradeIntrinsicFunction(LLVMValueRef Fn, | |
| 1820 | LLVMValueRef *NewFn) { | |
| 1821 | Function *F = unwrap<Function>(Fn); | |
| 1822 | Function *NewF = nullptr; | |
| 1823 | bool CanUpgrade = UpgradeIntrinsicFunction(F, NewF, false); | |
| 1824 | *NewFn = wrap(NewF); | |
| 1825 | return CanUpgrade; | |
| 1826 | } | |
| 1827 | ||
| 1828 | extern "C" bool LLVMRustIsTargetIntrinsic(unsigned ID) { | |
| 1829 | return Intrinsic::isTargetIntrinsic(ID); | |
| 1830 | } | |
| 1831 | ||
| 1818 | 1832 | // Statically assert that the fixed metadata kind IDs declared in |
| 1819 | 1833 | // `metadata_kind.rs` match the ones actually used by LLVM. |
| 1820 | 1834 | #define FIXED_MD_KIND(VARIANT, VALUE) \ |
compiler/rustc_middle/src/queries.rs+3-3| ... | ... | @@ -60,7 +60,7 @@ use rustc_data_structures::sorted_map::SortedMap; |
| 60 | 60 | use rustc_data_structures::steal::Steal; |
| 61 | 61 | use rustc_data_structures::svh::Svh; |
| 62 | 62 | use rustc_data_structures::unord::{UnordMap, UnordSet}; |
| 63 | use rustc_errors::ErrorGuaranteed; | |
| 63 | use rustc_errors::{ErrorGuaranteed, catch_fatal_errors}; | |
| 64 | 64 | use rustc_hir as hir; |
| 65 | 65 | use rustc_hir::attrs::{EiiDecl, EiiImpl, StrippedCfgItem}; |
| 66 | 66 | use rustc_hir::def::{DefKind, DocLinkResMap}; |
| ... | ... | @@ -1202,7 +1202,7 @@ rustc_queries! { |
| 1202 | 1202 | /// Return the live symbols in the crate for dead code check. |
| 1203 | 1203 | /// |
| 1204 | 1204 | /// The second return value maps from ADTs to ignored derived traits (e.g. Debug and Clone). |
| 1205 | query live_symbols_and_ignored_derived_traits(_: ()) -> &'tcx Result<( | |
| 1205 | query live_symbols_and_ignored_derived_traits(_: ()) -> Result<&'tcx ( | |
| 1206 | 1206 | LocalDefIdSet, |
| 1207 | 1207 | LocalDefIdMap<FxIndexSet<DefId>>, |
| 1208 | 1208 | ), ErrorGuaranteed> { |
| ... | ... | @@ -1292,7 +1292,7 @@ rustc_queries! { |
| 1292 | 1292 | |
| 1293 | 1293 | /// Return the set of (transitive) callees that may result in a recursive call to `key`, |
| 1294 | 1294 | /// if we were able to walk all callees. |
| 1295 | query mir_callgraph_cyclic(key: LocalDefId) -> &'tcx Option<UnordSet<LocalDefId>> { | |
| 1295 | query mir_callgraph_cyclic(key: LocalDefId) -> Option<&'tcx UnordSet<LocalDefId>> { | |
| 1296 | 1296 | arena_cache |
| 1297 | 1297 | desc { |
| 1298 | 1298 | "computing (transitive) callees of `{}` that may recurse", |
compiler/rustc_middle/src/query/arena_cached.rs+16| ... | ... | @@ -1,6 +1,7 @@ |
| 1 | 1 | use std::mem; |
| 2 | 2 | |
| 3 | 3 | use rustc_arena::TypedArena; |
| 4 | use rustc_span::ErrorGuaranteed; | |
| 4 | 5 | |
| 5 | 6 | use crate::ty::TyCtxt; |
| 6 | 7 | |
| ... | ... | @@ -51,6 +52,21 @@ impl<'tcx, T> ArenaCached<'tcx> for Option<&'tcx T> { |
| 51 | 52 | } |
| 52 | 53 | } |
| 53 | 54 | |
| 55 | impl<'tcx, T> ArenaCached<'tcx> for Result<&'tcx T, ErrorGuaranteed> { | |
| 56 | type Provided = Result<T, ErrorGuaranteed>; | |
| 57 | /// The provide value is `Result<T, ErrorGuaranteed>`, but we only store `T` in the arena. | |
| 58 | type Allocated = T; | |
| 59 | ||
| 60 | fn alloc_in_arena( | |
| 61 | tcx: TyCtxt<'tcx>, | |
| 62 | typed_arena: &'tcx TypedArena<T>, | |
| 63 | value: Result<T, ErrorGuaranteed>, | |
| 64 | ) -> Self { | |
| 65 | // Don't store Err(ErrorGuaranteed) in the arena, and wrap the allocated reference in Ok. | |
| 66 | try { do_alloc(tcx, typed_arena, value?) } | |
| 67 | } | |
| 68 | } | |
| 69 | ||
| 54 | 70 | /// Allocates a value in either its dedicated arena, or in the common dropless |
| 55 | 71 | /// arena, depending on whether it needs to be dropped. |
| 56 | 72 | fn do_alloc<'tcx, T>(tcx: TyCtxt<'tcx>, typed_arena: &'tcx TypedArena<T>, value: T) -> &'tcx T { |
compiler/rustc_middle/src/query/plumbing.rs+12| ... | ... | @@ -166,6 +166,8 @@ pub struct QuerySystem<'tcx> { |
| 166 | 166 | pub extern_providers: ExternProviders, |
| 167 | 167 | |
| 168 | 168 | pub jobs: AtomicU64, |
| 169 | ||
| 170 | pub cycle_handler_nesting: Lock<u8>, | |
| 169 | 171 | } |
| 170 | 172 | |
| 171 | 173 | #[derive(Copy, Clone)] |
| ... | ... | @@ -446,6 +448,11 @@ macro_rules! define_callbacks { |
| 446 | 448 | } |
| 447 | 449 | } |
| 448 | 450 | |
| 451 | /// Calls `self.description` or returns a fallback if there was a fatal error | |
| 452 | pub fn catch_description(&self, tcx: TyCtxt<'tcx>) -> String { | |
| 453 | catch_fatal_errors(|| self.description(tcx)).unwrap_or_else(|_| format!("<error describing {}>", self.query_name())) | |
| 454 | } | |
| 455 | ||
| 449 | 456 | /// Returns the default span for this query if `span` is a dummy span. |
| 450 | 457 | pub fn default_span(&self, tcx: TyCtxt<'tcx>, span: Span) -> Span { |
| 451 | 458 | if !span.is_dummy() { |
| ... | ... | @@ -463,6 +470,11 @@ macro_rules! define_callbacks { |
| 463 | 470 | )* |
| 464 | 471 | } |
| 465 | 472 | } |
| 473 | ||
| 474 | /// Calls `self.default_span` or returns `DUMMY_SP` if there was a fatal error | |
| 475 | pub fn catch_default_span(&self, tcx: TyCtxt<'tcx>, span: Span) -> Span { | |
| 476 | catch_fatal_errors(|| self.default_span(tcx, span)).unwrap_or(DUMMY_SP) | |
| 477 | } | |
| 466 | 478 | } |
| 467 | 479 | |
| 468 | 480 | /// Holds a `QueryVTable` for each query. |
compiler/rustc_middle/src/ty/mod.rs+1-1| ... | ... | @@ -689,7 +689,7 @@ impl<'tcx> TermKind<'tcx> { |
| 689 | 689 | /// `[[], [U:Bar<T>]]`. Now if there were some particular reference |
| 690 | 690 | /// like `Foo<isize,usize>`, then the `InstantiatedPredicates` would be `[[], |
| 691 | 691 | /// [usize:Bar<isize>]]`. |
| 692 | #[derive(Clone, Debug, TypeFoldable, TypeVisitable)] | |
| 692 | #[derive(Clone, Debug)] | |
| 693 | 693 | pub struct InstantiatedPredicates<'tcx> { |
| 694 | 694 | pub predicates: Vec<Clause<'tcx>>, |
| 695 | 695 | pub spans: Vec<Span>, |
compiler/rustc_parse/src/parser/item.rs+11-1| ... | ... | @@ -1235,6 +1235,7 @@ impl<'a> Parser<'a> { |
| 1235 | 1235 | mutability: _, |
| 1236 | 1236 | expr, |
| 1237 | 1237 | define_opaque, |
| 1238 | eii_impls: _, | |
| 1238 | 1239 | }) => { |
| 1239 | 1240 | self.dcx().emit_err(errors::AssociatedStaticItemNotAllowed { span }); |
| 1240 | 1241 | AssocItemKind::Const(Box::new(ConstItem { |
| ... | ... | @@ -1503,6 +1504,7 @@ impl<'a> Parser<'a> { |
| 1503 | 1504 | }, |
| 1504 | 1505 | safety: Safety::Default, |
| 1505 | 1506 | define_opaque: None, |
| 1507 | eii_impls: ThinVec::default(), | |
| 1506 | 1508 | })) |
| 1507 | 1509 | } |
| 1508 | 1510 | _ => return self.error_bad_item_kind(span, &kind, "`extern` blocks"), |
| ... | ... | @@ -1636,7 +1638,15 @@ impl<'a> Parser<'a> { |
| 1636 | 1638 | |
| 1637 | 1639 | self.expect_semi()?; |
| 1638 | 1640 | |
| 1639 | let item = StaticItem { ident, ty, safety, mutability, expr, define_opaque: None }; | |
| 1641 | let item = StaticItem { | |
| 1642 | ident, | |
| 1643 | ty, | |
| 1644 | safety, | |
| 1645 | mutability, | |
| 1646 | expr, | |
| 1647 | define_opaque: None, | |
| 1648 | eii_impls: ThinVec::default(), | |
| 1649 | }; | |
| 1640 | 1650 | Ok(ItemKind::Static(Box::new(item))) |
| 1641 | 1651 | } |
| 1642 | 1652 |
compiler/rustc_passes/src/check_attr.rs+2-2| ... | ... | @@ -552,9 +552,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> { |
| 552 | 552 | fn check_eii_impl(&self, impls: &[EiiImpl], target: Target) { |
| 553 | 553 | for EiiImpl { span, inner_span, resolution, impl_marked_unsafe, is_default: _ } in impls { |
| 554 | 554 | match target { |
| 555 | Target::Fn => {} | |
| 555 | Target::Fn | Target::Static => {} | |
| 556 | 556 | _ => { |
| 557 | self.dcx().emit_err(errors::EiiImplNotFunction { span: *span }); | |
| 557 | self.dcx().emit_err(errors::EiiImplTarget { span: *span }); | |
| 558 | 558 | } |
| 559 | 559 | } |
| 560 | 560 |
compiler/rustc_passes/src/errors.rs+2-2| ... | ... | @@ -1189,8 +1189,8 @@ pub(crate) struct ReprAlignShouldBeAlignStatic { |
| 1189 | 1189 | } |
| 1190 | 1190 | |
| 1191 | 1191 | #[derive(Diagnostic)] |
| 1192 | #[diag("`eii_macro_for` is only valid on functions")] | |
| 1193 | pub(crate) struct EiiImplNotFunction { | |
| 1192 | #[diag("`eii_macro_for` is only valid on functions and statics")] | |
| 1193 | pub(crate) struct EiiImplTarget { | |
| 1194 | 1194 | #[primary_span] |
| 1195 | 1195 | pub span: Span, |
| 1196 | 1196 | } |
compiler/rustc_query_impl/src/error.rs+25| ... | ... | @@ -79,3 +79,28 @@ pub(crate) struct Cycle { |
| 79 | 79 | )] |
| 80 | 80 | pub note_span: (), |
| 81 | 81 | } |
| 82 | ||
| 83 | #[derive(Subdiagnostic)] | |
| 84 | #[note("...when {$stack_bottom}")] | |
| 85 | pub(crate) struct NestedCycleBottom { | |
| 86 | pub stack_bottom: String, | |
| 87 | } | |
| 88 | ||
| 89 | #[derive(Diagnostic)] | |
| 90 | #[diag("internal compiler error: query cycle when printing cycle detected")] | |
| 91 | pub(crate) struct NestedCycle { | |
| 92 | #[primary_span] | |
| 93 | pub span: Span, | |
| 94 | #[subdiagnostic] | |
| 95 | pub stack_bottom: NestedCycleBottom, | |
| 96 | #[subdiagnostic] | |
| 97 | pub cycle_stack: Vec<CycleStack>, | |
| 98 | #[subdiagnostic] | |
| 99 | pub stack_count: StackCount, | |
| 100 | #[subdiagnostic] | |
| 101 | pub cycle_usage: Option<CycleUsage>, | |
| 102 | #[note( | |
| 103 | "see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information" | |
| 104 | )] | |
| 105 | pub note_span: (), | |
| 106 | } |
compiler/rustc_query_impl/src/execution.rs+25-3| ... | ... | @@ -4,7 +4,7 @@ use std::mem::ManuallyDrop; |
| 4 | 4 | use rustc_data_structures::hash_table::{Entry, HashTable}; |
| 5 | 5 | use rustc_data_structures::stack::ensure_sufficient_stack; |
| 6 | 6 | use rustc_data_structures::sync::{DynSend, DynSync}; |
| 7 | use rustc_data_structures::{outline, sharded, sync}; | |
| 7 | use rustc_data_structures::{defer, outline, sharded, sync}; | |
| 8 | 8 | use rustc_errors::FatalError; |
| 9 | 9 | use rustc_middle::dep_graph::{DepGraphData, DepNodeKey, SerializedDepNodeIndex}; |
| 10 | 10 | use rustc_middle::query::{ |
| ... | ... | @@ -17,6 +17,7 @@ use rustc_span::{DUMMY_SP, Span}; |
| 17 | 17 | use tracing::warn; |
| 18 | 18 | |
| 19 | 19 | use crate::dep_graph::{DepNode, DepNodeIndex}; |
| 20 | use crate::handle_cycle_error; | |
| 20 | 21 | use crate::job::{QueryJobInfo, QueryJobMap, create_cycle_error, find_cycle_in_stack}; |
| 21 | 22 | use crate::plumbing::{current_query_job, loadable_from_disk, next_job_id, start_query}; |
| 22 | 23 | use crate::query_impl::for_each_query_vtable; |
| ... | ... | @@ -114,8 +115,29 @@ fn handle_cycle<'tcx, C: QueryCache>( |
| 114 | 115 | key: C::Key, |
| 115 | 116 | cycle: Cycle<'tcx>, |
| 116 | 117 | ) -> C::Value { |
| 117 | let error = create_cycle_error(tcx, &cycle); | |
| 118 | (query.handle_cycle_error_fn)(tcx, key, cycle, error) | |
| 118 | let nested; | |
| 119 | { | |
| 120 | let mut nesting = tcx.query_system.cycle_handler_nesting.lock(); | |
| 121 | nested = match *nesting { | |
| 122 | 0 => false, | |
| 123 | 1 => true, | |
| 124 | _ => { | |
| 125 | // Don't print further nested errors to avoid cases of infinite recursion | |
| 126 | tcx.dcx().delayed_bug("doubly nested cycle error").raise_fatal() | |
| 127 | } | |
| 128 | }; | |
| 129 | *nesting += 1; | |
| 130 | } | |
| 131 | let _guard = defer(|| *tcx.query_system.cycle_handler_nesting.lock() -= 1); | |
| 132 | ||
| 133 | let error = create_cycle_error(tcx, &cycle, nested); | |
| 134 | ||
| 135 | if nested { | |
| 136 | // Avoid custom handlers and only use the robust `create_cycle_error` for nested cycle errors | |
| 137 | handle_cycle_error::default(error) | |
| 138 | } else { | |
| 139 | (query.handle_cycle_error_fn)(tcx, key, cycle, error) | |
| 140 | } | |
| 119 | 141 | } |
| 120 | 142 | |
| 121 | 143 | /// Guard object representing the responsibility to execute a query job and |
compiler/rustc_query_impl/src/handle_cycle_error.rs+1-1| ... | ... | @@ -210,7 +210,7 @@ pub(crate) fn layout_of<'tcx>( |
| 210 | 210 | ControlFlow::Continue(()) |
| 211 | 211 | } |
| 212 | 212 | }, |
| 213 | || create_cycle_error(tcx, &cycle), | |
| 213 | || create_cycle_error(tcx, &cycle, false), | |
| 214 | 214 | ); |
| 215 | 215 | |
| 216 | 216 | diag.emit().raise_fatal() |
compiler/rustc_query_impl/src/job.rs+35-21| ... | ... | @@ -413,15 +413,16 @@ pub fn print_query_stack<'tcx>( |
| 413 | 413 | pub(crate) fn create_cycle_error<'tcx>( |
| 414 | 414 | tcx: TyCtxt<'tcx>, |
| 415 | 415 | Cycle { usage, frames }: &Cycle<'tcx>, |
| 416 | nested: bool, | |
| 416 | 417 | ) -> Diag<'tcx> { |
| 417 | 418 | assert!(!frames.is_empty()); |
| 418 | 419 | |
| 419 | let span = frames[0].tagged_key.default_span(tcx, frames[1 % frames.len()].span); | |
| 420 | let span = frames[0].tagged_key.catch_default_span(tcx, frames[1 % frames.len()].span); | |
| 420 | 421 | |
| 421 | 422 | let mut cycle_stack = Vec::new(); |
| 422 | 423 | |
| 423 | 424 | use crate::error::StackCount; |
| 424 | let stack_bottom = frames[0].tagged_key.description(tcx); | |
| 425 | let stack_bottom = frames[0].tagged_key.catch_description(tcx); | |
| 425 | 426 | let stack_count = if frames.len() == 1 { |
| 426 | 427 | StackCount::Single { stack_bottom: stack_bottom.clone() } |
| 427 | 428 | } else { |
| ... | ... | @@ -430,14 +431,14 @@ pub(crate) fn create_cycle_error<'tcx>( |
| 430 | 431 | |
| 431 | 432 | for i in 1..frames.len() { |
| 432 | 433 | let frame = &frames[i]; |
| 433 | let span = frame.tagged_key.default_span(tcx, frames[(i + 1) % frames.len()].span); | |
| 434 | let span = frame.tagged_key.catch_default_span(tcx, frames[(i + 1) % frames.len()].span); | |
| 434 | 435 | cycle_stack |
| 435 | .push(crate::error::CycleStack { span, desc: frame.tagged_key.description(tcx) }); | |
| 436 | .push(crate::error::CycleStack { span, desc: frame.tagged_key.catch_description(tcx) }); | |
| 436 | 437 | } |
| 437 | 438 | |
| 438 | 439 | let cycle_usage = usage.as_ref().map(|usage| crate::error::CycleUsage { |
| 439 | span: usage.tagged_key.default_span(tcx, usage.span), | |
| 440 | usage: usage.tagged_key.description(tcx), | |
| 440 | span: usage.tagged_key.catch_default_span(tcx, usage.span), | |
| 441 | usage: usage.tagged_key.catch_description(tcx), | |
| 441 | 442 | }); |
| 442 | 443 | |
| 443 | 444 | let is_all_def_kind = |def_kind| { |
| ... | ... | @@ -454,23 +455,36 @@ pub(crate) fn create_cycle_error<'tcx>( |
| 454 | 455 | }) |
| 455 | 456 | }; |
| 456 | 457 | |
| 457 | let alias = if is_all_def_kind(DefKind::TyAlias) { | |
| 458 | Some(crate::error::Alias::Ty) | |
| 459 | } else if is_all_def_kind(DefKind::TraitAlias) { | |
| 460 | Some(crate::error::Alias::Trait) | |
| 458 | let alias = if !nested { | |
| 459 | if is_all_def_kind(DefKind::TyAlias) { | |
| 460 | Some(crate::error::Alias::Ty) | |
| 461 | } else if is_all_def_kind(DefKind::TraitAlias) { | |
| 462 | Some(crate::error::Alias::Trait) | |
| 463 | } else { | |
| 464 | None | |
| 465 | } | |
| 461 | 466 | } else { |
| 462 | 467 | None |
| 463 | 468 | }; |
| 464 | 469 | |
| 465 | let cycle_diag = crate::error::Cycle { | |
| 466 | span, | |
| 467 | cycle_stack, | |
| 468 | stack_bottom, | |
| 469 | alias, | |
| 470 | cycle_usage, | |
| 471 | stack_count, | |
| 472 | note_span: (), | |
| 473 | }; | |
| 474 | ||
| 475 | tcx.sess.dcx().create_err(cycle_diag) | |
| 470 | if nested { | |
| 471 | tcx.sess.dcx().create_err(crate::error::NestedCycle { | |
| 472 | span, | |
| 473 | cycle_stack, | |
| 474 | stack_bottom: crate::error::NestedCycleBottom { stack_bottom }, | |
| 475 | cycle_usage, | |
| 476 | stack_count, | |
| 477 | note_span: (), | |
| 478 | }) | |
| 479 | } else { | |
| 480 | tcx.sess.dcx().create_err(crate::error::Cycle { | |
| 481 | span, | |
| 482 | cycle_stack, | |
| 483 | stack_bottom, | |
| 484 | alias, | |
| 485 | cycle_usage, | |
| 486 | stack_count, | |
| 487 | note_span: (), | |
| 488 | }) | |
| 489 | } | |
| 476 | 490 | } |
compiler/rustc_query_impl/src/lib.rs+2-1| ... | ... | @@ -8,7 +8,7 @@ |
| 8 | 8 | #![feature(try_blocks)] |
| 9 | 9 | // tidy-alphabetical-end |
| 10 | 10 | |
| 11 | use rustc_data_structures::sync::AtomicU64; | |
| 11 | use rustc_data_structures::sync::{AtomicU64, Lock}; | |
| 12 | 12 | use rustc_middle::dep_graph; |
| 13 | 13 | use rustc_middle::queries::{ExternProviders, Providers}; |
| 14 | 14 | use rustc_middle::query::on_disk_cache::OnDiskCache; |
| ... | ... | @@ -56,6 +56,7 @@ pub fn query_system<'tcx>( |
| 56 | 56 | local_providers, |
| 57 | 57 | extern_providers, |
| 58 | 58 | jobs: AtomicU64::new(1), |
| 59 | cycle_handler_nesting: Lock::new(0), | |
| 59 | 60 | } |
| 60 | 61 | } |
| 61 | 62 |
compiler/rustc_resolve/src/def_collector.rs+1| ... | ... | @@ -274,6 +274,7 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { |
| 274 | 274 | expr: _, |
| 275 | 275 | safety, |
| 276 | 276 | define_opaque: _, |
| 277 | eii_impls: _, | |
| 277 | 278 | }) => { |
| 278 | 279 | let safety = match safety { |
| 279 | 280 | ast::Safety::Unsafe(_) | ast::Safety::Default => hir::Safety::Unsafe, |
compiler/rustc_resolve/src/diagnostics.rs+1-1| ... | ... | @@ -2983,7 +2983,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { |
| 2983 | 2983 | } |
| 2984 | 2984 | |
| 2985 | 2985 | let binding_key = BindingKey::new(IdentKey::new(ident), MacroNS); |
| 2986 | let binding = self.resolution(crate_module, binding_key)?.binding()?; | |
| 2986 | let binding = self.resolution(crate_module, binding_key)?.best_decl()?; | |
| 2987 | 2987 | let Res::Def(DefKind::Macro(kinds), _) = binding.res() else { |
| 2988 | 2988 | return None; |
| 2989 | 2989 | }; |
compiler/rustc_resolve/src/effective_visibilities.rs+1-1| ... | ... | @@ -114,7 +114,7 @@ impl<'a, 'ra, 'tcx> EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx> { |
| 114 | 114 | fn set_bindings_effective_visibilities(&mut self, module_id: LocalDefId) { |
| 115 | 115 | let module = self.r.expect_module(module_id.to_def_id()); |
| 116 | 116 | for (_, name_resolution) in self.r.resolutions(module).borrow().iter() { |
| 117 | let Some(mut decl) = name_resolution.borrow().binding() else { | |
| 117 | let Some(mut decl) = name_resolution.borrow().best_decl() else { | |
| 118 | 118 | continue; |
| 119 | 119 | }; |
| 120 | 120 | // Set the given effective visibility level to `Level::Direct` and |
compiler/rustc_resolve/src/errors.rs+15-11| ... | ... | @@ -1521,20 +1521,24 @@ pub(crate) struct RedundantImportVisibility { |
| 1521 | 1521 | #[diag("unknown diagnostic attribute")] |
| 1522 | 1522 | pub(crate) struct UnknownDiagnosticAttribute { |
| 1523 | 1523 | #[subdiagnostic] |
| 1524 | pub typo: Option<UnknownDiagnosticAttributeTypoSugg>, | |
| 1524 | pub help: Option<UnknownDiagnosticAttributeHelp>, | |
| 1525 | 1525 | } |
| 1526 | 1526 | |
| 1527 | 1527 | #[derive(Subdiagnostic)] |
| 1528 | #[suggestion( | |
| 1529 | "an attribute with a similar name exists", | |
| 1530 | style = "verbose", | |
| 1531 | code = "{typo_name}", | |
| 1532 | applicability = "machine-applicable" | |
| 1533 | )] | |
| 1534 | pub(crate) struct UnknownDiagnosticAttributeTypoSugg { | |
| 1535 | #[primary_span] | |
| 1536 | pub span: Span, | |
| 1537 | pub typo_name: Symbol, | |
| 1528 | pub(crate) enum UnknownDiagnosticAttributeHelp { | |
| 1529 | #[suggestion( | |
| 1530 | "an attribute with a similar name exists", | |
| 1531 | style = "verbose", | |
| 1532 | code = "{typo_name}", | |
| 1533 | applicability = "machine-applicable" | |
| 1534 | )] | |
| 1535 | Typo { | |
| 1536 | #[primary_span] | |
| 1537 | span: Span, | |
| 1538 | typo_name: Symbol, | |
| 1539 | }, | |
| 1540 | #[help("add `#![feature({$feature})]` to the crate attributes to enable")] | |
| 1541 | UseFeature { feature: Symbol }, | |
| 1538 | 1542 | } |
| 1539 | 1543 | |
| 1540 | 1544 | // FIXME: Make this properly translatable. |
compiler/rustc_resolve/src/imports.rs+41-51| ... | ... | @@ -289,15 +289,22 @@ impl<'ra> NameResolution<'ra> { |
| 289 | 289 | NameResolution { single_imports: FxIndexSet::default(), orig_ident_span, .. } |
| 290 | 290 | } |
| 291 | 291 | |
| 292 | /// Returns the binding for the name if it is known or None if it not known. | |
| 293 | pub(crate) fn binding(&self) -> Option<Decl<'ra>> { | |
| 294 | self.best_decl().and_then(|binding| { | |
| 295 | if !binding.is_glob_import() || self.single_imports.is_empty() { | |
| 296 | Some(binding) | |
| 297 | } else { | |
| 298 | None | |
| 299 | } | |
| 300 | }) | |
| 292 | /// Returns the best declaration if it is not going to change, and `None` if the best | |
| 293 | /// declaration may still change to something else. | |
| 294 | /// FIXME: this function considers `single_imports`, but not `unexpanded_invocations`, so | |
| 295 | /// the returned declaration may actually change after expanding macros in the same module, | |
| 296 | /// because of this fact we have glob overwriting (`select_glob_decl`). Consider using | |
| 297 | /// `unexpanded_invocations` here and avoiding glob overwriting entirely, if it doesn't cause | |
| 298 | /// code breakage in practice. | |
| 299 | /// FIXME: relationship between this function and similar `DeclData::determined` is unclear. | |
| 300 | pub(crate) fn determined_decl(&self) -> Option<Decl<'ra>> { | |
| 301 | if self.non_glob_decl.is_some() { | |
| 302 | self.non_glob_decl | |
| 303 | } else if self.glob_decl.is_some() && self.single_imports.is_empty() { | |
| 304 | self.glob_decl | |
| 305 | } else { | |
| 306 | None | |
| 307 | } | |
| 301 | 308 | } |
| 302 | 309 | |
| 303 | 310 | pub(crate) fn best_decl(&self) -> Option<Decl<'ra>> { |
| ... | ... | @@ -482,41 +489,21 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { |
| 482 | 489 | orig_ident_span, |
| 483 | 490 | warn_ambiguity, |
| 484 | 491 | |this, resolution| { |
| 485 | if let Some(old_decl) = resolution.best_decl() { | |
| 486 | assert_ne!(decl, old_decl); | |
| 487 | assert!(!decl.warn_ambiguity.get()); | |
| 488 | if res == Res::Err && old_decl.res() != Res::Err { | |
| 489 | // Do not override real declarations with `Res::Err`s from error recovery. | |
| 490 | return Ok(()); | |
| 491 | } | |
| 492 | match (old_decl.is_glob_import(), decl.is_glob_import()) { | |
| 493 | (true, true) => { | |
| 494 | resolution.glob_decl = | |
| 495 | Some(this.select_glob_decl(old_decl, decl, warn_ambiguity)); | |
| 496 | } | |
| 497 | (old_glob @ true, false) | (old_glob @ false, true) => { | |
| 498 | let (glob_decl, non_glob_decl) = | |
| 499 | if old_glob { (old_decl, decl) } else { (decl, old_decl) }; | |
| 500 | resolution.non_glob_decl = Some(non_glob_decl); | |
| 501 | if let Some(old_glob_decl) = resolution.glob_decl | |
| 502 | && old_glob_decl != glob_decl | |
| 503 | { | |
| 504 | resolution.glob_decl = | |
| 505 | Some(this.select_glob_decl(old_glob_decl, glob_decl, false)); | |
| 506 | } else { | |
| 507 | resolution.glob_decl = Some(glob_decl); | |
| 508 | } | |
| 509 | } | |
| 510 | (false, false) => { | |
| 511 | return Err(old_decl); | |
| 512 | } | |
| 513 | } | |
| 492 | assert!(!decl.warn_ambiguity.get()); | |
| 493 | if decl.is_glob_import() { | |
| 494 | resolution.glob_decl = Some(match resolution.glob_decl { | |
| 495 | Some(old_decl) => this.select_glob_decl( | |
| 496 | old_decl, | |
| 497 | decl, | |
| 498 | warn_ambiguity && resolution.non_glob_decl.is_none(), | |
| 499 | ), | |
| 500 | None => decl, | |
| 501 | }) | |
| 514 | 502 | } else { |
| 515 | if decl.is_glob_import() { | |
| 516 | resolution.glob_decl = Some(decl); | |
| 517 | } else { | |
| 518 | resolution.non_glob_decl = Some(decl); | |
| 519 | } | |
| 503 | resolution.non_glob_decl = Some(match resolution.non_glob_decl { | |
| 504 | Some(old_decl) => return Err(old_decl), | |
| 505 | None => decl, | |
| 506 | }) | |
| 520 | 507 | } |
| 521 | 508 | |
| 522 | 509 | Ok(()) |
| ... | ... | @@ -543,11 +530,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { |
| 543 | 530 | let resolution = &mut *self |
| 544 | 531 | .resolution_or_default(module, key, orig_ident_span) |
| 545 | 532 | .borrow_mut_unchecked(); |
| 546 | let old_decl = resolution.binding(); | |
| 533 | let old_decl = resolution.determined_decl(); | |
| 547 | 534 | |
| 548 | 535 | let t = f(self, resolution); |
| 549 | 536 | |
| 550 | if let Some(binding) = resolution.binding() | |
| 537 | if let Some(binding) = resolution.determined_decl() | |
| 551 | 538 | && old_decl != Some(binding) |
| 552 | 539 | { |
| 553 | 540 | (binding, t, warn_ambiguity || old_decl.is_some()) |
| ... | ... | @@ -573,13 +560,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { |
| 573 | 560 | }; |
| 574 | 561 | if self.is_accessible_from(binding.vis(), scope) { |
| 575 | 562 | let import_decl = self.new_import_decl(binding, *import); |
| 576 | let _ = self.try_plant_decl_into_local_module( | |
| 563 | self.try_plant_decl_into_local_module( | |
| 577 | 564 | ident, |
| 578 | 565 | orig_ident_span, |
| 579 | 566 | key.ns, |
| 580 | 567 | import_decl, |
| 581 | 568 | warn_ambiguity, |
| 582 | ); | |
| 569 | ) | |
| 570 | .expect("planting a glob cannot fail"); | |
| 583 | 571 | } |
| 584 | 572 | } |
| 585 | 573 | |
| ... | ... | @@ -598,6 +586,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { |
| 598 | 586 | self.per_ns(|this, ns| { |
| 599 | 587 | let module = import.parent_scope.module; |
| 600 | 588 | let ident = IdentKey::new(target); |
| 589 | // This can fail, dummies are inserted only in non-occupied slots. | |
| 601 | 590 | let _ = this.try_plant_decl_into_local_module( |
| 602 | 591 | ident, |
| 603 | 592 | target.span, |
| ... | ... | @@ -1676,7 +1665,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { |
| 1676 | 1665 | .iter() |
| 1677 | 1666 | .filter_map(|(key, resolution)| { |
| 1678 | 1667 | let resolution = resolution.borrow(); |
| 1679 | resolution.binding().map(|binding| (*key, binding, resolution.orig_ident_span)) | |
| 1668 | resolution.determined_decl().map(|decl| (*key, decl, resolution.orig_ident_span)) | |
| 1680 | 1669 | }) |
| 1681 | 1670 | .collect::<Vec<_>>(); |
| 1682 | 1671 | for (mut key, binding, orig_ident_span) in bindings { |
| ... | ... | @@ -1692,15 +1681,16 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { |
| 1692 | 1681 | let import_decl = self.new_import_decl(binding, import); |
| 1693 | 1682 | let warn_ambiguity = self |
| 1694 | 1683 | .resolution(import.parent_scope.module, key) |
| 1695 | .and_then(|r| r.binding()) | |
| 1684 | .and_then(|r| r.determined_decl()) | |
| 1696 | 1685 | .is_some_and(|binding| binding.warn_ambiguity_recursive()); |
| 1697 | let _ = self.try_plant_decl_into_local_module( | |
| 1686 | self.try_plant_decl_into_local_module( | |
| 1698 | 1687 | key.ident, |
| 1699 | 1688 | orig_ident_span, |
| 1700 | 1689 | key.ns, |
| 1701 | 1690 | import_decl, |
| 1702 | 1691 | warn_ambiguity, |
| 1703 | ); | |
| 1692 | ) | |
| 1693 | .expect("planting a glob cannot fail"); | |
| 1704 | 1694 | } |
| 1705 | 1695 | } |
| 1706 | 1696 |
compiler/rustc_resolve/src/late.rs+36-20| ... | ... | @@ -530,9 +530,8 @@ impl PathSource<'_, '_, '_> { |
| 530 | 530 | }, |
| 531 | 531 | _ => "value", |
| 532 | 532 | }, |
| 533 | PathSource::ReturnTypeNotation | |
| 534 | | PathSource::Delegation | |
| 535 | | PathSource::ExternItemImpl => "function", | |
| 533 | PathSource::ReturnTypeNotation | PathSource::Delegation => "function", | |
| 534 | PathSource::ExternItemImpl => "function or static", | |
| 536 | 535 | PathSource::PreciseCapturingArg(..) => "type or const parameter", |
| 537 | 536 | PathSource::Macro => "macro", |
| 538 | 537 | PathSource::Module => "module", |
| ... | ... | @@ -625,7 +624,13 @@ impl PathSource<'_, '_, '_> { |
| 625 | 624 | }, |
| 626 | 625 | PathSource::Delegation => matches!(res, Res::Def(DefKind::Fn | DefKind::AssocFn, _)), |
| 627 | 626 | PathSource::ExternItemImpl => { |
| 628 | matches!(res, Res::Def(DefKind::Fn | DefKind::AssocFn | DefKind::Ctor(..), _)) | |
| 627 | matches!( | |
| 628 | res, | |
| 629 | Res::Def( | |
| 630 | DefKind::Fn | DefKind::AssocFn | DefKind::Ctor(..) | DefKind::Static { .. }, | |
| 631 | _ | |
| 632 | ) | |
| 633 | ) | |
| 629 | 634 | } |
| 630 | 635 | PathSource::PreciseCapturingArg(ValueNS) => { |
| 631 | 636 | matches!(res, Res::Def(DefKind::ConstParam, _)) |
| ... | ... | @@ -1095,21 +1100,7 @@ impl<'ast, 'ra, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'ra, 'tc |
| 1095 | 1100 | debug!("(resolving function) entering function"); |
| 1096 | 1101 | |
| 1097 | 1102 | if let FnKind::Fn(_, _, f) = fn_kind { |
| 1098 | for EiiImpl { node_id, eii_macro_path, known_eii_macro_resolution, .. } in &f.eii_impls | |
| 1099 | { | |
| 1100 | // See docs on the `known_eii_macro_resolution` field: | |
| 1101 | // if we already know the resolution statically, don't bother resolving it. | |
| 1102 | if let Some(target) = known_eii_macro_resolution { | |
| 1103 | self.smart_resolve_path( | |
| 1104 | *node_id, | |
| 1105 | &None, | |
| 1106 | &target.foreign_item, | |
| 1107 | PathSource::ExternItemImpl, | |
| 1108 | ); | |
| 1109 | } else { | |
| 1110 | self.smart_resolve_path(*node_id, &None, &eii_macro_path, PathSource::Macro); | |
| 1111 | } | |
| 1112 | } | |
| 1103 | self.resolve_eii(&f.eii_impls); | |
| 1113 | 1104 | } |
| 1114 | 1105 | |
| 1115 | 1106 | // Create a value rib for the function. |
| ... | ... | @@ -2905,7 +2896,14 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { |
| 2905 | 2896 | self.parent_scope.module = orig_module; |
| 2906 | 2897 | } |
| 2907 | 2898 | |
| 2908 | ItemKind::Static(box ast::StaticItem { ident, ty, expr, define_opaque, .. }) => { | |
| 2899 | ItemKind::Static(box ast::StaticItem { | |
| 2900 | ident, | |
| 2901 | ty, | |
| 2902 | expr, | |
| 2903 | define_opaque, | |
| 2904 | eii_impls, | |
| 2905 | .. | |
| 2906 | }) => { | |
| 2909 | 2907 | self.with_static_rib(def_kind, |this| { |
| 2910 | 2908 | this.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Static), |this| { |
| 2911 | 2909 | this.visit_ty(ty); |
| ... | ... | @@ -2917,6 +2915,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { |
| 2917 | 2915 | } |
| 2918 | 2916 | }); |
| 2919 | 2917 | self.resolve_define_opaques(define_opaque); |
| 2918 | self.resolve_eii(&eii_impls); | |
| 2920 | 2919 | } |
| 2921 | 2920 | |
| 2922 | 2921 | ItemKind::Const(box ast::ConstItem { |
| ... | ... | @@ -5496,6 +5495,23 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { |
| 5496 | 5495 | } |
| 5497 | 5496 | } |
| 5498 | 5497 | } |
| 5498 | ||
| 5499 | fn resolve_eii(&mut self, eii_impls: &[EiiImpl]) { | |
| 5500 | for EiiImpl { node_id, eii_macro_path, known_eii_macro_resolution, .. } in eii_impls { | |
| 5501 | // See docs on the `known_eii_macro_resolution` field: | |
| 5502 | // if we already know the resolution statically, don't bother resolving it. | |
| 5503 | if let Some(target) = known_eii_macro_resolution { | |
| 5504 | self.smart_resolve_path( | |
| 5505 | *node_id, | |
| 5506 | &None, | |
| 5507 | &target.foreign_item, | |
| 5508 | PathSource::ExternItemImpl, | |
| 5509 | ); | |
| 5510 | } else { | |
| 5511 | self.smart_resolve_path(*node_id, &None, &eii_macro_path, PathSource::Macro); | |
| 5512 | } | |
| 5513 | } | |
| 5514 | } | |
| 5499 | 5515 | } |
| 5500 | 5516 | |
| 5501 | 5517 | /// Walks the whole crate in DFS order, visiting each item, counting the declared number of |
compiler/rustc_resolve/src/lib.rs+5-3| ... | ... | @@ -1101,9 +1101,11 @@ impl<'ra> DeclData<'ra> { |
| 1101 | 1101 | !(certainly_before_other_or_simultaneously || certainly_before_invoc_or_simultaneously) |
| 1102 | 1102 | } |
| 1103 | 1103 | |
| 1104 | // Its purpose is to postpone the determination of a single binding because | |
| 1105 | // we can't predict whether it will be overwritten by recently expanded macros. | |
| 1106 | // FIXME: How can we integrate it with the `update_resolution`? | |
| 1104 | /// Returns whether this declaration may be shadowed or overwritten by something else later. | |
| 1105 | /// FIXME: this function considers `unexpanded_invocations`, but not `single_imports`, so | |
| 1106 | /// the declaration may not be as "determined" as we think. | |
| 1107 | /// FIXME: relationship between this function and similar `NameResolution::determined_decl` | |
| 1108 | /// is unclear. | |
| 1107 | 1109 | fn determined(&self) -> bool { |
| 1108 | 1110 | match &self.kind { |
| 1109 | 1111 | DeclKind::Import { source_decl, import, .. } if import.is_glob() => { |
compiler/rustc_resolve/src/macros.rs+37-16| ... | ... | @@ -712,34 +712,55 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { |
| 712 | 712 | feature_err(&self.tcx.sess, sym::custom_inner_attributes, path.span, msg).emit(); |
| 713 | 713 | } |
| 714 | 714 | |
| 715 | let diagnostic_attributes: &[(Symbol, bool)] = &[ | |
| 716 | (sym::on_unimplemented, true), | |
| 717 | (sym::do_not_recommend, true), | |
| 718 | (sym::on_move, true), | |
| 719 | (sym::on_const, self.tcx.features().diagnostic_on_const()), | |
| 720 | (sym::on_unknown, self.tcx.features().diagnostic_on_unknown()), | |
| 715 | const DIAGNOSTIC_ATTRIBUTES: &[(Symbol, Option<Symbol>)] = &[ | |
| 716 | (sym::on_unimplemented, None), | |
| 717 | (sym::do_not_recommend, None), | |
| 718 | (sym::on_move, Some(sym::diagnostic_on_move)), | |
| 719 | (sym::on_const, Some(sym::diagnostic_on_const)), | |
| 720 | (sym::on_unknown, Some(sym::diagnostic_on_unknown)), | |
| 721 | 721 | ]; |
| 722 | 722 | |
| 723 | 723 | if res == Res::NonMacroAttr(NonMacroAttrKind::Tool) |
| 724 | 724 | && let [namespace, attribute, ..] = &*path.segments |
| 725 | 725 | && namespace.ident.name == sym::diagnostic |
| 726 | && !diagnostic_attributes | |
| 727 | .iter() | |
| 728 | .any(|(attr, stable)| *stable && attribute.ident.name == *attr) | |
| 726 | && !DIAGNOSTIC_ATTRIBUTES.iter().any(|(attr, feature)| { | |
| 727 | attribute.ident.name == *attr | |
| 728 | && feature.is_none_or(|f| self.tcx.features().enabled(f)) | |
| 729 | }) | |
| 729 | 730 | { |
| 731 | let name = attribute.ident.name; | |
| 730 | 732 | let span = attribute.span(); |
| 731 | let candidates = diagnostic_attributes | |
| 732 | .iter() | |
| 733 | .filter_map(|(sym, stable)| stable.then_some(*sym)) | |
| 734 | .collect::<Vec<_>>(); | |
| 735 | let typo = find_best_match_for_name(&candidates, attribute.ident.name, Some(5)) | |
| 736 | .map(|typo_name| errors::UnknownDiagnosticAttributeTypoSugg { span, typo_name }); | |
| 733 | ||
| 734 | let help = 'help: { | |
| 735 | if self.tcx.sess.is_nightly_build() { | |
| 736 | for (attr, feature) in DIAGNOSTIC_ATTRIBUTES { | |
| 737 | if let Some(feature) = *feature | |
| 738 | && *attr == name | |
| 739 | { | |
| 740 | break 'help Some(errors::UnknownDiagnosticAttributeHelp::UseFeature { | |
| 741 | feature, | |
| 742 | }); | |
| 743 | } | |
| 744 | } | |
| 745 | } | |
| 746 | ||
| 747 | let candidates = DIAGNOSTIC_ATTRIBUTES | |
| 748 | .iter() | |
| 749 | .filter_map(|(attr, feature)| { | |
| 750 | feature.is_none_or(|f| self.tcx.features().enabled(f)).then_some(*attr) | |
| 751 | }) | |
| 752 | .collect::<Vec<_>>(); | |
| 753 | ||
| 754 | find_best_match_for_name(&candidates, name, None).map(|typo_name| { | |
| 755 | errors::UnknownDiagnosticAttributeHelp::Typo { span, typo_name } | |
| 756 | }) | |
| 757 | }; | |
| 737 | 758 | |
| 738 | 759 | self.tcx.sess.psess.buffer_lint( |
| 739 | 760 | UNKNOWN_DIAGNOSTIC_ATTRIBUTES, |
| 740 | 761 | span, |
| 741 | 762 | node_id, |
| 742 | errors::UnknownDiagnosticAttribute { typo }, | |
| 763 | errors::UnknownDiagnosticAttribute { help }, | |
| 743 | 764 | ); |
| 744 | 765 | } |
| 745 | 766 |
compiler/rustc_trait_selection/src/traits/mod.rs+5-4| ... | ... | @@ -34,8 +34,8 @@ use rustc_middle::query::Providers; |
| 34 | 34 | use rustc_middle::span_bug; |
| 35 | 35 | use rustc_middle::ty::error::{ExpectedFound, TypeError}; |
| 36 | 36 | use rustc_middle::ty::{ |
| 37 | self, GenericArgs, GenericArgsRef, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, | |
| 38 | TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypingMode, Upcast, | |
| 37 | self, Clause, GenericArgs, GenericArgsRef, Ty, TyCtxt, TypeFoldable, TypeFolder, | |
| 38 | TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypingMode, Upcast, | |
| 39 | 39 | }; |
| 40 | 40 | use rustc_span::Span; |
| 41 | 41 | use rustc_span::def_id::DefId; |
| ... | ... | @@ -177,9 +177,10 @@ pub enum TraitQueryMode { |
| 177 | 177 | } |
| 178 | 178 | |
| 179 | 179 | /// Creates predicate obligations from the generic bounds. |
| 180 | #[instrument(level = "debug", skip(cause, param_env))] | |
| 180 | #[instrument(level = "debug", skip(cause, param_env, normalize_predicate))] | |
| 181 | 181 | pub fn predicates_for_generics<'tcx>( |
| 182 | 182 | cause: impl Fn(usize, Span) -> ObligationCause<'tcx>, |
| 183 | mut normalize_predicate: impl FnMut(Clause<'tcx>) -> Clause<'tcx>, | |
| 183 | 184 | param_env: ty::ParamEnv<'tcx>, |
| 184 | 185 | generic_bounds: ty::InstantiatedPredicates<'tcx>, |
| 185 | 186 | ) -> impl Iterator<Item = PredicateObligation<'tcx>> { |
| ... | ... | @@ -187,7 +188,7 @@ pub fn predicates_for_generics<'tcx>( |
| 187 | 188 | cause: cause(idx, span), |
| 188 | 189 | recursion_depth: 0, |
| 189 | 190 | param_env, |
| 190 | predicate: clause.as_predicate(), | |
| 191 | predicate: normalize_predicate(clause).as_predicate(), | |
| 191 | 192 | }) |
| 192 | 193 | } |
| 193 | 194 |
compiler/rustc_trait_selection/src/traits/specialize/mod.rs+11-8| ... | ... | @@ -185,12 +185,13 @@ fn fulfill_implication<'tcx>( |
| 185 | 185 | // Now check that the source trait ref satisfies all the where clauses of the target impl. |
| 186 | 186 | // This is not just for correctness; we also need this to constrain any params that may |
| 187 | 187 | // only be referenced via projection predicates. |
| 188 | let predicates = ocx.normalize( | |
| 189 | cause, | |
| 188 | let predicates = infcx.tcx.predicates_of(target_impl).instantiate(infcx.tcx, target_args); | |
| 189 | let obligations = predicates_for_generics( | |
| 190 | |_, _| cause.clone(), | |
| 191 | |pred| ocx.normalize(cause, param_env, pred), | |
| 190 | 192 | param_env, |
| 191 | infcx.tcx.predicates_of(target_impl).instantiate(infcx.tcx, target_args), | |
| 193 | predicates, | |
| 192 | 194 | ); |
| 193 | let obligations = predicates_for_generics(|_, _| cause.clone(), param_env, predicates); | |
| 194 | 195 | ocx.register_obligations(obligations); |
| 195 | 196 | |
| 196 | 197 | let errors = ocx.evaluate_obligations_error_on_ambiguity(); |
| ... | ... | @@ -315,12 +316,14 @@ pub(super) fn specializes( |
| 315 | 316 | // Now check that the source trait ref satisfies all the where clauses of the target impl. |
| 316 | 317 | // This is not just for correctness; we also need this to constrain any params that may |
| 317 | 318 | // only be referenced via projection predicates. |
| 318 | let predicates = ocx.normalize( | |
| 319 | cause, | |
| 319 | let predicates = | |
| 320 | infcx.tcx.predicates_of(parent_impl_def_id).instantiate(infcx.tcx, parent_args); | |
| 321 | let obligations = predicates_for_generics( | |
| 322 | |_, _| cause.clone(), | |
| 323 | |pred| ocx.normalize(cause, param_env, pred), | |
| 320 | 324 | param_env, |
| 321 | infcx.tcx.predicates_of(parent_impl_def_id).instantiate(infcx.tcx, parent_args), | |
| 325 | predicates, | |
| 322 | 326 | ); |
| 323 | let obligations = predicates_for_generics(|_, _| cause.clone(), param_env, predicates); | |
| 324 | 327 | ocx.register_obligations(obligations); |
| 325 | 328 | |
| 326 | 329 | let errors = ocx.evaluate_obligations_error_on_ambiguity(); |
library/core/src/cell/lazy.rs+2-1| ... | ... | @@ -346,7 +346,8 @@ impl<T, F: FnOnce() -> T> DerefMut for LazyCell<T, F> { |
| 346 | 346 | } |
| 347 | 347 | |
| 348 | 348 | #[stable(feature = "lazy_cell", since = "1.80.0")] |
| 349 | impl<T: Default> Default for LazyCell<T> { | |
| 349 | #[rustc_const_unstable(feature = "const_default", issue = "143894")] | |
| 350 | impl<T: Default> const Default for LazyCell<T> { | |
| 350 | 351 | /// Creates a new lazy value using `Default` as the initializing function. |
| 351 | 352 | #[inline] |
| 352 | 353 | fn default() -> LazyCell<T> { |
library/core/src/num/int_macros.rs+4-6| ... | ... | @@ -213,14 +213,13 @@ macro_rules! int_impl { |
| 213 | 213 | /// # Examples |
| 214 | 214 | /// |
| 215 | 215 | /// ``` |
| 216 | /// #![feature(int_lowest_highest_one)] | |
| 217 | /// | |
| 218 | 216 | #[doc = concat!("assert_eq!(0b0_", stringify!($SelfT), ".highest_one(), None);")] |
| 219 | 217 | #[doc = concat!("assert_eq!(0b1_", stringify!($SelfT), ".highest_one(), Some(0));")] |
| 220 | 218 | #[doc = concat!("assert_eq!(0b1_0000_", stringify!($SelfT), ".highest_one(), Some(4));")] |
| 221 | 219 | #[doc = concat!("assert_eq!(0b1_1111_", stringify!($SelfT), ".highest_one(), Some(4));")] |
| 222 | 220 | /// ``` |
| 223 | #[unstable(feature = "int_lowest_highest_one", issue = "145203")] | |
| 221 | #[stable(feature = "int_lowest_highest_one", since = "CURRENT_RUSTC_VERSION")] | |
| 222 | #[rustc_const_stable(feature = "int_lowest_highest_one", since = "CURRENT_RUSTC_VERSION")] | |
| 224 | 223 | #[must_use = "this returns the result of the operation, \ |
| 225 | 224 | without modifying the original"] |
| 226 | 225 | #[inline(always)] |
| ... | ... | @@ -234,14 +233,13 @@ macro_rules! int_impl { |
| 234 | 233 | /// # Examples |
| 235 | 234 | /// |
| 236 | 235 | /// ``` |
| 237 | /// #![feature(int_lowest_highest_one)] | |
| 238 | /// | |
| 239 | 236 | #[doc = concat!("assert_eq!(0b0_", stringify!($SelfT), ".lowest_one(), None);")] |
| 240 | 237 | #[doc = concat!("assert_eq!(0b1_", stringify!($SelfT), ".lowest_one(), Some(0));")] |
| 241 | 238 | #[doc = concat!("assert_eq!(0b1_0000_", stringify!($SelfT), ".lowest_one(), Some(4));")] |
| 242 | 239 | #[doc = concat!("assert_eq!(0b1_1111_", stringify!($SelfT), ".lowest_one(), Some(0));")] |
| 243 | 240 | /// ``` |
| 244 | #[unstable(feature = "int_lowest_highest_one", issue = "145203")] | |
| 241 | #[stable(feature = "int_lowest_highest_one", since = "CURRENT_RUSTC_VERSION")] | |
| 242 | #[rustc_const_stable(feature = "int_lowest_highest_one", since = "CURRENT_RUSTC_VERSION")] | |
| 245 | 243 | #[must_use = "this returns the result of the operation, \ |
| 246 | 244 | without modifying the original"] |
| 247 | 245 | #[inline(always)] |
library/core/src/num/nonzero.rs+6-9| ... | ... | @@ -711,8 +711,6 @@ macro_rules! nonzero_integer { |
| 711 | 711 | /// # Examples |
| 712 | 712 | /// |
| 713 | 713 | /// ``` |
| 714 | /// #![feature(int_lowest_highest_one)] | |
| 715 | /// | |
| 716 | 714 | /// # use core::num::NonZero; |
| 717 | 715 | /// # fn main() { test().unwrap(); } |
| 718 | 716 | /// # fn test() -> Option<()> { |
| ... | ... | @@ -722,7 +720,8 @@ macro_rules! nonzero_integer { |
| 722 | 720 | /// # Some(()) |
| 723 | 721 | /// # } |
| 724 | 722 | /// ``` |
| 725 | #[unstable(feature = "int_lowest_highest_one", issue = "145203")] | |
| 723 | #[stable(feature = "int_lowest_highest_one", since = "CURRENT_RUSTC_VERSION")] | |
| 724 | #[rustc_const_stable(feature = "int_lowest_highest_one", since = "CURRENT_RUSTC_VERSION")] | |
| 726 | 725 | #[must_use = "this returns the result of the operation, \ |
| 727 | 726 | without modifying the original"] |
| 728 | 727 | #[inline(always)] |
| ... | ... | @@ -735,8 +734,6 @@ macro_rules! nonzero_integer { |
| 735 | 734 | /// # Examples |
| 736 | 735 | /// |
| 737 | 736 | /// ``` |
| 738 | /// #![feature(int_lowest_highest_one)] | |
| 739 | /// | |
| 740 | 737 | /// # use core::num::NonZero; |
| 741 | 738 | /// # fn main() { test().unwrap(); } |
| 742 | 739 | /// # fn test() -> Option<()> { |
| ... | ... | @@ -746,7 +743,8 @@ macro_rules! nonzero_integer { |
| 746 | 743 | /// # Some(()) |
| 747 | 744 | /// # } |
| 748 | 745 | /// ``` |
| 749 | #[unstable(feature = "int_lowest_highest_one", issue = "145203")] | |
| 746 | #[stable(feature = "int_lowest_highest_one", since = "CURRENT_RUSTC_VERSION")] | |
| 747 | #[rustc_const_stable(feature = "int_lowest_highest_one", since = "CURRENT_RUSTC_VERSION")] | |
| 750 | 748 | #[must_use = "this returns the result of the operation, \ |
| 751 | 749 | without modifying the original"] |
| 752 | 750 | #[inline(always)] |
| ... | ... | @@ -1948,8 +1946,6 @@ macro_rules! nonzero_integer_signedness_dependent_methods { |
| 1948 | 1946 | /// # Examples |
| 1949 | 1947 | /// |
| 1950 | 1948 | /// ``` |
| 1951 | /// #![feature(uint_bit_width)] | |
| 1952 | /// | |
| 1953 | 1949 | /// # use core::num::NonZero; |
| 1954 | 1950 | /// # |
| 1955 | 1951 | /// # fn main() { test().unwrap(); } |
| ... | ... | @@ -1960,7 +1956,8 @@ macro_rules! nonzero_integer_signedness_dependent_methods { |
| 1960 | 1956 | /// # Some(()) |
| 1961 | 1957 | /// # } |
| 1962 | 1958 | /// ``` |
| 1963 | #[unstable(feature = "uint_bit_width", issue = "142326")] | |
| 1959 | #[stable(feature = "uint_bit_width", since = "CURRENT_RUSTC_VERSION")] | |
| 1960 | #[rustc_const_stable(feature = "uint_bit_width", since = "CURRENT_RUSTC_VERSION")] | |
| 1964 | 1961 | #[must_use = "this returns the result of the operation, \ |
| 1965 | 1962 | without modifying the original"] |
| 1966 | 1963 | #[inline(always)] |
library/core/src/num/uint_macros.rs+6-9| ... | ... | @@ -232,14 +232,13 @@ macro_rules! uint_impl { |
| 232 | 232 | /// # Examples |
| 233 | 233 | /// |
| 234 | 234 | /// ``` |
| 235 | /// #![feature(uint_bit_width)] | |
| 236 | /// | |
| 237 | 235 | #[doc = concat!("assert_eq!(0_", stringify!($SelfT), ".bit_width(), 0);")] |
| 238 | 236 | #[doc = concat!("assert_eq!(0b111_", stringify!($SelfT), ".bit_width(), 3);")] |
| 239 | 237 | #[doc = concat!("assert_eq!(0b1110_", stringify!($SelfT), ".bit_width(), 4);")] |
| 240 | 238 | #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.bit_width(), ", stringify!($BITS), ");")] |
| 241 | 239 | /// ``` |
| 242 | #[unstable(feature = "uint_bit_width", issue = "142326")] | |
| 240 | #[stable(feature = "uint_bit_width", since = "CURRENT_RUSTC_VERSION")] | |
| 241 | #[rustc_const_stable(feature = "uint_bit_width", since = "CURRENT_RUSTC_VERSION")] | |
| 243 | 242 | #[must_use = "this returns the result of the operation, \ |
| 244 | 243 | without modifying the original"] |
| 245 | 244 | #[inline(always)] |
| ... | ... | @@ -293,14 +292,13 @@ macro_rules! uint_impl { |
| 293 | 292 | /// # Examples |
| 294 | 293 | /// |
| 295 | 294 | /// ``` |
| 296 | /// #![feature(int_lowest_highest_one)] | |
| 297 | /// | |
| 298 | 295 | #[doc = concat!("assert_eq!(0b0_", stringify!($SelfT), ".highest_one(), None);")] |
| 299 | 296 | #[doc = concat!("assert_eq!(0b1_", stringify!($SelfT), ".highest_one(), Some(0));")] |
| 300 | 297 | #[doc = concat!("assert_eq!(0b1_0000_", stringify!($SelfT), ".highest_one(), Some(4));")] |
| 301 | 298 | #[doc = concat!("assert_eq!(0b1_1111_", stringify!($SelfT), ".highest_one(), Some(4));")] |
| 302 | 299 | /// ``` |
| 303 | #[unstable(feature = "int_lowest_highest_one", issue = "145203")] | |
| 300 | #[stable(feature = "int_lowest_highest_one", since = "CURRENT_RUSTC_VERSION")] | |
| 301 | #[rustc_const_stable(feature = "int_lowest_highest_one", since = "CURRENT_RUSTC_VERSION")] | |
| 304 | 302 | #[must_use = "this returns the result of the operation, \ |
| 305 | 303 | without modifying the original"] |
| 306 | 304 | #[inline(always)] |
| ... | ... | @@ -317,14 +315,13 @@ macro_rules! uint_impl { |
| 317 | 315 | /// # Examples |
| 318 | 316 | /// |
| 319 | 317 | /// ``` |
| 320 | /// #![feature(int_lowest_highest_one)] | |
| 321 | /// | |
| 322 | 318 | #[doc = concat!("assert_eq!(0b0_", stringify!($SelfT), ".lowest_one(), None);")] |
| 323 | 319 | #[doc = concat!("assert_eq!(0b1_", stringify!($SelfT), ".lowest_one(), Some(0));")] |
| 324 | 320 | #[doc = concat!("assert_eq!(0b1_0000_", stringify!($SelfT), ".lowest_one(), Some(4));")] |
| 325 | 321 | #[doc = concat!("assert_eq!(0b1_1111_", stringify!($SelfT), ".lowest_one(), Some(0));")] |
| 326 | 322 | /// ``` |
| 327 | #[unstable(feature = "int_lowest_highest_one", issue = "145203")] | |
| 323 | #[stable(feature = "int_lowest_highest_one", since = "CURRENT_RUSTC_VERSION")] | |
| 324 | #[rustc_const_stable(feature = "int_lowest_highest_one", since = "CURRENT_RUSTC_VERSION")] | |
| 328 | 325 | #[must_use = "this returns the result of the operation, \ |
| 329 | 326 | without modifying the original"] |
| 330 | 327 | #[inline(always)] |
library/core/src/ops/deref.rs+1| ... | ... | @@ -293,6 +293,7 @@ impl<T: ?Sized> const DerefMut for &mut T { |
| 293 | 293 | /// unchanged. |
| 294 | 294 | #[unstable(feature = "deref_pure_trait", issue = "87121")] |
| 295 | 295 | #[lang = "deref_pure"] |
| 296 | #[rustc_dyn_incompatible_trait] | |
| 296 | 297 | pub unsafe trait DerefPure: PointeeSized {} |
| 297 | 298 | |
| 298 | 299 | #[unstable(feature = "deref_pure_trait", issue = "87121")] |
library/coretests/tests/lib.rs-2| ... | ... | @@ -66,7 +66,6 @@ |
| 66 | 66 | #![feature(hasher_prefixfree_extras)] |
| 67 | 67 | #![feature(hashmap_internals)] |
| 68 | 68 | #![feature(int_from_ascii)] |
| 69 | #![feature(int_lowest_highest_one)] | |
| 70 | 69 | #![feature(int_roundings)] |
| 71 | 70 | #![feature(ip)] |
| 72 | 71 | #![feature(is_ascii_octdigit)] |
| ... | ... | @@ -120,7 +119,6 @@ |
| 120 | 119 | #![feature(try_find)] |
| 121 | 120 | #![feature(try_trait_v2)] |
| 122 | 121 | #![feature(type_info)] |
| 123 | #![feature(uint_bit_width)] | |
| 124 | 122 | #![feature(uint_carryless_mul)] |
| 125 | 123 | #![feature(uint_gather_scatter_bits)] |
| 126 | 124 | #![feature(unicode_internals)] |
library/std/src/sync/lazy_lock.rs+2-1| ... | ... | @@ -375,7 +375,8 @@ impl<T, F: FnOnce() -> T> DerefMut for LazyLock<T, F> { |
| 375 | 375 | } |
| 376 | 376 | |
| 377 | 377 | #[stable(feature = "lazy_cell", since = "1.80.0")] |
| 378 | impl<T: Default> Default for LazyLock<T> { | |
| 378 | #[rustc_const_unstable(feature = "const_default", issue = "143894")] | |
| 379 | impl<T: Default> const Default for LazyLock<T> { | |
| 379 | 380 | /// Creates a new lazy value using `Default` as the initializing function. |
| 380 | 381 | #[inline] |
| 381 | 382 | fn default() -> LazyLock<T> { |
library/std/src/sys/thread/unix.rs+1| ... | ... | @@ -155,6 +155,7 @@ pub fn available_parallelism() -> io::Result<NonZero<usize>> { |
| 155 | 155 | target_os = "aix", |
| 156 | 156 | target_vendor = "apple", |
| 157 | 157 | target_os = "cygwin", |
| 158 | target_os = "wasi", | |
| 158 | 159 | ) => { |
| 159 | 160 | #[allow(unused_assignments)] |
| 160 | 161 | #[allow(unused_mut)] |
library/std/tests/sync/lazy_lock.rs+9| ... | ... | @@ -33,6 +33,15 @@ fn lazy_default() { |
| 33 | 33 | assert_eq!(CALLED.load(SeqCst), 1); |
| 34 | 34 | } |
| 35 | 35 | |
| 36 | #[test] | |
| 37 | fn const_lazy_default() { | |
| 38 | // using Box as it cannot be initialized in const contexts | |
| 39 | const X: LazyLock<Box<u8>> = <_>::default(); | |
| 40 | const Y: LazyCell<Box<u8>> = <_>::default(); | |
| 41 | assert_eq!(**X, 0); | |
| 42 | assert_eq!(**Y, 0); | |
| 43 | } | |
| 44 | ||
| 36 | 45 | #[test] |
| 37 | 46 | #[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads |
| 38 | 47 | fn sync_lazy_new() { |
library/std/tests/sync/lib.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | #![feature(const_default)] | |
| 2 | #![feature(const_trait_impl)] | |
| 1 | 3 | #![feature(mapped_lock_guards)] |
| 2 | 4 | #![feature(mpmc_channel)] |
| 3 | 5 | #![feature(oneshot_channel)] |
library/std/tests/thread.rs-1| ... | ... | @@ -85,7 +85,6 @@ fn thread_local_hygeiene() { |
| 85 | 85 | target_env = "sgx", |
| 86 | 86 | target_os = "solid_asp3", |
| 87 | 87 | target_os = "teeos", |
| 88 | target_os = "wasi" | |
| 89 | 88 | ), |
| 90 | 89 | should_panic |
| 91 | 90 | )] |
src/bootstrap/src/core/build_steps/dist.rs+2-2| ... | ... | @@ -636,9 +636,9 @@ impl Step for Rustc { |
| 636 | 636 | let page_src = file_entry.path(); |
| 637 | 637 | let page_dst = man_dst.join(file_entry.file_name()); |
| 638 | 638 | let src_text = t!(std::fs::read_to_string(&page_src)); |
| 639 | let new_text = src_text.replace("<INSERT VERSION HERE>", &builder.version); | |
| 639 | let version = builder.rust_info().version(builder.build, &builder.version); | |
| 640 | let new_text = src_text.replace("<INSERT VERSION HERE>", &version); | |
| 640 | 641 | t!(std::fs::write(&page_dst, &new_text)); |
| 641 | t!(fs::copy(&page_src, &page_dst)); | |
| 642 | 642 | } |
| 643 | 643 | |
| 644 | 644 | // Debugger scripts |
src/bootstrap/src/core/build_steps/test.rs+4| ... | ... | @@ -2334,6 +2334,10 @@ Please disable assertions with `rust.debug-assertions = false`. |
| 2334 | 2334 | cmd.arg("--verbose"); |
| 2335 | 2335 | } |
| 2336 | 2336 | |
| 2337 | if builder.config.cmd.verbose_run_make_subprocess_output() { | |
| 2338 | cmd.arg("--verbose-run-make-subprocess-output"); | |
| 2339 | } | |
| 2340 | ||
| 2337 | 2341 | if builder.config.rustc_debug_assertions { |
| 2338 | 2342 | cmd.arg("--with-rustc-debug-assertions"); |
| 2339 | 2343 | } |
src/bootstrap/src/core/config/flags.rs+13| ... | ... | @@ -422,6 +422,10 @@ pub enum Subcommand { |
| 422 | 422 | #[arg(long)] |
| 423 | 423 | /// don't capture stdout/stderr of tests |
| 424 | 424 | no_capture: bool, |
| 425 | #[arg(long, default_value_t = true, action = clap::ArgAction::Set, default_missing_value = "true", num_args = 0..=1, require_equals = true)] | |
| 426 | /// whether to show verbose subprocess output for run-make tests; | |
| 427 | /// set to false to suppress output for passing tests (e.g. for cg_clif with --no-capture) | |
| 428 | verbose_run_make_subprocess_output: bool, | |
| 425 | 429 | #[arg(long)] |
| 426 | 430 | /// Use a different codegen backend when running tests. |
| 427 | 431 | test_codegen_backend: Option<CodegenBackendKind>, |
| ... | ... | @@ -631,6 +635,15 @@ impl Subcommand { |
| 631 | 635 | } |
| 632 | 636 | } |
| 633 | 637 | |
| 638 | pub fn verbose_run_make_subprocess_output(&self) -> bool { | |
| 639 | match *self { | |
| 640 | Subcommand::Test { verbose_run_make_subprocess_output, .. } => { | |
| 641 | verbose_run_make_subprocess_output | |
| 642 | } | |
| 643 | _ => true, | |
| 644 | } | |
| 645 | } | |
| 646 | ||
| 634 | 647 | pub fn rustfix_coverage(&self) -> bool { |
| 635 | 648 | match *self { |
| 636 | 649 | Subcommand::Test { rustfix_coverage, .. } => rustfix_coverage, |
src/bootstrap/src/utils/change_tracker.rs+5| ... | ... | @@ -621,4 +621,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[ |
| 621 | 621 | severity: ChangeSeverity::Info, |
| 622 | 622 | summary: "`x.py` stopped accepting partial argument names. Use full names to avoid errors.", |
| 623 | 623 | }, |
| 624 | ChangeInfo { | |
| 625 | change_id: 154587, | |
| 626 | severity: ChangeSeverity::Info, | |
| 627 | summary: "New `--verbose-run-make-subprocess-output` flag for `x.py test` (defaults to true). Set `--verbose-run-make-subprocess-output=false` to suppress verbose subprocess output for passing run-make tests when using `--no-capture`.", | |
| 628 | }, | |
| 624 | 629 | ]; |
src/doc/rustc-dev-guide/src/tests/compiletest.md+9| ... | ... | @@ -460,6 +460,15 @@ However, revisions or building auxiliary via directives are not currently suppor |
| 460 | 460 | `rmake.rs` and `run-make-support` may *not* use any nightly/unstable features, |
| 461 | 461 | as they must be compilable by a stage 0 rustc that may be a beta or even stable rustc. |
| 462 | 462 | |
| 463 | By default, run-make tests print each subprocess command and its stdout/stderr. | |
| 464 | When running with `--no-capture` on `panic=abort` test suites (such as `cg_clif`), | |
| 465 | this can flood the terminal. Omit `--verbose-run-make-subprocess-output` to | |
| 466 | suppress this output for passing tests — failing tests always print regardless: | |
| 467 | ||
| 468 | ```bash | |
| 469 | ./x test tests/run-make --no-capture --verbose-run-make-subprocess-output=false | |
| 470 | ``` | |
| 471 | ||
| 463 | 472 | #### Quickly check if `rmake.rs` tests can be compiled |
| 464 | 473 | |
| 465 | 474 | You can quickly check if `rmake.rs` tests can be compiled without having to |
src/etc/completions/x.fish+2| ... | ... | @@ -420,6 +420,7 @@ complete -c x -n "__fish_x_using_subcommand test" -l extra-checks -d 'comma-sepa |
| 420 | 420 | complete -c x -n "__fish_x_using_subcommand test" -l compare-mode -d 'mode describing what file the actual ui output will be compared to' -r |
| 421 | 421 | complete -c x -n "__fish_x_using_subcommand test" -l pass -d 'force {check,build,run}-pass tests to this mode' -r |
| 422 | 422 | complete -c x -n "__fish_x_using_subcommand test" -l run -d 'whether to execute run-* tests' -r |
| 423 | complete -c x -n "__fish_x_using_subcommand test" -l verbose-run-make-subprocess-output -d 'whether to show verbose subprocess output for run-make tests; set to false to suppress output for passing tests (e.g. for cg_clif with --no-capture)' -r -f -a "{true\t'',false\t''}" | |
| 423 | 424 | complete -c x -n "__fish_x_using_subcommand test" -l test-codegen-backend -d 'Use a different codegen backend when running tests' -r |
| 424 | 425 | complete -c x -n "__fish_x_using_subcommand test" -l config -d 'TOML configuration file for build' -r -F |
| 425 | 426 | complete -c x -n "__fish_x_using_subcommand test" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" |
| ... | ... | @@ -473,6 +474,7 @@ complete -c x -n "__fish_x_using_subcommand t" -l extra-checks -d 'comma-separat |
| 473 | 474 | complete -c x -n "__fish_x_using_subcommand t" -l compare-mode -d 'mode describing what file the actual ui output will be compared to' -r |
| 474 | 475 | complete -c x -n "__fish_x_using_subcommand t" -l pass -d 'force {check,build,run}-pass tests to this mode' -r |
| 475 | 476 | complete -c x -n "__fish_x_using_subcommand t" -l run -d 'whether to execute run-* tests' -r |
| 477 | complete -c x -n "__fish_x_using_subcommand t" -l verbose-run-make-subprocess-output -d 'whether to show verbose subprocess output for run-make tests; set to false to suppress output for passing tests (e.g. for cg_clif with --no-capture)' -r -f -a "{true\t'',false\t''}" | |
| 476 | 478 | complete -c x -n "__fish_x_using_subcommand t" -l test-codegen-backend -d 'Use a different codegen backend when running tests' -r |
| 477 | 479 | complete -c x -n "__fish_x_using_subcommand t" -l config -d 'TOML configuration file for build' -r -F |
| 478 | 480 | complete -c x -n "__fish_x_using_subcommand t" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" |
src/etc/completions/x.ps1+2| ... | ... | @@ -487,6 +487,7 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { |
| 487 | 487 | [CompletionResult]::new('--compare-mode', '--compare-mode', [CompletionResultType]::ParameterName, 'mode describing what file the actual ui output will be compared to') |
| 488 | 488 | [CompletionResult]::new('--pass', '--pass', [CompletionResultType]::ParameterName, 'force {check,build,run}-pass tests to this mode') |
| 489 | 489 | [CompletionResult]::new('--run', '--run', [CompletionResultType]::ParameterName, 'whether to execute run-* tests') |
| 490 | [CompletionResult]::new('--verbose-run-make-subprocess-output', '--verbose-run-make-subprocess-output', [CompletionResultType]::ParameterName, 'whether to show verbose subprocess output for run-make tests; set to false to suppress output for passing tests (e.g. for cg_clif with --no-capture)') | |
| 490 | 491 | [CompletionResult]::new('--test-codegen-backend', '--test-codegen-backend', [CompletionResultType]::ParameterName, 'Use a different codegen backend when running tests') |
| 491 | 492 | [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') |
| 492 | 493 | [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') |
| ... | ... | @@ -547,6 +548,7 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { |
| 547 | 548 | [CompletionResult]::new('--compare-mode', '--compare-mode', [CompletionResultType]::ParameterName, 'mode describing what file the actual ui output will be compared to') |
| 548 | 549 | [CompletionResult]::new('--pass', '--pass', [CompletionResultType]::ParameterName, 'force {check,build,run}-pass tests to this mode') |
| 549 | 550 | [CompletionResult]::new('--run', '--run', [CompletionResultType]::ParameterName, 'whether to execute run-* tests') |
| 551 | [CompletionResult]::new('--verbose-run-make-subprocess-output', '--verbose-run-make-subprocess-output', [CompletionResultType]::ParameterName, 'whether to show verbose subprocess output for run-make tests; set to false to suppress output for passing tests (e.g. for cg_clif with --no-capture)') | |
| 550 | 552 | [CompletionResult]::new('--test-codegen-backend', '--test-codegen-backend', [CompletionResultType]::ParameterName, 'Use a different codegen backend when running tests') |
| 551 | 553 | [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') |
| 552 | 554 | [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') |
src/etc/completions/x.py.fish+2| ... | ... | @@ -420,6 +420,7 @@ complete -c x.py -n "__fish_x.py_using_subcommand test" -l extra-checks -d 'comm |
| 420 | 420 | complete -c x.py -n "__fish_x.py_using_subcommand test" -l compare-mode -d 'mode describing what file the actual ui output will be compared to' -r |
| 421 | 421 | complete -c x.py -n "__fish_x.py_using_subcommand test" -l pass -d 'force {check,build,run}-pass tests to this mode' -r |
| 422 | 422 | complete -c x.py -n "__fish_x.py_using_subcommand test" -l run -d 'whether to execute run-* tests' -r |
| 423 | complete -c x.py -n "__fish_x.py_using_subcommand test" -l verbose-run-make-subprocess-output -d 'whether to show verbose subprocess output for run-make tests; set to false to suppress output for passing tests (e.g. for cg_clif with --no-capture)' -r -f -a "{true\t'',false\t''}" | |
| 423 | 424 | complete -c x.py -n "__fish_x.py_using_subcommand test" -l test-codegen-backend -d 'Use a different codegen backend when running tests' -r |
| 424 | 425 | complete -c x.py -n "__fish_x.py_using_subcommand test" -l config -d 'TOML configuration file for build' -r -F |
| 425 | 426 | complete -c x.py -n "__fish_x.py_using_subcommand test" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" |
| ... | ... | @@ -473,6 +474,7 @@ complete -c x.py -n "__fish_x.py_using_subcommand t" -l extra-checks -d 'comma-s |
| 473 | 474 | complete -c x.py -n "__fish_x.py_using_subcommand t" -l compare-mode -d 'mode describing what file the actual ui output will be compared to' -r |
| 474 | 475 | complete -c x.py -n "__fish_x.py_using_subcommand t" -l pass -d 'force {check,build,run}-pass tests to this mode' -r |
| 475 | 476 | complete -c x.py -n "__fish_x.py_using_subcommand t" -l run -d 'whether to execute run-* tests' -r |
| 477 | complete -c x.py -n "__fish_x.py_using_subcommand t" -l verbose-run-make-subprocess-output -d 'whether to show verbose subprocess output for run-make tests; set to false to suppress output for passing tests (e.g. for cg_clif with --no-capture)' -r -f -a "{true\t'',false\t''}" | |
| 476 | 478 | complete -c x.py -n "__fish_x.py_using_subcommand t" -l test-codegen-backend -d 'Use a different codegen backend when running tests' -r |
| 477 | 479 | complete -c x.py -n "__fish_x.py_using_subcommand t" -l config -d 'TOML configuration file for build' -r -F |
| 478 | 480 | complete -c x.py -n "__fish_x.py_using_subcommand t" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" |
src/etc/completions/x.py.ps1+2| ... | ... | @@ -487,6 +487,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { |
| 487 | 487 | [CompletionResult]::new('--compare-mode', '--compare-mode', [CompletionResultType]::ParameterName, 'mode describing what file the actual ui output will be compared to') |
| 488 | 488 | [CompletionResult]::new('--pass', '--pass', [CompletionResultType]::ParameterName, 'force {check,build,run}-pass tests to this mode') |
| 489 | 489 | [CompletionResult]::new('--run', '--run', [CompletionResultType]::ParameterName, 'whether to execute run-* tests') |
| 490 | [CompletionResult]::new('--verbose-run-make-subprocess-output', '--verbose-run-make-subprocess-output', [CompletionResultType]::ParameterName, 'whether to show verbose subprocess output for run-make tests; set to false to suppress output for passing tests (e.g. for cg_clif with --no-capture)') | |
| 490 | 491 | [CompletionResult]::new('--test-codegen-backend', '--test-codegen-backend', [CompletionResultType]::ParameterName, 'Use a different codegen backend when running tests') |
| 491 | 492 | [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') |
| 492 | 493 | [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') |
| ... | ... | @@ -547,6 +548,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { |
| 547 | 548 | [CompletionResult]::new('--compare-mode', '--compare-mode', [CompletionResultType]::ParameterName, 'mode describing what file the actual ui output will be compared to') |
| 548 | 549 | [CompletionResult]::new('--pass', '--pass', [CompletionResultType]::ParameterName, 'force {check,build,run}-pass tests to this mode') |
| 549 | 550 | [CompletionResult]::new('--run', '--run', [CompletionResultType]::ParameterName, 'whether to execute run-* tests') |
| 551 | [CompletionResult]::new('--verbose-run-make-subprocess-output', '--verbose-run-make-subprocess-output', [CompletionResultType]::ParameterName, 'whether to show verbose subprocess output for run-make tests; set to false to suppress output for passing tests (e.g. for cg_clif with --no-capture)') | |
| 550 | 552 | [CompletionResult]::new('--test-codegen-backend', '--test-codegen-backend', [CompletionResultType]::ParameterName, 'Use a different codegen backend when running tests') |
| 551 | 553 | [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') |
| 552 | 554 | [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') |
src/etc/completions/x.py.sh+10-2| ... | ... | @@ -4638,7 +4638,7 @@ _x.py() { |
| 4638 | 4638 | return 0 |
| 4639 | 4639 | ;; |
| 4640 | 4640 | x.py__test) |
| 4641 | opts="-v -i -j -h --no-fail-fast --test-args --compiletest-rustc-args --all-targets --doc --tests --bless --extra-checks --force-rerun --only-modified --compare-mode --pass --run --rustfix-coverage --no-capture --test-codegen-backend --bypass-ignore-backends --no-doc --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..." | |
| 4641 | opts="-v -i -j -h --no-fail-fast --test-args --compiletest-rustc-args --all-targets --doc --tests --bless --extra-checks --force-rerun --only-modified --compare-mode --pass --run --rustfix-coverage --no-capture --verbose-run-make-subprocess-output --test-codegen-backend --bypass-ignore-backends --no-doc --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..." | |
| 4642 | 4642 | if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then |
| 4643 | 4643 | COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) |
| 4644 | 4644 | return 0 |
| ... | ... | @@ -4668,6 +4668,10 @@ _x.py() { |
| 4668 | 4668 | COMPREPLY=($(compgen -f "${cur}")) |
| 4669 | 4669 | return 0 |
| 4670 | 4670 | ;; |
| 4671 | --verbose-run-make-subprocess-output) | |
| 4672 | COMPREPLY=($(compgen -W "true false" -- "${cur}")) | |
| 4673 | return 0 | |
| 4674 | ;; | |
| 4671 | 4675 | --test-codegen-backend) |
| 4672 | 4676 | COMPREPLY=($(compgen -f "${cur}")) |
| 4673 | 4677 | return 0 |
| ... | ... | @@ -4852,7 +4856,7 @@ _x.py() { |
| 4852 | 4856 | return 0 |
| 4853 | 4857 | ;; |
| 4854 | 4858 | x.py__test) |
| 4855 | opts="-v -i -j -h --no-fail-fast --test-args --compiletest-rustc-args --all-targets --doc --tests --bless --extra-checks --force-rerun --only-modified --compare-mode --pass --run --rustfix-coverage --no-capture --test-codegen-backend --bypass-ignore-backends --no-doc --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..." | |
| 4859 | opts="-v -i -j -h --no-fail-fast --test-args --compiletest-rustc-args --all-targets --doc --tests --bless --extra-checks --force-rerun --only-modified --compare-mode --pass --run --rustfix-coverage --no-capture --verbose-run-make-subprocess-output --test-codegen-backend --bypass-ignore-backends --no-doc --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..." | |
| 4856 | 4860 | if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then |
| 4857 | 4861 | COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) |
| 4858 | 4862 | return 0 |
| ... | ... | @@ -4882,6 +4886,10 @@ _x.py() { |
| 4882 | 4886 | COMPREPLY=($(compgen -f "${cur}")) |
| 4883 | 4887 | return 0 |
| 4884 | 4888 | ;; |
| 4889 | --verbose-run-make-subprocess-output) | |
| 4890 | COMPREPLY=($(compgen -W "true false" -- "${cur}")) | |
| 4891 | return 0 | |
| 4892 | ;; | |
| 4885 | 4893 | --test-codegen-backend) |
| 4886 | 4894 | COMPREPLY=($(compgen -f "${cur}")) |
| 4887 | 4895 | return 0 |
src/etc/completions/x.py.zsh+2| ... | ... | @@ -488,6 +488,7 @@ _arguments "${_arguments_options[@]}" : \ |
| 488 | 488 | '--compare-mode=[mode describing what file the actual ui output will be compared to]:COMPARE MODE:_default' \ |
| 489 | 489 | '--pass=[force {check,build,run}-pass tests to this mode]:check | build | run:_default' \ |
| 490 | 490 | '--run=[whether to execute run-* tests]:auto | always | never:_default' \ |
| 491 | '--verbose-run-make-subprocess-output=[whether to show verbose subprocess output for run-make tests; set to false to suppress output for passing tests (e.g. for cg_clif with --no-capture)]' \ | |
| 491 | 492 | '--test-codegen-backend=[Use a different codegen backend when running tests]:TEST_CODEGEN_BACKEND:_default' \ |
| 492 | 493 | '--config=[TOML configuration file for build]:FILE:_files' \ |
| 493 | 494 | '--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ |
| ... | ... | @@ -550,6 +551,7 @@ _arguments "${_arguments_options[@]}" : \ |
| 550 | 551 | '--compare-mode=[mode describing what file the actual ui output will be compared to]:COMPARE MODE:_default' \ |
| 551 | 552 | '--pass=[force {check,build,run}-pass tests to this mode]:check | build | run:_default' \ |
| 552 | 553 | '--run=[whether to execute run-* tests]:auto | always | never:_default' \ |
| 554 | '--verbose-run-make-subprocess-output=[whether to show verbose subprocess output for run-make tests; set to false to suppress output for passing tests (e.g. for cg_clif with --no-capture)]' \ | |
| 553 | 555 | '--test-codegen-backend=[Use a different codegen backend when running tests]:TEST_CODEGEN_BACKEND:_default' \ |
| 554 | 556 | '--config=[TOML configuration file for build]:FILE:_files' \ |
| 555 | 557 | '--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ |
src/etc/completions/x.sh+10-2| ... | ... | @@ -4638,7 +4638,7 @@ _x() { |
| 4638 | 4638 | return 0 |
| 4639 | 4639 | ;; |
| 4640 | 4640 | x__test) |
| 4641 | opts="-v -i -j -h --no-fail-fast --test-args --compiletest-rustc-args --all-targets --doc --tests --bless --extra-checks --force-rerun --only-modified --compare-mode --pass --run --rustfix-coverage --no-capture --test-codegen-backend --bypass-ignore-backends --no-doc --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..." | |
| 4641 | opts="-v -i -j -h --no-fail-fast --test-args --compiletest-rustc-args --all-targets --doc --tests --bless --extra-checks --force-rerun --only-modified --compare-mode --pass --run --rustfix-coverage --no-capture --verbose-run-make-subprocess-output --test-codegen-backend --bypass-ignore-backends --no-doc --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..." | |
| 4642 | 4642 | if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then |
| 4643 | 4643 | COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) |
| 4644 | 4644 | return 0 |
| ... | ... | @@ -4668,6 +4668,10 @@ _x() { |
| 4668 | 4668 | COMPREPLY=($(compgen -f "${cur}")) |
| 4669 | 4669 | return 0 |
| 4670 | 4670 | ;; |
| 4671 | --verbose-run-make-subprocess-output) | |
| 4672 | COMPREPLY=($(compgen -W "true false" -- "${cur}")) | |
| 4673 | return 0 | |
| 4674 | ;; | |
| 4671 | 4675 | --test-codegen-backend) |
| 4672 | 4676 | COMPREPLY=($(compgen -f "${cur}")) |
| 4673 | 4677 | return 0 |
| ... | ... | @@ -4852,7 +4856,7 @@ _x() { |
| 4852 | 4856 | return 0 |
| 4853 | 4857 | ;; |
| 4854 | 4858 | x__test) |
| 4855 | opts="-v -i -j -h --no-fail-fast --test-args --compiletest-rustc-args --all-targets --doc --tests --bless --extra-checks --force-rerun --only-modified --compare-mode --pass --run --rustfix-coverage --no-capture --test-codegen-backend --bypass-ignore-backends --no-doc --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..." | |
| 4859 | opts="-v -i -j -h --no-fail-fast --test-args --compiletest-rustc-args --all-targets --doc --tests --bless --extra-checks --force-rerun --only-modified --compare-mode --pass --run --rustfix-coverage --no-capture --verbose-run-make-subprocess-output --test-codegen-backend --bypass-ignore-backends --no-doc --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..." | |
| 4856 | 4860 | if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then |
| 4857 | 4861 | COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) |
| 4858 | 4862 | return 0 |
| ... | ... | @@ -4882,6 +4886,10 @@ _x() { |
| 4882 | 4886 | COMPREPLY=($(compgen -f "${cur}")) |
| 4883 | 4887 | return 0 |
| 4884 | 4888 | ;; |
| 4889 | --verbose-run-make-subprocess-output) | |
| 4890 | COMPREPLY=($(compgen -W "true false" -- "${cur}")) | |
| 4891 | return 0 | |
| 4892 | ;; | |
| 4885 | 4893 | --test-codegen-backend) |
| 4886 | 4894 | COMPREPLY=($(compgen -f "${cur}")) |
| 4887 | 4895 | return 0 |
src/etc/completions/x.zsh+2| ... | ... | @@ -488,6 +488,7 @@ _arguments "${_arguments_options[@]}" : \ |
| 488 | 488 | '--compare-mode=[mode describing what file the actual ui output will be compared to]:COMPARE MODE:_default' \ |
| 489 | 489 | '--pass=[force {check,build,run}-pass tests to this mode]:check | build | run:_default' \ |
| 490 | 490 | '--run=[whether to execute run-* tests]:auto | always | never:_default' \ |
| 491 | '--verbose-run-make-subprocess-output=[whether to show verbose subprocess output for run-make tests; set to false to suppress output for passing tests (e.g. for cg_clif with --no-capture)]' \ | |
| 491 | 492 | '--test-codegen-backend=[Use a different codegen backend when running tests]:TEST_CODEGEN_BACKEND:_default' \ |
| 492 | 493 | '--config=[TOML configuration file for build]:FILE:_files' \ |
| 493 | 494 | '--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ |
| ... | ... | @@ -550,6 +551,7 @@ _arguments "${_arguments_options[@]}" : \ |
| 550 | 551 | '--compare-mode=[mode describing what file the actual ui output will be compared to]:COMPARE MODE:_default' \ |
| 551 | 552 | '--pass=[force {check,build,run}-pass tests to this mode]:check | build | run:_default' \ |
| 552 | 553 | '--run=[whether to execute run-* tests]:auto | always | never:_default' \ |
| 554 | '--verbose-run-make-subprocess-output=[whether to show verbose subprocess output for run-make tests; set to false to suppress output for passing tests (e.g. for cg_clif with --no-capture)]' \ | |
| 553 | 555 | '--test-codegen-backend=[Use a different codegen backend when running tests]:TEST_CODEGEN_BACKEND:_default' \ |
| 554 | 556 | '--config=[TOML configuration file for build]:FILE:_files' \ |
| 555 | 557 | '--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ |
src/tools/clippy/clippy_utils/src/ast_utils/mod.rs+4| ... | ... | @@ -339,6 +339,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { |
| 339 | 339 | expr: le, |
| 340 | 340 | safety: ls, |
| 341 | 341 | define_opaque: _, |
| 342 | eii_impls: _, | |
| 342 | 343 | }), |
| 343 | 344 | Static(box StaticItem { |
| 344 | 345 | ident: ri, |
| ... | ... | @@ -347,6 +348,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { |
| 347 | 348 | expr: re, |
| 348 | 349 | safety: rs, |
| 349 | 350 | define_opaque: _, |
| 351 | eii_impls: _, | |
| 350 | 352 | }), |
| 351 | 353 | ) => eq_id(*li, *ri) && lm == rm && ls == rs && eq_ty(lt, rt) && eq_expr_opt(le.as_deref(), re.as_deref()), |
| 352 | 354 | ( |
| ... | ... | @@ -540,6 +542,7 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool { |
| 540 | 542 | expr: le, |
| 541 | 543 | safety: ls, |
| 542 | 544 | define_opaque: _, |
| 545 | eii_impls: _, | |
| 543 | 546 | }), |
| 544 | 547 | Static(box StaticItem { |
| 545 | 548 | ident: ri, |
| ... | ... | @@ -548,6 +551,7 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool { |
| 548 | 551 | expr: re, |
| 549 | 552 | safety: rs, |
| 550 | 553 | define_opaque: _, |
| 554 | eii_impls: _, | |
| 551 | 555 | }), |
| 552 | 556 | ) => eq_id(*li, *ri) && eq_ty(lt, rt) && lm == rm && eq_expr_opt(le.as_deref(), re.as_deref()) && ls == rs, |
| 553 | 557 | ( |
src/tools/compiletest/src/common.rs+4| ... | ... | @@ -603,6 +603,10 @@ pub(crate) struct Config { |
| 603 | 603 | /// FIXME: this is *way* too coarse; the user can't select *which* info to verbosely dump. |
| 604 | 604 | pub(crate) verbose: bool, |
| 605 | 605 | |
| 606 | /// Whether to enable verbose subprocess output for run-make tests. | |
| 607 | /// Set to false to suppress output for passing tests (e.g. for cg_clif with --no-capture). | |
| 608 | pub verbose_run_make_subprocess_output: bool, | |
| 609 | ||
| 606 | 610 | /// Where to find the remote test client process, if we're using it. |
| 607 | 611 | /// |
| 608 | 612 | /// Note: this is *only* used for target platform executables created by `run-make` test |
src/tools/compiletest/src/lib.rs+7| ... | ... | @@ -134,6 +134,11 @@ fn parse_config(args: Vec<String>) -> Config { |
| 134 | 134 | ) |
| 135 | 135 | .optflag("", "optimize-tests", "run tests with optimizations enabled") |
| 136 | 136 | .optflag("", "verbose", "run tests verbosely, showing all output") |
| 137 | .optflag( | |
| 138 | "", | |
| 139 | "verbose-run-make-subprocess-output", | |
| 140 | "show verbose subprocess output for successful run-make tests", | |
| 141 | ) | |
| 137 | 142 | .optflag( |
| 138 | 143 | "", |
| 139 | 144 | "bless", |
| ... | ... | @@ -471,6 +476,8 @@ fn parse_config(args: Vec<String>) -> Config { |
| 471 | 476 | adb_test_dir, |
| 472 | 477 | adb_device_status, |
| 473 | 478 | verbose: matches.opt_present("verbose"), |
| 479 | verbose_run_make_subprocess_output: matches | |
| 480 | .opt_present("verbose-run-make-subprocess-output"), | |
| 474 | 481 | only_modified: matches.opt_present("only-modified"), |
| 475 | 482 | remote_test_client: matches.opt_str("remote-test-client").map(Utf8PathBuf::from), |
| 476 | 483 | compare_mode, |
src/tools/compiletest/src/runtest/run_make.rs+7| ... | ... | @@ -231,6 +231,13 @@ impl TestCx<'_> { |
| 231 | 231 | } |
| 232 | 232 | |
| 233 | 233 | // Guard against externally-set env vars. |
| 234 | // Set env var to enable verbose output for successful commands. | |
| 235 | // Only set when --verbose-run-make-subprocess-output is passed. | |
| 236 | cmd.env_remove("__RMAKE_VERBOSE_SUBPROCESS_OUTPUT"); | |
| 237 | if self.config.verbose_run_make_subprocess_output { | |
| 238 | cmd.env("__RMAKE_VERBOSE_SUBPROCESS_OUTPUT", "1"); | |
| 239 | } | |
| 240 | ||
| 234 | 241 | cmd.env_remove("__RUSTC_DEBUG_ASSERTIONS_ENABLED"); |
| 235 | 242 | if self.config.with_rustc_debug_assertions { |
| 236 | 243 | // Used for `run_make_support::env::rustc_debug_assertions_enabled`. |
src/tools/compiletest/src/rustdoc_gui_test.rs+1| ... | ... | @@ -109,6 +109,7 @@ fn incomplete_config_for_rustdoc_gui_test() -> Config { |
| 109 | 109 | adb_test_dir: Default::default(), |
| 110 | 110 | adb_device_status: Default::default(), |
| 111 | 111 | verbose: Default::default(), |
| 112 | verbose_run_make_subprocess_output: Default::default(), | |
| 112 | 113 | remote_test_client: Default::default(), |
| 113 | 114 | compare_mode: Default::default(), |
| 114 | 115 | rustfix_coverage: Default::default(), |
src/tools/run-make-support/src/util.rs+11-2| ... | ... | @@ -4,7 +4,7 @@ use crate::command::{Command, CompletedProcess}; |
| 4 | 4 | use crate::env::env_var; |
| 5 | 5 | use crate::path_helpers::cwd; |
| 6 | 6 | |
| 7 | pub(crate) fn verbose_print_command(cmd: &Command, output: &CompletedProcess) { | |
| 7 | fn print_command_output(cmd: &Command, output: &CompletedProcess) { | |
| 8 | 8 | cmd.inspect(|std_cmd| { |
| 9 | 9 | eprintln!("{std_cmd:?}"); |
| 10 | 10 | }); |
| ... | ... | @@ -16,6 +16,15 @@ pub(crate) fn verbose_print_command(cmd: &Command, output: &CompletedProcess) { |
| 16 | 16 | } |
| 17 | 17 | } |
| 18 | 18 | |
| 19 | pub(crate) fn verbose_print_command(cmd: &Command, output: &CompletedProcess) { | |
| 20 | // Only prints when `--verbose-run-make-subprocess-output` is active (env var set), | |
| 21 | // so that passing tests don't flood the terminal when using `--no-capture`. | |
| 22 | if std::env::var_os("__RMAKE_VERBOSE_SUBPROCESS_OUTPUT").is_none() { | |
| 23 | return; | |
| 24 | } | |
| 25 | print_command_output(cmd, output); | |
| 26 | } | |
| 27 | ||
| 19 | 28 | /// If a given [`Command`] failed (as indicated by its [`CompletedProcess`]), verbose print the |
| 20 | 29 | /// executed command, failure location, output status and stdout/stderr, and abort the process with |
| 21 | 30 | /// exit code `1`. |
| ... | ... | @@ -29,7 +38,7 @@ pub(crate) fn handle_failed_output( |
| 29 | 38 | } else { |
| 30 | 39 | eprintln!("command failed at line {caller_line_number}"); |
| 31 | 40 | } |
| 32 | verbose_print_command(cmd, &output); | |
| 41 | print_command_output(cmd, &output); | |
| 33 | 42 | std::process::exit(1) |
| 34 | 43 | } |
| 35 | 44 |
tests/codegen-llvm/inject-autocast.rs created+93| ... | ... | @@ -0,0 +1,93 @@ |
| 1 | //@ compile-flags: -C opt-level=0 -C target-feature=+kl,+avx512vp2intersect,+avx512vl,+avxneconvert | |
| 2 | //@ only-x86_64 | |
| 3 | ||
| 4 | #![feature(link_llvm_intrinsics, abi_unadjusted, simd_ffi, portable_simd)] | |
| 5 | #![crate_type = "lib"] | |
| 6 | ||
| 7 | use std::simd::{f32x4, i16x8, i64x2}; | |
| 8 | ||
| 9 | #[repr(C, packed)] | |
| 10 | pub struct Bar(u32, i64x2, i64x2, i64x2, i64x2, i64x2, i64x2); | |
| 11 | // CHECK: %Bar = type <{ i32, <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64> }> | |
| 12 | ||
| 13 | // CHECK-LABEL: @struct_autocast | |
| 14 | #[no_mangle] | |
| 15 | pub unsafe fn struct_autocast(key_metadata: u32, key: i64x2) -> Bar { | |
| 16 | extern "unadjusted" { | |
| 17 | #[link_name = "llvm.x86.encodekey128"] | |
| 18 | fn foo(key_metadata: u32, key: i64x2) -> Bar; | |
| 19 | } | |
| 20 | ||
| 21 | // CHECK: [[A:%[0-9]+]] = call { i32, <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64> } @llvm.x86.encodekey128(i32 {{.*}}, <2 x i64> {{.*}}) | |
| 22 | // CHECK: [[B:%[0-9]+]] = extractvalue { i32, <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64> } [[A]], 0 | |
| 23 | // CHECK: [[C:%[0-9]+]] = insertvalue %Bar poison, i32 [[B]], 0 | |
| 24 | // CHECK: [[D:%[0-9]+]] = extractvalue { i32, <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64> } [[A]], 1 | |
| 25 | // CHECK: [[E:%[0-9]+]] = insertvalue %Bar [[C]], <2 x i64> [[D]], 1 | |
| 26 | // CHECK: [[F:%[0-9]+]] = extractvalue { i32, <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64> } [[A]], 2 | |
| 27 | // CHECK: [[G:%[0-9]+]] = insertvalue %Bar [[E]], <2 x i64> [[F]], 2 | |
| 28 | // CHECK: [[H:%[0-9]+]] = extractvalue { i32, <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64> } [[A]], 3 | |
| 29 | // CHECK: [[I:%[0-9]+]] = insertvalue %Bar [[G]], <2 x i64> [[H]], 3 | |
| 30 | // CHECK: [[J:%[0-9]+]] = extractvalue { i32, <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64> } [[A]], 4 | |
| 31 | // CHECK: [[K:%[0-9]+]] = insertvalue %Bar [[I]], <2 x i64> [[J]], 4 | |
| 32 | // CHECK: [[L:%[0-9]+]] = extractvalue { i32, <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64> } [[A]], 5 | |
| 33 | // CHECK: [[M:%[0-9]+]] = insertvalue %Bar [[K]], <2 x i64> [[L]], 5 | |
| 34 | // CHECK: [[N:%[0-9]+]] = extractvalue { i32, <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64> } [[A]], 6 | |
| 35 | // CHECK: insertvalue %Bar [[M]], <2 x i64> [[N]], 6 | |
| 36 | foo(key_metadata, key) | |
| 37 | } | |
| 38 | ||
| 39 | // CHECK-LABEL: @struct_with_i1_vector_autocast | |
| 40 | #[no_mangle] | |
| 41 | pub unsafe fn struct_with_i1_vector_autocast(a: i64x2, b: i64x2) -> (u8, u8) { | |
| 42 | extern "unadjusted" { | |
| 43 | #[link_name = "llvm.x86.avx512.vp2intersect.q.128"] | |
| 44 | fn foo(a: i64x2, b: i64x2) -> (u8, u8); | |
| 45 | } | |
| 46 | ||
| 47 | // CHECK: [[A:%[0-9]+]] = call { <2 x i1>, <2 x i1> } @llvm.x86.avx512.vp2intersect.q.128(<2 x i64> {{.*}}, <2 x i64> {{.*}}) | |
| 48 | // CHECK: [[B:%[0-9]+]] = extractvalue { <2 x i1>, <2 x i1> } [[A]], 0 | |
| 49 | // CHECK: [[C:%[0-9]+]] = shufflevector <2 x i1> [[B]], <2 x i1> zeroinitializer, <8 x i32> <i32 0, i32 1, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2> | |
| 50 | // CHECK: [[D:%[0-9]+]] = bitcast <8 x i1> [[C]] to i8 | |
| 51 | // CHECK: [[E:%[0-9]+]] = insertvalue { i8, i8 } poison, i8 [[D]], 0 | |
| 52 | // CHECK: [[F:%[0-9]+]] = extractvalue { <2 x i1>, <2 x i1> } [[A]], 1 | |
| 53 | // CHECK: [[G:%[0-9]+]] = shufflevector <2 x i1> [[F]], <2 x i1> zeroinitializer, <8 x i32> <i32 0, i32 1, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2> | |
| 54 | // CHECK: [[H:%[0-9]+]] = bitcast <8 x i1> [[G]] to i8 | |
| 55 | // CHECK: insertvalue { i8, i8 } [[E]], i8 [[H]], 1 | |
| 56 | foo(a, b) | |
| 57 | } | |
| 58 | ||
| 59 | // CHECK-LABEL: @i1_vector_autocast | |
| 60 | #[no_mangle] | |
| 61 | pub unsafe fn i1_vector_autocast(a: u8, b: u8) -> u8 { | |
| 62 | extern "unadjusted" { | |
| 63 | #[link_name = "llvm.x86.avx512.kadd.b"] | |
| 64 | fn foo(a: u8, b: u8) -> u8; | |
| 65 | } | |
| 66 | ||
| 67 | // CHECK: [[A:%[0-9]+]] = bitcast i8 {{.*}} to <8 x i1> | |
| 68 | // CHECK: [[B:%[0-9]+]] = bitcast i8 {{.*}} to <8 x i1> | |
| 69 | // CHECK: [[C:%[0-9]+]] = call <8 x i1> @llvm.x86.avx512.kadd.b(<8 x i1> [[A]], <8 x i1> [[B]]) | |
| 70 | // CHECK: bitcast <8 x i1> [[C]] to i8 | |
| 71 | foo(a, b) | |
| 72 | } | |
| 73 | ||
| 74 | // CHECK-LABEL: @bf16_vector_autocast | |
| 75 | #[no_mangle] | |
| 76 | pub unsafe fn bf16_vector_autocast(a: f32x4) -> i16x8 { | |
| 77 | extern "unadjusted" { | |
| 78 | #[link_name = "llvm.x86.vcvtneps2bf16128"] | |
| 79 | fn foo(a: f32x4) -> i16x8; | |
| 80 | } | |
| 81 | ||
| 82 | // CHECK: [[A:%[0-9]+]] = call <8 x bfloat> @llvm.x86.vcvtneps2bf16128(<4 x float> {{.*}}) | |
| 83 | // CHECK: bitcast <8 x bfloat> [[A]] to <8 x i16> | |
| 84 | foo(a) | |
| 85 | } | |
| 86 | ||
| 87 | // CHECK: declare { i32, <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64> } @llvm.x86.encodekey128(i32, <2 x i64>) | |
| 88 | ||
| 89 | // CHECK: declare { <2 x i1>, <2 x i1> } @llvm.x86.avx512.vp2intersect.q.128(<2 x i64>, <2 x i64>) | |
| 90 | ||
| 91 | // CHECK: declare <8 x i1> @llvm.x86.avx512.kadd.b(<8 x i1>, <8 x i1>) | |
| 92 | ||
| 93 | // CHECK: declare <8 x bfloat> @llvm.x86.vcvtneps2bf16128(<4 x float>) |
tests/debuginfo/basic-stepping.rs+35-24| ... | ... | @@ -9,9 +9,20 @@ |
| 9 | 9 | // Debugger tests need debuginfo |
| 10 | 10 | //@ compile-flags: -g |
| 11 | 11 | |
| 12 | // FIXME(#128945): SingleUseConsts shouldn't need to be disabled. | |
| 13 | //@ revisions: default-mir-passes no-SingleUseConsts-mir-pass | |
| 14 | //@ [no-SingleUseConsts-mir-pass] compile-flags: -Zmir-enable-passes=-SingleUseConsts | |
| 12 | // Some optimization passes _improve_ compile times [1]. So we want to run some | |
| 13 | // passes even with `-Copt-level=0`. That means that some of the lines below can | |
| 14 | // be optimized away. To make regression testing more robust, we also want to | |
| 15 | // run this test with such passes disabled. The solution is to use two | |
| 16 | // revisions. One with default `-Copt-level=0` passes, and one "even less | |
| 17 | // optimized", with enough optimization passes disabled to keep the maximum | |
| 18 | // number of lines steppable. | |
| 19 | // | |
| 20 | // If `-Zmir-enable-passes=-...` ends up being annoying to maintain, we can try | |
| 21 | // switching to `-Zmir-opt-level=0` instead. | |
| 22 | // | |
| 23 | // [1]: https://github.com/rust-lang/compiler-team/issues/319 | |
| 24 | //@ revisions: opt-level-0 maximally-steppable | |
| 25 | //@ [maximally-steppable] compile-flags: -Zmir-enable-passes=-SingleUseConsts | |
| 15 | 26 | |
| 16 | 27 | // === GDB TESTS =================================================================================== |
| 17 | 28 | |
| ... | ... | @@ -20,12 +31,12 @@ |
| 20 | 31 | //@ gdb-command: next |
| 21 | 32 | //@ gdb-check: let d = c = 99; |
| 22 | 33 | //@ gdb-command: next |
| 23 | //@ [no-SingleUseConsts-mir-pass] gdb-check: let e = "hi bob"; | |
| 24 | //@ [no-SingleUseConsts-mir-pass] gdb-command: next | |
| 25 | //@ [no-SingleUseConsts-mir-pass] gdb-check: let f = b"hi bob"; | |
| 26 | //@ [no-SingleUseConsts-mir-pass] gdb-command: next | |
| 27 | //@ [no-SingleUseConsts-mir-pass] gdb-check: let g = b'9'; | |
| 28 | //@ [no-SingleUseConsts-mir-pass] gdb-command: next | |
| 34 | //@ [maximally-steppable] gdb-check: let e = "hi bob"; | |
| 35 | //@ [maximally-steppable] gdb-command: next | |
| 36 | //@ [maximally-steppable] gdb-check: let f = b"hi bob"; | |
| 37 | //@ [maximally-steppable] gdb-command: next | |
| 38 | //@ [maximally-steppable] gdb-check: let g = b'9'; | |
| 39 | //@ [maximally-steppable] gdb-command: next | |
| 29 | 40 | //@ gdb-check: let h = ["whatever"; 8]; |
| 30 | 41 | //@ gdb-command: next |
| 31 | 42 | //@ gdb-check: let i = [1,2,3,4]; |
| ... | ... | @@ -61,15 +72,15 @@ |
| 61 | 72 | //@ lldb-check: [...]let d = c = 99;[...] |
| 62 | 73 | //@ lldb-command: next |
| 63 | 74 | //@ lldb-command: frame select |
| 64 | //@ [no-SingleUseConsts-mir-pass] lldb-check: [...]let e = "hi bob";[...] | |
| 65 | //@ [no-SingleUseConsts-mir-pass] lldb-command: next | |
| 66 | //@ [no-SingleUseConsts-mir-pass] lldb-command: frame select | |
| 67 | //@ [no-SingleUseConsts-mir-pass] lldb-check: [...]let f = b"hi bob";[...] | |
| 68 | //@ [no-SingleUseConsts-mir-pass] lldb-command: next | |
| 69 | //@ [no-SingleUseConsts-mir-pass] lldb-command: frame select | |
| 70 | //@ [no-SingleUseConsts-mir-pass] lldb-check: [...]let g = b'9';[...] | |
| 71 | //@ [no-SingleUseConsts-mir-pass] lldb-command: next | |
| 72 | //@ [no-SingleUseConsts-mir-pass] lldb-command: frame select | |
| 75 | //@ [maximally-steppable] lldb-check: [...]let e = "hi bob";[...] | |
| 76 | //@ [maximally-steppable] lldb-command: next | |
| 77 | //@ [maximally-steppable] lldb-command: frame select | |
| 78 | //@ [maximally-steppable] lldb-check: [...]let f = b"hi bob";[...] | |
| 79 | //@ [maximally-steppable] lldb-command: next | |
| 80 | //@ [maximally-steppable] lldb-command: frame select | |
| 81 | //@ [maximally-steppable] lldb-check: [...]let g = b'9';[...] | |
| 82 | //@ [maximally-steppable] lldb-command: next | |
| 83 | //@ [maximally-steppable] lldb-command: frame select | |
| 73 | 84 | //@ lldb-check: [...]let h = ["whatever"; 8];[...] |
| 74 | 85 | //@ lldb-command: next |
| 75 | 86 | //@ lldb-command: frame select |
| ... | ... | @@ -107,12 +118,12 @@ |
| 107 | 118 | //@ cdb-check: [...]: let mut c = 27; |
| 108 | 119 | //@ cdb-command: p |
| 109 | 120 | //@ cdb-check: [...]: let d = c = 99; |
| 110 | //@ [no-SingleUseConsts-mir-pass] cdb-command: p | |
| 111 | //@ [no-SingleUseConsts-mir-pass] cdb-check: [...]: let e = "hi bob"; | |
| 112 | //@ [no-SingleUseConsts-mir-pass] cdb-command: p | |
| 113 | //@ [no-SingleUseConsts-mir-pass] cdb-check: [...]: let f = b"hi bob"; | |
| 114 | //@ [no-SingleUseConsts-mir-pass] cdb-command: p | |
| 115 | //@ [no-SingleUseConsts-mir-pass] cdb-check: [...]: let g = b'9'; | |
| 121 | //@ [maximally-steppable] cdb-command: p | |
| 122 | //@ [maximally-steppable] cdb-check: [...]: let e = "hi bob"; | |
| 123 | //@ [maximally-steppable] cdb-command: p | |
| 124 | //@ [maximally-steppable] cdb-check: [...]: let f = b"hi bob"; | |
| 125 | //@ [maximally-steppable] cdb-command: p | |
| 126 | //@ [maximally-steppable] cdb-check: [...]: let g = b'9'; | |
| 116 | 127 | //@ cdb-command: p |
| 117 | 128 | //@ cdb-check: [...]: let h = ["whatever"; 8]; |
| 118 | 129 | //@ cdb-command: p |
tests/debuginfo/macro-stepping.rs+4-4| ... | ... | @@ -16,9 +16,9 @@ |
| 16 | 16 | extern crate macro_stepping; // exports new_scope!() |
| 17 | 17 | |
| 18 | 18 | //@ compile-flags: -g |
| 19 | // FIXME(#128945): SingleUseConsts shouldn't need to be disabled. | |
| 20 | //@ revisions: default-mir-passes no-SingleUseConsts-mir-pass | |
| 21 | //@ [no-SingleUseConsts-mir-pass] compile-flags: -Zmir-enable-passes=-SingleUseConsts | |
| 19 | // See explanation in `tests/debuginfo/basic-stepping.rs`. | |
| 20 | //@ revisions: opt-level-0 maximally-steppable | |
| 21 | //@ [maximally-steppable] compile-flags: -Zmir-enable-passes=-SingleUseConsts | |
| 22 | 22 | |
| 23 | 23 | // === GDB TESTS =================================================================================== |
| 24 | 24 | |
| ... | ... | @@ -51,7 +51,7 @@ extern crate macro_stepping; // exports new_scope!() |
| 51 | 51 | //@ gdb-check:[...]#inc-loc2[...] |
| 52 | 52 | //@ gdb-command:next |
| 53 | 53 | //@ gdb-command:frame |
| 54 | //@ [no-SingleUseConsts-mir-pass] gdb-check:[...]#inc-loc3[...] | |
| 54 | //@ [maximally-steppable] gdb-check:[...]#inc-loc3[...] | |
| 55 | 55 | |
| 56 | 56 | // === LLDB TESTS ================================================================================== |
| 57 | 57 |
tests/run-make/simd-ffi/simd.rs+1-1| ... | ... | @@ -35,7 +35,7 @@ extern "C" { |
| 35 | 35 | fn integer(a: i32x4, b: i32x4) -> i32x4; |
| 36 | 36 | // vmaxq_s32 |
| 37 | 37 | #[cfg(target_arch = "aarch64")] |
| 38 | #[link_name = "llvm.aarch64.neon.maxs.v4i32"] | |
| 38 | #[link_name = "llvm.aarch64.neon.smax.v4i32"] | |
| 39 | 39 | fn integer(a: i32x4, b: i32x4) -> i32x4; |
| 40 | 40 | |
| 41 | 41 | // Use a generic LLVM intrinsic to do type checking on other platforms |
tests/ui/associated-types/hr-associated-type-bound-param-6.stderr+12-12| ... | ... | @@ -9,18 +9,6 @@ help: consider restricting type parameter `T` with trait `X` |
| 9 | 9 | LL | impl<S, T: for<'b> X<'b, T>> X<'_, T> for (S,) { |
| 10 | 10 | | ++++++++++++++++++ |
| 11 | 11 | |
| 12 | error[E0277]: the trait bound `for<'b> i32: X<'b, i32>` is not satisfied | |
| 13 | --> $DIR/hr-associated-type-bound-param-6.rs:18:5 | |
| 14 | | | |
| 15 | LL | <(i32,) as X<i32>>::f("abc"); | |
| 16 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'b> X<'b, i32>` is not implemented for `i32` | |
| 17 | | | |
| 18 | help: the trait `X<'_, T>` is implemented for `(S,)` | |
| 19 | --> $DIR/hr-associated-type-bound-param-6.rs:12:1 | |
| 20 | | | |
| 21 | LL | impl<S, T> X<'_, T> for (S,) { | |
| 22 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
| 23 | ||
| 24 | 12 | error[E0277]: the trait bound `for<'b> i32: X<'b, i32>` is not satisfied |
| 25 | 13 | --> $DIR/hr-associated-type-bound-param-6.rs:18:18 |
| 26 | 14 | | |
| ... | ... | @@ -41,6 +29,18 @@ LL | for<'b> T: X<'b, T>, |
| 41 | 29 | LL | fn f(x: &<T as X<'_, T>>::U) { |
| 42 | 30 | | - required by a bound in this associated function |
| 43 | 31 | |
| 32 | error[E0277]: the trait bound `for<'b> i32: X<'b, i32>` is not satisfied | |
| 33 | --> $DIR/hr-associated-type-bound-param-6.rs:18:5 | |
| 34 | | | |
| 35 | LL | <(i32,) as X<i32>>::f("abc"); | |
| 36 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'b> X<'b, i32>` is not implemented for `i32` | |
| 37 | | | |
| 38 | help: the trait `X<'_, T>` is implemented for `(S,)` | |
| 39 | --> $DIR/hr-associated-type-bound-param-6.rs:12:1 | |
| 40 | | | |
| 41 | LL | impl<S, T> X<'_, T> for (S,) { | |
| 42 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
| 43 | ||
| 44 | 44 | error[E0277]: the trait bound `i32: X<'_, i32>` is not satisfied |
| 45 | 45 | --> $DIR/hr-associated-type-bound-param-6.rs:18:27 |
| 46 | 46 | | |
tests/ui/auto-traits/distinct-type-tuple-by-negative-impl.rs created+21| ... | ... | @@ -0,0 +1,21 @@ |
| 1 | //! Regression test for <https://github.com/rust-lang/rust/issues/29516> | |
| 2 | //@ check-pass | |
| 3 | #![feature(auto_traits)] | |
| 4 | #![feature(negative_impls)] | |
| 5 | ||
| 6 | auto trait NotSame {} | |
| 7 | ||
| 8 | impl<A> !NotSame for (A, A) {} | |
| 9 | ||
| 10 | trait OneOfEach {} | |
| 11 | ||
| 12 | impl<A> OneOfEach for (A,) {} | |
| 13 | ||
| 14 | impl<A, B> OneOfEach for (A, B) | |
| 15 | where | |
| 16 | (B,): OneOfEach, | |
| 17 | (A, B): NotSame, | |
| 18 | { | |
| 19 | } | |
| 20 | ||
| 21 | fn main() {} |
tests/ui/binding/ref-in-let-lhs-in-field.rs created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | //! Regression test for <https://github.com/rust-lang/rust/issues/3874> | |
| 2 | //@ build-pass | |
| 3 | #![allow(dead_code)] | |
| 4 | ||
| 5 | enum PureCounter { PureCounterVariant(usize) } | |
| 6 | ||
| 7 | fn each<F>(thing: PureCounter, blk: F) where F: FnOnce(&usize) { | |
| 8 | let PureCounter::PureCounterVariant(ref x) = thing; | |
| 9 | blk(x); | |
| 10 | } | |
| 11 | ||
| 12 | pub fn main() {} |
tests/ui/codegen/deprecated-llvm-intrinsic.rs created+28| ... | ... | @@ -0,0 +1,28 @@ |
| 1 | //@ add-minicore | |
| 2 | //@ build-fail | |
| 3 | //@ compile-flags: --target aarch64-unknown-linux-gnu | |
| 4 | //@ needs-llvm-components: aarch64 | |
| 5 | //@ ignore-backends: gcc | |
| 6 | #![feature(no_core, lang_items, link_llvm_intrinsics, abi_unadjusted, repr_simd, simd_ffi)] | |
| 7 | #![no_std] | |
| 8 | #![no_core] | |
| 9 | #![allow(internal_features, non_camel_case_types, improper_ctypes)] | |
| 10 | #![crate_type = "lib"] | |
| 11 | ||
| 12 | extern crate minicore; | |
| 13 | use minicore::*; | |
| 14 | ||
| 15 | #[repr(simd)] | |
| 16 | pub struct i8x8([i8; 8]); | |
| 17 | ||
| 18 | extern "unadjusted" { | |
| 19 | #[deny(deprecated_llvm_intrinsic)] | |
| 20 | #[link_name = "llvm.aarch64.neon.rbit.v8i8"] | |
| 21 | fn foo(a: i8x8) -> i8x8; | |
| 22 | //~^ ERROR: using deprecated intrinsic `llvm.aarch64.neon.rbit.v8i8`, `llvm.bitreverse.v8i8` can be used instead | |
| 23 | } | |
| 24 | ||
| 25 | #[target_feature(enable = "neon")] | |
| 26 | pub unsafe fn bar(a: i8x8) -> i8x8 { | |
| 27 | foo(a) | |
| 28 | } |
tests/ui/codegen/deprecated-llvm-intrinsic.stderr created+14| ... | ... | @@ -0,0 +1,14 @@ |
| 1 | error: using deprecated intrinsic `llvm.aarch64.neon.rbit.v8i8`, `llvm.bitreverse.v8i8` can be used instead | |
| 2 | --> $DIR/deprecated-llvm-intrinsic.rs:21:5 | |
| 3 | | | |
| 4 | LL | fn foo(a: i8x8) -> i8x8; | |
| 5 | | ^^^^^^^^^^^^^^^^^^^^^^^^ | |
| 6 | | | |
| 7 | note: the lint level is defined here | |
| 8 | --> $DIR/deprecated-llvm-intrinsic.rs:19:12 | |
| 9 | | | |
| 10 | LL | #[deny(deprecated_llvm_intrinsic)] | |
| 11 | | ^^^^^^^^^^^^^^^^^^^^^^^^^ | |
| 12 | ||
| 13 | error: aborting due to 1 previous error | |
| 14 |
tests/ui/codegen/incorrect-arch-intrinsic.rs created+18| ... | ... | @@ -0,0 +1,18 @@ |
| 1 | //@ build-fail | |
| 2 | //@ ignore-s390x | |
| 3 | //@ normalize-stderr: "target arch `(.*)`" -> "target arch `TARGET_ARCH`" | |
| 4 | //@ ignore-backends: gcc | |
| 5 | ||
| 6 | #![feature(link_llvm_intrinsics, abi_unadjusted)] | |
| 7 | ||
| 8 | extern "unadjusted" { | |
| 9 | #[link_name = "llvm.s390.sfpc"] | |
| 10 | fn foo(a: i32); | |
| 11 | //~^ ERROR: intrinsic `llvm.s390.sfpc` cannot be used with target arch | |
| 12 | } | |
| 13 | ||
| 14 | pub fn main() { | |
| 15 | unsafe { | |
| 16 | foo(0); | |
| 17 | } | |
| 18 | } |
tests/ui/codegen/incorrect-arch-intrinsic.stderr created+8| ... | ... | @@ -0,0 +1,8 @@ |
| 1 | error: intrinsic `llvm.s390.sfpc` cannot be used with target arch `TARGET_ARCH` | |
| 2 | --> $DIR/incorrect-arch-intrinsic.rs:10:5 | |
| 3 | | | |
| 4 | LL | fn foo(a: i32); | |
| 5 | | ^^^^^^^^^^^^^^^ | |
| 6 | ||
| 7 | error: aborting due to 1 previous error | |
| 8 |
tests/ui/codegen/incorrect-llvm-intrinsic-signature.rs created+14| ... | ... | @@ -0,0 +1,14 @@ |
| 1 | //@ build-fail | |
| 2 | //@ ignore-backends: gcc | |
| 3 | ||
| 4 | #![feature(link_llvm_intrinsics, abi_unadjusted)] | |
| 5 | ||
| 6 | extern "unadjusted" { | |
| 7 | #[link_name = "llvm.assume"] | |
| 8 | fn foo(); | |
| 9 | //~^ ERROR: intrinsic signature mismatch for `llvm.assume`: expected signature `void (i1)`, found `void ()` | |
| 10 | } | |
| 11 | ||
| 12 | pub fn main() { | |
| 13 | unsafe { foo() } | |
| 14 | } |
tests/ui/codegen/incorrect-llvm-intrinsic-signature.stderr created+8| ... | ... | @@ -0,0 +1,8 @@ |
| 1 | error: intrinsic signature mismatch for `llvm.assume`: expected signature `void (i1)`, found `void ()` | |
| 2 | --> $DIR/incorrect-llvm-intrinsic-signature.rs:8:5 | |
| 3 | | | |
| 4 | LL | fn foo(); | |
| 5 | | ^^^^^^^^^ | |
| 6 | ||
| 7 | error: aborting due to 1 previous error | |
| 8 |
tests/ui/codegen/unknown-llvm-intrinsic.rs created+14| ... | ... | @@ -0,0 +1,14 @@ |
| 1 | //@ build-fail | |
| 2 | //@ ignore-backends: gcc | |
| 3 | ||
| 4 | #![feature(link_llvm_intrinsics, abi_unadjusted)] | |
| 5 | ||
| 6 | extern "unadjusted" { | |
| 7 | #[link_name = "llvm.abcde"] | |
| 8 | fn foo(); | |
| 9 | //~^ ERROR: unknown LLVM intrinsic `llvm.abcde` | |
| 10 | } | |
| 11 | ||
| 12 | pub fn main() { | |
| 13 | unsafe { foo() } | |
| 14 | } |
tests/ui/codegen/unknown-llvm-intrinsic.stderr created+8| ... | ... | @@ -0,0 +1,8 @@ |
| 1 | error: unknown LLVM intrinsic `llvm.abcde` | |
| 2 | --> $DIR/unknown-llvm-intrinsic.rs:8:5 | |
| 3 | | | |
| 4 | LL | fn foo(); | |
| 5 | | ^^^^^^^^^ | |
| 6 | ||
| 7 | error: aborting due to 1 previous error | |
| 8 |
tests/ui/deref/derefmut-closure-drop-order.rs created+47| ... | ... | @@ -0,0 +1,47 @@ |
| 1 | //! Regression test for https://github.com/rust-lang/rust/issues/16774 | |
| 2 | ||
| 3 | //@ run-pass | |
| 4 | #![feature(box_patterns)] | |
| 5 | ||
| 6 | use std::ops::{Deref, DerefMut}; | |
| 7 | ||
| 8 | struct X(Box<isize>); | |
| 9 | ||
| 10 | static mut DESTRUCTOR_RAN: bool = false; | |
| 11 | ||
| 12 | impl Drop for X { | |
| 13 | fn drop(&mut self) { | |
| 14 | unsafe { | |
| 15 | assert!(!DESTRUCTOR_RAN); | |
| 16 | DESTRUCTOR_RAN = true; | |
| 17 | } | |
| 18 | } | |
| 19 | } | |
| 20 | ||
| 21 | impl Deref for X { | |
| 22 | type Target = isize; | |
| 23 | ||
| 24 | fn deref(&self) -> &isize { | |
| 25 | let &X(box ref x) = self; | |
| 26 | x | |
| 27 | } | |
| 28 | } | |
| 29 | ||
| 30 | impl DerefMut for X { | |
| 31 | fn deref_mut(&mut self) -> &mut isize { | |
| 32 | let &mut X(box ref mut x) = self; | |
| 33 | x | |
| 34 | } | |
| 35 | } | |
| 36 | ||
| 37 | fn main() { | |
| 38 | { | |
| 39 | let mut test = X(Box::new(5)); | |
| 40 | { | |
| 41 | let mut change = || { *test = 10 }; | |
| 42 | change(); | |
| 43 | } | |
| 44 | assert_eq!(*test, 10); | |
| 45 | } | |
| 46 | assert!(unsafe { DESTRUCTOR_RAN }); | |
| 47 | } |
tests/ui/eii/attribute_targets.stderr+18-18| ... | ... | @@ -1,106 +1,106 @@ |
| 1 | error: `#[foo]` is only valid on functions | |
| 1 | error: `#[foo]` is only valid on functions and statics | |
| 2 | 2 | --> $DIR/attribute_targets.rs:7:1 |
| 3 | 3 | | |
| 4 | 4 | LL | #[foo] |
| 5 | 5 | | ^^^^^^ |
| 6 | 6 | |
| 7 | error: `#[eii]` is only valid on functions | |
| 7 | error: `#[eii]` is only valid on functions and statics | |
| 8 | 8 | --> $DIR/attribute_targets.rs:9:1 |
| 9 | 9 | | |
| 10 | 10 | LL | #[eii] |
| 11 | 11 | | ^^^^^^ |
| 12 | 12 | |
| 13 | error: `#[foo]` is only valid on functions | |
| 13 | error: `#[foo]` is only valid on functions and statics | |
| 14 | 14 | --> $DIR/attribute_targets.rs:13:1 |
| 15 | 15 | | |
| 16 | 16 | LL | #[foo] |
| 17 | 17 | | ^^^^^^ |
| 18 | 18 | |
| 19 | error: `#[eii]` is only valid on functions | |
| 19 | error: `#[eii]` is only valid on functions and statics | |
| 20 | 20 | --> $DIR/attribute_targets.rs:15:1 |
| 21 | 21 | | |
| 22 | 22 | LL | #[eii] |
| 23 | 23 | | ^^^^^^ |
| 24 | 24 | |
| 25 | error: `#[foo]` is only valid on functions | |
| 25 | error: `#[foo]` is only valid on functions and statics | |
| 26 | 26 | --> $DIR/attribute_targets.rs:21:1 |
| 27 | 27 | | |
| 28 | 28 | LL | #[foo] |
| 29 | 29 | | ^^^^^^ |
| 30 | 30 | |
| 31 | error: `#[eii]` is only valid on functions | |
| 31 | error: `#[eii]` is only valid on functions and statics | |
| 32 | 32 | --> $DIR/attribute_targets.rs:23:1 |
| 33 | 33 | | |
| 34 | 34 | LL | #[eii] |
| 35 | 35 | | ^^^^^^ |
| 36 | 36 | |
| 37 | error: `#[foo]` is only valid on functions | |
| 37 | error: `#[foo]` is only valid on functions and statics | |
| 38 | 38 | --> $DIR/attribute_targets.rs:27:1 |
| 39 | 39 | | |
| 40 | 40 | LL | #[foo] |
| 41 | 41 | | ^^^^^^ |
| 42 | 42 | |
| 43 | error: `#[eii]` is only valid on functions | |
| 43 | error: `#[eii]` is only valid on functions and statics | |
| 44 | 44 | --> $DIR/attribute_targets.rs:29:1 |
| 45 | 45 | | |
| 46 | 46 | LL | #[eii] |
| 47 | 47 | | ^^^^^^ |
| 48 | 48 | |
| 49 | error: `#[foo]` is only valid on functions | |
| 49 | error: `#[foo]` is only valid on functions and statics | |
| 50 | 50 | --> $DIR/attribute_targets.rs:32:5 |
| 51 | 51 | | |
| 52 | 52 | LL | #[foo] |
| 53 | 53 | | ^^^^^^ |
| 54 | 54 | |
| 55 | error: `#[eii]` is only valid on functions | |
| 55 | error: `#[eii]` is only valid on functions and statics | |
| 56 | 56 | --> $DIR/attribute_targets.rs:34:5 |
| 57 | 57 | | |
| 58 | 58 | LL | #[eii] |
| 59 | 59 | | ^^^^^^ |
| 60 | 60 | |
| 61 | error: `#[foo]` is only valid on functions | |
| 61 | error: `#[foo]` is only valid on functions and statics | |
| 62 | 62 | --> $DIR/attribute_targets.rs:39:1 |
| 63 | 63 | | |
| 64 | 64 | LL | #[foo] |
| 65 | 65 | | ^^^^^^ |
| 66 | 66 | |
| 67 | error: `#[eii]` is only valid on functions | |
| 67 | error: `#[eii]` is only valid on functions and statics | |
| 68 | 68 | --> $DIR/attribute_targets.rs:41:1 |
| 69 | 69 | | |
| 70 | 70 | LL | #[eii] |
| 71 | 71 | | ^^^^^^ |
| 72 | 72 | |
| 73 | error: `#[foo]` is only valid on functions | |
| 73 | error: `#[foo]` is only valid on functions and statics | |
| 74 | 74 | --> $DIR/attribute_targets.rs:44:5 |
| 75 | 75 | | |
| 76 | 76 | LL | #[foo] |
| 77 | 77 | | ^^^^^^ |
| 78 | 78 | |
| 79 | error: `#[eii]` is only valid on functions | |
| 79 | error: `#[eii]` is only valid on functions and statics | |
| 80 | 80 | --> $DIR/attribute_targets.rs:46:5 |
| 81 | 81 | | |
| 82 | 82 | LL | #[eii] |
| 83 | 83 | | ^^^^^^ |
| 84 | 84 | |
| 85 | error: `#[foo]` is only valid on functions | |
| 85 | error: `#[foo]` is only valid on functions and statics | |
| 86 | 86 | --> $DIR/attribute_targets.rs:51:1 |
| 87 | 87 | | |
| 88 | 88 | LL | #[foo] |
| 89 | 89 | | ^^^^^^ |
| 90 | 90 | |
| 91 | error: `#[eii]` is only valid on functions | |
| 91 | error: `#[eii]` is only valid on functions and statics | |
| 92 | 92 | --> $DIR/attribute_targets.rs:53:1 |
| 93 | 93 | | |
| 94 | 94 | LL | #[eii] |
| 95 | 95 | | ^^^^^^ |
| 96 | 96 | |
| 97 | error: `#[foo]` is only valid on functions | |
| 97 | error: `#[foo]` is only valid on functions and statics | |
| 98 | 98 | --> $DIR/attribute_targets.rs:56:5 |
| 99 | 99 | | |
| 100 | 100 | LL | #[foo] |
| 101 | 101 | | ^^^^^^ |
| 102 | 102 | |
| 103 | error: `#[eii]` is only valid on functions | |
| 103 | error: `#[eii]` is only valid on functions and statics | |
| 104 | 104 | --> $DIR/attribute_targets.rs:58:5 |
| 105 | 105 | | |
| 106 | 106 | LL | #[eii] |
tests/ui/eii/default/call_default.rs+1-1| ... | ... | @@ -3,7 +3,7 @@ |
| 3 | 3 | //@ run-pass |
| 4 | 4 | //@ check-run-results |
| 5 | 5 | //@ ignore-backends: gcc |
| 6 | // FIXME: linking on windows (speciifcally mingw) not yet supported, see tracking issue #125418 | |
| 6 | // FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418 | |
| 7 | 7 | //@ ignore-windows |
| 8 | 8 | // Tests EIIs with default implementations. |
| 9 | 9 | // When there's no explicit declaration, the default should be called from the declaring crate. |
tests/ui/eii/default/call_default_panics.rs+1-1| ... | ... | @@ -5,7 +5,7 @@ |
| 5 | 5 | //@ needs-unwind |
| 6 | 6 | //@ exec-env:RUST_BACKTRACE=1 |
| 7 | 7 | //@ ignore-backends: gcc |
| 8 | // FIXME: linking on windows (speciifcally mingw) not yet supported, see tracking issue #125418 | |
| 8 | // FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418 | |
| 9 | 9 | //@ ignore-windows |
| 10 | 10 | // A small test to make sure that unwinding works properly. |
| 11 | 11 | // |
tests/ui/eii/default/call_impl.rs+1-1| ... | ... | @@ -4,7 +4,7 @@ |
| 4 | 4 | //@ run-pass |
| 5 | 5 | //@ check-run-results |
| 6 | 6 | //@ ignore-backends: gcc |
| 7 | // FIXME: linking on windows (speciifcally mingw) not yet supported, see tracking issue #125418 | |
| 7 | // FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418 | |
| 8 | 8 | //@ ignore-windows |
| 9 | 9 | // Tests EIIs with default implementations. |
| 10 | 10 | // When an explicit implementation is given in one dependency, and the declaration is in another, |
tests/ui/eii/default/local_crate.rs+1-1| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | //@ run-pass |
| 2 | 2 | //@ check-run-results |
| 3 | 3 | //@ ignore-backends: gcc |
| 4 | // FIXME: linking on windows (speciifcally mingw) not yet supported, see tracking issue #125418 | |
| 4 | // FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418 | |
| 5 | 5 | //@ ignore-windows |
| 6 | 6 | // Tests EIIs with default implementations. |
| 7 | 7 | // In the same crate, when there's no explicit declaration, the default should be called. |
tests/ui/eii/default/local_crate_explicit.rs+1-1| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | //@ run-pass |
| 2 | 2 | //@ check-run-results |
| 3 | 3 | //@ ignore-backends: gcc |
| 4 | // FIXME: linking on windows (speciifcally mingw) not yet supported, see tracking issue #125418 | |
| 4 | // FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418 | |
| 5 | 5 | //@ ignore-windows |
| 6 | 6 | // Tests EIIs with default implementations. |
| 7 | 7 | // In the same crate, the explicit implementation should get priority. |
tests/ui/eii/duplicate/duplicate1.rs+1-1| ... | ... | @@ -2,7 +2,7 @@ |
| 2 | 2 | //@ aux-build: impl1.rs |
| 3 | 3 | //@ aux-build: impl2.rs |
| 4 | 4 | //@ ignore-backends: gcc |
| 5 | // FIXME: linking on windows (speciifcally mingw) not yet supported, see tracking issue #125418 | |
| 5 | // FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418 | |
| 6 | 6 | //@ ignore-windows |
| 7 | 7 | // tests that EIIs error properly, even if the conflicting implementations live in another crate. |
| 8 | 8 | #![feature(extern_item_impls)] |
tests/ui/eii/duplicate/duplicate2.rs+1-1| ... | ... | @@ -3,7 +3,7 @@ |
| 3 | 3 | //@ aux-build: impl2.rs |
| 4 | 4 | //@ aux-build: impl3.rs |
| 5 | 5 | //@ ignore-backends: gcc |
| 6 | // FIXME: linking on windows (speciifcally mingw) not yet supported, see tracking issue #125418 | |
| 6 | // FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418 | |
| 7 | 7 | //@ ignore-windows |
| 8 | 8 | // Tests the error message when there are multiple implementations of an EII in many crates. |
| 9 | 9 | #![feature(extern_item_impls)] |
tests/ui/eii/duplicate/duplicate3.rs+1-1| ... | ... | @@ -4,7 +4,7 @@ |
| 4 | 4 | //@ aux-build: impl3.rs |
| 5 | 5 | //@ aux-build: impl4.rs |
| 6 | 6 | //@ ignore-backends: gcc |
| 7 | // FIXME: linking on windows (speciifcally mingw) not yet supported, see tracking issue #125418 | |
| 7 | // FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418 | |
| 8 | 8 | //@ ignore-windows |
| 9 | 9 | // Tests the error message when there are multiple implementations of an EII in many crates. |
| 10 | 10 | #![feature(extern_item_impls)] |
tests/ui/eii/duplicate/multiple_impls.rs+1-1| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | //@ run-pass |
| 2 | 2 | //@ check-run-results |
| 3 | 3 | //@ ignore-backends: gcc |
| 4 | // FIXME: linking on windows (speciifcally mingw) not yet supported, see tracking issue #125418 | |
| 4 | // FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418 | |
| 5 | 5 | //@ ignore-windows |
| 6 | 6 | // Tests whether one function could implement two EIIs. |
| 7 | 7 | #![feature(extern_item_impls)] |
tests/ui/eii/eii-declaration-not-fn-issue-152337.rs+2-2| ... | ... | @@ -6,7 +6,7 @@ |
| 6 | 6 | const A: () = (); |
| 7 | 7 | #[eii] |
| 8 | 8 | fn A() {} //~ ERROR the name `A` is defined multiple times |
| 9 | //~^ ERROR expected function, found constant | |
| 10 | //~| ERROR expected function, found constant | |
| 9 | //~^ ERROR expected function or static, found constant | |
| 10 | //~| ERROR expected function or static, found constant | |
| 11 | 11 | |
| 12 | 12 | fn main() {} |
tests/ui/eii/eii-declaration-not-fn-issue-152337.stderr+4-4| ... | ... | @@ -9,17 +9,17 @@ LL | fn A() {} |
| 9 | 9 | | |
| 10 | 10 | = note: `A` must be defined only once in the value namespace of this module |
| 11 | 11 | |
| 12 | error[E0423]: expected function, found constant `self::A` | |
| 12 | error[E0423]: expected function or static, found constant `self::A` | |
| 13 | 13 | --> $DIR/eii-declaration-not-fn-issue-152337.rs:8:4 |
| 14 | 14 | | |
| 15 | 15 | LL | fn A() {} |
| 16 | | ^ not a function | |
| 16 | | ^ not a function or static | |
| 17 | 17 | |
| 18 | error[E0423]: expected function, found constant `A` | |
| 18 | error[E0423]: expected function or static, found constant `A` | |
| 19 | 19 | --> $DIR/eii-declaration-not-fn-issue-152337.rs:8:4 |
| 20 | 20 | | |
| 21 | 21 | LL | fn A() {} |
| 22 | | ^ not a function | |
| 22 | | ^ not a function or static | |
| 23 | 23 | |
| 24 | 24 | error: aborting due to 3 previous errors |
| 25 | 25 |
tests/ui/eii/error_statement_position.stderr+1-1| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | error: `#[eii]` is only valid on functions | |
| 1 | error: `#[eii]` is only valid on functions and statics | |
| 2 | 2 | --> $DIR/error_statement_position.rs:8:5 |
| 3 | 3 | | |
| 4 | 4 | LL | #[eii] |
tests/ui/eii/errors.rs+2-4| ... | ... | @@ -25,11 +25,9 @@ unsafe extern "Rust" { |
| 25 | 25 | safe fn bar(x: u64) -> u64; |
| 26 | 26 | } |
| 27 | 27 | |
| 28 | #[foo] //~ ERROR `#[foo]` is only valid on functions | |
| 29 | static X: u64 = 4; | |
| 30 | #[foo] //~ ERROR `#[foo]` is only valid on functions | |
| 28 | #[foo] //~ ERROR `#[foo]` is only valid on functions and statics | |
| 31 | 29 | const Y: u64 = 4; |
| 32 | #[foo] //~ ERROR `#[foo]` is only valid on functions | |
| 30 | #[foo] //~ ERROR `#[foo]` is only valid on functions and statics | |
| 33 | 31 | macro bar() {} |
| 34 | 32 | |
| 35 | 33 | #[foo()] |
tests/ui/eii/errors.stderr+7-13| ... | ... | @@ -52,47 +52,41 @@ error: `#[eii_declaration(...)]` expects a list of one or two elements |
| 52 | 52 | LL | #[eii_declaration = "unsafe"] |
| 53 | 53 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 54 | 54 | |
| 55 | error: `#[foo]` is only valid on functions | |
| 55 | error: `#[foo]` is only valid on functions and statics | |
| 56 | 56 | --> $DIR/errors.rs:28:1 |
| 57 | 57 | | |
| 58 | 58 | LL | #[foo] |
| 59 | 59 | | ^^^^^^ |
| 60 | 60 | |
| 61 | error: `#[foo]` is only valid on functions | |
| 61 | error: `#[foo]` is only valid on functions and statics | |
| 62 | 62 | --> $DIR/errors.rs:30:1 |
| 63 | 63 | | |
| 64 | 64 | LL | #[foo] |
| 65 | 65 | | ^^^^^^ |
| 66 | 66 | |
| 67 | error: `#[foo]` is only valid on functions | |
| 68 | --> $DIR/errors.rs:32:1 | |
| 69 | | | |
| 70 | LL | #[foo] | |
| 71 | | ^^^^^^ | |
| 72 | ||
| 73 | 67 | error: `#[foo]` expected no arguments or a single argument: `#[foo(default)]` |
| 74 | --> $DIR/errors.rs:35:1 | |
| 68 | --> $DIR/errors.rs:33:1 | |
| 75 | 69 | | |
| 76 | 70 | LL | #[foo()] |
| 77 | 71 | | ^^^^^^^^ |
| 78 | 72 | |
| 79 | 73 | error: `#[foo]` expected no arguments or a single argument: `#[foo(default)]` |
| 80 | --> $DIR/errors.rs:37:1 | |
| 74 | --> $DIR/errors.rs:35:1 | |
| 81 | 75 | | |
| 82 | 76 | LL | #[foo(default, bar)] |
| 83 | 77 | | ^^^^^^^^^^^^^^^^^^^^ |
| 84 | 78 | |
| 85 | 79 | error: `#[foo]` expected no arguments or a single argument: `#[foo(default)]` |
| 86 | --> $DIR/errors.rs:39:1 | |
| 80 | --> $DIR/errors.rs:37:1 | |
| 87 | 81 | | |
| 88 | 82 | LL | #[foo("default")] |
| 89 | 83 | | ^^^^^^^^^^^^^^^^^ |
| 90 | 84 | |
| 91 | 85 | error: `#[foo]` expected no arguments or a single argument: `#[foo(default)]` |
| 92 | --> $DIR/errors.rs:41:1 | |
| 86 | --> $DIR/errors.rs:39:1 | |
| 93 | 87 | | |
| 94 | 88 | LL | #[foo = "default"] |
| 95 | 89 | | ^^^^^^^^^^^^^^^^^^ |
| 96 | 90 | |
| 97 | error: aborting due to 15 previous errors | |
| 91 | error: aborting due to 14 previous errors | |
| 98 | 92 |
tests/ui/eii/linking/codegen_cross_crate.rs+1-1| ... | ... | @@ -3,7 +3,7 @@ |
| 3 | 3 | //@ aux-build: codegen_cross_crate_other_crate.rs |
| 4 | 4 | //@ compile-flags: -O |
| 5 | 5 | //@ ignore-backends: gcc |
| 6 | // FIXME: linking on windows (speciifcally mingw) not yet supported, see tracking issue #125418 | |
| 6 | // FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418 | |
| 7 | 7 | //@ ignore-windows |
| 8 | 8 | // Tests whether calling EIIs works with the declaration in another crate. |
| 9 | 9 |
tests/ui/eii/linking/codegen_single_crate.rs+1-1| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | //@ run-pass |
| 2 | 2 | //@ check-run-results |
| 3 | 3 | //@ ignore-backends: gcc |
| 4 | // FIXME: linking on windows (speciifcally mingw) not yet supported, see tracking issue #125418 | |
| 4 | // FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418 | |
| 5 | 5 | //@ ignore-windows |
| 6 | 6 | // Tests whether calling EIIs works with the declaration in the same crate. |
| 7 | 7 | #![feature(extern_item_impls)] |
tests/ui/eii/linking/same-symbol.rs+1-1| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | //@ run-pass |
| 2 | 2 | //@ check-run-results |
| 3 | 3 | //@ ignore-backends: gcc |
| 4 | // FIXME: linking on windows (speciifcally mingw) not yet supported, see tracking issue #125418 | |
| 4 | // FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418 | |
| 5 | 5 | //@ ignore-windows |
| 6 | 6 | #![feature(extern_item_impls)] |
| 7 | 7 |
tests/ui/eii/shadow_builtin.rs created+17| ... | ... | @@ -0,0 +1,17 @@ |
| 1 | //@ ignore-backends: gcc | |
| 2 | // FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418 | |
| 3 | //@ ignore-windows | |
| 4 | // Tests whether calling EIIs works with the declaration in the same crate. | |
| 5 | #![feature(extern_item_impls)] | |
| 6 | ||
| 7 | #[eii(inline)] | |
| 8 | //~^ ERROR `#[inline]` required, but not found | |
| 9 | fn test(x: u64); | |
| 10 | ||
| 11 | #[inline] | |
| 12 | //~^ ERROR `inline` is ambiguous | |
| 13 | fn test_impl(x: u64) { | |
| 14 | println!("{x:?}") | |
| 15 | } | |
| 16 | ||
| 17 | fn main() { } |
tests/ui/eii/shadow_builtin.stderr created+26| ... | ... | @@ -0,0 +1,26 @@ |
| 1 | error[E0659]: `inline` is ambiguous | |
| 2 | --> $DIR/shadow_builtin.rs:11:3 | |
| 3 | | | |
| 4 | LL | #[inline] | |
| 5 | | ^^^^^^ ambiguous name | |
| 6 | | | |
| 7 | = note: ambiguous because of a name conflict with a builtin attribute | |
| 8 | = note: `inline` could refer to a built-in attribute | |
| 9 | note: `inline` could also refer to the attribute macro defined here | |
| 10 | --> $DIR/shadow_builtin.rs:7:1 | |
| 11 | | | |
| 12 | LL | #[eii(inline)] | |
| 13 | | ^^^^^^^^^^^^^^ | |
| 14 | = help: use `crate::inline` to refer to this attribute macro unambiguously | |
| 15 | ||
| 16 | error: `#[inline]` required, but not found | |
| 17 | --> $DIR/shadow_builtin.rs:7:7 | |
| 18 | | | |
| 19 | LL | #[eii(inline)] | |
| 20 | | ^^^^^^ expected because `#[inline]` was declared here in crate `shadow_builtin` | |
| 21 | | | |
| 22 | = help: expected at least one implementation in crate `shadow_builtin` or any of its dependencies | |
| 23 | ||
| 24 | error: aborting due to 2 previous errors | |
| 25 | ||
| 26 | For more information about this error, try `rustc --explain E0659`. |
tests/ui/eii/static/argument_required.rs created+11| ... | ... | @@ -0,0 +1,11 @@ |
| 1 | //@ ignore-backends: gcc | |
| 2 | // FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418 | |
| 3 | //@ ignore-windows | |
| 4 | // Tests whether EIIs work on statics | |
| 5 | #![feature(extern_item_impls)] | |
| 6 | ||
| 7 | #[eii] | |
| 8 | //~^ ERROR `#[eii]` requires the name as an explicit argument when used on a static | |
| 9 | static HELLO: u64; | |
| 10 | ||
| 11 | fn main() { } |
tests/ui/eii/static/argument_required.stderr created+8| ... | ... | @@ -0,0 +1,8 @@ |
| 1 | error: `#[eii]` requires the name as an explicit argument when used on a static | |
| 2 | --> $DIR/argument_required.rs:7:1 | |
| 3 | | | |
| 4 | LL | #[eii] | |
| 5 | | ^^^^^^ | |
| 6 | ||
| 7 | error: aborting due to 1 previous error | |
| 8 |
tests/ui/eii/static/auxiliary/cross_crate_decl.rs created+6| ... | ... | @@ -0,0 +1,6 @@ |
| 1 | //@ no-prefer-dynamic | |
| 2 | #![crate_type = "rlib"] | |
| 3 | #![feature(extern_item_impls)] | |
| 4 | ||
| 5 | #[eii(eii1)] | |
| 6 | pub static DECL1: u64; |
tests/ui/eii/static/auxiliary/cross_crate_def.rs created+9| ... | ... | @@ -0,0 +1,9 @@ |
| 1 | //@ no-prefer-dynamic | |
| 2 | #![crate_type = "rlib"] | |
| 3 | #![feature(extern_item_impls)] | |
| 4 | ||
| 5 | #[eii(eii1)] | |
| 6 | pub static DECL1: u64; | |
| 7 | ||
| 8 | #[eii1] | |
| 9 | pub static EII1_IMPL: u64 = 5; |
tests/ui/eii/static/cross_crate_decl.rs created+21| ... | ... | @@ -0,0 +1,21 @@ |
| 1 | //@ run-pass | |
| 2 | //@ check-run-results | |
| 3 | //@ aux-build: cross_crate_decl.rs | |
| 4 | //@ compile-flags: -O | |
| 5 | //@ ignore-backends: gcc | |
| 6 | // FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418 | |
| 7 | //@ ignore-windows | |
| 8 | // Tests whether calling EIIs works with the declaration in another crate. | |
| 9 | ||
| 10 | extern crate cross_crate_decl as codegen; | |
| 11 | ||
| 12 | #[codegen::eii1] | |
| 13 | static EII1_IMPL: u64 = 5; | |
| 14 | ||
| 15 | // what you would write: | |
| 16 | fn main() { | |
| 17 | // directly | |
| 18 | println!("{}", EII1_IMPL); | |
| 19 | // through the alias | |
| 20 | println!("{}", codegen::DECL1); | |
| 21 | } |
tests/ui/eii/static/cross_crate_decl.run.stdout created+2| ... | ... | @@ -0,0 +1,2 @@ |
| 1 | 5 | |
| 2 | 5 |
tests/ui/eii/static/cross_crate_def.rs created+18| ... | ... | @@ -0,0 +1,18 @@ |
| 1 | //@ run-pass | |
| 2 | //@ check-run-results | |
| 3 | //@ aux-build: cross_crate_def.rs | |
| 4 | //@ compile-flags: -O | |
| 5 | //@ ignore-backends: gcc | |
| 6 | // FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418 | |
| 7 | //@ ignore-windows | |
| 8 | // Tests whether calling EIIs works with the declaration and definition in another crate. | |
| 9 | ||
| 10 | extern crate cross_crate_def as codegen; | |
| 11 | ||
| 12 | // what you would write: | |
| 13 | fn main() { | |
| 14 | // directly | |
| 15 | println!("{}", codegen::EII1_IMPL); | |
| 16 | // through the alias | |
| 17 | println!("{}", codegen::DECL1); | |
| 18 | } |
tests/ui/eii/static/cross_crate_def.run.stdout created+2| ... | ... | @@ -0,0 +1,2 @@ |
| 1 | 5 | |
| 2 | 5 |
tests/ui/eii/static/duplicate.rs created+25| ... | ... | @@ -0,0 +1,25 @@ |
| 1 | //@ ignore-backends: gcc | |
| 2 | // FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418 | |
| 3 | //@ ignore-windows | |
| 4 | // Tests whether EIIs work on statics | |
| 5 | #![feature(extern_item_impls)] | |
| 6 | ||
| 7 | #[eii(hello)] | |
| 8 | static HELLO: u64; | |
| 9 | ||
| 10 | #[hello] | |
| 11 | static HELLO_IMPL1: u64 = 5; | |
| 12 | //~^ ERROR multiple implementations of `#[hello]` | |
| 13 | ||
| 14 | #[hello] | |
| 15 | static HELLO_IMPL2: u64 = 6; | |
| 16 | ||
| 17 | // what you would write: | |
| 18 | fn main() { | |
| 19 | // directly | |
| 20 | println!("{HELLO_IMPL1}"); | |
| 21 | println!("{HELLO_IMPL2}"); | |
| 22 | ||
| 23 | // through the alias | |
| 24 | println!("{HELLO}"); | |
| 25 | } |
tests/ui/eii/static/duplicate.stderr created+13| ... | ... | @@ -0,0 +1,13 @@ |
| 1 | error: multiple implementations of `#[hello]` | |
| 2 | --> $DIR/duplicate.rs:11:1 | |
| 3 | | | |
| 4 | LL | static HELLO_IMPL1: u64 = 5; | |
| 5 | | ^^^^^^^^^^^^^^^^^^^^^^^ first implemented here in crate `duplicate` | |
| 6 | ... | |
| 7 | LL | static HELLO_IMPL2: u64 = 6; | |
| 8 | | ----------------------- also implemented here in crate `duplicate` | |
| 9 | | | |
| 10 | = help: an "externally implementable item" can only have a single implementation in the final artifact. When multiple implementations are found, also in different crates, they conflict | |
| 11 | ||
| 12 | error: aborting due to 1 previous error | |
| 13 |
tests/ui/eii/static/mismatch_fn_static.rs created+14| ... | ... | @@ -0,0 +1,14 @@ |
| 1 | //@ ignore-backends: gcc | |
| 2 | // FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418 | |
| 3 | //@ ignore-windows | |
| 4 | // Tests whether EIIs work on statics | |
| 5 | #![feature(extern_item_impls)] | |
| 6 | ||
| 7 | #[eii(hello)] | |
| 8 | fn hello() -> u64; | |
| 9 | ||
| 10 | #[hello] | |
| 11 | //~^ ERROR `#[hello]` must be used on a function | |
| 12 | static HELLO_IMPL: u64 = 5; | |
| 13 | ||
| 14 | fn main() { } |
tests/ui/eii/static/mismatch_fn_static.stderr created+8| ... | ... | @@ -0,0 +1,8 @@ |
| 1 | error: `#[hello]` must be used on a function | |
| 2 | --> $DIR/mismatch_fn_static.rs:10:1 | |
| 3 | | | |
| 4 | LL | #[hello] | |
| 5 | | ^^^^^^^^ | |
| 6 | ||
| 7 | error: aborting due to 1 previous error | |
| 8 |
tests/ui/eii/static/mismatch_mut.rs created+22| ... | ... | @@ -0,0 +1,22 @@ |
| 1 | //@ ignore-backends: gcc | |
| 2 | // FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418 | |
| 3 | //@ ignore-windows | |
| 4 | // Tests whether EIIs work on statics | |
| 5 | #![feature(extern_item_impls)] | |
| 6 | ||
| 7 | #[eii(hello)] | |
| 8 | //~^ ERROR `#[eii]` cannot be used on mutable statics | |
| 9 | static mut HELLO: u64; | |
| 10 | ||
| 11 | #[hello] | |
| 12 | //~^ ERROR mutability does not match with the definition of`#[hello]` | |
| 13 | static HELLO_IMPL: u64 = 5; | |
| 14 | ||
| 15 | // what you would write: | |
| 16 | fn main() { | |
| 17 | // directly | |
| 18 | println!("{HELLO_IMPL}"); | |
| 19 | ||
| 20 | // through the alias | |
| 21 | println!("{}", unsafe { HELLO }); | |
| 22 | } |
tests/ui/eii/static/mismatch_mut.stderr created+14| ... | ... | @@ -0,0 +1,14 @@ |
| 1 | error: `#[eii]` cannot be used on mutable statics | |
| 2 | --> $DIR/mismatch_mut.rs:7:1 | |
| 3 | | | |
| 4 | LL | #[eii(hello)] | |
| 5 | | ^^^^^^^^^^^^^ | |
| 6 | ||
| 7 | error: mutability does not match with the definition of`#[hello]` | |
| 8 | --> $DIR/mismatch_mut.rs:11:1 | |
| 9 | | | |
| 10 | LL | #[hello] | |
| 11 | | ^^^^^^^^ | |
| 12 | ||
| 13 | error: aborting due to 2 previous errors | |
| 14 |
tests/ui/eii/static/mismatch_mut2.rs created+21| ... | ... | @@ -0,0 +1,21 @@ |
| 1 | //@ ignore-backends: gcc | |
| 2 | // FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418 | |
| 3 | //@ ignore-windows | |
| 4 | // Tests whether EIIs work on statics | |
| 5 | #![feature(extern_item_impls)] | |
| 6 | ||
| 7 | #[eii(hello)] | |
| 8 | static HELLO: u64; | |
| 9 | ||
| 10 | #[hello] | |
| 11 | //~^ ERROR mutability does not match with the definition of`#[hello]` | |
| 12 | static mut HELLO_IMPL: u64 = 5; | |
| 13 | ||
| 14 | // what you would write: | |
| 15 | fn main() { | |
| 16 | // directly | |
| 17 | println!("{}", unsafe { HELLO_IMPL }); | |
| 18 | ||
| 19 | // through the alias | |
| 20 | println!("{HELLO}"); | |
| 21 | } |
tests/ui/eii/static/mismatch_mut2.stderr created+8| ... | ... | @@ -0,0 +1,8 @@ |
| 1 | error: mutability does not match with the definition of`#[hello]` | |
| 2 | --> $DIR/mismatch_mut2.rs:10:1 | |
| 3 | | | |
| 4 | LL | #[hello] | |
| 5 | | ^^^^^^^^ | |
| 6 | ||
| 7 | error: aborting due to 1 previous error | |
| 8 |
tests/ui/eii/static/mismatch_safety.rs created+21| ... | ... | @@ -0,0 +1,21 @@ |
| 1 | //@ ignore-backends: gcc | |
| 2 | // FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418 | |
| 3 | //@ ignore-windows | |
| 4 | // Tests whether EIIs work on statics | |
| 5 | #![feature(extern_item_impls)] | |
| 6 | ||
| 7 | #[eii(hello)] | |
| 8 | unsafe static HELLO: u64; | |
| 9 | ||
| 10 | #[hello] | |
| 11 | //~^ ERROR safety does not match with the definition of`#[hello]` | |
| 12 | static HELLO_IMPL: u64 = 5; | |
| 13 | ||
| 14 | // what you would write: | |
| 15 | fn main() { | |
| 16 | // directly | |
| 17 | println!("{HELLO_IMPL}"); | |
| 18 | ||
| 19 | // through the alias | |
| 20 | println!("{}", unsafe { HELLO }); | |
| 21 | } |
tests/ui/eii/static/mismatch_safety.stderr created+8| ... | ... | @@ -0,0 +1,8 @@ |
| 1 | error: safety does not match with the definition of`#[hello]` | |
| 2 | --> $DIR/mismatch_safety.rs:10:1 | |
| 3 | | | |
| 4 | LL | #[hello] | |
| 5 | | ^^^^^^^^ | |
| 6 | ||
| 7 | error: aborting due to 1 previous error | |
| 8 |
tests/ui/eii/static/mismatch_safety2.rs created+21| ... | ... | @@ -0,0 +1,21 @@ |
| 1 | //@ ignore-backends: gcc | |
| 2 | // FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418 | |
| 3 | //@ ignore-windows | |
| 4 | // Tests whether EIIs work on statics | |
| 5 | #![feature(extern_item_impls)] | |
| 6 | ||
| 7 | #[eii(hello)] | |
| 8 | static HELLO: u64; | |
| 9 | ||
| 10 | #[hello] | |
| 11 | unsafe static HELLO_IMPL: u64 = 5; | |
| 12 | //~^ ERROR static items cannot be declared with `unsafe` safety qualifier outside of `extern` block | |
| 13 | ||
| 14 | // what you would write: | |
| 15 | fn main() { | |
| 16 | // directly | |
| 17 | println!("{HELLO_IMPL}"); | |
| 18 | ||
| 19 | // through the alias | |
| 20 | println!("{}", unsafe { HELLO }); | |
| 21 | } |
tests/ui/eii/static/mismatch_safety2.stderr created+8| ... | ... | @@ -0,0 +1,8 @@ |
| 1 | error: static items cannot be declared with `unsafe` safety qualifier outside of `extern` block | |
| 2 | --> $DIR/mismatch_safety2.rs:11:1 | |
| 3 | | | |
| 4 | LL | unsafe static HELLO_IMPL: u64 = 5; | |
| 5 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
| 6 | ||
| 7 | error: aborting due to 1 previous error | |
| 8 |
tests/ui/eii/static/mismatch_static_fn.rs created+16| ... | ... | @@ -0,0 +1,16 @@ |
| 1 | //@ ignore-backends: gcc | |
| 2 | // FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418 | |
| 3 | //@ ignore-windows | |
| 4 | // Tests whether EIIs work on statics | |
| 5 | #![feature(extern_item_impls)] | |
| 6 | ||
| 7 | #[eii(hello)] | |
| 8 | static HELLO: u64; | |
| 9 | ||
| 10 | #[hello] | |
| 11 | //~^ ERROR `#[hello]` must be used on a static | |
| 12 | fn hello_impl() -> u64 { | |
| 13 | 5 | |
| 14 | } | |
| 15 | ||
| 16 | fn main() { } |
tests/ui/eii/static/mismatch_static_fn.stderr created+8| ... | ... | @@ -0,0 +1,8 @@ |
| 1 | error: `#[hello]` must be used on a static | |
| 2 | --> $DIR/mismatch_static_fn.rs:10:1 | |
| 3 | | | |
| 4 | LL | #[hello] | |
| 5 | | ^^^^^^^^ | |
| 6 | ||
| 7 | error: aborting due to 1 previous error | |
| 8 |
tests/ui/eii/static/multiple_decls.rs created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | #![feature(extern_item_impls)] | |
| 2 | ||
| 3 | const A: () = (); | |
| 4 | #[eii(A)] | |
| 5 | static A: u64; | |
| 6 | //~^ ERROR the name `A` is defined multiple times | |
| 7 | //~| ERROR expected function or static, found constant `A` | |
| 8 | ||
| 9 | #[A] | |
| 10 | static A_IMPL: u64 = 5; | |
| 11 | ||
| 12 | fn main() {} |
tests/ui/eii/static/multiple_decls.stderr created+21| ... | ... | @@ -0,0 +1,21 @@ |
| 1 | error[E0428]: the name `A` is defined multiple times | |
| 2 | --> $DIR/multiple_decls.rs:5:1 | |
| 3 | | | |
| 4 | LL | const A: () = (); | |
| 5 | | ----------------- previous definition of the value `A` here | |
| 6 | LL | #[eii(A)] | |
| 7 | LL | static A: u64; | |
| 8 | | ^^^^^^^^^^^^^^ `A` redefined here | |
| 9 | | | |
| 10 | = note: `A` must be defined only once in the value namespace of this module | |
| 11 | ||
| 12 | error[E0423]: expected function or static, found constant `A` | |
| 13 | --> $DIR/multiple_decls.rs:5:8 | |
| 14 | | | |
| 15 | LL | static A: u64; | |
| 16 | | ^ not a function or static | |
| 17 | ||
| 18 | error: aborting due to 2 previous errors | |
| 19 | ||
| 20 | Some errors have detailed explanations: E0423, E0428. | |
| 21 | For more information about an error, try `rustc --explain E0423`. |
tests/ui/eii/static/multiple_impls.rs created+20| ... | ... | @@ -0,0 +1,20 @@ |
| 1 | //@ ignore-backends: gcc | |
| 2 | // FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418 | |
| 3 | //@ ignore-windows | |
| 4 | // Tests whether one function could implement two EIIs. | |
| 5 | #![feature(extern_item_impls)] | |
| 6 | ||
| 7 | #[eii(a)] | |
| 8 | static A: u64; | |
| 9 | ||
| 10 | #[eii(b)] | |
| 11 | static B: u64; | |
| 12 | ||
| 13 | #[a] | |
| 14 | #[b] | |
| 15 | //~^ ERROR static cannot implement multiple EIIs | |
| 16 | static IMPL: u64 = 5; | |
| 17 | ||
| 18 | fn main() { | |
| 19 | println!("{A} {B} {IMPL}") | |
| 20 | } |
tests/ui/eii/static/multiple_impls.run.stdout created+1| ... | ... | @@ -0,0 +1 @@ |
| 1 | 5 5 5 |
tests/ui/eii/static/multiple_impls.stderr created+10| ... | ... | @@ -0,0 +1,10 @@ |
| 1 | error: static cannot implement multiple EIIs | |
| 2 | --> $DIR/multiple_impls.rs:14:1 | |
| 3 | | | |
| 4 | LL | #[b] | |
| 5 | | ^^^^ | |
| 6 | | | |
| 7 | = note: this is not allowed because multiple externally implementable statics that alias may be unintuitive | |
| 8 | ||
| 9 | error: aborting due to 1 previous error | |
| 10 |
tests/ui/eii/static/mut.rs created+21| ... | ... | @@ -0,0 +1,21 @@ |
| 1 | //@ ignore-backends: gcc | |
| 2 | // FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418 | |
| 3 | //@ ignore-windows | |
| 4 | // Tests whether EIIs work on statics | |
| 5 | #![feature(extern_item_impls)] | |
| 6 | ||
| 7 | #[eii(hello)] | |
| 8 | //~^ ERROR `#[eii]` cannot be used on mutable statics | |
| 9 | static mut HELLO: u64; | |
| 10 | ||
| 11 | #[hello] | |
| 12 | static mut HELLO_IMPL: u64 = 5; | |
| 13 | ||
| 14 | // what you would write: | |
| 15 | fn main() { | |
| 16 | // directly | |
| 17 | println!("{}", unsafe { HELLO_IMPL }); | |
| 18 | ||
| 19 | // through the alias | |
| 20 | println!("{}", unsafe { HELLO }); | |
| 21 | } |
tests/ui/eii/static/mut.run.stdout created+2| ... | ... | @@ -0,0 +1,2 @@ |
| 1 | 5 | |
| 2 | 5 |
tests/ui/eii/static/mut.stderr created+8| ... | ... | @@ -0,0 +1,8 @@ |
| 1 | error: `#[eii]` cannot be used on mutable statics | |
| 2 | --> $DIR/mut.rs:7:1 | |
| 3 | | | |
| 4 | LL | #[eii(hello)] | |
| 5 | | ^^^^^^^^^^^^^ | |
| 6 | ||
| 7 | error: aborting due to 1 previous error | |
| 8 |
tests/ui/eii/static/same_address.rs created+21| ... | ... | @@ -0,0 +1,21 @@ |
| 1 | //@ run-pass | |
| 2 | //@ check-run-results | |
| 3 | //@ ignore-backends: gcc | |
| 4 | // FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418 | |
| 5 | //@ ignore-windows | |
| 6 | // Tests whether EIIs and their declarations share the same address | |
| 7 | #![feature(extern_item_impls)] | |
| 8 | ||
| 9 | #[eii(hello)] | |
| 10 | static HELLO: u64; | |
| 11 | ||
| 12 | #[hello] | |
| 13 | static HELLO_IMPL: u64 = 5; | |
| 14 | ||
| 15 | // what you would write: | |
| 16 | fn main() { | |
| 17 | assert_eq!( | |
| 18 | &HELLO as *const u64 as usize, | |
| 19 | &HELLO_IMPL as *const u64 as usize, | |
| 20 | ) | |
| 21 | } |
tests/ui/eii/static/simple.rs created+22| ... | ... | @@ -0,0 +1,22 @@ |
| 1 | //@ run-pass | |
| 2 | //@ check-run-results | |
| 3 | //@ ignore-backends: gcc | |
| 4 | // FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418 | |
| 5 | //@ ignore-windows | |
| 6 | // Tests whether EIIs work on statics | |
| 7 | #![feature(extern_item_impls)] | |
| 8 | ||
| 9 | #[eii(hello)] | |
| 10 | static HELLO: u64; | |
| 11 | ||
| 12 | #[hello] | |
| 13 | static HELLO_IMPL: u64 = 5; | |
| 14 | ||
| 15 | // what you would write: | |
| 16 | fn main() { | |
| 17 | // directly | |
| 18 | println!("{HELLO_IMPL}"); | |
| 19 | ||
| 20 | // through the alias | |
| 21 | println!("{HELLO}"); | |
| 22 | } |
tests/ui/eii/static/simple.run.stdout created+2| ... | ... | @@ -0,0 +1,2 @@ |
| 1 | 5 | |
| 2 | 5 |
tests/ui/eii/static/subtype.rs created+18| ... | ... | @@ -0,0 +1,18 @@ |
| 1 | //@ check-pass | |
| 2 | //@ ignore-backends: gcc | |
| 3 | // FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418 | |
| 4 | //@ ignore-windows | |
| 5 | // Tests that mismatching types of the declaration and definition are rejected | |
| 6 | #![feature(extern_item_impls)] | |
| 7 | ||
| 8 | use std::ptr; | |
| 9 | ||
| 10 | #[eii(hello)] | |
| 11 | static HELLO: for<'a> fn(&'a u8) -> &'a u8; | |
| 12 | ||
| 13 | #[hello] | |
| 14 | static HELLO_IMPL: for<'a> fn(&'a u8) -> &'static u8 = |_| todo!(); | |
| 15 | ||
| 16 | fn main() { | |
| 17 | ||
| 18 | } |
tests/ui/eii/static/subtype_wrong.rs created+17| ... | ... | @@ -0,0 +1,17 @@ |
| 1 | //@ ignore-backends: gcc | |
| 2 | // FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418 | |
| 3 | //@ ignore-windows | |
| 4 | // Tests that mismatching types of the declaration and definition are rejected | |
| 5 | #![feature(extern_item_impls)] | |
| 6 | ||
| 7 | use std::ptr; | |
| 8 | ||
| 9 | #[eii(hello)] | |
| 10 | static HELLO: for<'a> fn(&'a u8) -> &'static u8; | |
| 11 | ||
| 12 | #[hello] | |
| 13 | static HELLO_IMPL: for<'a> fn(&'a u8) -> &'a u8 = |_| todo!(); | |
| 14 | //~^ ERROR mismatched types | |
| 15 | ||
| 16 | fn main() { | |
| 17 | } |
tests/ui/eii/static/subtype_wrong.stderr created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | error[E0308]: mismatched types | |
| 2 | --> $DIR/subtype_wrong.rs:13:1 | |
| 3 | | | |
| 4 | LL | static HELLO_IMPL: for<'a> fn(&'a u8) -> &'a u8 = |_| todo!(); | |
| 5 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other | |
| 6 | | | |
| 7 | = note: expected fn pointer `for<'a> fn(&'a _) -> &'static _` | |
| 8 | found fn pointer `for<'a> fn(&'a _) -> &'a _` | |
| 9 | ||
| 10 | error: aborting due to 1 previous error | |
| 11 | ||
| 12 | For more information about this error, try `rustc --explain E0308`. |
tests/ui/eii/static/wrong_ty.rs created+18| ... | ... | @@ -0,0 +1,18 @@ |
| 1 | //@ ignore-backends: gcc | |
| 2 | // FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418 | |
| 3 | //@ ignore-windows | |
| 4 | // Tests that mismatching types of the declaration and definition are rejected | |
| 5 | #![feature(extern_item_impls)] | |
| 6 | ||
| 7 | use std::ptr; | |
| 8 | ||
| 9 | #[eii(hello)] | |
| 10 | static HELLO: u64; | |
| 11 | ||
| 12 | #[hello] | |
| 13 | static HELLO_IMPL: bool = true; | |
| 14 | //~^ ERROR static `HELLO_IMPL` has a type that is incompatible with the declaration of `#[hello]` [E0806] | |
| 15 | ||
| 16 | fn main() { | |
| 17 | ||
| 18 | } |
tests/ui/eii/static/wrong_ty.stderr created+15| ... | ... | @@ -0,0 +1,15 @@ |
| 1 | error[E0806]: static `HELLO_IMPL` has a type that is incompatible with the declaration of `#[hello]` | |
| 2 | --> $DIR/wrong_ty.rs:13:1 | |
| 3 | | | |
| 4 | LL | static HELLO_IMPL: bool = true; | |
| 5 | | ^^^^^^^^^^^^^^^^^^^^^^^ | |
| 6 | | | |
| 7 | note: expected this because of this attribute | |
| 8 | --> $DIR/wrong_ty.rs:12:1 | |
| 9 | | | |
| 10 | LL | #[hello] | |
| 11 | | ^^^^^^^^ | |
| 12 | ||
| 13 | error: aborting due to 1 previous error | |
| 14 | ||
| 15 | For more information about this error, try `rustc --explain E0806`. |
tests/ui/feature-gates/feature-gate-check-nested-macro-invocation.rs created+16| ... | ... | @@ -0,0 +1,16 @@ |
| 1 | //! Regression test for <https://github.com/rust-lang/rust/issues/32782> | |
| 2 | macro_rules! bar ( | |
| 3 | () => () | |
| 4 | ); | |
| 5 | ||
| 6 | macro_rules! foo ( | |
| 7 | () => ( | |
| 8 | #[allow_internal_unstable()] | |
| 9 | //~^ ERROR allow_internal_unstable side-steps | |
| 10 | //~| ERROR `#[allow_internal_unstable]` attribute cannot be used on macro calls | |
| 11 | bar!(); | |
| 12 | ); | |
| 13 | ); | |
| 14 | ||
| 15 | foo!(); | |
| 16 | fn main() {} |
tests/ui/feature-gates/feature-gate-check-nested-macro-invocation.stderr created+28| ... | ... | @@ -0,0 +1,28 @@ |
| 1 | error[E0658]: allow_internal_unstable side-steps feature gating and stability checks | |
| 2 | --> $DIR/feature-gate-check-nested-macro-invocation.rs:8:9 | |
| 3 | | | |
| 4 | LL | #[allow_internal_unstable()] | |
| 5 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
| 6 | ... | |
| 7 | LL | foo!(); | |
| 8 | | ------ in this macro invocation | |
| 9 | | | |
| 10 | = help: add `#![feature(allow_internal_unstable)]` to the crate attributes to enable | |
| 11 | = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date | |
| 12 | = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) | |
| 13 | ||
| 14 | error: `#[allow_internal_unstable]` attribute cannot be used on macro calls | |
| 15 | --> $DIR/feature-gate-check-nested-macro-invocation.rs:8:9 | |
| 16 | | | |
| 17 | LL | #[allow_internal_unstable()] | |
| 18 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
| 19 | ... | |
| 20 | LL | foo!(); | |
| 21 | | ------ in this macro invocation | |
| 22 | | | |
| 23 | = help: `#[allow_internal_unstable]` can be applied to functions and macro defs | |
| 24 | = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) | |
| 25 | ||
| 26 | error: aborting due to 2 previous errors | |
| 27 | ||
| 28 | For more information about this error, try `rustc --explain E0658`. |
tests/ui/feature-gates/feature-gate-diagnostic-on-move.rs+2-3| ... | ... | @@ -2,9 +2,8 @@ |
| 2 | 2 | //! gate, but the fact that not adding the feature gate will cause the |
| 3 | 3 | //! diagnostic to not emit the custom diagnostic message |
| 4 | 4 | //! |
| 5 | #[diagnostic::on_move( | |
| 6 | message = "Foo" | |
| 7 | )] | |
| 5 | #[diagnostic::on_move(message = "Foo")] | |
| 6 | //~^ WARN unknown diagnostic attribute | |
| 8 | 7 | #[derive(Debug)] |
| 9 | 8 | struct Foo; |
| 10 | 9 |
tests/ui/feature-gates/feature-gate-diagnostic-on-move.stderr+13-4| ... | ... | @@ -1,5 +1,14 @@ |
| 1 | warning: unknown diagnostic attribute | |
| 2 | --> $DIR/feature-gate-diagnostic-on-move.rs:5:15 | |
| 3 | | | |
| 4 | LL | #[diagnostic::on_move(message = "Foo")] | |
| 5 | | ^^^^^^^ | |
| 6 | | | |
| 7 | = help: add `#![feature(diagnostic_on_move)]` to the crate attributes to enable | |
| 8 | = note: `#[warn(unknown_diagnostic_attributes)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default | |
| 9 | ||
| 1 | 10 | error[E0382]: use of moved value: `foo` |
| 2 | --> $DIR/feature-gate-diagnostic-on-move.rs:16:15 | |
| 11 | --> $DIR/feature-gate-diagnostic-on-move.rs:15:15 | |
| 3 | 12 | | |
| 4 | 13 | LL | let foo = Foo; |
| 5 | 14 | | --- move occurs because `foo` has type `Foo`, which does not implement the `Copy` trait |
| ... | ... | @@ -9,14 +18,14 @@ LL | let bar = foo; |
| 9 | 18 | | ^^^ value used here after move |
| 10 | 19 | | |
| 11 | 20 | note: consider changing this parameter type in function `takes_foo` to borrow instead if owning the value isn't necessary |
| 12 | --> $DIR/feature-gate-diagnostic-on-move.rs:11:17 | |
| 21 | --> $DIR/feature-gate-diagnostic-on-move.rs:10:17 | |
| 13 | 22 | | |
| 14 | 23 | LL | fn takes_foo(_: Foo) {} |
| 15 | 24 | | --------- ^^^ this parameter takes ownership of the value |
| 16 | 25 | | | |
| 17 | 26 | | in this function |
| 18 | 27 | note: if `Foo` implemented `Clone`, you could clone the value |
| 19 | --> $DIR/feature-gate-diagnostic-on-move.rs:9:1 | |
| 28 | --> $DIR/feature-gate-diagnostic-on-move.rs:8:1 | |
| 20 | 29 | | |
| 21 | 30 | LL | struct Foo; |
| 22 | 31 | | ^^^^^^^^^^ consider implementing `Clone` for this type |
| ... | ... | @@ -24,6 +33,6 @@ LL | struct Foo; |
| 24 | 33 | LL | takes_foo(foo); |
| 25 | 34 | | --- you could clone this value |
| 26 | 35 | |
| 27 | error: aborting due to 1 previous error | |
| 36 | error: aborting due to 1 previous error; 1 warning emitted | |
| 28 | 37 | |
| 29 | 38 | For more information about this error, try `rustc --explain E0382`. |
tests/ui/feature-gates/feature-gate-diagnostic-on-unknown.stderr+1| ... | ... | @@ -10,6 +10,7 @@ error: unknown diagnostic attribute |
| 10 | 10 | LL | #[diagnostic::on_unknown(message = "Tada")] |
| 11 | 11 | | ^^^^^^^^^^ |
| 12 | 12 | | |
| 13 | = help: add `#![feature(diagnostic_on_unknown)]` to the crate attributes to enable | |
| 13 | 14 | note: the lint level is defined here |
| 14 | 15 | --> $DIR/feature-gate-diagnostic-on-unknown.rs:1:9 |
| 15 | 16 | | |
tests/ui/imports/issue-56125.rs+1-1| ... | ... | @@ -15,7 +15,7 @@ mod m2 { |
| 15 | 15 | mod m3 { |
| 16 | 16 | mod empty {} |
| 17 | 17 | use empty::issue_56125; //~ ERROR unresolved import `empty::issue_56125` |
| 18 | use issue_56125::*; //~ ERROR `issue_56125` is ambiguous | |
| 18 | use issue_56125::*; | |
| 19 | 19 | } |
| 20 | 20 | |
| 21 | 21 | fn main() {} |
tests/ui/imports/issue-56125.stderr+1-18| ... | ... | @@ -54,24 +54,7 @@ LL | use issue_56125::non_last_segment::non_last_segment::*; |
| 54 | 54 | = help: consider adding an explicit import of `issue_56125` to disambiguate |
| 55 | 55 | = help: or use `self::issue_56125` to refer to this module unambiguously |
| 56 | 56 | |
| 57 | error[E0659]: `issue_56125` is ambiguous | |
| 58 | --> $DIR/issue-56125.rs:18:9 | |
| 59 | | | |
| 60 | LL | use issue_56125::*; | |
| 61 | | ^^^^^^^^^^^ ambiguous name | |
| 62 | | | |
| 63 | = note: ambiguous because of a conflict between a name from a glob import and an outer scope during import or macro resolution | |
| 64 | = note: `issue_56125` could refer to a crate passed with `--extern` | |
| 65 | = help: use `::issue_56125` to refer to this crate unambiguously | |
| 66 | note: `issue_56125` could also refer to the module imported here | |
| 67 | --> $DIR/issue-56125.rs:18:9 | |
| 68 | | | |
| 69 | LL | use issue_56125::*; | |
| 70 | | ^^^^^^^^^^^^^^ | |
| 71 | = help: consider adding an explicit import of `issue_56125` to disambiguate | |
| 72 | = help: or use `self::issue_56125` to refer to this module unambiguously | |
| 73 | ||
| 74 | error: aborting due to 4 previous errors | |
| 57 | error: aborting due to 3 previous errors | |
| 75 | 58 | |
| 76 | 59 | Some errors have detailed explanations: E0432, E0659. |
| 77 | 60 | For more information about an error, try `rustc --explain E0432`. |
tests/ui/imports/shadow-glob-module-resolution-2.rs-2| ... | ... | @@ -14,7 +14,5 @@ use a::*; |
| 14 | 14 | use e as b; |
| 15 | 15 | //~^ ERROR: unresolved import `e` |
| 16 | 16 | use b::c::D as e; |
| 17 | //~^ ERROR: cannot determine resolution for the import | |
| 18 | //~| ERROR: cannot determine resolution for the import | |
| 19 | 17 | |
| 20 | 18 | fn main() { } |
tests/ui/imports/shadow-glob-module-resolution-2.stderr+1-15| ... | ... | @@ -1,17 +1,3 @@ |
| 1 | error: cannot determine resolution for the import | |
| 2 | --> $DIR/shadow-glob-module-resolution-2.rs:16:5 | |
| 3 | | | |
| 4 | LL | use b::c::D as e; | |
| 5 | | ^^^^^^^^^^^^ | |
| 6 | ||
| 7 | error: cannot determine resolution for the import | |
| 8 | --> $DIR/shadow-glob-module-resolution-2.rs:16:5 | |
| 9 | | | |
| 10 | LL | use b::c::D as e; | |
| 11 | | ^^^^^^^^^^^^ | |
| 12 | | | |
| 13 | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` | |
| 14 | ||
| 15 | 1 | error[E0432]: unresolved import `e` |
| 16 | 2 | --> $DIR/shadow-glob-module-resolution-2.rs:14:5 |
| 17 | 3 | | |
| ... | ... | @@ -24,6 +10,6 @@ LL - use e as b; |
| 24 | 10 | LL + use a as b; |
| 25 | 11 | | |
| 26 | 12 | |
| 27 | error: aborting due to 3 previous errors | |
| 13 | error: aborting due to 1 previous error | |
| 28 | 14 | |
| 29 | 15 | For more information about this error, try `rustc --explain E0432`. |
tests/ui/imports/shadow-glob-module-resolution-4.rs-2| ... | ... | @@ -12,8 +12,6 @@ use e as b; |
| 12 | 12 | |
| 13 | 13 | use b::C as e; |
| 14 | 14 | //~^ ERROR: unresolved import `b::C` |
| 15 | //~| ERROR: cannot determine resolution for the import | |
| 16 | //~| ERROR: cannot determine resolution for the import | |
| 17 | 15 | |
| 18 | 16 | fn e() {} |
| 19 | 17 |
tests/ui/imports/shadow-glob-module-resolution-4.stderr+1-15| ... | ... | @@ -1,23 +1,9 @@ |
| 1 | error: cannot determine resolution for the import | |
| 2 | --> $DIR/shadow-glob-module-resolution-4.rs:13:5 | |
| 3 | | | |
| 4 | LL | use b::C as e; | |
| 5 | | ^^^^^^^^^ | |
| 6 | ||
| 7 | error: cannot determine resolution for the import | |
| 8 | --> $DIR/shadow-glob-module-resolution-4.rs:13:5 | |
| 9 | | | |
| 10 | LL | use b::C as e; | |
| 11 | | ^^^^^^^^^ | |
| 12 | | | |
| 13 | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` | |
| 14 | ||
| 15 | 1 | error[E0432]: unresolved import `b::C` |
| 16 | 2 | --> $DIR/shadow-glob-module-resolution-4.rs:13:5 |
| 17 | 3 | | |
| 18 | 4 | LL | use b::C as e; |
| 19 | 5 | | ^^^^^^^^^ |
| 20 | 6 | |
| 21 | error: aborting due to 3 previous errors | |
| 7 | error: aborting due to 1 previous error | |
| 22 | 8 | |
| 23 | 9 | For more information about this error, try `rustc --explain E0432`. |
tests/ui/issues/issue-21033.rs deleted-47| ... | ... | @@ -1,47 +0,0 @@ |
| 1 | //@ run-pass | |
| 2 | #![allow(unused_mut)] | |
| 3 | #![allow(unused_variables)] | |
| 4 | ||
| 5 | #![feature(box_patterns)] | |
| 6 | ||
| 7 | enum E { | |
| 8 | StructVar { boxed: Box<i32> } | |
| 9 | } | |
| 10 | ||
| 11 | fn main() { | |
| 12 | ||
| 13 | // Test matching each shorthand notation for field patterns. | |
| 14 | let mut a = E::StructVar { boxed: Box::new(3) }; | |
| 15 | match a { | |
| 16 | E::StructVar { box boxed } => { } | |
| 17 | } | |
| 18 | match a { | |
| 19 | E::StructVar { box ref boxed } => { } | |
| 20 | } | |
| 21 | match a { | |
| 22 | E::StructVar { box mut boxed } => { } | |
| 23 | } | |
| 24 | match a { | |
| 25 | E::StructVar { box ref mut boxed } => { } | |
| 26 | } | |
| 27 | match a { | |
| 28 | E::StructVar { ref boxed } => { } | |
| 29 | } | |
| 30 | match a { | |
| 31 | E::StructVar { ref mut boxed } => { } | |
| 32 | } | |
| 33 | match a { | |
| 34 | E::StructVar { mut boxed } => { } | |
| 35 | } | |
| 36 | ||
| 37 | // Test matching non shorthand notation. Recreate a since last test | |
| 38 | // moved `boxed` | |
| 39 | let mut a = E::StructVar { boxed: Box::new(3) }; | |
| 40 | match a { | |
| 41 | E::StructVar { boxed: box ref mut num } => { } | |
| 42 | } | |
| 43 | match a { | |
| 44 | E::StructVar { boxed: ref mut num } => { } | |
| 45 | } | |
| 46 | ||
| 47 | } |
tests/ui/issues/issue-29516.rs deleted-20| ... | ... | @@ -1,20 +0,0 @@ |
| 1 | //@ check-pass | |
| 2 | #![feature(auto_traits)] | |
| 3 | #![feature(negative_impls)] | |
| 4 | ||
| 5 | auto trait NotSame {} | |
| 6 | ||
| 7 | impl<A> !NotSame for (A, A) {} | |
| 8 | ||
| 9 | trait OneOfEach {} | |
| 10 | ||
| 11 | impl<A> OneOfEach for (A,) {} | |
| 12 | ||
| 13 | impl<A, B> OneOfEach for (A, B) | |
| 14 | where | |
| 15 | (B,): OneOfEach, | |
| 16 | (A, B): NotSame, | |
| 17 | { | |
| 18 | } | |
| 19 | ||
| 20 | fn main() {} |
tests/ui/issues/issue-3154.rs deleted-11| ... | ... | @@ -1,11 +0,0 @@ |
| 1 | struct Thing<'a, Q:'a> { | |
| 2 | x: &'a Q | |
| 3 | } | |
| 4 | ||
| 5 | fn thing<'a,Q>(x: &Q) -> Thing<'a,Q> { | |
| 6 | Thing { x: x } //~ ERROR explicit lifetime required in the type of `x` [E0621] | |
| 7 | } | |
| 8 | ||
| 9 | fn main() { | |
| 10 | thing(&()); | |
| 11 | } |
tests/ui/issues/issue-3154.stderr deleted-14| ... | ... | @@ -1,14 +0,0 @@ |
| 1 | error[E0621]: explicit lifetime required in the type of `x` | |
| 2 | --> $DIR/issue-3154.rs:6:5 | |
| 3 | | | |
| 4 | LL | Thing { x: x } | |
| 5 | | ^^^^^^^^^^^^^^ lifetime `'a` required | |
| 6 | | | |
| 7 | help: add explicit lifetime `'a` to the type of `x` | |
| 8 | | | |
| 9 | LL | fn thing<'a,Q>(x: &'a Q) -> Thing<'a,Q> { | |
| 10 | | ++ | |
| 11 | ||
| 12 | error: aborting due to 1 previous error | |
| 13 | ||
| 14 | For more information about this error, try `rustc --explain E0621`. |
tests/ui/issues/issue-32782.rs deleted-15| ... | ... | @@ -1,15 +0,0 @@ |
| 1 | macro_rules! bar ( | |
| 2 | () => () | |
| 3 | ); | |
| 4 | ||
| 5 | macro_rules! foo ( | |
| 6 | () => ( | |
| 7 | #[allow_internal_unstable()] | |
| 8 | //~^ ERROR allow_internal_unstable side-steps | |
| 9 | //~| ERROR `#[allow_internal_unstable]` attribute cannot be used on macro calls | |
| 10 | bar!(); | |
| 11 | ); | |
| 12 | ); | |
| 13 | ||
| 14 | foo!(); | |
| 15 | fn main() {} |
tests/ui/issues/issue-32782.stderr deleted-28| ... | ... | @@ -1,28 +0,0 @@ |
| 1 | error[E0658]: allow_internal_unstable side-steps feature gating and stability checks | |
| 2 | --> $DIR/issue-32782.rs:7:9 | |
| 3 | | | |
| 4 | LL | #[allow_internal_unstable()] | |
| 5 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
| 6 | ... | |
| 7 | LL | foo!(); | |
| 8 | | ------ in this macro invocation | |
| 9 | | | |
| 10 | = help: add `#![feature(allow_internal_unstable)]` to the crate attributes to enable | |
| 11 | = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date | |
| 12 | = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) | |
| 13 | ||
| 14 | error: `#[allow_internal_unstable]` attribute cannot be used on macro calls | |
| 15 | --> $DIR/issue-32782.rs:7:9 | |
| 16 | | | |
| 17 | LL | #[allow_internal_unstable()] | |
| 18 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
| 19 | ... | |
| 20 | LL | foo!(); | |
| 21 | | ------ in this macro invocation | |
| 22 | | | |
| 23 | = help: `#[allow_internal_unstable]` can be applied to functions and macro defs | |
| 24 | = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) | |
| 25 | ||
| 26 | error: aborting due to 2 previous errors | |
| 27 | ||
| 28 | For more information about this error, try `rustc --explain E0658`. |
tests/ui/issues/issue-3874.rs deleted-11| ... | ... | @@ -1,11 +0,0 @@ |
| 1 | //@ build-pass | |
| 2 | #![allow(dead_code)] | |
| 3 | ||
| 4 | enum PureCounter { PureCounterVariant(usize) } | |
| 5 | ||
| 6 | fn each<F>(thing: PureCounter, blk: F) where F: FnOnce(&usize) { | |
| 7 | let PureCounter::PureCounterVariant(ref x) = thing; | |
| 8 | blk(x); | |
| 9 | } | |
| 10 | ||
| 11 | pub fn main() {} |
tests/ui/issues/issue-5100.rs deleted-58| ... | ... | @@ -1,58 +0,0 @@ |
| 1 | //@ dont-require-annotations: NOTE | |
| 2 | ||
| 3 | #![feature(box_patterns)] | |
| 4 | ||
| 5 | enum A { B, C } | |
| 6 | ||
| 7 | fn main() { | |
| 8 | match (true, false) { | |
| 9 | A::B => (), | |
| 10 | //~^ ERROR mismatched types | |
| 11 | //~| NOTE expected `(bool, bool)`, found `A` | |
| 12 | //~| NOTE expected tuple `(bool, bool)` | |
| 13 | //~| NOTE found enum `A` | |
| 14 | _ => () | |
| 15 | } | |
| 16 | ||
| 17 | match (true, false) { | |
| 18 | (true, false, false) => () | |
| 19 | //~^ ERROR mismatched types | |
| 20 | //~| NOTE expected a tuple with 2 elements, found one with 3 elements | |
| 21 | //~| NOTE expected tuple `(bool, bool)` | |
| 22 | //~| NOTE found tuple `(_, _, _)` | |
| 23 | } | |
| 24 | ||
| 25 | match (true, false) { | |
| 26 | (true, false, false) => () | |
| 27 | //~^ ERROR mismatched types | |
| 28 | //~| NOTE expected a tuple with 2 elements, found one with 3 elements | |
| 29 | //~| NOTE expected tuple `(bool, bool)` | |
| 30 | //~| NOTE found tuple `(_, _, _)` | |
| 31 | } | |
| 32 | ||
| 33 | match (true, false) { | |
| 34 | box (true, false) => () | |
| 35 | //~^ ERROR mismatched types | |
| 36 | //~| NOTE expected tuple `(bool, bool)` | |
| 37 | //~| NOTE found struct `Box<_>` | |
| 38 | } | |
| 39 | ||
| 40 | match (true, false) { | |
| 41 | &(true, false) => () | |
| 42 | //~^ ERROR mismatched types | |
| 43 | //~| NOTE expected `(bool, bool)`, found `&_` | |
| 44 | //~| NOTE expected tuple `(bool, bool)` | |
| 45 | //~| NOTE found reference `&_` | |
| 46 | } | |
| 47 | ||
| 48 | ||
| 49 | let v = [('a', 'b') //~ ERROR expected function, found `(char, char)` | |
| 50 | ('c', 'd'), | |
| 51 | ('e', 'f')]; | |
| 52 | ||
| 53 | for &(x,y) in &v {} // should be OK | |
| 54 | ||
| 55 | // Make sure none of the errors above were fatal | |
| 56 | let x: char = true; //~ ERROR mismatched types | |
| 57 | //~| NOTE expected `char`, found `bool` | |
| 58 | } |
tests/ui/issues/issue-5100.stderr deleted-73| ... | ... | @@ -1,73 +0,0 @@ |
| 1 | error[E0308]: mismatched types | |
| 2 | --> $DIR/issue-5100.rs:9:9 | |
| 3 | | | |
| 4 | LL | match (true, false) { | |
| 5 | | ------------- this expression has type `(bool, bool)` | |
| 6 | LL | A::B => (), | |
| 7 | | ^^^^ expected `(bool, bool)`, found `A` | |
| 8 | | | |
| 9 | = note: expected tuple `(bool, bool)` | |
| 10 | found enum `A` | |
| 11 | ||
| 12 | error[E0308]: mismatched types | |
| 13 | --> $DIR/issue-5100.rs:18:9 | |
| 14 | | | |
| 15 | LL | match (true, false) { | |
| 16 | | ------------- this expression has type `(bool, bool)` | |
| 17 | LL | (true, false, false) => () | |
| 18 | | ^^^^^^^^^^^^^^^^^^^^ expected a tuple with 2 elements, found one with 3 elements | |
| 19 | | | |
| 20 | = note: expected tuple `(bool, bool)` | |
| 21 | found tuple `(_, _, _)` | |
| 22 | ||
| 23 | error[E0308]: mismatched types | |
| 24 | --> $DIR/issue-5100.rs:26:9 | |
| 25 | | | |
| 26 | LL | match (true, false) { | |
| 27 | | ------------- this expression has type `(bool, bool)` | |
| 28 | LL | (true, false, false) => () | |
| 29 | | ^^^^^^^^^^^^^^^^^^^^ expected a tuple with 2 elements, found one with 3 elements | |
| 30 | | | |
| 31 | = note: expected tuple `(bool, bool)` | |
| 32 | found tuple `(_, _, _)` | |
| 33 | ||
| 34 | error[E0308]: mismatched types | |
| 35 | --> $DIR/issue-5100.rs:34:9 | |
| 36 | | | |
| 37 | LL | match (true, false) { | |
| 38 | | ------------- this expression has type `(bool, bool)` | |
| 39 | LL | box (true, false) => () | |
| 40 | | ^^^^^^^^^^^^^^^^^ expected `(bool, bool)`, found `Box<_>` | |
| 41 | | | |
| 42 | = note: expected tuple `(bool, bool)` | |
| 43 | found struct `Box<_>` | |
| 44 | ||
| 45 | error[E0308]: mismatched types | |
| 46 | --> $DIR/issue-5100.rs:41:9 | |
| 47 | | | |
| 48 | LL | match (true, false) { | |
| 49 | | ------------- this expression has type `(bool, bool)` | |
| 50 | LL | &(true, false) => () | |
| 51 | | ^^^^^^^^^^^^^^ expected `(bool, bool)`, found `&_` | |
| 52 | | | |
| 53 | = note: expected tuple `(bool, bool)` | |
| 54 | found reference `&_` | |
| 55 | ||
| 56 | error[E0618]: expected function, found `(char, char)` | |
| 57 | --> $DIR/issue-5100.rs:49:14 | |
| 58 | | | |
| 59 | LL | let v = [('a', 'b') | |
| 60 | | ^^^^^^^^^^- help: consider separating array elements with a comma: `,` | |
| 61 | ||
| 62 | error[E0308]: mismatched types | |
| 63 | --> $DIR/issue-5100.rs:56:19 | |
| 64 | | | |
| 65 | LL | let x: char = true; | |
| 66 | | ---- ^^^^ expected `char`, found `bool` | |
| 67 | | | | |
| 68 | | expected due to this | |
| 69 | ||
| 70 | error: aborting due to 7 previous errors | |
| 71 | ||
| 72 | Some errors have detailed explanations: E0308, E0618. | |
| 73 | For more information about an error, try `rustc --explain E0308`. |
tests/ui/lifetimes/missing-lifetime-in-return.rs created+13| ... | ... | @@ -0,0 +1,13 @@ |
| 1 | //! Regression test for https://github.com/rust-lang/rust/issues/3154 | |
| 2 | ||
| 3 | struct Thing<'a, Q:'a> { | |
| 4 | x: &'a Q | |
| 5 | } | |
| 6 | ||
| 7 | fn thing<'a,Q>(x: &Q) -> Thing<'a,Q> { | |
| 8 | Thing { x: x } //~ ERROR explicit lifetime required in the type of `x` [E0621] | |
| 9 | } | |
| 10 | ||
| 11 | fn main() { | |
| 12 | thing(&()); | |
| 13 | } |
tests/ui/lifetimes/missing-lifetime-in-return.stderr created+14| ... | ... | @@ -0,0 +1,14 @@ |
| 1 | error[E0621]: explicit lifetime required in the type of `x` | |
| 2 | --> $DIR/missing-lifetime-in-return.rs:8:5 | |
| 3 | | | |
| 4 | LL | Thing { x: x } | |
| 5 | | ^^^^^^^^^^^^^^ lifetime `'a` required | |
| 6 | | | |
| 7 | help: add explicit lifetime `'a` to the type of `x` | |
| 8 | | | |
| 9 | LL | fn thing<'a,Q>(x: &'a Q) -> Thing<'a,Q> { | |
| 10 | | ++ | |
| 11 | ||
| 12 | error: aborting due to 1 previous error | |
| 13 | ||
| 14 | For more information about this error, try `rustc --explain E0621`. |
tests/ui/parallel-rustc/default-trait-shadow-cycle-issue-151358.rs+2-1| ... | ... | @@ -1,5 +1,6 @@ |
| 1 | 1 | // Test for #151358, assertion failed: !worker_thread.is_null() |
| 2 | //~^ ERROR cycle detected when looking up span for `Default` | |
| 2 | //~^ ERROR internal compiler error: query cycle when printing cycle detected | |
| 3 | //~^^ ERROR cycle detected when getting the resolver for lowering | |
| 3 | 4 | // |
| 4 | 5 | //@ compile-flags: -Z threads=2 |
| 5 | 6 | //@ compare-output-by-lines |
tests/ui/parallel-rustc/default-trait-shadow-cycle-issue-151358.stderr+16-4| ... | ... | @@ -1,9 +1,21 @@ |
| 1 | error[E0391]: cycle detected when looking up span for `Default` | |
| 1 | error: internal compiler error: query cycle when printing cycle detected | |
| 2 | 2 | | |
| 3 | = note: ...which immediately requires looking up span for `Default` again | |
| 4 | = note: cycle used when perform lints prior to AST lowering | |
| 3 | = note: ...when getting HIR ID of `Default` | |
| 4 | = note: ...which requires getting the crate HIR... | |
| 5 | = note: ...which requires perform lints prior to AST lowering... | |
| 6 | = note: ...which requires looking up span for `Default`... | |
| 7 | = note: ...which again requires getting HIR ID of `Default`, completing the cycle | |
| 8 | = note: cycle used when getting the resolver for lowering | |
| 5 | 9 | = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information |
| 6 | 10 | |
| 7 | error: aborting due to 1 previous error | |
| 11 | error[E0391]: cycle detected when getting the resolver for lowering | |
| 12 | | | |
| 13 | = note: ...which requires getting HIR ID of `Default`... | |
| 14 | = note: ...which requires getting the crate HIR... | |
| 15 | = note: ...which requires perform lints prior to AST lowering... | |
| 16 | = note: ...which again requires getting the resolver for lowering, completing the cycle | |
| 17 | = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information | |
| 18 | ||
| 19 | error: aborting due to 2 previous errors | |
| 8 | 20 | |
| 9 | 21 | For more information about this error, try `rustc --explain E0391`. |
tests/ui/pattern/match-errors-derived-error-suppression.rs created+59| ... | ... | @@ -0,0 +1,59 @@ |
| 1 | //! Regression test for <https://github.com/rust-lang/rust/issues/5100> | |
| 2 | //@ dont-require-annotations: NOTE | |
| 3 | ||
| 4 | #![feature(box_patterns)] | |
| 5 | ||
| 6 | enum A { B, C } | |
| 7 | ||
| 8 | fn main() { | |
| 9 | match (true, false) { | |
| 10 | A::B => (), | |
| 11 | //~^ ERROR mismatched types | |
| 12 | //~| NOTE expected `(bool, bool)`, found `A` | |
| 13 | //~| NOTE expected tuple `(bool, bool)` | |
| 14 | //~| NOTE found enum `A` | |
| 15 | _ => () | |
| 16 | } | |
| 17 | ||
| 18 | match (true, false) { | |
| 19 | (true, false, false) => () | |
| 20 | //~^ ERROR mismatched types | |
| 21 | //~| NOTE expected a tuple with 2 elements, found one with 3 elements | |
| 22 | //~| NOTE expected tuple `(bool, bool)` | |
| 23 | //~| NOTE found tuple `(_, _, _)` | |
| 24 | } | |
| 25 | ||
| 26 | match (true, false) { | |
| 27 | (true, false, false) => () | |
| 28 | //~^ ERROR mismatched types | |
| 29 | //~| NOTE expected a tuple with 2 elements, found one with 3 elements | |
| 30 | //~| NOTE expected tuple `(bool, bool)` | |
| 31 | //~| NOTE found tuple `(_, _, _)` | |
| 32 | } | |
| 33 | ||
| 34 | match (true, false) { | |
| 35 | box (true, false) => () | |
| 36 | //~^ ERROR mismatched types | |
| 37 | //~| NOTE expected tuple `(bool, bool)` | |
| 38 | //~| NOTE found struct `Box<_>` | |
| 39 | } | |
| 40 | ||
| 41 | match (true, false) { | |
| 42 | &(true, false) => () | |
| 43 | //~^ ERROR mismatched types | |
| 44 | //~| NOTE expected `(bool, bool)`, found `&_` | |
| 45 | //~| NOTE expected tuple `(bool, bool)` | |
| 46 | //~| NOTE found reference `&_` | |
| 47 | } | |
| 48 | ||
| 49 | ||
| 50 | let v = [('a', 'b') //~ ERROR expected function, found `(char, char)` | |
| 51 | ('c', 'd'), | |
| 52 | ('e', 'f')]; | |
| 53 | ||
| 54 | for &(x,y) in &v {} // should be OK | |
| 55 | ||
| 56 | // Make sure none of the errors above were fatal | |
| 57 | let x: char = true; //~ ERROR mismatched types | |
| 58 | //~| NOTE expected `char`, found `bool` | |
| 59 | } |
tests/ui/pattern/match-errors-derived-error-suppression.stderr created+73| ... | ... | @@ -0,0 +1,73 @@ |
| 1 | error[E0308]: mismatched types | |
| 2 | --> $DIR/match-errors-derived-error-suppression.rs:10:9 | |
| 3 | | | |
| 4 | LL | match (true, false) { | |
| 5 | | ------------- this expression has type `(bool, bool)` | |
| 6 | LL | A::B => (), | |
| 7 | | ^^^^ expected `(bool, bool)`, found `A` | |
| 8 | | | |
| 9 | = note: expected tuple `(bool, bool)` | |
| 10 | found enum `A` | |
| 11 | ||
| 12 | error[E0308]: mismatched types | |
| 13 | --> $DIR/match-errors-derived-error-suppression.rs:19:9 | |
| 14 | | | |
| 15 | LL | match (true, false) { | |
| 16 | | ------------- this expression has type `(bool, bool)` | |
| 17 | LL | (true, false, false) => () | |
| 18 | | ^^^^^^^^^^^^^^^^^^^^ expected a tuple with 2 elements, found one with 3 elements | |
| 19 | | | |
| 20 | = note: expected tuple `(bool, bool)` | |
| 21 | found tuple `(_, _, _)` | |
| 22 | ||
| 23 | error[E0308]: mismatched types | |
| 24 | --> $DIR/match-errors-derived-error-suppression.rs:27:9 | |
| 25 | | | |
| 26 | LL | match (true, false) { | |
| 27 | | ------------- this expression has type `(bool, bool)` | |
| 28 | LL | (true, false, false) => () | |
| 29 | | ^^^^^^^^^^^^^^^^^^^^ expected a tuple with 2 elements, found one with 3 elements | |
| 30 | | | |
| 31 | = note: expected tuple `(bool, bool)` | |
| 32 | found tuple `(_, _, _)` | |
| 33 | ||
| 34 | error[E0308]: mismatched types | |
| 35 | --> $DIR/match-errors-derived-error-suppression.rs:35:9 | |
| 36 | | | |
| 37 | LL | match (true, false) { | |
| 38 | | ------------- this expression has type `(bool, bool)` | |
| 39 | LL | box (true, false) => () | |
| 40 | | ^^^^^^^^^^^^^^^^^ expected `(bool, bool)`, found `Box<_>` | |
| 41 | | | |
| 42 | = note: expected tuple `(bool, bool)` | |
| 43 | found struct `Box<_>` | |
| 44 | ||
| 45 | error[E0308]: mismatched types | |
| 46 | --> $DIR/match-errors-derived-error-suppression.rs:42:9 | |
| 47 | | | |
| 48 | LL | match (true, false) { | |
| 49 | | ------------- this expression has type `(bool, bool)` | |
| 50 | LL | &(true, false) => () | |
| 51 | | ^^^^^^^^^^^^^^ expected `(bool, bool)`, found `&_` | |
| 52 | | | |
| 53 | = note: expected tuple `(bool, bool)` | |
| 54 | found reference `&_` | |
| 55 | ||
| 56 | error[E0618]: expected function, found `(char, char)` | |
| 57 | --> $DIR/match-errors-derived-error-suppression.rs:50:14 | |
| 58 | | | |
| 59 | LL | let v = [('a', 'b') | |
| 60 | | ^^^^^^^^^^- help: consider separating array elements with a comma: `,` | |
| 61 | ||
| 62 | error[E0308]: mismatched types | |
| 63 | --> $DIR/match-errors-derived-error-suppression.rs:57:19 | |
| 64 | | | |
| 65 | LL | let x: char = true; | |
| 66 | | ---- ^^^^ expected `char`, found `bool` | |
| 67 | | | | |
| 68 | | expected due to this | |
| 69 | ||
| 70 | error: aborting due to 7 previous errors | |
| 71 | ||
| 72 | Some errors have detailed explanations: E0308, E0618. | |
| 73 | For more information about an error, try `rustc --explain E0308`. |
tests/ui/pattern/match-struct-var-having-boxed-field.rs created+48| ... | ... | @@ -0,0 +1,48 @@ |
| 1 | //! Regression test for <https://github.com/rust-lang/rust/issues/21033> | |
| 2 | //@ run-pass | |
| 3 | #![allow(unused_mut)] | |
| 4 | #![allow(unused_variables)] | |
| 5 | ||
| 6 | #![feature(box_patterns)] | |
| 7 | ||
| 8 | enum E { | |
| 9 | StructVar { boxed: Box<i32> } | |
| 10 | } | |
| 11 | ||
| 12 | fn main() { | |
| 13 | ||
| 14 | // Test matching each shorthand notation for field patterns. | |
| 15 | let mut a = E::StructVar { boxed: Box::new(3) }; | |
| 16 | match a { | |
| 17 | E::StructVar { box boxed } => { } | |
| 18 | } | |
| 19 | match a { | |
| 20 | E::StructVar { box ref boxed } => { } | |
| 21 | } | |
| 22 | match a { | |
| 23 | E::StructVar { box mut boxed } => { } | |
| 24 | } | |
| 25 | match a { | |
| 26 | E::StructVar { box ref mut boxed } => { } | |
| 27 | } | |
| 28 | match a { | |
| 29 | E::StructVar { ref boxed } => { } | |
| 30 | } | |
| 31 | match a { | |
| 32 | E::StructVar { ref mut boxed } => { } | |
| 33 | } | |
| 34 | match a { | |
| 35 | E::StructVar { mut boxed } => { } | |
| 36 | } | |
| 37 | ||
| 38 | // Test matching non shorthand notation. Recreate a since last test | |
| 39 | // moved `boxed` | |
| 40 | let mut a = E::StructVar { boxed: Box::new(3) }; | |
| 41 | match a { | |
| 42 | E::StructVar { boxed: box ref mut num } => { } | |
| 43 | } | |
| 44 | match a { | |
| 45 | E::StructVar { boxed: ref mut num } => { } | |
| 46 | } | |
| 47 | ||
| 48 | } |
tests/ui/query-system/query-cycle-printing-issue-151358.rs+2-1| ... | ... | @@ -1,4 +1,5 @@ |
| 1 | //~ ERROR: cycle detected when looking up span for `Default` | |
| 1 | //~ ERROR: cycle when printing cycle detected | |
| 2 | //~^ ERROR: cycle detected | |
| 2 | 3 | trait Default {} |
| 3 | 4 | use std::num::NonZero; |
| 4 | 5 | fn main() { |
tests/ui/query-system/query-cycle-printing-issue-151358.stderr+16-4| ... | ... | @@ -1,9 +1,21 @@ |
| 1 | error[E0391]: cycle detected when looking up span for `Default` | |
| 1 | error: internal compiler error: query cycle when printing cycle detected | |
| 2 | 2 | | |
| 3 | = note: ...which immediately requires looking up span for `Default` again | |
| 4 | = note: cycle used when perform lints prior to AST lowering | |
| 3 | = note: ...when getting HIR ID of `Default` | |
| 4 | = note: ...which requires getting the crate HIR... | |
| 5 | = note: ...which requires perform lints prior to AST lowering... | |
| 6 | = note: ...which requires looking up span for `Default`... | |
| 7 | = note: ...which again requires getting HIR ID of `Default`, completing the cycle | |
| 8 | = note: cycle used when getting the resolver for lowering | |
| 5 | 9 | = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information |
| 6 | 10 | |
| 7 | error: aborting due to 1 previous error | |
| 11 | error[E0391]: cycle detected when getting the resolver for lowering | |
| 12 | | | |
| 13 | = note: ...which requires getting HIR ID of `Default`... | |
| 14 | = note: ...which requires getting the crate HIR... | |
| 15 | = note: ...which requires perform lints prior to AST lowering... | |
| 16 | = note: ...which again requires getting the resolver for lowering, completing the cycle | |
| 17 | = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information | |
| 18 | ||
| 19 | error: aborting due to 2 previous errors | |
| 8 | 20 | |
| 9 | 21 | For more information about this error, try `rustc --explain E0391`. |
tests/ui/resolve/query-cycle-issue-124901.rs+2-1| ... | ... | @@ -1,4 +1,5 @@ |
| 1 | //~ ERROR: cycle detected when looking up span for `Default` | |
| 1 | //~ ERROR: cycle when printing cycle detected | |
| 2 | //~^ ERROR: cycle detected | |
| 2 | 3 | trait Default { |
| 3 | 4 | type Id; |
| 4 | 5 |
tests/ui/resolve/query-cycle-issue-124901.stderr+16-4| ... | ... | @@ -1,9 +1,21 @@ |
| 1 | error[E0391]: cycle detected when looking up span for `Default` | |
| 1 | error: internal compiler error: query cycle when printing cycle detected | |
| 2 | 2 | | |
| 3 | = note: ...which immediately requires looking up span for `Default` again | |
| 4 | = note: cycle used when perform lints prior to AST lowering | |
| 3 | = note: ...when getting HIR ID of `Default` | |
| 4 | = note: ...which requires getting the crate HIR... | |
| 5 | = note: ...which requires perform lints prior to AST lowering... | |
| 6 | = note: ...which requires looking up span for `Default`... | |
| 7 | = note: ...which again requires getting HIR ID of `Default`, completing the cycle | |
| 8 | = note: cycle used when getting the resolver for lowering | |
| 5 | 9 | = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information |
| 6 | 10 | |
| 7 | error: aborting due to 1 previous error | |
| 11 | error[E0391]: cycle detected when getting the resolver for lowering | |
| 12 | | | |
| 13 | = note: ...which requires getting HIR ID of `Default`... | |
| 14 | = note: ...which requires getting the crate HIR... | |
| 15 | = note: ...which requires perform lints prior to AST lowering... | |
| 16 | = note: ...which again requires getting the resolver for lowering, completing the cycle | |
| 17 | = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information | |
| 18 | ||
| 19 | error: aborting due to 2 previous errors | |
| 8 | 20 | |
| 9 | 21 | For more information about this error, try `rustc --explain E0391`. |
tests/ui/scalable-vectors/transmute.rs created+39| ... | ... | @@ -0,0 +1,39 @@ |
| 1 | //@ build-pass | |
| 2 | //@ compile-flags: -Copt-level=3 | |
| 3 | //@ only-aarch64 | |
| 4 | #![crate_type = "lib"] | |
| 5 | #![allow(incomplete_features, internal_features, dead_code, improper_ctypes)] | |
| 6 | #![allow(nonstandard_style, private_interfaces)] | |
| 7 | #![feature(abi_unadjusted, link_llvm_intrinsics, rustc_attrs)] | |
| 8 | ||
| 9 | // Tests that use of transmute between `svuint8x2_t` and `svint8x2_t` builds with optimisations | |
| 10 | // without any failures from LLVM. | |
| 11 | ||
| 12 | use std::mem::transmute; | |
| 13 | ||
| 14 | #[rustc_scalable_vector(16)] | |
| 15 | struct svbool_t(bool); | |
| 16 | ||
| 17 | #[rustc_scalable_vector(16)] | |
| 18 | struct svuint8_t(u8); | |
| 19 | ||
| 20 | #[rustc_scalable_vector] | |
| 21 | struct svuint8x2_t(svuint8_t, svuint8_t); | |
| 22 | ||
| 23 | #[rustc_scalable_vector(16)] | |
| 24 | struct svint8_t(i8); | |
| 25 | ||
| 26 | #[rustc_scalable_vector] | |
| 27 | struct svint8x2_t(svint8_t, svint8_t); | |
| 28 | ||
| 29 | #[target_feature(enable = "sve")] | |
| 30 | pub unsafe fn svld2_u8(pg: svbool_t, base: *const i8) -> svuint8x2_t { | |
| 31 | unsafe extern "unadjusted" { | |
| 32 | #[cfg_attr( | |
| 33 | target_arch = "aarch64", | |
| 34 | link_name = "llvm.aarch64.sve.ld2.sret.nxv16i8" | |
| 35 | )] | |
| 36 | fn _svld2_s8(pg: svbool_t, base: *const i8) -> svint8x2_t; | |
| 37 | } | |
| 38 | transmute(_svld2_s8(pg, base)) | |
| 39 | } |