From 86b112204ade0203d1c2272a523e26b4593fb60a Mon Sep 17 00:00:00 2001 From: clubby789 Date: Fri, 21 Jul 2023 15:59:28 +0000 Subject: [PATCH 001/435] Improve diagnostic for const ctors in array repeat expressions --- compiler/rustc_hir_typeck/src/expr.rs | 35 ++++++++++++--- compiler/rustc_middle/src/traits/mod.rs | 26 +++++++++-- .../src/traits/error_reporting/suggestions.rs | 29 ++++++++---- .../const-blocks/fn-call-in-non-const.stderr | 6 ++- .../ui/consts/const-blocks/trait-error.stderr | 6 ++- tests/ui/consts/const-fn-in-vec.rs | 8 +++- tests/ui/consts/const-fn-in-vec.stderr | 44 ++++++++++++++++--- 7 files changed, 126 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 29488c9011a1..b04d83a884f5 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1507,21 +1507,42 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } _ => {} } - // If someone calls a const fn, they can extract that call out into a separate constant (or a const - // block in the future), so we check that to tell them that in the diagnostic. Does not affect typeck. - let is_const_fn = match element.kind { + // If someone calls a const fn or constructs a const value, they can extract that + // out into a separate constant (or a const block in the future), so we check that + // to tell them that in the diagnostic. Does not affect typeck. + let is_constable = match element.kind { hir::ExprKind::Call(func, _args) => match *self.node_ty(func.hir_id).kind() { - ty::FnDef(def_id, _) => tcx.is_const_fn(def_id), - _ => false, + ty::FnDef(def_id, _) if tcx.is_const_fn(def_id) => traits::IsConstable::Fn, + _ => traits::IsConstable::No, }, - _ => false, + hir::ExprKind::Path(qpath) => { + match self.typeck_results.borrow().qpath_res(&qpath, element.hir_id) { + Res::Def(DefKind::Ctor(_, CtorKind::Const), _) => traits::IsConstable::Ctor, + _ => traits::IsConstable::No, + } + } + _ => traits::IsConstable::No, }; // If the length is 0, we don't create any elements, so we don't copy any. If the length is 1, we // don't copy that one element, we move it. Only check for Copy if the length is larger. if count.try_eval_target_usize(tcx, self.param_env).map_or(true, |len| len > 1) { let lang_item = self.tcx.require_lang_item(LangItem::Copy, None); - let code = traits::ObligationCauseCode::RepeatElementCopy { is_const_fn }; + let code = traits::ObligationCauseCode::RepeatElementCopy { + is_constable, + elt_type: element_ty, + elt_span: element.span, + elt_stmt_span: self + .tcx + .hir() + .parent_iter(element.hir_id) + .find_map(|(_, node)| match node { + hir::Node::Item(it) => Some(it.span), + hir::Node::Stmt(stmt) => Some(stmt.span), + _ => None, + }) + .expect("array repeat expressions must be inside an item or statement"), + }; self.require_type_meets(element_ty, element.span, code, lang_item); } } diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index b7ffed57a0be..2e1c3fe1fed2 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -301,9 +301,14 @@ pub enum ObligationCauseCode<'tcx> { InlineAsmSized, /// `[expr; N]` requires `type_of(expr): Copy`. RepeatElementCopy { - /// If element is a `const fn` we display a help message suggesting to move the - /// function call to a new `const` item while saying that `T` doesn't implement `Copy`. - is_const_fn: bool, + /// If element is a `const fn` or const ctor we display a help message suggesting + /// to move it to a new `const` item while saying that `T` doesn't implement `Copy`. + is_constable: IsConstable, + elt_type: Ty<'tcx>, + elt_span: Span, + /// Span of the statement/item in which the repeat expression occurs. We can use this to + /// place a `const` declaration before it + elt_stmt_span: Span, }, /// Types of fields (other than the last, except for packed structs) in a struct must be sized. @@ -448,6 +453,21 @@ pub enum ObligationCauseCode<'tcx> { TypeAlias(InternedObligationCauseCode<'tcx>, Span, DefId), } +/// Whether a value can be extracted into a const. +/// Used for diagnostics around array repeat expressions. +#[derive(Copy, Clone, Debug, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)] +pub enum IsConstable { + No, + /// Call to a const fn + Fn, + /// Use of a const ctor + Ctor, +} + +crate::TrivialTypeTraversalAndLiftImpls! { + IsConstable, +} + /// The 'location' at which we try to perform HIR-based wf checking. /// This information is used to obtain an `hir::Ty`, which /// we can walk in order to obtain precise spans for any diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 073a2a2b1a0c..edae9e10818b 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -27,6 +27,7 @@ use rustc_infer::infer::error_reporting::TypeErrCtxt; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::{DefineOpaqueTypes, InferOk, LateBoundRegionConversionTime}; use rustc_middle::hir::map; +use rustc_middle::traits::IsConstable; use rustc_middle::ty::error::TypeError::{self, Sorts}; use rustc_middle::ty::{ self, suggest_arbitrary_trait_bound, suggest_constraining_type_param, AdtKind, @@ -2832,20 +2833,30 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { )); } } - ObligationCauseCode::RepeatElementCopy { is_const_fn } => { + ObligationCauseCode::RepeatElementCopy { is_constable, elt_type, elt_span, elt_stmt_span } => { err.note( "the `Copy` trait is required because this value will be copied for each element of the array", ); - - if is_const_fn { - err.help( - "consider creating a new `const` item and initializing it with the result \ - of the function call to be used in the repeat position, like \ - `const VAL: Type = const_fn();` and `let x = [VAL; 42];`", - ); + let value_kind = match is_constable { + IsConstable::Fn => Some("the result of the function call"), + IsConstable::Ctor => Some("the result of the constructor"), + _ => None + }; + let sm = tcx.sess.source_map(); + if let Some(value_kind) = value_kind && + let Ok(snip) = sm.span_to_snippet(elt_span) + { + let help_msg = format!( + "consider creating a new `const` item and initializing it with {value_kind} \ + to be used in the repeat position"); + let indentation = sm.indentation_before(elt_stmt_span).unwrap_or_default(); + err.multipart_suggestion(help_msg, vec![ + (elt_stmt_span.shrink_to_lo(), format!("const ARRAY_REPEAT_VALUE: {elt_type} = {snip};\n{indentation}")), + (elt_span, "ARRAY_REPEAT_VALUE".to_string()) + ], Applicability::MachineApplicable); } - if self.tcx.sess.is_nightly_build() && is_const_fn { + if self.tcx.sess.is_nightly_build() && matches!(is_constable, IsConstable::Fn|IsConstable::Ctor) { err.help( "create an inline `const` block, see RFC #2920 \ for more information", diff --git a/tests/ui/consts/const-blocks/fn-call-in-non-const.stderr b/tests/ui/consts/const-blocks/fn-call-in-non-const.stderr index 174103eeba4c..eb8b8ac75343 100644 --- a/tests/ui/consts/const-blocks/fn-call-in-non-const.stderr +++ b/tests/ui/consts/const-blocks/fn-call-in-non-const.stderr @@ -6,13 +6,17 @@ LL | let _: [Option; 2] = [no_copy(); 2]; | = note: required for `Option` to implement `Copy` = note: the `Copy` trait is required because this value will be copied for each element of the array - = help: consider creating a new `const` item and initializing it with the result of the function call to be used in the repeat position, like `const VAL: Type = const_fn();` and `let x = [VAL; 42];` = help: create an inline `const` block, see RFC #2920 for more information help: consider annotating `Bar` with `#[derive(Copy)]` | LL + #[derive(Copy)] LL | struct Bar; | +help: consider creating a new `const` item and initializing it with the result of the function call to be used in the repeat position + | +LL ~ const ARRAY_REPEAT_VALUE: Option = no_copy(); +LL ~ let _: [Option; 2] = [ARRAY_REPEAT_VALUE; 2]; + | error: aborting due to previous error diff --git a/tests/ui/consts/const-blocks/trait-error.stderr b/tests/ui/consts/const-blocks/trait-error.stderr index 06fa4b0b1f30..858ffa820e21 100644 --- a/tests/ui/consts/const-blocks/trait-error.stderr +++ b/tests/ui/consts/const-blocks/trait-error.stderr @@ -10,9 +10,13 @@ note: required for `Foo` to implement `Copy` LL | #[derive(Copy, Clone)] | ^^^^ unsatisfied trait bound introduced in this `derive` macro = note: the `Copy` trait is required because this value will be copied for each element of the array - = help: consider creating a new `const` item and initializing it with the result of the function call to be used in the repeat position, like `const VAL: Type = const_fn();` and `let x = [VAL; 42];` = help: create an inline `const` block, see RFC #2920 for more information = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider creating a new `const` item and initializing it with the result of the function call to be used in the repeat position + | +LL ~ const ARRAY_REPEAT_VALUE: Foo = Foo(String::new()); +LL ~ [ARRAY_REPEAT_VALUE; 4]; + | error: aborting due to previous error diff --git a/tests/ui/consts/const-fn-in-vec.rs b/tests/ui/consts/const-fn-in-vec.rs index a40290eca097..0483800efefd 100644 --- a/tests/ui/consts/const-fn-in-vec.rs +++ b/tests/ui/consts/const-fn-in-vec.rs @@ -1,7 +1,11 @@ +static _MAYBE_STRINGS: [Option; 5] = [None; 5]; +//~^ ERROR the trait bound `String: Copy` is not satisfied + fn main() { // should hint to create an inline `const` block // or to create a new `const` item - let strings: [String; 5] = [String::new(); 5]; + let _strings: [String; 5] = [String::new(); 5]; + //~^ ERROR the trait bound `String: Copy` is not satisfied + let _maybe_strings: [Option; 5] = [None; 5]; //~^ ERROR the trait bound `String: Copy` is not satisfied - println!("{:?}", strings); } diff --git a/tests/ui/consts/const-fn-in-vec.stderr b/tests/ui/consts/const-fn-in-vec.stderr index 9eb7524b5044..4593034bfaea 100644 --- a/tests/ui/consts/const-fn-in-vec.stderr +++ b/tests/ui/consts/const-fn-in-vec.stderr @@ -1,13 +1,47 @@ error[E0277]: the trait bound `String: Copy` is not satisfied - --> $DIR/const-fn-in-vec.rs:4:33 + --> $DIR/const-fn-in-vec.rs:1:47 | -LL | let strings: [String; 5] = [String::new(); 5]; - | ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String` +LL | static _MAYBE_STRINGS: [Option; 5] = [None; 5]; + | ^^^^ the trait `Copy` is not implemented for `String` + | + = note: required for `Option` to implement `Copy` + = note: the `Copy` trait is required because this value will be copied for each element of the array + = help: create an inline `const` block, see RFC #2920 for more information +help: consider creating a new `const` item and initializing it with the result of the constructor to be used in the repeat position + | +LL + const ARRAY_REPEAT_VALUE: Option = None; +LL ~ static _MAYBE_STRINGS: [Option; 5] = [ARRAY_REPEAT_VALUE; 5]; + | + +error[E0277]: the trait bound `String: Copy` is not satisfied + --> $DIR/const-fn-in-vec.rs:7:34 + | +LL | let _strings: [String; 5] = [String::new(); 5]; + | ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String` | = note: the `Copy` trait is required because this value will be copied for each element of the array - = help: consider creating a new `const` item and initializing it with the result of the function call to be used in the repeat position, like `const VAL: Type = const_fn();` and `let x = [VAL; 42];` = help: create an inline `const` block, see RFC #2920 for more information +help: consider creating a new `const` item and initializing it with the result of the function call to be used in the repeat position + | +LL ~ const ARRAY_REPEAT_VALUE: String = String::new(); +LL ~ let _strings: [String; 5] = [ARRAY_REPEAT_VALUE; 5]; + | -error: aborting due to previous error +error[E0277]: the trait bound `String: Copy` is not satisfied + --> $DIR/const-fn-in-vec.rs:9:48 + | +LL | let _maybe_strings: [Option; 5] = [None; 5]; + | ^^^^ the trait `Copy` is not implemented for `String` + | + = note: required for `Option` to implement `Copy` + = note: the `Copy` trait is required because this value will be copied for each element of the array + = help: create an inline `const` block, see RFC #2920 for more information +help: consider creating a new `const` item and initializing it with the result of the constructor to be used in the repeat position + | +LL ~ const ARRAY_REPEAT_VALUE: Option = None; +LL ~ let _maybe_strings: [Option; 5] = [ARRAY_REPEAT_VALUE; 5]; + | + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0277`. From 6cdb7df44313d395ce582331c9191e278f227422 Mon Sep 17 00:00:00 2001 From: SabrinaJewson Date: Thu, 27 Jul 2023 16:29:13 +0100 Subject: [PATCH 002/435] Override `Waker::clone_from` to avoid cloning `Waker`s unnecessarily --- library/core/src/task/wake.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index b63fd5c9095f..817e39942c05 100644 --- a/library/core/src/task/wake.rs +++ b/library/core/src/task/wake.rs @@ -231,6 +231,10 @@ impl fmt::Debug for Context<'_> { /// this might be done to wake a future when a blocking function call completes on another /// thread. /// +/// Note that it is preferable to use `waker.clone_from(&new_waker)` instead +/// of `*waker = new_waker.clone()`, as the former will avoid cloning the waker +/// unnecessarily if the two wakers [wake the same task](Self::will_wake). +/// /// [`Future::poll()`]: core::future::Future::poll /// [`Poll::Pending`]: core::task::Poll::Pending #[cfg_attr(not(doc), repr(transparent))] // work around https://github.com/rust-lang/rust/issues/66401 @@ -302,7 +306,9 @@ impl Waker { /// when the `Waker`s would awaken the same task. However, if this function /// returns `true`, it is guaranteed that the `Waker`s will awaken the same task. /// - /// This function is primarily used for optimization purposes. + /// This function is primarily used for optimization purposes — for example, + /// this type's [`clone_from`](Self::clone_from) implementation uses it to + /// avoid cloning the waker when they would wake the same task anyway. #[inline] #[must_use] #[stable(feature = "futures_api", since = "1.36.0")] @@ -382,6 +388,13 @@ impl Clone for Waker { waker: unsafe { (self.waker.vtable.clone)(self.waker.data) }, } } + + #[inline] + fn clone_from(&mut self, source: &Self) { + if !self.will_wake(source) { + *self = source.clone(); + } + } } #[stable(feature = "futures_api", since = "1.36.0")] From 40a83be6eb91efffa1965f4480b8c035524d44be Mon Sep 17 00:00:00 2001 From: Ramon de C Valle Date: Thu, 27 Jul 2023 13:14:43 -0700 Subject: [PATCH 003/435] Format exploit mitigations documentation Formats lines in the exploit mitigations documentation to be at maximum 80 characters long. --- src/doc/rustc/src/exploit-mitigations.md | 336 +++++++++++------------ 1 file changed, 160 insertions(+), 176 deletions(-) diff --git a/src/doc/rustc/src/exploit-mitigations.md b/src/doc/rustc/src/exploit-mitigations.md index 172048704f48..f02a4dcf963a 100644 --- a/src/doc/rustc/src/exploit-mitigations.md +++ b/src/doc/rustc/src/exploit-mitigations.md @@ -1,12 +1,12 @@ # Exploit Mitigations -This chapter documents the exploit mitigations supported by the Rust -compiler, and is by no means an extensive survey of the Rust programming -language’s security features. +This chapter documents the exploit mitigations supported by the Rust compiler, +and is by no means an extensive survey of the Rust programming language’s +security features. This chapter is for software engineers working with the Rust programming -language, and assumes prior knowledge of the Rust programming language and -its toolchain. +language, and assumes prior knowledge of the Rust programming language and its +toolchain. ## Introduction @@ -14,8 +14,8 @@ its toolchain. The Rust programming language provides memory[1] and thread[2] safety guarantees via its ownership[3], references and borrowing[4], and slice types[5] features. However, Unsafe Rust[6] introduces unsafe blocks, unsafe -functions and methods, unsafe traits, and new types that are not subject to -the borrowing rules. +functions and methods, unsafe traits, and new types that are not subject to the +borrowing rules. Parts of the Rust standard library are implemented as safe abstractions over unsafe code (and historically have been vulnerable to memory corruption[7]). @@ -23,33 +23,31 @@ Furthermore, the Rust code and documentation encourage creating safe abstractions over unsafe code. This can cause a false sense of security if unsafe code is not properly reviewed and tested. -Unsafe Rust introduces features that do not provide the same memory and -thread safety guarantees. This causes programs or libraries to be -susceptible to memory corruption (CWE-119)[8] and concurrency issues -(CWE-557)[9]. Modern C and C++ compilers provide exploit mitigations to -increase the difficulty to exploit vulnerabilities resulting from these -issues. Therefore, the Rust compiler must also support these exploit -mitigations in order to mitigate vulnerabilities resulting from the use of -Unsafe Rust. This chapter documents these exploit mitigations and how they -apply to Rust. +Unsafe Rust introduces features that do not provide the same memory and thread +safety guarantees. This causes programs or libraries to be susceptible to +memory corruption (CWE-119)[8] and concurrency issues (CWE-557)[9]. Modern C +and C++ compilers provide exploit mitigations to increase the difficulty to +exploit vulnerabilities resulting from these issues. Therefore, the Rust +compiler must also support these exploit mitigations in order to mitigate +vulnerabilities resulting from the use of Unsafe Rust. This chapter documents +these exploit mitigations and how they apply to Rust. -This chapter does not discuss the effectiveness of these exploit mitigations -as they vary greatly depending on several factors besides their design and -implementation, but rather describe what they do, so their effectiveness can -be understood within a given context. +This chapter does not discuss the effectiveness of these exploit mitigations as +they vary greatly depending on several factors besides their design and +implementation, but rather describe what they do, so their effectiveness can be +understood within a given context. ## Exploit mitigations -This section documents the exploit mitigations applicable to the Rust -compiler when building programs for the Linux operating system on the AMD64 -architecture and equivalent.1 +This section documents the exploit mitigations applicable to the Rust compiler +when building programs for the Linux operating system on the AMD64 architecture +and equivalent.1 -The Rust Programming Language currently has no specification. The Rust -compiler (i.e., rustc) is the language reference implementation. All -references to “the Rust compiler” in this chapter refer to the language -reference implementation. +The Rust Programming Language currently has no specification. The Rust compiler +(i.e., rustc) is the language reference implementation. All references to “the +Rust compiler” in this chapter refer to the language reference implementation. Table I \ Summary of exploit mitigations supported by the Rust compiler when building @@ -83,8 +81,8 @@ instructing the dynamic linker to load it similarly to a shared object at a random load address, thus also benefiting from address-space layout randomization (ASLR). This is also referred to as “full ASLR”. -The Rust compiler supports position-independent executable, and enables it -by default since version 0.12.0 (2014-10-09)[10]–[13]. +The Rust compiler supports position-independent executable, and enables it by +default since version 0.12.0 (2014-10-09)[10]–[13]. ```text $ readelf -h target/release/hello-rust | grep Type: @@ -93,8 +91,7 @@ $ readelf -h target/release/hello-rust | grep Type: Fig. 1. Checking if an executable is a position-independent executable. An executable with an object type of `ET_DYN` (i.e., shared object) and not -`ET_EXEC` (i.e., executable) is a position-independent executable (see Fig. -1). +`ET_EXEC` (i.e., executable) is a position-independent executable (see Fig. 1). ### Integer overflow checks @@ -104,8 +101,8 @@ behavior (which may cause vulnerabilities) by checking for results of signed and unsigned integer computations that cannot be represented in their type, resulting in an overflow or wraparound. -The Rust compiler supports integer overflow checks, and enables it when -debug assertions are enabled since version 1.1.0 (2015-06-25)[14]–[20]. +The Rust compiler supports integer overflow checks, and enables it when debug +assertions are enabled since version 1.1.0 (2015-06-25)[14]–[20]. ```compile_fail fn main() { @@ -123,7 +120,7 @@ $ cargo run thread 'main' panicked at 'attempt to add with overflow', src/main.rs:3:23 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace. ``` -Fig. 3. Build and execution of hello-rust-integer with debug assertions +Fig. 3. Build and execution of hello-rust-integer with debug assertions enabled. ```text @@ -133,24 +130,24 @@ $ cargo run --release Running `target/release/hello-rust-integer` u: 0 ``` -Fig. 4. Build and execution of hello-rust-integer with debug assertions +Fig. 4. Build and execution of hello-rust-integer with debug assertions disabled. -Integer overflow checks are enabled when debug assertions are enabled (see -Fig. 3), and disabled when debug assertions are disabled (see Fig. 4). To -enable integer overflow checks independently, use the option to control -integer overflow checks, scoped attributes, or explicit checking methods -such as `checked_add`2. -It is recommended that explicit wrapping methods such as `wrapping_add` be -used when wrapping semantics are intended, and that explicit checking and -wrapping methods always be used when using Unsafe Rust. +It is recommended that explicit wrapping methods such as `wrapping_add` be used +when wrapping semantics are intended, and that explicit checking and wrapping +methods always be used when using Unsafe Rust. -2\. See [the `u32` docs](../std/primitive.u32.html) -for more information on the checked, overflowing, saturating, and wrapping -methods (using u32 as an example). +2\. See [the `u32` docs](../std/primitive.u32.html) for more +information on the checked, overflowing, saturating, and wrapping methods +(using u32 as an example). ### Non-executable memory regions @@ -158,29 +155,28 @@ class="reversefootnote" role="doc-backlink">↩ Non-executable memory regions increase the difficulty of exploitation by limiting the memory regions that can be used to execute arbitrary code. Most modern processors provide support for the operating system to mark memory -regions as non executable, but it was previously emulated by software, such -as in grsecurity/PaX's -[PAGEEXEC](https://pax.grsecurity.net/docs/pageexec.txt) and -[SEGMEXEC](https://pax.grsecurity.net/docs/segmexec.txt), on processors that -did not provide support for it. This is also known as “No Execute (NX) Bit”, -“Execute Disable (XD) Bit”, “Execute Never (XN) Bit”, and others. +regions as non executable, but it was previously emulated by software, such as +in grsecurity/PaX's [PAGEEXEC](https://pax.grsecurity.net/docs/pageexec.txt) +and [SEGMEXEC](https://pax.grsecurity.net/docs/segmexec.txt), on processors +that did not provide support for it. This is also known as “No Execute (NX) +Bit”, “Execute Disable (XD) Bit”, “Execute Never (XN) Bit”, and others. The Rust compiler supports non-executable memory regions, and enables it by -default since its initial release, version 0.1 (2012-01-20)[21], [22], but -has regressed since then[23]–[25], and enforced by default since version -1.8.0 (2016-04-14)[25]. +default since its initial release, version 0.1 (2012-01-20)[21], [22], but has +regressed since then[23]–[25], and enforced by default since version 1.8.0 +(2016-04-14)[25]. ```text $ readelf -l target/release/hello-rust | grep -A 1 GNU_STACK GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 RW 0x10 ``` -Fig. 5. Checking if non-executable memory regions are enabled for a given +Fig. 5. Checking if non-executable memory regions are enabled for a given binary. -The presence of an element of type `PT_GNU_STACK` in the program header -table with the `PF_X` (i.e., executable) flag unset indicates non-executable -memory regions3 are enabled for a given binary (see Fig. 5). Conversely, the presence of an element of type `PT_GNU_STACK` in the program header table with the `PF_X` flag set or the absence of an element of type @@ -196,16 +192,15 @@ class="reversefootnote" role="doc-backlink">↩ Stack clashing protection protects the stack from overlapping with another memory region—allowing arbitrary data in both to be overwritten using each -other—by reading from the stack pages as the stack grows to cause a page -fault when attempting to read from the guard page/region. This is also -referred to as “stack probes” or “stack probing”. +other—by reading from the stack pages as the stack grows to cause a page fault +when attempting to read from the guard page/region. This is also referred to as +“stack probes” or “stack probing”. The Rust compiler supports stack clashing protection via stack probing, and enables it by default since version 1.20.0 (2017-08-31)[26]–[29]. ![Screenshot of IDA Pro listing cross references to __rust_probestack in hello-rust.](images/image1.png "Cross references to __rust_probestack in hello-rust.") -Fig. 6. IDA Pro listing cross references to `__rust_probestack` in -hello-rust. +Fig. 6. IDA Pro listing cross references to `__rust_probestack` in hello-rust. ```rust fn hello() { @@ -223,11 +218,11 @@ Fig 7. Modified hello-rust. Fig. 8. IDA Pro listing cross references to `__rust_probestack` in modified hello-rust. -To check if stack clashing protection is enabled for a given binary, search -for cross references to `__rust_probestack`. The `__rust_probestack` is -called in the prologue of functions whose stack size is larger than a page -size (see Fig. 6), and can be forced for illustration purposes by modifying -the hello-rust example as seen in Fig. 7 and Fig. 8. +To check if stack clashing protection is enabled for a given binary, search for +cross references to `__rust_probestack`. The `__rust_probestack` is called in +the prologue of functions whose stack size is larger than a page size (see Fig. +6), and can be forced for illustration purposes by modifying the hello-rust +example as seen in Fig. 7 and Fig. 8. ### Read-only relocations and immediate binding @@ -246,21 +241,20 @@ $ readelf -l target/release/hello-rust | grep GNU_RELRO ``` Fig. 9. Checking if read-only relocations is enabled for a given binary. -The presence of an element of type `PT_GNU_RELRO` in the program header -table indicates read-only relocations are enabled for a given binary (see -Fig. 9). Conversely, the absence of an element of type `PT_GNU_RELRO` in the -program header table indicates read-only relocations are not enabled for a -given binary. +The presence of an element of type `PT_GNU_RELRO` in the program header table +indicates read-only relocations are enabled for a given binary (see Fig. 9). +Conversely, the absence of an element of type `PT_GNU_RELRO` in the program +header table indicates read-only relocations are not enabled for a given +binary. **Immediate binding** protects additional segments containing relocations -(i.e., `.got.plt`) from being overwritten by instructing the dynamic linker -to perform all relocations before transferring control to the program during -startup, so all segments containing relocations can be marked read only -(when combined with read-only relocations). This is also referred to as -“full RELRO”. +(i.e., `.got.plt`) from being overwritten by instructing the dynamic linker to +perform all relocations before transferring control to the program during +startup, so all segments containing relocations can be marked read only (when +combined with read-only relocations). This is also referred to as “full RELRO”. -The Rust compiler supports immediate binding, and enables it by default -since version 1.21.0 (2017-10-12)[30], [31]. +The Rust compiler supports immediate binding, and enables it by default since +version 1.21.0 (2017-10-12)[30], [31]. ```text $ readelf -d target/release/hello-rust | grep BIND_NOW @@ -270,16 +264,15 @@ Fig. 10. Checking if immediate binding is enabled for a given binary. The presence of an element with the `DT_BIND_NOW` tag and the `DF_BIND_NOW` flag4 in the dynamic section indicates immediate -binding is enabled for a given binary (see Fig. 10). Conversely, the absence -of an element with the `DT_BIND_NOW` tag and the `DF_BIND_NOW` flag in the -dynamic section indicates immediate binding is not enabled for a given -binary. +class="footnote">4 in the dynamic section indicates immediate binding +is enabled for a given binary (see Fig. 10). Conversely, the absence of an +element with the `DT_BIND_NOW` tag and the `DF_BIND_NOW` flag in the dynamic +section indicates immediate binding is not enabled for a given binary. The presence of both an element of type `PT_GNU_RELRO` in the program header -table and of an element with the `DT_BIND_NOW` tag and the `DF_BIND_NOW` -flag in the dynamic section indicates full RELRO is enabled for a given -binary (see Fig. 9 and Fig. 10). +table and of an element with the `DT_BIND_NOW` tag and the `DF_BIND_NOW` flag +in the dynamic section indicates full RELRO is enabled for a given binary (see +Fig. 9 and Fig. 10). 4\. And the `DF_1_NOW` flag for some link editors. @@ -287,26 +280,24 @@ href="#fnref:4" class="reversefootnote" role="doc-backlink">↩ ### Heap corruption protection -Heap corruption protection protects memory allocated dynamically by -performing several checks, such as checks for corrupted links between list -elements, invalid pointers, invalid sizes, double/multiple “frees” of the -same memory allocated, and many corner cases of these. These checks are -implementation specific, and vary per allocator. +Heap corruption protection protects memory allocated dynamically by performing +several checks, such as checks for corrupted links between list elements, +invalid pointers, invalid sizes, double/multiple “frees” of the same memory +allocated, and many corner cases of these. These checks are implementation +specific, and vary per allocator. [ARM Memory Tagging Extension (MTE)](https://community.arm.com/developer/ip-products/processors/b/processors-ip-blog/posts/enhancing-memory-safety), -when available, will provide hardware assistance for a probabilistic -mitigation to detect memory safety violations by tagging memory allocations, -and automatically checking that the correct tag is used on every memory -access. +when available, will provide hardware assistance for a probabilistic mitigation +to detect memory safety violations by tagging memory allocations, and +automatically checking that the correct tag is used on every memory access. Rust’s default allocator has historically been -[jemalloc](http://jemalloc.net/), and it has long been the cause of issues -and the subject of much discussion[32]–[38]. Consequently, it has been -removed as the default allocator in favor of the operating system’s standard -C library default allocator5 since version 1.32.0 -(2019-01-17)[39]. +[jemalloc](http://jemalloc.net/), and it has long been the cause of issues and +the subject of much discussion[32]–[38]. Consequently, it has been removed as +the default allocator in favor of the operating system’s standard C library +default allocator5 since version 1.32.0 (2019-01-17)[39]. ```rust,no_run fn main() { @@ -330,8 +321,7 @@ $ cargo run free(): invalid next size (normal) Aborted ``` -Fig. 12. Build and execution of hello-rust-heap with debug assertions -enabled. +Fig. 12. Build and execution of hello-rust-heap with debug assertions enabled. ```text $ cargo run --release @@ -341,47 +331,43 @@ $ cargo run --release free(): invalid next size (normal) Aborted ``` -Fig. 13. Build and execution of hello-rust-heap with debug assertions -disabled. +Fig. 13. Build and execution of hello-rust-heap with debug assertions disabled. Heap corruption checks are being performed when using the default allocator (i.e., the GNU Allocator) as seen in Fig. 12 and Fig. 13. 5\. Linux's standard C library default allocator is the GNU -Allocator, which is derived from ptmalloc (pthreads malloc) by Wolfram -Gloger, which in turn is derived from dlmalloc (Doug Lea malloc) by Doug -Lea. +Allocator, which is derived from ptmalloc (pthreads malloc) by Wolfram Gloger, +which in turn is derived from dlmalloc (Doug Lea malloc) by Doug Lea. ### Stack smashing protection -Stack smashing protection protects programs from stack-based buffer -overflows by inserting a random guard value between local variables and the -saved return instruction pointer, and checking if this value has changed -when returning from a function. This is also known as “Stack Protector” or -“Stack Smashing Protector (SSP)”. +Stack smashing protection protects programs from stack-based buffer overflows +by inserting a random guard value between local variables and the saved return +instruction pointer, and checking if this value has changed when returning from +a function. This is also known as “Stack Protector” or “Stack Smashing +Protector (SSP)”. The Rust compiler supports stack smashing protection on nightly builds[42]. ![Screenshot of IDA Pro listing cross references to __stack_chk_fail in hello-rust.](images/image3.png "Cross references to __stack_chk_fail in hello-rust.") -Fig. 14. IDA Pro listing cross references to `__stack_chk_fail` in -hello-rust. +Fig. 14. IDA Pro listing cross references to `__stack_chk_fail` in hello-rust. -To check if stack smashing protection is enabled for a given binary, search -for cross references to `__stack_chk_fail`. The presence of these -cross-references in Rust-compiled code (e.g., `hello_rust::main`) indicates -that the stack smashing protection is enabled (see Fig. 14). +To check if stack smashing protection is enabled for a given binary, search for +cross references to `__stack_chk_fail`. The presence of these cross-references +in Rust-compiled code (e.g., `hello_rust::main`) indicates that the stack +smashing protection is enabled (see Fig. 14). ### Forward-edge control flow protection -Forward-edge control flow protection protects programs from having its -control flow changed/hijacked by performing checks to ensure that -destinations of indirect branches are one of their valid destinations in the -control flow graph. The comprehensiveness of these checks vary per -implementation. This is also known as “forward-edge control flow integrity -(CFI)”. +Forward-edge control flow protection protects programs from having its control +flow changed/hijacked by performing checks to ensure that destinations of +indirect branches are one of their valid destinations in the control flow +graph. The comprehensiveness of these checks vary per implementation. This is +also known as “forward-edge control flow integrity (CFI)”. Newer processors provide hardware assistance for forward-edge control flow protection, such as ARM Branch Target Identification (BTI), ARM Pointer @@ -407,9 +393,9 @@ $ readelf -s -W target/debug/rust-cfi | grep "\.cfi" Fig. 15. Checking if LLVM CFI is enabled for a given binary[41]. The presence of symbols suffixed with ".cfi" or the `__cfi_init` symbol (and -references to `__cfi_check`) indicates that LLVM CFI (i.e., forward-edge control -flow protection) is enabled for a given binary. Conversely, the absence of -symbols suffixed with ".cfi" or the `__cfi_init` symbol (and references to +references to `__cfi_check`) indicates that LLVM CFI (i.e., forward-edge +control flow protection) is enabled for a given binary. Conversely, the absence +of symbols suffixed with ".cfi" or the `__cfi_init` symbol (and references to `__cfi_check`) indicates that LLVM CFI is not enabled for a given binary (see Fig. 15). @@ -421,32 +407,32 @@ class="reversefootnote" role="doc-backlink">↩ ### Backward-edge control flow protection **Shadow stack** protects saved return instruction pointers from being -overwritten by storing a copy of them on a separate (shadow) stack, and -using these copies as authoritative values when returning from functions. -This is also known as “ShadowCallStack” and “Return Flow Guard”, and is -considered an implementation of backward-edge control flow protection (or -“backward-edge CFI”). +overwritten by storing a copy of them on a separate (shadow) stack, and using +these copies as authoritative values when returning from functions. This is +also known as “ShadowCallStack” and “Return Flow Guard”, and is considered an +implementation of backward-edge control flow protection (or “backward-edge +CFI”). **Safe stack** protects not only the saved return instruction pointers, but -also register spills and some local variables from being overwritten by -storing unsafe variables, such as large arrays, on a separate (unsafe) -stack, and using these unsafe variables on the separate stack instead. This -is also known as “SafeStack”, and is also considered an implementation of -backward-edge control flow protection. +also register spills and some local variables from being overwritten by storing +unsafe variables, such as large arrays, on a separate (unsafe) stack, and using +these unsafe variables on the separate stack instead. This is also known as +“SafeStack”, and is also considered an implementation of backward-edge control +flow protection. -Both shadow and safe stack are intended to be a more comprehensive -alternatives to stack smashing protection as they protect the saved return -instruction pointers (and other data in the case of safe stack) from -arbitrary writes and non-linear out-of-bounds writes. +Both shadow and safe stack are intended to be a more comprehensive alternatives +to stack smashing protection as they protect the saved return instruction +pointers (and other data in the case of safe stack) from arbitrary writes and +non-linear out-of-bounds writes. Newer processors provide hardware assistance for backward-edge control flow -protection, such as ARM Pointer Authentication, and Intel Shadow Stack as -part of Intel CET. +protection, such as ARM Pointer Authentication, and Intel Shadow Stack as part +of Intel CET. -The Rust compiler supports shadow stack for aarch64 only -7 -on nightly Rust compilers [43]-[44]. Safe stack is available on nightly -Rust compilers [45]-[46]. +The Rust compiler supports shadow stack for aarch64 only 7 on nightly Rust +compilers [43]-[44]. Safe stack is available on nightly Rust compilers +[45]-[46]. ```text $ readelf -s target/release/hello-rust | grep __safestack_init @@ -454,15 +440,14 @@ $ readelf -s target/release/hello-rust | grep __safestack_init ``` Fig. 16. Checking if LLVM SafeStack is enabled for a given binary. -The presence of the `__safestack_init` symbol indicates that LLVM SafeStack -is enabled for a given binary (see Fig. 16). Conversely, the absence of the +The presence of the `__safestack_init` symbol indicates that LLVM SafeStack is +enabled for a given binary (see Fig. 16). Conversely, the absence of the `__safestack_init` symbol indicates that LLVM SafeStack is not enabled for a given binary. -7\. The shadow stack implementation for the AMD64 -architecture and equivalent in LLVM was removed due to performance and -security issues. +7\. The shadow stack implementation for the AMD64 architecture +and equivalent in LLVM was removed due to performance and security issues. ## Appendix @@ -470,29 +455,28 @@ role="doc-backlink">↩ As of the latest version of the [Linux Standard Base (LSB) Core Specification](https://refspecs.linuxfoundation.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/progheader.html), the `PT_GNU_STACK` program header indicates whether the stack should be -executable, and the absence of this header indicates that the stack should -be executable. However, the Linux kernel currently sets the -`READ_IMPLIES_EXEC` personality upon loading any executable with the -`PT_GNU_STACK` program header and the `PF_X `flag set or with the absence of -this header, resulting in not only the stack, but also all readable virtual -memory mappings being executable. +executable, and the absence of this header indicates that the stack should be +executable. However, the Linux kernel currently sets the `READ_IMPLIES_EXEC` +personality upon loading any executable with the `PT_GNU_STACK` program header +and the `PF_X `flag set or with the absence of this header, resulting in not +only the stack, but also all readable virtual memory mappings being executable. An attempt to fix this [was made in 2012](https://lore.kernel.org/lkml/f298f914-2239-44e4-8aa1-a51282e7fac0@zmail15.collab.prod.int.phx2.redhat.com/), and another [was made in 2020](https://lore.kernel.org/kernel-hardening/20200327064820.12602-1-keescook@chromium.org/). The former never landed, and the latter partially fixed it, but introduced -other issues—the absence of the `PT_GNU_STACK` program header still causes -not only the stack, but also all readable virtual memory mappings to be -executable in some architectures, such as IA-32 and equivalent (or causes -the stack to be non-executable in some architectures, such as AMD64 and -equivalent, contradicting the LSB). +other issues—the absence of the `PT_GNU_STACK` program header still causes not +only the stack, but also all readable virtual memory mappings to be executable +in some architectures, such as IA-32 and equivalent (or causes the stack to be +non-executable in some architectures, such as AMD64 and equivalent, +contradicting the LSB). -The `READ_IMPLIES_EXEC` personality needs to be completely separated from -the `PT_GNU_STACK` program header by having a separate option for it (or -setarch -X could just be used whenever `READ_IMPLIES_EXEC` is needed), and -the absence of the `PT_GNU_STACK` program header needs to have more secure -defaults (unrelated to `READ_IMPLIES_EXEC`). +The `READ_IMPLIES_EXEC` personality needs to be completely separated from the +`PT_GNU_STACK` program header by having a separate option for it (or setarch -X +could just be used whenever `READ_IMPLIES_EXEC` is needed), and the absence of +the `PT_GNU_STACK` program header needs to have more secure defaults (unrelated +to `READ_IMPLIES_EXEC`). ## References From 103b2df63b689a19169a7134a0b77d1c3c153943 Mon Sep 17 00:00:00 2001 From: Alex Zepeda Date: Fri, 28 Jul 2023 02:14:45 -0700 Subject: [PATCH 004/435] rustc_llvm: Link to libkstat on Solaris/SPARC getHostCPUName calls into libkstat but as of LLVM 16.0.6 libLLVMTargetParser is not explicitly linked against libkstat causing builds to fail due to undefined symbols. See also: llvm/llvm-project#64186 --- compiler/rustc_llvm/build.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/compiler/rustc_llvm/build.rs b/compiler/rustc_llvm/build.rs index aa1121d6bb3f..107f2b65171b 100644 --- a/compiler/rustc_llvm/build.rs +++ b/compiler/rustc_llvm/build.rs @@ -241,6 +241,11 @@ fn main() { cmd.arg("--system-libs"); } + // We need libkstat for getHostCPUName on SPARC builds. + if target.starts_with("sparcv9") && target.contains("solaris") { + println!("cargo:rustc-link-lib=kstat"); + } + if (target.starts_with("arm") && !target.contains("freebsd")) || target.starts_with("mips-") || target.starts_with("mipsel-") From 940d87b2d05dcf074bfe5461999f244ca82f6403 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 21 Aug 2023 10:41:49 +0200 Subject: [PATCH 005/435] extend check.overrideCommand and buildScripts.overrideCommand docs regarding invocation strategy and location --- crates/rust-analyzer/src/config.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 40c50f6d1768..dc678dae6ebc 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -90,6 +90,12 @@ config_data! { /// and should therefore include `--message-format=json` or a similar /// option. /// + /// If there are multiple linked projects, this command is invoked for + /// each of them, with the working directory being the project root + /// (i.e., the folder containing the `Cargo.toml`). This can be overwritten + /// by changing `#rust-analyzer.cargo.buildScripts.invocationStrategy#` and + /// `#rust-analyzer.cargo.buildScripts.invocationLocation#`. + /// /// By default, a cargo invocation will be constructed for the configured /// targets and features, with the following base command line: /// @@ -183,7 +189,9 @@ config_data! { /// /// If there are multiple linked projects, this command is invoked for /// each of them, with the working directory being the project root - /// (i.e., the folder containing the `Cargo.toml`). + /// (i.e., the folder containing the `Cargo.toml`). This can be overwritten + /// by changing `#rust-analyzer.cargo.check.invocationStrategy#` and + /// `#rust-analyzer.cargo.check.invocationLocation#`. /// /// An example command would be: /// From 2de62be09b33a86f5f9f23bdc88c589dde2f767e Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 21 Aug 2023 10:51:58 +0200 Subject: [PATCH 006/435] projects/workspaces --- crates/rust-analyzer/src/config.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index dc678dae6ebc..a6803b1b4803 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -90,8 +90,8 @@ config_data! { /// and should therefore include `--message-format=json` or a similar /// option. /// - /// If there are multiple linked projects, this command is invoked for - /// each of them, with the working directory being the project root + /// If there are multiple linked projects/workspaces, this command is invoked for + /// each of them, with the working directory being the workspace root /// (i.e., the folder containing the `Cargo.toml`). This can be overwritten /// by changing `#rust-analyzer.cargo.buildScripts.invocationStrategy#` and /// `#rust-analyzer.cargo.buildScripts.invocationLocation#`. @@ -187,8 +187,8 @@ config_data! { /// Cargo, you might also want to change /// `#rust-analyzer.cargo.buildScripts.overrideCommand#`. /// - /// If there are multiple linked projects, this command is invoked for - /// each of them, with the working directory being the project root + /// If there are multiple linked projects/workspaces, this command is invoked for + /// each of them, with the working directory being the workspace root /// (i.e., the folder containing the `Cargo.toml`). This can be overwritten /// by changing `#rust-analyzer.cargo.check.invocationStrategy#` and /// `#rust-analyzer.cargo.check.invocationLocation#`. From 11a64a18342865b166d2da703a06deb447f834c1 Mon Sep 17 00:00:00 2001 From: Zachary S Date: Fri, 1 Sep 2023 20:20:29 -0500 Subject: [PATCH 007/435] don't panic in BorrowedCursor::write --- library/std/src/io/readbuf.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/library/std/src/io/readbuf.rs b/library/std/src/io/readbuf.rs index 034ddd8df9ae..95044de2a09e 100644 --- a/library/std/src/io/readbuf.rs +++ b/library/std/src/io/readbuf.rs @@ -306,8 +306,9 @@ impl<'a> BorrowedCursor<'a> { impl<'a> Write for BorrowedCursor<'a> { fn write(&mut self, buf: &[u8]) -> Result { - self.append(buf); - Ok(buf.len()) + let amt = cmp::min(buf.len(), self.capacity()); + self.append(&buf[..amt]); + Ok(amt) } #[inline] From 23ffda1a97726ccdb70e43910ae4363f3e5b8448 Mon Sep 17 00:00:00 2001 From: vxpm Date: Sun, 3 Sep 2023 22:42:56 -0300 Subject: [PATCH 008/435] full function signatures option --- crates/ide-completion/src/config.rs | 1 + crates/ide-completion/src/render/function.rs | 8 ++++++-- crates/rust-analyzer/src/config.rs | 3 +++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/crates/ide-completion/src/config.rs b/crates/ide-completion/src/config.rs index 8f6a97e1e09d..3d025f284bbb 100644 --- a/crates/ide-completion/src/config.rs +++ b/crates/ide-completion/src/config.rs @@ -14,6 +14,7 @@ pub struct CompletionConfig { pub enable_imports_on_the_fly: bool, pub enable_self_on_the_fly: bool, pub enable_private_editable: bool, + pub full_function_signatures: bool, pub callable: Option, pub snippet_cap: Option, pub insert_use: InsertUseConfig, diff --git a/crates/ide-completion/src/render/function.rs b/crates/ide-completion/src/render/function.rs index 8afce8db5ea8..1672826f3306 100644 --- a/crates/ide-completion/src/render/function.rs +++ b/crates/ide-completion/src/render/function.rs @@ -100,7 +100,7 @@ fn render( item.set_documentation(ctx.docs(func)) .set_deprecated(ctx.is_deprecated(func) || ctx.is_deprecated_assoc_item(func)) - .detail(detail(db, func)) + .detail(detail(db, func, ctx.completion.config.full_function_signatures)) .lookup_by(name.unescaped().to_smol_str()); match ctx.completion.config.snippet_cap { @@ -239,7 +239,11 @@ fn ref_of_param(ctx: &CompletionContext<'_>, arg: &str, ty: &hir::Type) -> &'sta "" } -fn detail(db: &dyn HirDatabase, func: hir::Function) -> String { +fn detail(db: &dyn HirDatabase, func: hir::Function, full_function_signature: bool) -> String { + if full_function_signature { + return format!("{}", func.display(db)).replace("\n", " "); + } + let mut ret_ty = func.ret_type(db); let mut detail = String::new(); diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index ea3a21241cb6..07c6457b9c75 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -215,6 +215,8 @@ config_data! { completion_postfix_enable: bool = "true", /// Enables completions of private items and fields that are defined in the current workspace even if they are not visible at the current position. completion_privateEditable_enable: bool = "false", + /// Whether to show full function/method signatures in completion docs. + completion_fullFunctionSignatures_enable: bool = "false", /// Custom completion snippets. // NOTE: Keep this list in sync with the feature docs of user snippets. completion_snippets_custom: FxHashMap = r#"{ @@ -1444,6 +1446,7 @@ impl Config { && completion_item_edit_resolve(&self.caps), enable_self_on_the_fly: self.data.completion_autoself_enable, enable_private_editable: self.data.completion_privateEditable_enable, + full_function_signatures: self.data.completion_fullFunctionSignatures_enable, callable: match self.data.completion_callable_snippets { CallableCompletionDef::FillArguments => Some(CallableSnippets::FillArguments), CallableCompletionDef::AddParentheses => Some(CallableSnippets::AddParentheses), From 6afa5b0ba28c46905c0d0ac3022d4e1af0f1de36 Mon Sep 17 00:00:00 2001 From: vxpm Date: Sun, 3 Sep 2023 23:41:13 -0300 Subject: [PATCH 009/435] better handling of spaces & newlines --- crates/ide-completion/src/render/function.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/crates/ide-completion/src/render/function.rs b/crates/ide-completion/src/render/function.rs index 1672826f3306..dd7de72190d1 100644 --- a/crates/ide-completion/src/render/function.rs +++ b/crates/ide-completion/src/render/function.rs @@ -241,7 +241,18 @@ fn ref_of_param(ctx: &CompletionContext<'_>, arg: &str, ty: &hir::Type) -> &'sta fn detail(db: &dyn HirDatabase, func: hir::Function, full_function_signature: bool) -> String { if full_function_signature { - return format!("{}", func.display(db)).replace("\n", " "); + let signature = format!("{}", func.display(db)); + let mut singleline = String::with_capacity(signature.len()); + + for segment in signature.split_whitespace() { + if !singleline.is_empty() { + singleline.push(' '); + } + + singleline.push_str(segment); + } + + return singleline; } let mut ret_ty = func.ret_type(db); From 6b487ed4be81e723e0ed2035f79b27d9efb93b8a Mon Sep 17 00:00:00 2001 From: vxpm Date: Mon, 4 Sep 2023 00:02:08 -0300 Subject: [PATCH 010/435] fix & run tests --- crates/ide-completion/src/tests.rs | 1 + crates/rust-analyzer/src/config.rs | 4 ++-- crates/rust-analyzer/src/integrated_benchmarks.rs | 2 ++ docs/user/generated_config.adoc | 5 +++++ editors/code/package.json | 5 +++++ 5 files changed, 15 insertions(+), 2 deletions(-) diff --git a/crates/ide-completion/src/tests.rs b/crates/ide-completion/src/tests.rs index 2464e8d5f817..284bdd8af21f 100644 --- a/crates/ide-completion/src/tests.rs +++ b/crates/ide-completion/src/tests.rs @@ -64,6 +64,7 @@ pub(crate) const TEST_CONFIG: CompletionConfig = CompletionConfig { enable_imports_on_the_fly: true, enable_self_on_the_fly: true, enable_private_editable: false, + full_function_signatures: false, callable: Some(CallableSnippets::FillArguments), snippet_cap: SnippetCap::new(true), prefer_no_std: false, diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 07c6457b9c75..9382f4ea19ef 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -209,14 +209,14 @@ config_data! { completion_autoself_enable: bool = "true", /// Whether to add parenthesis and argument snippets when completing function. completion_callable_snippets: CallableCompletionDef = "\"fill_arguments\"", + /// Whether to show full function/method signatures in completion docs. + completion_fullFunctionSignatures_enable: bool = "false", /// Maximum number of completions to return. If `None`, the limit is infinite. completion_limit: Option = "null", /// Whether to show postfix snippets like `dbg`, `if`, `not`, etc. completion_postfix_enable: bool = "true", /// Enables completions of private items and fields that are defined in the current workspace even if they are not visible at the current position. completion_privateEditable_enable: bool = "false", - /// Whether to show full function/method signatures in completion docs. - completion_fullFunctionSignatures_enable: bool = "false", /// Custom completion snippets. // NOTE: Keep this list in sync with the feature docs of user snippets. completion_snippets_custom: FxHashMap = r#"{ diff --git a/crates/rust-analyzer/src/integrated_benchmarks.rs b/crates/rust-analyzer/src/integrated_benchmarks.rs index 5a11012b93cf..2c402552919f 100644 --- a/crates/rust-analyzer/src/integrated_benchmarks.rs +++ b/crates/rust-analyzer/src/integrated_benchmarks.rs @@ -134,6 +134,7 @@ fn integrated_completion_benchmark() { enable_imports_on_the_fly: true, enable_self_on_the_fly: true, enable_private_editable: true, + full_function_signatures: false, callable: Some(CallableSnippets::FillArguments), snippet_cap: SnippetCap::new(true), insert_use: InsertUseConfig { @@ -173,6 +174,7 @@ fn integrated_completion_benchmark() { enable_imports_on_the_fly: true, enable_self_on_the_fly: true, enable_private_editable: true, + full_function_signatures: false, callable: Some(CallableSnippets::FillArguments), snippet_cap: SnippetCap::new(true), insert_use: InsertUseConfig { diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc index 71feed0f72ca..cf549565fe1d 100644 --- a/docs/user/generated_config.adoc +++ b/docs/user/generated_config.adoc @@ -244,6 +244,11 @@ with `self` prefixed to them when inside a method. -- Whether to add parenthesis and argument snippets when completing function. -- +[[rust-analyzer.completion.fullFunctionSignatures.enable]]rust-analyzer.completion.fullFunctionSignatures.enable (default: `false`):: ++ +-- +Whether to show full function/method signatures in completion docs. +-- [[rust-analyzer.completion.limit]]rust-analyzer.completion.limit (default: `null`):: + -- diff --git a/editors/code/package.json b/editors/code/package.json index 233e7bf44b16..e075e227625a 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -799,6 +799,11 @@ "Do no snippet completions for callables." ] }, + "rust-analyzer.completion.fullFunctionSignatures.enable": { + "markdownDescription": "Whether to show full function/method signatures in completion docs.", + "default": false, + "type": "boolean" + }, "rust-analyzer.completion.limit": { "markdownDescription": "Maximum number of completions to return. If `None`, the limit is infinite.", "default": null, From d7a8e800c9270023d5a19f793f28054b936f7c5d Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Sat, 19 Aug 2023 16:49:26 -0600 Subject: [PATCH 011/435] feat: initial version of bool_to_enum assist --- .../ide-assists/src/handlers/bool_to_enum.rs | 724 ++++++++++++++++++ crates/ide-assists/src/lib.rs | 2 + crates/syntax/src/ast/make.rs | 28 + 3 files changed, 754 insertions(+) create mode 100644 crates/ide-assists/src/handlers/bool_to_enum.rs diff --git a/crates/ide-assists/src/handlers/bool_to_enum.rs b/crates/ide-assists/src/handlers/bool_to_enum.rs new file mode 100644 index 000000000000..dd11824b992d --- /dev/null +++ b/crates/ide-assists/src/handlers/bool_to_enum.rs @@ -0,0 +1,724 @@ +use ide_db::{ + assists::{AssistId, AssistKind}, + defs::Definition, + search::{FileReference, SearchScope, UsageSearchResult}, + source_change::SourceChangeBuilder, +}; +use syntax::{ + ast::{ + self, + edit::IndentLevel, + edit_in_place::{AttrsOwnerEdit, Indent}, + make, HasName, + }, + ted, AstNode, NodeOrToken, SyntaxNode, T, +}; + +use crate::assist_context::{AssistContext, Assists}; + +// Assist: bool_to_enum +// +// This converts boolean local variables, fields, constants, and statics into a new +// enum with two variants `Bool::True` and `Bool::False`, as well as replacing +// all assignments with the variants and replacing all usages with `== Bool::True` or +// `== Bool::False`. +// +// ``` +// fn main() { +// let $0bool = true; +// +// if bool { +// println!("foo"); +// } +// } +// ``` +// -> +// ``` +// fn main() { +// #[derive(PartialEq, Eq)] +// enum Bool { True, False } +// +// let bool = Bool::True; +// +// if bool == Bool::True { +// println!("foo"); +// } +// } +// ``` +pub(crate) fn bool_to_enum(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { + let BoolNodeData { target_node, name, ty_annotation, initializer, definition } = + find_bool_node(ctx)?; + + let target = name.syntax().text_range(); + acc.add( + AssistId("bool_to_enum", AssistKind::RefactorRewrite), + "Convert boolean to enum", + target, + |edit| { + if let Some(ty) = &ty_annotation { + cov_mark::hit!(replaces_ty_annotation); + edit.replace(ty.syntax().text_range(), "Bool"); + } + + if let Some(initializer) = initializer { + replace_bool_expr(edit, initializer); + } + + let usages = definition + .usages(&ctx.sema) + .in_scope(&SearchScope::single_file(ctx.file_id())) + .all(); + replace_usages(edit, &usages); + + add_enum_def(edit, ctx, &usages, target_node); + }, + ) +} + +struct BoolNodeData { + target_node: SyntaxNode, + name: ast::Name, + ty_annotation: Option, + initializer: Option, + definition: Definition, +} + +/// Attempts to find an appropriate node to apply the action to. +fn find_bool_node(ctx: &AssistContext<'_>) -> Option { + if let Some(let_stmt) = ctx.find_node_at_offset::() { + let bind_pat = match let_stmt.pat()? { + ast::Pat::IdentPat(pat) => pat, + _ => { + cov_mark::hit!(not_applicable_in_non_ident_pat); + return None; + } + }; + let def = ctx.sema.to_def(&bind_pat)?; + if !def.ty(ctx.db()).is_bool() { + cov_mark::hit!(not_applicable_non_bool_local); + return None; + } + + Some(BoolNodeData { + target_node: let_stmt.syntax().clone(), + name: bind_pat.name()?, + ty_annotation: let_stmt.ty(), + initializer: let_stmt.initializer(), + definition: Definition::Local(def), + }) + } else if let Some(const_) = ctx.find_node_at_offset::() { + let def = ctx.sema.to_def(&const_)?; + if !def.ty(ctx.db()).is_bool() { + cov_mark::hit!(not_applicable_non_bool_const); + return None; + } + + Some(BoolNodeData { + target_node: const_.syntax().clone(), + name: const_.name()?, + ty_annotation: const_.ty(), + initializer: const_.body(), + definition: Definition::Const(def), + }) + } else if let Some(static_) = ctx.find_node_at_offset::() { + let def = ctx.sema.to_def(&static_)?; + if !def.ty(ctx.db()).is_bool() { + cov_mark::hit!(not_applicable_non_bool_static); + return None; + } + + Some(BoolNodeData { + target_node: static_.syntax().clone(), + name: static_.name()?, + ty_annotation: static_.ty(), + initializer: static_.body(), + definition: Definition::Static(def), + }) + } else if let Some(field_name) = ctx.find_node_at_offset::() { + let field = field_name.syntax().ancestors().find_map(ast::RecordField::cast)?; + if field.name()? != field_name { + return None; + } + + let strukt = field.syntax().ancestors().find_map(ast::Struct::cast)?; + let def = ctx.sema.to_def(&field)?; + if !def.ty(ctx.db()).is_bool() { + cov_mark::hit!(not_applicable_non_bool_field); + return None; + } + Some(BoolNodeData { + target_node: strukt.syntax().clone(), + name: field_name, + ty_annotation: field.ty(), + initializer: None, + definition: Definition::Field(def), + }) + } else { + None + } +} + +fn replace_bool_expr(edit: &mut SourceChangeBuilder, expr: ast::Expr) { + let expr_range = expr.syntax().text_range(); + let enum_expr = bool_expr_to_enum_expr(expr); + edit.replace(expr_range, enum_expr.syntax().text()) +} + +/// Converts an expression of type `bool` to one of the new enum type. +fn bool_expr_to_enum_expr(expr: ast::Expr) -> ast::Expr { + let true_expr = make::expr_path(make::path_from_text("Bool::True")).clone_for_update(); + let false_expr = make::expr_path(make::path_from_text("Bool::False")).clone_for_update(); + + if let ast::Expr::Literal(literal) = &expr { + match literal.kind() { + ast::LiteralKind::Bool(true) => true_expr, + ast::LiteralKind::Bool(false) => false_expr, + _ => expr, + } + } else { + make::expr_if( + expr, + make::tail_only_block_expr(true_expr), + Some(ast::ElseBranch::Block(make::tail_only_block_expr(false_expr))), + ) + .clone_for_update() + } +} + +/// Replaces all usages of the target identifier, both when read and written to. +fn replace_usages(edit: &mut SourceChangeBuilder, usages: &UsageSearchResult) { + for (_, references) in usages.iter() { + references + .into_iter() + .filter_map(|FileReference { range, name, .. }| match name { + ast::NameLike::NameRef(name) => Some((*range, name)), + _ => None, + }) + .for_each(|(range, name_ref)| { + if let Some(initializer) = find_assignment_usage(name_ref) { + cov_mark::hit!(replaces_assignment); + + replace_bool_expr(edit, initializer); + } else if let Some((prefix_expr, expr)) = find_negated_usage(name_ref) { + cov_mark::hit!(replaces_negation); + + edit.replace( + prefix_expr.syntax().text_range(), + format!("{} == Bool::False", expr), + ); + } else if let Some((record_field, initializer)) = find_record_expr_usage(name_ref) { + cov_mark::hit!(replaces_record_expr); + + let record_field = edit.make_mut(record_field); + let enum_expr = bool_expr_to_enum_expr(initializer); + record_field.replace_expr(enum_expr); + } else if name_ref.syntax().ancestors().find_map(ast::Expr::cast).is_some() { + // for any other usage in an expression, replace it with a check that it is the true variant + edit.replace(range, format!("{} == Bool::True", name_ref.text())); + } + }) + } +} + +fn find_assignment_usage(name_ref: &ast::NameRef) -> Option { + let bin_expr = name_ref.syntax().ancestors().find_map(ast::BinExpr::cast)?; + + if let Some(ast::BinaryOp::Assignment { op: None }) = bin_expr.op_kind() { + bin_expr.rhs() + } else { + None + } +} + +fn find_negated_usage(name_ref: &ast::NameRef) -> Option<(ast::PrefixExpr, ast::Expr)> { + let prefix_expr = name_ref.syntax().ancestors().find_map(ast::PrefixExpr::cast)?; + + if let Some(ast::UnaryOp::Not) = prefix_expr.op_kind() { + let initializer = prefix_expr.expr()?; + Some((prefix_expr, initializer)) + } else { + None + } +} + +fn find_record_expr_usage(name_ref: &ast::NameRef) -> Option<(ast::RecordExprField, ast::Expr)> { + let record_field = name_ref.syntax().ancestors().find_map(ast::RecordExprField::cast)?; + let initializer = record_field.expr()?; + + Some((record_field, initializer)) +} + +/// Adds the definition of the new enum before the target node. +fn add_enum_def( + edit: &mut SourceChangeBuilder, + ctx: &AssistContext<'_>, + usages: &UsageSearchResult, + target_node: SyntaxNode, +) { + let make_enum_pub = usages.iter().any(|(file_id, _)| file_id != &ctx.file_id()); + let enum_def = make_bool_enum(make_enum_pub); + + let indent = IndentLevel::from_node(&target_node); + enum_def.reindent_to(indent); + + ted::insert_all( + ted::Position::before(&edit.make_syntax_mut(target_node)), + vec![ + enum_def.syntax().clone().into(), + make::tokens::whitespace(&format!("\n\n{indent}")).into(), + ], + ); +} + +fn make_bool_enum(make_pub: bool) -> ast::Enum { + let enum_def = make::enum_( + if make_pub { Some(make::visibility_pub()) } else { None }, + make::name("Bool"), + make::variant_list(vec![ + make::variant(make::name("True"), None), + make::variant(make::name("False"), None), + ]), + ) + .clone_for_update(); + + let derive_eq = make::attr_outer(make::meta_token_tree( + make::ext::ident_path("derive"), + make::token_tree( + T!['('], + vec![ + NodeOrToken::Token(make::tokens::ident("PartialEq")), + NodeOrToken::Token(make::token(T![,])), + NodeOrToken::Token(make::tokens::single_space()), + NodeOrToken::Token(make::tokens::ident("Eq")), + ], + ), + )) + .clone_for_update(); + enum_def.add_attr(derive_eq); + + enum_def +} + +#[cfg(test)] +mod tests { + use super::*; + + use crate::tests::{check_assist, check_assist_not_applicable}; + + #[test] + fn local_variable_with_usage() { + check_assist( + bool_to_enum, + r#" +fn main() { + let $0foo = true; + + if foo { + println!("foo"); + } +} +"#, + r#" +fn main() { + #[derive(PartialEq, Eq)] + enum Bool { True, False } + + let foo = Bool::True; + + if foo == Bool::True { + println!("foo"); + } +} +"#, + ) + } + + #[test] + fn local_variable_with_usage_negated() { + cov_mark::check!(replaces_negation); + check_assist( + bool_to_enum, + r#" +fn main() { + let $0foo = true; + + if !foo { + println!("foo"); + } +} +"#, + r#" +fn main() { + #[derive(PartialEq, Eq)] + enum Bool { True, False } + + let foo = Bool::True; + + if foo == Bool::False { + println!("foo"); + } +} +"#, + ) + } + + #[test] + fn local_variable_with_type_annotation() { + cov_mark::check!(replaces_ty_annotation); + check_assist( + bool_to_enum, + r#" +fn main() { + let $0foo: bool = false; +} +"#, + r#" +fn main() { + #[derive(PartialEq, Eq)] + enum Bool { True, False } + + let foo: Bool = Bool::False; +} +"#, + ) + } + + #[test] + fn local_variable_with_non_literal_initializer() { + check_assist( + bool_to_enum, + r#" +fn main() { + let $0foo = 1 == 2; +} +"#, + r#" +fn main() { + #[derive(PartialEq, Eq)] + enum Bool { True, False } + + let foo = if 1 == 2 { Bool::True } else { Bool::False }; +} +"#, + ) + } + + #[test] + fn local_variable_binexpr_usage() { + check_assist( + bool_to_enum, + r#" +fn main() { + let $0foo = false; + let bar = true; + + if !foo && bar { + println!("foobar"); + } +} +"#, + r#" +fn main() { + #[derive(PartialEq, Eq)] + enum Bool { True, False } + + let foo = Bool::False; + let bar = true; + + if foo == Bool::False && bar { + println!("foobar"); + } +} +"#, + ) + } + + #[test] + fn local_variable_unop_usage() { + check_assist( + bool_to_enum, + r#" +fn main() { + let $0foo = true; + + if *&foo { + println!("foobar"); + } +} +"#, + r#" +fn main() { + #[derive(PartialEq, Eq)] + enum Bool { True, False } + + let foo = Bool::True; + + if *&foo == Bool::True { + println!("foobar"); + } +} +"#, + ) + } + + #[test] + fn local_variable_assigned_later() { + cov_mark::check!(replaces_assignment); + check_assist( + bool_to_enum, + r#" +fn main() { + let $0foo: bool; + foo = true; +} +"#, + r#" +fn main() { + #[derive(PartialEq, Eq)] + enum Bool { True, False } + + let foo: Bool; + foo = Bool::True; +} +"#, + ) + } + + #[test] + fn local_variable_does_not_apply_recursively() { + check_assist( + bool_to_enum, + r#" +fn main() { + let $0foo = true; + let bar = !foo; + + if bar { + println!("bar"); + } +} +"#, + r#" +fn main() { + #[derive(PartialEq, Eq)] + enum Bool { True, False } + + let foo = Bool::True; + let bar = foo == Bool::False; + + if bar { + println!("bar"); + } +} +"#, + ) + } + + #[test] + fn local_variable_non_bool() { + cov_mark::check!(not_applicable_non_bool_local); + check_assist_not_applicable( + bool_to_enum, + r#" +fn main() { + let $0foo = 1; +} +"#, + ) + } + + #[test] + fn local_variable_non_ident_pat() { + cov_mark::check!(not_applicable_in_non_ident_pat); + check_assist_not_applicable( + bool_to_enum, + r#" +fn main() { + let ($0foo, bar) = (true, false); +} +"#, + ) + } + + #[test] + fn field_basic() { + cov_mark::check!(replaces_record_expr); + check_assist( + bool_to_enum, + r#" +struct Foo { + $0bar: bool, + baz: bool, +} + +fn main() { + let foo = Foo { bar: true, baz: false }; + + if foo.bar { + println!("foo"); + } +} +"#, + r#" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +struct Foo { + bar: Bool, + baz: bool, +} + +fn main() { + let foo = Foo { bar: Bool::True, baz: false }; + + if foo.bar == Bool::True { + println!("foo"); + } +} +"#, + ) + } + + #[test] + fn field_in_mod_properly_indented() { + check_assist( + bool_to_enum, + r#" +mod foo { + struct Bar { + $0baz: bool, + } + + impl Bar { + fn new(baz: bool) -> Self { + Self { baz } + } + } +} +"#, + r#" +mod foo { + #[derive(PartialEq, Eq)] + enum Bool { True, False } + + struct Bar { + baz: Bool, + } + + impl Bar { + fn new(baz: bool) -> Self { + Self { baz: if baz { Bool::True } else { Bool::False } } + } + } +} +"#, + ) + } + + #[test] + fn field_non_bool() { + cov_mark::check!(not_applicable_non_bool_field); + check_assist_not_applicable( + bool_to_enum, + r#" +struct Foo { + $0bar: usize, +} + +fn main() { + let foo = Foo { bar: 1 }; +} +"#, + ) + } + + #[test] + fn const_basic() { + check_assist( + bool_to_enum, + r#" +const $0FOO: bool = false; + +fn main() { + if FOO { + println!("foo"); + } +} +"#, + r#" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +const FOO: Bool = Bool::False; + +fn main() { + if FOO == Bool::True { + println!("foo"); + } +} +"#, + ) + } + + #[test] + fn const_non_bool() { + cov_mark::check!(not_applicable_non_bool_const); + check_assist_not_applicable( + bool_to_enum, + r#" +const $0FOO: &str = "foo"; + +fn main() { + println!("{FOO}"); +} +"#, + ) + } + + #[test] + fn static_basic() { + check_assist( + bool_to_enum, + r#" +static mut $0BOOL: bool = true; + +fn main() { + unsafe { BOOL = false }; + if unsafe { BOOL } { + println!("foo"); + } +} +"#, + r#" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +static mut BOOL: Bool = Bool::True; + +fn main() { + unsafe { BOOL = Bool::False }; + if unsafe { BOOL == Bool::True } { + println!("foo"); + } +} +"#, + ) + } + + #[test] + fn static_non_bool() { + cov_mark::check!(not_applicable_non_bool_static); + check_assist_not_applicable( + bool_to_enum, + r#" +static mut $0FOO: usize = 0; + +fn main() { + if unsafe { FOO } == 0 { + println!("foo"); + } +} +"#, + ) + } +} diff --git a/crates/ide-assists/src/lib.rs b/crates/ide-assists/src/lib.rs index 6f973ab53eec..a17ce93e928c 100644 --- a/crates/ide-assists/src/lib.rs +++ b/crates/ide-assists/src/lib.rs @@ -115,6 +115,7 @@ mod handlers { mod apply_demorgan; mod auto_import; mod bind_unused_param; + mod bool_to_enum; mod change_visibility; mod convert_bool_then; mod convert_comment_block; @@ -227,6 +228,7 @@ mod handlers { apply_demorgan::apply_demorgan, auto_import::auto_import, bind_unused_param::bind_unused_param, + bool_to_enum::bool_to_enum, change_visibility::change_visibility, convert_bool_then::convert_bool_then_to_if, convert_bool_then::convert_if_to_bool_then, diff --git a/crates/syntax/src/ast/make.rs b/crates/syntax/src/ast/make.rs index 17e311c0c502..e0055be6e69e 100644 --- a/crates/syntax/src/ast/make.rs +++ b/crates/syntax/src/ast/make.rs @@ -973,6 +973,11 @@ pub fn tuple_field(visibility: Option, ty: ast::Type) -> ast::T ast_from_text(&format!("struct f({visibility}{ty});")) } +pub fn variant_list(variants: impl IntoIterator) -> ast::VariantList { + let variants = variants.into_iter().join(", "); + ast_from_text(&format!("enum f {{ {variants} }}")) +} + pub fn variant(name: ast::Name, field_list: Option) -> ast::Variant { let field_list = match field_list { None => String::new(), @@ -1037,6 +1042,19 @@ pub fn struct_( ast_from_text(&format!("{visibility}struct {strukt_name}{type_params}{field_list}{semicolon}",)) } +pub fn enum_( + visibility: Option, + enum_name: ast::Name, + variant_list: ast::VariantList, +) -> ast::Enum { + let visibility = match visibility { + None => String::new(), + Some(it) => format!("{it} "), + }; + + ast_from_text(&format!("{visibility}enum {enum_name} {variant_list}")) +} + pub fn attr_outer(meta: ast::Meta) -> ast::Attr { ast_from_text(&format!("#[{meta}]")) } @@ -1149,6 +1167,16 @@ pub mod tokens { lit.syntax().first_child_or_token().unwrap().into_token().unwrap() } + pub fn ident(text: &str) -> SyntaxToken { + assert_eq!(text.trim(), text); + let path: ast::Path = super::ext::ident_path(text); + path.syntax() + .descendants_with_tokens() + .filter_map(|it| it.into_token()) + .find(|it| it.kind() == IDENT) + .unwrap() + } + pub fn single_newline() -> SyntaxToken { let res = SOURCE_FILE .tree() From 59738d5fd5f868cec69e0ff30e27a6b80fc81ee4 Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Sat, 19 Aug 2023 17:41:44 -0600 Subject: [PATCH 012/435] fix: add generated doctest --- crates/ide-assists/src/tests/generated.rs | 28 +++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/crates/ide-assists/src/tests/generated.rs b/crates/ide-assists/src/tests/generated.rs index dfaa53449f42..63a08a0e5697 100644 --- a/crates/ide-assists/src/tests/generated.rs +++ b/crates/ide-assists/src/tests/generated.rs @@ -280,6 +280,34 @@ fn some_function(x: i32) { ) } +#[test] +fn doctest_bool_to_enum() { + check_doc_test( + "bool_to_enum", + r#####" +fn main() { + let $0bool = true; + + if bool { + println!("foo"); + } +} +"#####, + r#####" +fn main() { + #[derive(PartialEq, Eq)] + enum Bool { True, False } + + let bool = Bool::True; + + if bool == Bool::True { + println!("foo"); + } +} +"#####, + ) +} + #[test] fn doctest_change_visibility() { check_doc_test( From 83196fd4d9ed8544410fc82fee5d54830163f248 Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Sat, 19 Aug 2023 17:45:16 -0600 Subject: [PATCH 013/435] fix: remove trailing whitespace --- crates/ide-assists/src/handlers/bool_to_enum.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/ide-assists/src/handlers/bool_to_enum.rs b/crates/ide-assists/src/handlers/bool_to_enum.rs index dd11824b992d..279e5583624f 100644 --- a/crates/ide-assists/src/handlers/bool_to_enum.rs +++ b/crates/ide-assists/src/handlers/bool_to_enum.rs @@ -369,7 +369,7 @@ fn main() { bool_to_enum, r#" fn main() { - let $0foo: bool = false; + let $0foo: bool = false; } "#, r#" @@ -377,7 +377,7 @@ fn main() { #[derive(PartialEq, Eq)] enum Bool { True, False } - let foo: Bool = Bool::False; + let foo: Bool = Bool::False; } "#, ) @@ -389,7 +389,7 @@ fn main() { bool_to_enum, r#" fn main() { - let $0foo = 1 == 2; + let $0foo = 1 == 2; } "#, r#" @@ -397,7 +397,7 @@ fn main() { #[derive(PartialEq, Eq)] enum Bool { True, False } - let foo = if 1 == 2 { Bool::True } else { Bool::False }; + let foo = if 1 == 2 { Bool::True } else { Bool::False }; } "#, ) @@ -468,7 +468,7 @@ fn main() { bool_to_enum, r#" fn main() { - let $0foo: bool; + let $0foo: bool; foo = true; } "#, @@ -477,7 +477,7 @@ fn main() { #[derive(PartialEq, Eq)] enum Bool { True, False } - let foo: Bool; + let foo: Bool; foo = Bool::True; } "#, From 91ac1d619475e1b61bf4ae8d318c4740a0adce66 Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Fri, 8 Sep 2023 07:45:23 -0700 Subject: [PATCH 014/435] fix: initializing struct multiple times --- .../ide-assists/src/handlers/bool_to_enum.rs | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/crates/ide-assists/src/handlers/bool_to_enum.rs b/crates/ide-assists/src/handlers/bool_to_enum.rs index 279e5583624f..4158b75dc00c 100644 --- a/crates/ide-assists/src/handlers/bool_to_enum.rs +++ b/crates/ide-assists/src/handlers/bool_to_enum.rs @@ -194,6 +194,7 @@ fn replace_usages(edit: &mut SourceChangeBuilder, usages: &UsageSearchResult) { ast::NameLike::NameRef(name) => Some((*range, name)), _ => None, }) + .rev() .for_each(|(range, name_ref)| { if let Some(initializer) = find_assignment_usage(name_ref) { cov_mark::hit!(replaces_assignment); @@ -615,6 +616,46 @@ mod foo { ) } + #[test] + fn field_multiple_initializations() { + check_assist( + bool_to_enum, + r#" +struct Foo { + $0bar: bool, + baz: bool, +} + +fn main() { + let foo1 = Foo { bar: true, baz: false }; + let foo2 = Foo { bar: false, baz: false }; + + if foo1.bar && foo2.bar { + println!("foo"); + } +} +"#, + r#" +#[derive(PartialEq, Eq)] +enum $0Bool { True, False } + +struct Foo { + bar: Bool, + baz: bool, +} + +fn main() { + let foo1 = Foo { bar: Bool::True, baz: false }; + let foo2 = Foo { bar: Bool::False, baz: false }; + + if foo1.bar == Bool::True && foo2.bar == Bool::True { + println!("foo"); + } +} +"#, + ) + } + #[test] fn field_non_bool() { cov_mark::check!(not_applicable_non_bool_field); From 455dacfd3b5387bcf2854f2a88edb9b69361e69f Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Fri, 8 Sep 2023 10:06:17 -0700 Subject: [PATCH 015/435] fix: only trigger assist on Name --- .../ide-assists/src/handlers/bool_to_enum.rs | 41 +++++++++++++------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/crates/ide-assists/src/handlers/bool_to_enum.rs b/crates/ide-assists/src/handlers/bool_to_enum.rs index 4158b75dc00c..56749edf4636 100644 --- a/crates/ide-assists/src/handlers/bool_to_enum.rs +++ b/crates/ide-assists/src/handlers/bool_to_enum.rs @@ -85,7 +85,9 @@ struct BoolNodeData { /// Attempts to find an appropriate node to apply the action to. fn find_bool_node(ctx: &AssistContext<'_>) -> Option { - if let Some(let_stmt) = ctx.find_node_at_offset::() { + let name: ast::Name = ctx.find_node_at_offset()?; + + if let Some(let_stmt) = name.syntax().ancestors().find_map(ast::LetStmt::cast) { let bind_pat = match let_stmt.pat()? { ast::Pat::IdentPat(pat) => pat, _ => { @@ -101,12 +103,12 @@ fn find_bool_node(ctx: &AssistContext<'_>) -> Option { Some(BoolNodeData { target_node: let_stmt.syntax().clone(), - name: bind_pat.name()?, + name, ty_annotation: let_stmt.ty(), initializer: let_stmt.initializer(), definition: Definition::Local(def), }) - } else if let Some(const_) = ctx.find_node_at_offset::() { + } else if let Some(const_) = name.syntax().ancestors().find_map(ast::Const::cast) { let def = ctx.sema.to_def(&const_)?; if !def.ty(ctx.db()).is_bool() { cov_mark::hit!(not_applicable_non_bool_const); @@ -115,12 +117,12 @@ fn find_bool_node(ctx: &AssistContext<'_>) -> Option { Some(BoolNodeData { target_node: const_.syntax().clone(), - name: const_.name()?, + name, ty_annotation: const_.ty(), initializer: const_.body(), definition: Definition::Const(def), }) - } else if let Some(static_) = ctx.find_node_at_offset::() { + } else if let Some(static_) = name.syntax().ancestors().find_map(ast::Static::cast) { let def = ctx.sema.to_def(&static_)?; if !def.ty(ctx.db()).is_bool() { cov_mark::hit!(not_applicable_non_bool_static); @@ -129,14 +131,14 @@ fn find_bool_node(ctx: &AssistContext<'_>) -> Option { Some(BoolNodeData { target_node: static_.syntax().clone(), - name: static_.name()?, + name, ty_annotation: static_.ty(), initializer: static_.body(), definition: Definition::Static(def), }) - } else if let Some(field_name) = ctx.find_node_at_offset::() { - let field = field_name.syntax().ancestors().find_map(ast::RecordField::cast)?; - if field.name()? != field_name { + } else { + let field = name.syntax().ancestors().find_map(ast::RecordField::cast)?; + if field.name()? != name { return None; } @@ -148,13 +150,11 @@ fn find_bool_node(ctx: &AssistContext<'_>) -> Option { } Some(BoolNodeData { target_node: strukt.syntax().clone(), - name: field_name, + name, ty_annotation: field.ty(), initializer: None, definition: Definition::Field(def), }) - } else { - None } } @@ -528,6 +528,18 @@ fn main() { ) } + #[test] + fn local_variable_cursor_not_on_ident() { + check_assist_not_applicable( + bool_to_enum, + r#" +fn main() { + let foo = $0true; +} +"#, + ) + } + #[test] fn local_variable_non_ident_pat() { cov_mark::check!(not_applicable_in_non_ident_pat); @@ -762,4 +774,9 @@ fn main() { "#, ) } + + #[test] + fn not_applicable_to_other_names() { + check_assist_not_applicable(bool_to_enum, "fn $0main() {}") + } } From 136a9dbe36606cb00b546c3562088c462d8a0926 Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Fri, 8 Sep 2023 10:54:30 -0700 Subject: [PATCH 016/435] style: rename some locals --- crates/ide-assists/src/handlers/bool_to_enum.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/ide-assists/src/handlers/bool_to_enum.rs b/crates/ide-assists/src/handlers/bool_to_enum.rs index 56749edf4636..975226484403 100644 --- a/crates/ide-assists/src/handlers/bool_to_enum.rs +++ b/crates/ide-assists/src/handlers/bool_to_enum.rs @@ -200,12 +200,12 @@ fn replace_usages(edit: &mut SourceChangeBuilder, usages: &UsageSearchResult) { cov_mark::hit!(replaces_assignment); replace_bool_expr(edit, initializer); - } else if let Some((prefix_expr, expr)) = find_negated_usage(name_ref) { + } else if let Some((prefix_expr, inner_expr)) = find_negated_usage(name_ref) { cov_mark::hit!(replaces_negation); edit.replace( prefix_expr.syntax().text_range(), - format!("{} == Bool::False", expr), + format!("{} == Bool::False", inner_expr), ); } else if let Some((record_field, initializer)) = find_record_expr_usage(name_ref) { cov_mark::hit!(replaces_record_expr); @@ -235,8 +235,8 @@ fn find_negated_usage(name_ref: &ast::NameRef) -> Option<(ast::PrefixExpr, ast:: let prefix_expr = name_ref.syntax().ancestors().find_map(ast::PrefixExpr::cast)?; if let Some(ast::UnaryOp::Not) = prefix_expr.op_kind() { - let initializer = prefix_expr.expr()?; - Some((prefix_expr, initializer)) + let inner_expr = prefix_expr.expr()?; + Some((prefix_expr, inner_expr)) } else { None } From 2e13aed3bc235d47d92f9ce3b8fd4fa3c5f87939 Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Sat, 9 Sep 2023 11:40:29 -0700 Subject: [PATCH 017/435] feat: support cross module imports --- .../ide-assists/src/handlers/bool_to_enum.rs | 226 +++++++++++++++++- 1 file changed, 214 insertions(+), 12 deletions(-) diff --git a/crates/ide-assists/src/handlers/bool_to_enum.rs b/crates/ide-assists/src/handlers/bool_to_enum.rs index 975226484403..f59b0528131e 100644 --- a/crates/ide-assists/src/handlers/bool_to_enum.rs +++ b/crates/ide-assists/src/handlers/bool_to_enum.rs @@ -1,9 +1,13 @@ +use hir::ModuleDef; use ide_db::{ assists::{AssistId, AssistKind}, defs::Definition, - search::{FileReference, SearchScope, UsageSearchResult}, + helpers::mod_path_to_ast, + imports::insert_use::{insert_use, ImportScope}, + search::{FileReference, UsageSearchResult}, source_change::SourceChangeBuilder, }; +use itertools::Itertools; use syntax::{ ast::{ self, @@ -48,6 +52,7 @@ use crate::assist_context::{AssistContext, Assists}; pub(crate) fn bool_to_enum(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { let BoolNodeData { target_node, name, ty_annotation, initializer, definition } = find_bool_node(ctx)?; + let target_module = ctx.sema.scope(&target_node)?.module(); let target = name.syntax().text_range(); acc.add( @@ -64,13 +69,10 @@ pub(crate) fn bool_to_enum(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option replace_bool_expr(edit, initializer); } - let usages = definition - .usages(&ctx.sema) - .in_scope(&SearchScope::single_file(ctx.file_id())) - .all(); - replace_usages(edit, &usages); + let usages = definition.usages(&ctx.sema).all(); - add_enum_def(edit, ctx, &usages, target_node); + add_enum_def(edit, ctx, &usages, target_node, &target_module); + replace_usages(edit, ctx, &usages, &target_module); }, ) } @@ -186,8 +188,45 @@ fn bool_expr_to_enum_expr(expr: ast::Expr) -> ast::Expr { } /// Replaces all usages of the target identifier, both when read and written to. -fn replace_usages(edit: &mut SourceChangeBuilder, usages: &UsageSearchResult) { - for (_, references) in usages.iter() { +fn replace_usages( + edit: &mut SourceChangeBuilder, + ctx: &AssistContext<'_>, + usages: &UsageSearchResult, + target_module: &hir::Module, +) { + for (file_id, references) in usages.iter() { + edit.edit_file(*file_id); + + // add imports across modules where needed + references + .iter() + .filter_map(|FileReference { name, .. }| { + ctx.sema.scope(name.syntax()).map(|scope| (name, scope.module())) + }) + .unique_by(|name_and_module| name_and_module.1) + .filter(|(_, module)| module != target_module) + .filter_map(|(name, module)| { + let import_scope = ImportScope::find_insert_use_container(name.syntax(), &ctx.sema); + let mod_path = module.find_use_path_prefixed( + ctx.sema.db, + ModuleDef::Module(*target_module), + ctx.config.insert_use.prefix_kind, + ctx.config.prefer_no_std, + ); + import_scope.zip(mod_path) + }) + .for_each(|(import_scope, mod_path)| { + let import_scope = match import_scope { + ImportScope::File(it) => ImportScope::File(edit.make_mut(it)), + ImportScope::Module(it) => ImportScope::Module(edit.make_mut(it)), + ImportScope::Block(it) => ImportScope::Block(edit.make_mut(it)), + }; + let path = + make::path_concat(mod_path_to_ast(&mod_path), make::path_from_text("Bool")); + insert_use(&import_scope, path, &ctx.config.insert_use); + }); + + // replace the usages in expressions references .into_iter() .filter_map(|FileReference { range, name, .. }| match name { @@ -213,7 +252,7 @@ fn replace_usages(edit: &mut SourceChangeBuilder, usages: &UsageSearchResult) { let record_field = edit.make_mut(record_field); let enum_expr = bool_expr_to_enum_expr(initializer); record_field.replace_expr(enum_expr); - } else if name_ref.syntax().ancestors().find_map(ast::Expr::cast).is_some() { + } else if name_ref.syntax().ancestors().find_map(ast::UseTree::cast).is_none() { // for any other usage in an expression, replace it with a check that it is the true variant edit.replace(range, format!("{} == Bool::True", name_ref.text())); } @@ -255,8 +294,15 @@ fn add_enum_def( ctx: &AssistContext<'_>, usages: &UsageSearchResult, target_node: SyntaxNode, + target_module: &hir::Module, ) { - let make_enum_pub = usages.iter().any(|(file_id, _)| file_id != &ctx.file_id()); + let make_enum_pub = usages + .iter() + .flat_map(|(_, refs)| refs) + .filter_map(|FileReference { name, .. }| { + ctx.sema.scope(name.syntax()).map(|scope| scope.module()) + }) + .any(|module| &module != target_module); let enum_def = make_bool_enum(make_enum_pub); let indent = IndentLevel::from_node(&target_node); @@ -649,7 +695,7 @@ fn main() { "#, r#" #[derive(PartialEq, Eq)] -enum $0Bool { True, False } +enum Bool { True, False } struct Foo { bar: Bool, @@ -713,6 +759,162 @@ fn main() { ) } + #[test] + fn const_in_module() { + check_assist( + bool_to_enum, + r#" +fn main() { + if foo::FOO { + println!("foo"); + } +} + +mod foo { + pub const $0FOO: bool = true; +} +"#, + r#" +use foo::Bool; + +fn main() { + if foo::FOO == Bool::True { + println!("foo"); + } +} + +mod foo { + #[derive(PartialEq, Eq)] + pub enum Bool { True, False } + + pub const FOO: Bool = Bool::True; +} +"#, + ) + } + + #[test] + fn const_in_module_with_import() { + check_assist( + bool_to_enum, + r#" +fn main() { + use foo::FOO; + + if FOO { + println!("foo"); + } +} + +mod foo { + pub const $0FOO: bool = true; +} +"#, + r#" +use crate::foo::Bool; + +fn main() { + use foo::FOO; + + if FOO == Bool::True { + println!("foo"); + } +} + +mod foo { + #[derive(PartialEq, Eq)] + pub enum Bool { True, False } + + pub const FOO: Bool = Bool::True; +} +"#, + ) + } + + #[test] + fn const_cross_file() { + check_assist( + bool_to_enum, + r#" +//- /main.rs +mod foo; + +fn main() { + if foo::FOO { + println!("foo"); + } +} + +//- /foo.rs +pub const $0FOO: bool = true; +"#, + r#" +//- /main.rs +use foo::Bool; + +mod foo; + +fn main() { + if foo::FOO == Bool::True { + println!("foo"); + } +} + +//- /foo.rs +#[derive(PartialEq, Eq)] +pub enum Bool { True, False } + +pub const FOO: Bool = Bool::True; +"#, + ) + } + + #[test] + fn const_cross_file_and_module() { + check_assist( + bool_to_enum, + r#" +//- /main.rs +mod foo; + +fn main() { + use foo::bar; + + if bar::BAR { + println!("foo"); + } +} + +//- /foo.rs +pub mod bar { + pub const $0BAR: bool = false; +} +"#, + r#" +//- /main.rs +use crate::foo::bar::Bool; + +mod foo; + +fn main() { + use foo::bar; + + if bar::BAR == Bool::True { + println!("foo"); + } +} + +//- /foo.rs +pub mod bar { + #[derive(PartialEq, Eq)] + pub enum Bool { True, False } + + pub const BAR: Bool = Bool::False; +} +"#, + ) + } + #[test] fn const_non_bool() { cov_mark::check!(not_applicable_non_bool_const); From 7ba2e130b975f62906fff6ea82aacff883a9e528 Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Sat, 9 Sep 2023 23:54:25 -0700 Subject: [PATCH 018/435] fix: add checks for overwriting incorrect ancestor --- .../ide-assists/src/handlers/bool_to_enum.rs | 166 +++++++++++++++++- 1 file changed, 165 insertions(+), 1 deletion(-) diff --git a/crates/ide-assists/src/handlers/bool_to_enum.rs b/crates/ide-assists/src/handlers/bool_to_enum.rs index f59b0528131e..784a0d355997 100644 --- a/crates/ide-assists/src/handlers/bool_to_enum.rs +++ b/crates/ide-assists/src/handlers/bool_to_enum.rs @@ -263,6 +263,11 @@ fn replace_usages( fn find_assignment_usage(name_ref: &ast::NameRef) -> Option { let bin_expr = name_ref.syntax().ancestors().find_map(ast::BinExpr::cast)?; + if !bin_expr.lhs()?.syntax().descendants().contains(name_ref.syntax()) { + cov_mark::hit!(dont_assign_incorrect_ref); + return None; + } + if let Some(ast::BinaryOp::Assignment { op: None }) = bin_expr.op_kind() { bin_expr.rhs() } else { @@ -273,6 +278,11 @@ fn find_assignment_usage(name_ref: &ast::NameRef) -> Option { fn find_negated_usage(name_ref: &ast::NameRef) -> Option<(ast::PrefixExpr, ast::Expr)> { let prefix_expr = name_ref.syntax().ancestors().find_map(ast::PrefixExpr::cast)?; + if !matches!(prefix_expr.expr()?, ast::Expr::PathExpr(_) | ast::Expr::FieldExpr(_)) { + cov_mark::hit!(dont_overwrite_expression_inside_negation); + return None; + } + if let Some(ast::UnaryOp::Not) = prefix_expr.op_kind() { let inner_expr = prefix_expr.expr()?; Some((prefix_expr, inner_expr)) @@ -285,7 +295,12 @@ fn find_record_expr_usage(name_ref: &ast::NameRef) -> Option<(ast::RecordExprFie let record_field = name_ref.syntax().ancestors().find_map(ast::RecordExprField::cast)?; let initializer = record_field.expr()?; - Some((record_field, initializer)) + if record_field.field_name()?.syntax().descendants().contains(name_ref.syntax()) { + Some((record_field, initializer)) + } else { + cov_mark::hit!(dont_overwrite_wrong_record_field); + None + } } /// Adds the definition of the new enum before the target node. @@ -561,6 +576,37 @@ fn main() { ) } + #[test] + fn local_variable_nested_in_negation() { + cov_mark::check!(dont_overwrite_expression_inside_negation); + check_assist( + bool_to_enum, + r#" +fn main() { + if !"foo".chars().any(|c| { + let $0foo = true; + foo + }) { + println!("foo"); + } +} +"#, + r#" +fn main() { + if !"foo".chars().any(|c| { + #[derive(PartialEq, Eq)] + enum Bool { True, False } + + let foo = Bool::True; + foo == Bool::True + }) { + println!("foo"); + } +} +"#, + ) + } + #[test] fn local_variable_non_bool() { cov_mark::check!(not_applicable_non_bool_local); @@ -638,6 +684,42 @@ fn main() { ) } + #[test] + fn field_negated() { + check_assist( + bool_to_enum, + r#" +struct Foo { + $0bar: bool, +} + +fn main() { + let foo = Foo { bar: false }; + + if !foo.bar { + println!("foo"); + } +} +"#, + r#" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +struct Foo { + bar: Bool, +} + +fn main() { + let foo = Foo { bar: Bool::False }; + + if foo.bar == Bool::False { + println!("foo"); + } +} +"#, + ) + } + #[test] fn field_in_mod_properly_indented() { check_assist( @@ -714,6 +796,88 @@ fn main() { ) } + #[test] + fn field_assigned_to_another() { + cov_mark::check!(dont_assign_incorrect_ref); + check_assist( + bool_to_enum, + r#" +struct Foo { + $0foo: bool, +} + +struct Bar { + bar: bool, +} + +fn main() { + let foo = Foo { foo: true }; + let mut bar = Bar { bar: true }; + + bar.bar = foo.foo; +} +"#, + r#" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +struct Foo { + foo: Bool, +} + +struct Bar { + bar: bool, +} + +fn main() { + let foo = Foo { foo: Bool::True }; + let mut bar = Bar { bar: true }; + + bar.bar = foo.foo == Bool::True; +} +"#, + ) + } + + #[test] + fn field_initialized_with_other() { + cov_mark::check!(dont_overwrite_wrong_record_field); + check_assist( + bool_to_enum, + r#" +struct Foo { + $0foo: bool, +} + +struct Bar { + bar: bool, +} + +fn main() { + let foo = Foo { foo: true }; + let bar = Bar { bar: foo.foo }; +} +"#, + r#" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +struct Foo { + foo: Bool, +} + +struct Bar { + bar: bool, +} + +fn main() { + let foo = Foo { foo: Bool::True }; + let bar = Bar { bar: foo.foo == Bool::True }; +} +"#, + ) + } + #[test] fn field_non_bool() { cov_mark::check!(not_applicable_non_bool_field); From 5683df2965f9577ca1307f10af766aeecd6b560e Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Thu, 10 Aug 2023 01:18:05 +0200 Subject: [PATCH 019/435] Deunwrap inline call --- .../ide-assists/src/handlers/inline_call.rs | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/crates/ide-assists/src/handlers/inline_call.rs b/crates/ide-assists/src/handlers/inline_call.rs index ffab58509b18..b7787e4c33a4 100644 --- a/crates/ide-assists/src/handlers/inline_call.rs +++ b/crates/ide-assists/src/handlers/inline_call.rs @@ -116,7 +116,8 @@ pub(crate) fn inline_into_callers(acc: &mut Assists, ctx: &AssistContext<'_>) -> .into_iter() .map(|(call_info, mut_node)| { let replacement = - inline(&ctx.sema, def_file, function, &func_body, ¶ms, &call_info); + inline(&ctx.sema, def_file, function, &func_body, ¶ms, &call_info) + .unwrap(); ted::replace(mut_node, replacement.syntax()); }) .count(); @@ -218,13 +219,12 @@ pub(crate) fn inline_call(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option< } let syntax = call_info.node.syntax().clone(); + let replacement = inline(&ctx.sema, file_id, function, &fn_body, ¶ms, &call_info)?; acc.add( AssistId("inline_call", AssistKind::RefactorInline), label, syntax.text_range(), |builder| { - let replacement = inline(&ctx.sema, file_id, function, &fn_body, ¶ms, &call_info); - builder.replace_ast( match call_info.node { ast::CallableExpr::Call(it) => ast::Expr::CallExpr(it), @@ -305,7 +305,7 @@ fn inline( fn_body: &ast::BlockExpr, params: &[(ast::Pat, Option, hir::Param)], CallInfo { node, arguments, generic_arg_list }: &CallInfo, -) -> ast::Expr { +) -> Option { let mut body = if sema.hir_file_for(fn_body.syntax()).is_macro() { cov_mark::hit!(inline_call_defined_in_macro); if let Some(body) = ast::BlockExpr::cast(insert_ws_into(fn_body.syntax().clone())) { @@ -363,16 +363,17 @@ fn inline( .collect(); if function.self_param(sema.db).is_some() { - let this = || make::name_ref("this").syntax().clone_for_update().first_token().unwrap(); + let this = || make::name_ref("this").syntax().clone_for_update().first_token(); if let Some(self_local) = params[0].2.as_local(sema.db) { - usages_for_locals(self_local) - .filter_map(|FileReference { name, range, .. }| match name { + let usages = usages_for_locals(self_local).filter_map( + |FileReference { name, range, .. }| match name { ast::NameLike::NameRef(_) => Some(body.syntax().covering_element(range)), _ => None, - }) - .for_each(|it| { - ted::replace(it, &this()); - }) + }, + ); + for usage in usages { + ted::replace(usage, &this()?); + } } } @@ -470,7 +471,7 @@ fn inline( } } else if let Some(stmt_list) = body.stmt_list() { ted::insert_all( - ted::Position::after(stmt_list.l_curly_token().unwrap()), + ted::Position::after(stmt_list.l_curly_token()?), let_stmts.into_iter().map(|stmt| stmt.syntax().clone().into()).collect(), ); } @@ -481,7 +482,7 @@ fn inline( }; body.reindent_to(original_indentation); - match body.tail_expr() { + Some(match body.tail_expr() { Some(expr) if !is_async_fn && body.statements().next().is_none() => expr, _ => match node .syntax() @@ -494,7 +495,7 @@ fn inline( } _ => ast::Expr::BlockExpr(body), }, - } + }) } fn path_expr_as_record_field(usage: &PathExpr) -> Option { From 68d24b69d45f357e7309c497f683c8b1e6ad691a Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Sat, 9 Sep 2023 14:35:26 +0200 Subject: [PATCH 020/435] Deunwrap inline call v2 --- .../ide-assists/src/handlers/inline_call.rs | 28 ++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/crates/ide-assists/src/handlers/inline_call.rs b/crates/ide-assists/src/handlers/inline_call.rs index b7787e4c33a4..4751de312559 100644 --- a/crates/ide-assists/src/handlers/inline_call.rs +++ b/crates/ide-assists/src/handlers/inline_call.rs @@ -117,7 +117,7 @@ pub(crate) fn inline_into_callers(acc: &mut Assists, ctx: &AssistContext<'_>) -> .map(|(call_info, mut_node)| { let replacement = inline(&ctx.sema, def_file, function, &func_body, ¶ms, &call_info) - .unwrap(); + .expect("inline() should return an Expr"); ted::replace(mut_node, replacement.syntax()); }) .count(); @@ -363,17 +363,23 @@ fn inline( .collect(); if function.self_param(sema.db).is_some() { - let this = || make::name_ref("this").syntax().clone_for_update().first_token(); + let this = || { + make::name_ref("this") + .syntax() + .clone_for_update() + .first_token() + .expect("NameRef should have had a token.") + }; if let Some(self_local) = params[0].2.as_local(sema.db) { - let usages = usages_for_locals(self_local).filter_map( - |FileReference { name, range, .. }| match name { + usages_for_locals(self_local) + .filter_map(|FileReference { name, range, .. }| match name { ast::NameLike::NameRef(_) => Some(body.syntax().covering_element(range)), _ => None, - }, - ); - for usage in usages { - ted::replace(usage, &this()?); - } + }) + .into_iter() + .for_each(|usage| { + ted::replace(usage, &this()); + }); } } @@ -471,7 +477,9 @@ fn inline( } } else if let Some(stmt_list) = body.stmt_list() { ted::insert_all( - ted::Position::after(stmt_list.l_curly_token()?), + ted::Position::after( + stmt_list.l_curly_token().expect("L_CURLY for StatementList is missing."), + ), let_stmts.into_iter().map(|stmt| stmt.syntax().clone().into()).collect(), ); } From 38491fcf0785a33720ccfd746d2ebe2ad2686207 Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Sun, 10 Sep 2023 22:14:58 +0200 Subject: [PATCH 021/435] v3 --- crates/ide-assists/src/handlers/inline_call.rs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/crates/ide-assists/src/handlers/inline_call.rs b/crates/ide-assists/src/handlers/inline_call.rs index 4751de312559..9b4ac8a02a35 100644 --- a/crates/ide-assists/src/handlers/inline_call.rs +++ b/crates/ide-assists/src/handlers/inline_call.rs @@ -116,8 +116,7 @@ pub(crate) fn inline_into_callers(acc: &mut Assists, ctx: &AssistContext<'_>) -> .into_iter() .map(|(call_info, mut_node)| { let replacement = - inline(&ctx.sema, def_file, function, &func_body, ¶ms, &call_info) - .expect("inline() should return an Expr"); + inline(&ctx.sema, def_file, function, &func_body, ¶ms, &call_info); ted::replace(mut_node, replacement.syntax()); }) .count(); @@ -219,7 +218,7 @@ pub(crate) fn inline_call(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option< } let syntax = call_info.node.syntax().clone(); - let replacement = inline(&ctx.sema, file_id, function, &fn_body, ¶ms, &call_info)?; + let replacement = inline(&ctx.sema, file_id, function, &fn_body, ¶ms, &call_info); acc.add( AssistId("inline_call", AssistKind::RefactorInline), label, @@ -305,7 +304,7 @@ fn inline( fn_body: &ast::BlockExpr, params: &[(ast::Pat, Option, hir::Param)], CallInfo { node, arguments, generic_arg_list }: &CallInfo, -) -> Option { +) -> ast::Expr { let mut body = if sema.hir_file_for(fn_body.syntax()).is_macro() { cov_mark::hit!(inline_call_defined_in_macro); if let Some(body) = ast::BlockExpr::cast(insert_ws_into(fn_body.syntax().clone())) { @@ -376,7 +375,6 @@ fn inline( ast::NameLike::NameRef(_) => Some(body.syntax().covering_element(range)), _ => None, }) - .into_iter() .for_each(|usage| { ted::replace(usage, &this()); }); @@ -490,7 +488,7 @@ fn inline( }; body.reindent_to(original_indentation); - Some(match body.tail_expr() { + match body.tail_expr() { Some(expr) if !is_async_fn && body.statements().next().is_none() => expr, _ => match node .syntax() @@ -503,7 +501,7 @@ fn inline( } _ => ast::Expr::BlockExpr(body), }, - }) + } } fn path_expr_as_record_field(usage: &PathExpr) -> Option { From 9c6257138de5f093b2dd03893aa694b6165ea157 Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Wed, 9 Aug 2023 17:09:57 +0200 Subject: [PATCH 022/435] Deunwrap convert_comment_block --- .../src/handlers/convert_comment_block.rs | 29 +++++++++------- .../src/handlers/desugar_doc_comment.rs | 33 +++++++++++-------- 2 files changed, 36 insertions(+), 26 deletions(-) diff --git a/crates/ide-assists/src/handlers/convert_comment_block.rs b/crates/ide-assists/src/handlers/convert_comment_block.rs index 1acd5ee97283..b6ad2dc0b65d 100644 --- a/crates/ide-assists/src/handlers/convert_comment_block.rs +++ b/crates/ide-assists/src/handlers/convert_comment_block.rs @@ -78,21 +78,26 @@ fn line_to_block(acc: &mut Assists, comment: ast::Comment) -> Option<()> { // Establish the target of our edit based on the comments we found let target = TextRange::new( comments[0].syntax().text_range().start(), - comments.last().unwrap().syntax().text_range().end(), + comments.last()?.syntax().text_range().end(), ); + // We pick a single indentation level for the whole block comment based on the + // comment where the assist was invoked. This will be prepended to the + // contents of each line comment when they're put into the block comment. + let indentation = IndentLevel::from_token(comment.syntax()); + + let mut cms: Vec = Vec::new(); + for cm in comments { + let lcm = line_comment_text(indentation, cm)?; + cms.push(lcm); + } + acc.add( AssistId("line_to_block", AssistKind::RefactorRewrite), "Replace line comments with a single block comment", target, |edit| { - // We pick a single indentation level for the whole block comment based on the - // comment where the assist was invoked. This will be prepended to the - // contents of each line comment when they're put into the block comment. - let indentation = IndentLevel::from_token(comment.syntax()); - - let block_comment_body = - comments.into_iter().map(|c| line_comment_text(indentation, c)).join("\n"); + let block_comment_body = cms.into_iter().join("\n"); let block_prefix = CommentKind { shape: CommentShape::Block, ..comment.kind() }.prefix(); @@ -159,15 +164,15 @@ pub(crate) fn relevant_line_comments(comment: &ast::Comment) -> Vec { // */ // // But since such comments aren't idiomatic we're okay with this. -pub(crate) fn line_comment_text(indentation: IndentLevel, comm: ast::Comment) -> String { - let contents_without_prefix = comm.text().strip_prefix(comm.prefix()).unwrap(); +pub(crate) fn line_comment_text(indentation: IndentLevel, comm: ast::Comment) -> Option { + let contents_without_prefix = comm.text().strip_prefix(comm.prefix())?; let contents = contents_without_prefix.strip_prefix(' ').unwrap_or(contents_without_prefix); // Don't add the indentation if the line is empty if contents.is_empty() { - contents.to_owned() + Some(contents.to_owned()) } else { - indentation.to_string() + contents + Some(indentation.to_string() + contents) } } diff --git a/crates/ide-assists/src/handlers/desugar_doc_comment.rs b/crates/ide-assists/src/handlers/desugar_doc_comment.rs index ddc8a50ed400..daa2c1df0cc4 100644 --- a/crates/ide-assists/src/handlers/desugar_doc_comment.rs +++ b/crates/ide-assists/src/handlers/desugar_doc_comment.rs @@ -57,25 +57,30 @@ pub(crate) fn desugar_doc_comment(acc: &mut Assists, ctx: &AssistContext<'_>) -> } }; + let text = match comments { + Either::Left(comment) => { + let text = comment.text(); + text[comment.prefix().len()..(text.len() - "*/".len())] + .trim() + .lines() + .map(|l| l.strip_prefix(&indentation).unwrap_or(l)) + .join("\n") + } + Either::Right(comments) => { + let mut cms: Vec = Vec::new(); + for cm in comments { + let lcm = line_comment_text(IndentLevel(0), cm)?; + cms.push(lcm); + } + cms.into_iter().join("\n") + } + }; + acc.add( AssistId("desugar_doc_comment", AssistKind::RefactorRewrite), "Desugar doc-comment to attribute macro", target, |edit| { - let text = match comments { - Either::Left(comment) => { - let text = comment.text(); - text[comment.prefix().len()..(text.len() - "*/".len())] - .trim() - .lines() - .map(|l| l.strip_prefix(&indentation).unwrap_or(l)) - .join("\n") - } - Either::Right(comments) => { - comments.into_iter().map(|c| line_comment_text(IndentLevel(0), c)).join("\n") - } - }; - let hashes = "#".repeat(required_hashes(&text)); let prefix = match placement { From b316bccc9716dc058120b4cf73c753973e2cd802 Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Wed, 9 Aug 2023 23:34:30 +0200 Subject: [PATCH 023/435] replace for loops with sth more idiomatic --- .../src/handlers/convert_comment_block.rs | 9 ++++----- .../src/handlers/desugar_doc_comment.rs | 15 ++++++--------- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/crates/ide-assists/src/handlers/convert_comment_block.rs b/crates/ide-assists/src/handlers/convert_comment_block.rs index b6ad2dc0b65d..4cbb30ec15c5 100644 --- a/crates/ide-assists/src/handlers/convert_comment_block.rs +++ b/crates/ide-assists/src/handlers/convert_comment_block.rs @@ -86,11 +86,10 @@ fn line_to_block(acc: &mut Assists, comment: ast::Comment) -> Option<()> { // contents of each line comment when they're put into the block comment. let indentation = IndentLevel::from_token(comment.syntax()); - let mut cms: Vec = Vec::new(); - for cm in comments { - let lcm = line_comment_text(indentation, cm)?; - cms.push(lcm); - } + let cms = comments + .into_iter() + .map(|c| line_comment_text(indentation, c)) + .collect::>>()?; acc.add( AssistId("line_to_block", AssistKind::RefactorRewrite), diff --git a/crates/ide-assists/src/handlers/desugar_doc_comment.rs b/crates/ide-assists/src/handlers/desugar_doc_comment.rs index daa2c1df0cc4..2f8cef1e4a7a 100644 --- a/crates/ide-assists/src/handlers/desugar_doc_comment.rs +++ b/crates/ide-assists/src/handlers/desugar_doc_comment.rs @@ -50,7 +50,7 @@ pub(crate) fn desugar_doc_comment(acc: &mut Assists, ctx: &AssistContext<'_>) -> ( TextRange::new( comments[0].syntax().text_range().start(), - comments.last().unwrap().syntax().text_range().end(), + comments.last()?.syntax().text_range().end(), ), Either::Right(comments), ) @@ -66,14 +66,11 @@ pub(crate) fn desugar_doc_comment(acc: &mut Assists, ctx: &AssistContext<'_>) -> .map(|l| l.strip_prefix(&indentation).unwrap_or(l)) .join("\n") } - Either::Right(comments) => { - let mut cms: Vec = Vec::new(); - for cm in comments { - let lcm = line_comment_text(IndentLevel(0), cm)?; - cms.push(lcm); - } - cms.into_iter().join("\n") - } + Either::Right(comments) => comments + .into_iter() + .map(|cm| line_comment_text(IndentLevel(0), cm)) + .collect::>>()? + .join("\n"), }; acc.add( From a66dbd11ed1501c0efbea265f76bc92147554ab7 Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Tue, 15 Aug 2023 19:29:09 +0200 Subject: [PATCH 024/435] v2 --- crates/ide-assists/src/handlers/convert_comment_block.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/ide-assists/src/handlers/convert_comment_block.rs b/crates/ide-assists/src/handlers/convert_comment_block.rs index 4cbb30ec15c5..a850d28e918f 100644 --- a/crates/ide-assists/src/handlers/convert_comment_block.rs +++ b/crates/ide-assists/src/handlers/convert_comment_block.rs @@ -164,7 +164,8 @@ pub(crate) fn relevant_line_comments(comment: &ast::Comment) -> Vec { // // But since such comments aren't idiomatic we're okay with this. pub(crate) fn line_comment_text(indentation: IndentLevel, comm: ast::Comment) -> Option { - let contents_without_prefix = comm.text().strip_prefix(comm.prefix())?; + let text = comm.text(); + let contents_without_prefix = text.strip_prefix(comm.prefix()).unwrap_or(text); let contents = contents_without_prefix.strip_prefix(' ').unwrap_or(contents_without_prefix); // Don't add the indentation if the line is empty From 2fdf7e4b752c8ac50585879163a3aebccfa82d4f Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Sun, 10 Sep 2023 23:15:37 +0200 Subject: [PATCH 025/435] v3 --- .../src/handlers/convert_comment_block.rs | 16 ++++++---------- .../src/handlers/desugar_doc_comment.rs | 6 ++---- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/crates/ide-assists/src/handlers/convert_comment_block.rs b/crates/ide-assists/src/handlers/convert_comment_block.rs index a850d28e918f..1f048ac10fa5 100644 --- a/crates/ide-assists/src/handlers/convert_comment_block.rs +++ b/crates/ide-assists/src/handlers/convert_comment_block.rs @@ -25,9 +25,7 @@ pub(crate) fn convert_comment_block(acc: &mut Assists, ctx: &AssistContext<'_>) let comment = ctx.find_token_at_offset::()?; // Only allow comments which are alone on their line if let Some(prev) = comment.syntax().prev_token() { - if Whitespace::cast(prev).filter(|w| w.text().contains('\n')).is_none() { - return None; - } + Whitespace::cast(prev).filter(|w| w.text().contains('\n'))?; } match comment.kind().shape { @@ -86,10 +84,8 @@ fn line_to_block(acc: &mut Assists, comment: ast::Comment) -> Option<()> { // contents of each line comment when they're put into the block comment. let indentation = IndentLevel::from_token(comment.syntax()); - let cms = comments - .into_iter() - .map(|c| line_comment_text(indentation, c)) - .collect::>>()?; + let cms = + comments.into_iter().map(|c| line_comment_text(indentation, c)).collect::>(); acc.add( AssistId("line_to_block", AssistKind::RefactorRewrite), @@ -163,16 +159,16 @@ pub(crate) fn relevant_line_comments(comment: &ast::Comment) -> Vec { // */ // // But since such comments aren't idiomatic we're okay with this. -pub(crate) fn line_comment_text(indentation: IndentLevel, comm: ast::Comment) -> Option { +pub(crate) fn line_comment_text(indentation: IndentLevel, comm: ast::Comment) -> String { let text = comm.text(); let contents_without_prefix = text.strip_prefix(comm.prefix()).unwrap_or(text); let contents = contents_without_prefix.strip_prefix(' ').unwrap_or(contents_without_prefix); // Don't add the indentation if the line is empty if contents.is_empty() { - Some(contents.to_owned()) + contents.to_owned() } else { - Some(indentation.to_string() + contents) + indentation.to_string() + contents } } diff --git a/crates/ide-assists/src/handlers/desugar_doc_comment.rs b/crates/ide-assists/src/handlers/desugar_doc_comment.rs index 2f8cef1e4a7a..b7919bd1502c 100644 --- a/crates/ide-assists/src/handlers/desugar_doc_comment.rs +++ b/crates/ide-assists/src/handlers/desugar_doc_comment.rs @@ -33,9 +33,7 @@ pub(crate) fn desugar_doc_comment(acc: &mut Assists, ctx: &AssistContext<'_>) -> // Only allow comments which are alone on their line if let Some(prev) = comment.syntax().prev_token() { - if Whitespace::cast(prev).filter(|w| w.text().contains('\n')).is_none() { - return None; - } + Whitespace::cast(prev).filter(|w| w.text().contains('\n'))?; } let indentation = IndentLevel::from_token(comment.syntax()).to_string(); @@ -69,7 +67,7 @@ pub(crate) fn desugar_doc_comment(acc: &mut Assists, ctx: &AssistContext<'_>) -> Either::Right(comments) => comments .into_iter() .map(|cm| line_comment_text(IndentLevel(0), cm)) - .collect::>>()? + .collect::>() .join("\n"), }; From 25b1b3e753c4cb6fa75b2004c8d753daf240b1c6 Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Sun, 10 Sep 2023 22:21:12 -0700 Subject: [PATCH 026/435] feat: add support for other ADT types and destructuring patterns --- .../ide-assists/src/handlers/bool_to_enum.rs | 492 +++++++++++++++--- 1 file changed, 429 insertions(+), 63 deletions(-) diff --git a/crates/ide-assists/src/handlers/bool_to_enum.rs b/crates/ide-assists/src/handlers/bool_to_enum.rs index 784a0d355997..b9dbd6e98fcb 100644 --- a/crates/ide-assists/src/handlers/bool_to_enum.rs +++ b/crates/ide-assists/src/handlers/bool_to_enum.rs @@ -6,6 +6,7 @@ use ide_db::{ imports::insert_use::{insert_use, ImportScope}, search::{FileReference, UsageSearchResult}, source_change::SourceChangeBuilder, + FxHashSet, }; use itertools::Itertools; use syntax::{ @@ -17,6 +18,7 @@ use syntax::{ }, ted, AstNode, NodeOrToken, SyntaxNode, T, }; +use text_edit::TextRange; use crate::assist_context::{AssistContext, Assists}; @@ -52,7 +54,7 @@ use crate::assist_context::{AssistContext, Assists}; pub(crate) fn bool_to_enum(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { let BoolNodeData { target_node, name, ty_annotation, initializer, definition } = find_bool_node(ctx)?; - let target_module = ctx.sema.scope(&target_node)?.module(); + let target_module = ctx.sema.scope(&target_node)?.module().nearest_non_block_module(ctx.db()); let target = name.syntax().text_range(); acc.add( @@ -70,9 +72,8 @@ pub(crate) fn bool_to_enum(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option } let usages = definition.usages(&ctx.sema).all(); - add_enum_def(edit, ctx, &usages, target_node, &target_module); - replace_usages(edit, ctx, &usages, &target_module); + replace_usages(edit, ctx, &usages, definition, &target_module); }, ) } @@ -144,14 +145,14 @@ fn find_bool_node(ctx: &AssistContext<'_>) -> Option { return None; } - let strukt = field.syntax().ancestors().find_map(ast::Struct::cast)?; + let adt = field.syntax().ancestors().find_map(ast::Adt::cast)?; let def = ctx.sema.to_def(&field)?; if !def.ty(ctx.db()).is_bool() { cov_mark::hit!(not_applicable_non_bool_field); return None; } Some(BoolNodeData { - target_node: strukt.syntax().clone(), + target_node: adt.syntax().clone(), name, ty_annotation: field.ty(), initializer: None, @@ -192,78 +193,171 @@ fn replace_usages( edit: &mut SourceChangeBuilder, ctx: &AssistContext<'_>, usages: &UsageSearchResult, + target_definition: Definition, target_module: &hir::Module, ) { for (file_id, references) in usages.iter() { edit.edit_file(*file_id); - // add imports across modules where needed - references - .iter() - .filter_map(|FileReference { name, .. }| { - ctx.sema.scope(name.syntax()).map(|scope| (name, scope.module())) - }) - .unique_by(|name_and_module| name_and_module.1) - .filter(|(_, module)| module != target_module) - .filter_map(|(name, module)| { - let import_scope = ImportScope::find_insert_use_container(name.syntax(), &ctx.sema); - let mod_path = module.find_use_path_prefixed( - ctx.sema.db, - ModuleDef::Module(*target_module), - ctx.config.insert_use.prefix_kind, - ctx.config.prefer_no_std, - ); - import_scope.zip(mod_path) - }) - .for_each(|(import_scope, mod_path)| { - let import_scope = match import_scope { - ImportScope::File(it) => ImportScope::File(edit.make_mut(it)), - ImportScope::Module(it) => ImportScope::Module(edit.make_mut(it)), - ImportScope::Block(it) => ImportScope::Block(edit.make_mut(it)), - }; - let path = - make::path_concat(mod_path_to_ast(&mod_path), make::path_from_text("Bool")); - insert_use(&import_scope, path, &ctx.config.insert_use); - }); + let refs_with_imports = + augment_references_with_imports(edit, ctx, references, target_module); - // replace the usages in expressions - references - .into_iter() - .filter_map(|FileReference { range, name, .. }| match name { - ast::NameLike::NameRef(name) => Some((*range, name)), - _ => None, - }) - .rev() - .for_each(|(range, name_ref)| { - if let Some(initializer) = find_assignment_usage(name_ref) { + refs_with_imports.into_iter().rev().for_each( + |FileReferenceWithImport { range, old_name, new_name, import_data }| { + // replace the usages in patterns and expressions + if let Some(ident_pat) = old_name.syntax().ancestors().find_map(ast::IdentPat::cast) + { + cov_mark::hit!(replaces_record_pat_shorthand); + + let definition = ctx.sema.to_def(&ident_pat).map(Definition::Local); + if let Some(def) = definition { + replace_usages( + edit, + ctx, + &def.usages(&ctx.sema).all(), + target_definition, + target_module, + ) + } + } else if let Some(initializer) = find_assignment_usage(&new_name) { cov_mark::hit!(replaces_assignment); replace_bool_expr(edit, initializer); - } else if let Some((prefix_expr, inner_expr)) = find_negated_usage(name_ref) { + } else if let Some((prefix_expr, inner_expr)) = find_negated_usage(&new_name) { cov_mark::hit!(replaces_negation); edit.replace( prefix_expr.syntax().text_range(), format!("{} == Bool::False", inner_expr), ); - } else if let Some((record_field, initializer)) = find_record_expr_usage(name_ref) { + } else if let Some((record_field, initializer)) = old_name + .as_name_ref() + .and_then(ast::RecordExprField::for_field_name) + .and_then(|record_field| ctx.sema.resolve_record_field(&record_field)) + .and_then(|(got_field, _, _)| { + find_record_expr_usage(&new_name, got_field, target_definition) + }) + { cov_mark::hit!(replaces_record_expr); let record_field = edit.make_mut(record_field); let enum_expr = bool_expr_to_enum_expr(initializer); record_field.replace_expr(enum_expr); - } else if name_ref.syntax().ancestors().find_map(ast::UseTree::cast).is_none() { + } else if let Some(pat) = find_record_pat_field_usage(&old_name) { + match pat { + ast::Pat::IdentPat(ident_pat) => { + cov_mark::hit!(replaces_record_pat); + + let definition = ctx.sema.to_def(&ident_pat).map(Definition::Local); + if let Some(def) = definition { + replace_usages( + edit, + ctx, + &def.usages(&ctx.sema).all(), + target_definition, + target_module, + ) + } + } + ast::Pat::LiteralPat(literal_pat) => { + cov_mark::hit!(replaces_literal_pat); + + if let Some(expr) = literal_pat.literal().and_then(|literal| { + literal.syntax().ancestors().find_map(ast::Expr::cast) + }) { + replace_bool_expr(edit, expr); + } + } + _ => (), + } + } else if new_name.syntax().ancestors().find_map(ast::UseTree::cast).is_none() { // for any other usage in an expression, replace it with a check that it is the true variant - edit.replace(range, format!("{} == Bool::True", name_ref.text())); + if let Some((record_field, expr)) = new_name + .as_name_ref() + .and_then(ast::RecordExprField::for_field_name) + .and_then(|record_field| { + record_field.expr().map(|expr| (record_field, expr)) + }) + { + record_field.replace_expr( + make::expr_bin_op( + expr, + ast::BinaryOp::CmpOp(ast::CmpOp::Eq { negated: false }), + make::expr_path(make::path_from_text("Bool::True")), + ) + .clone_for_update(), + ); + } else { + edit.replace(range, format!("{} == Bool::True", new_name.text())); + } } - }) + + // add imports across modules where needed + if let Some((import_scope, path)) = import_data { + insert_use(&import_scope, path, &ctx.config.insert_use); + } + }, + ) } } -fn find_assignment_usage(name_ref: &ast::NameRef) -> Option { - let bin_expr = name_ref.syntax().ancestors().find_map(ast::BinExpr::cast)?; +struct FileReferenceWithImport { + range: TextRange, + old_name: ast::NameLike, + new_name: ast::NameLike, + import_data: Option<(ImportScope, ast::Path)>, +} - if !bin_expr.lhs()?.syntax().descendants().contains(name_ref.syntax()) { +fn augment_references_with_imports( + edit: &mut SourceChangeBuilder, + ctx: &AssistContext<'_>, + references: &[FileReference], + target_module: &hir::Module, +) -> Vec { + let mut visited_modules = FxHashSet::default(); + + references + .iter() + .filter_map(|FileReference { range, name, .. }| { + ctx.sema.scope(name.syntax()).map(|scope| (*range, name, scope.module())) + }) + .map(|(range, name, ref_module)| { + let old_name = name.clone(); + let new_name = edit.make_mut(name.clone()); + + // if the referenced module is not the same as the target one and has not been seen before, add an import + let import_data = if ref_module.nearest_non_block_module(ctx.db()) != *target_module + && !visited_modules.contains(&ref_module) + { + visited_modules.insert(ref_module); + + let import_scope = + ImportScope::find_insert_use_container(new_name.syntax(), &ctx.sema); + let path = ref_module + .find_use_path_prefixed( + ctx.sema.db, + ModuleDef::Module(*target_module), + ctx.config.insert_use.prefix_kind, + ctx.config.prefer_no_std, + ) + .map(|mod_path| { + make::path_concat(mod_path_to_ast(&mod_path), make::path_from_text("Bool")) + }); + + import_scope.zip(path) + } else { + None + }; + + FileReferenceWithImport { range, old_name, new_name, import_data } + }) + .collect() +} + +fn find_assignment_usage(name: &ast::NameLike) -> Option { + let bin_expr = name.syntax().ancestors().find_map(ast::BinExpr::cast)?; + + if !bin_expr.lhs()?.syntax().descendants().contains(name.syntax()) { cov_mark::hit!(dont_assign_incorrect_ref); return None; } @@ -275,8 +369,8 @@ fn find_assignment_usage(name_ref: &ast::NameRef) -> Option { } } -fn find_negated_usage(name_ref: &ast::NameRef) -> Option<(ast::PrefixExpr, ast::Expr)> { - let prefix_expr = name_ref.syntax().ancestors().find_map(ast::PrefixExpr::cast)?; +fn find_negated_usage(name: &ast::NameLike) -> Option<(ast::PrefixExpr, ast::Expr)> { + let prefix_expr = name.syntax().ancestors().find_map(ast::PrefixExpr::cast)?; if !matches!(prefix_expr.expr()?, ast::Expr::PathExpr(_) | ast::Expr::FieldExpr(_)) { cov_mark::hit!(dont_overwrite_expression_inside_negation); @@ -291,15 +385,31 @@ fn find_negated_usage(name_ref: &ast::NameRef) -> Option<(ast::PrefixExpr, ast:: } } -fn find_record_expr_usage(name_ref: &ast::NameRef) -> Option<(ast::RecordExprField, ast::Expr)> { - let record_field = name_ref.syntax().ancestors().find_map(ast::RecordExprField::cast)?; +fn find_record_expr_usage( + name: &ast::NameLike, + got_field: hir::Field, + target_definition: Definition, +) -> Option<(ast::RecordExprField, ast::Expr)> { + let name_ref = name.as_name_ref()?; + let record_field = ast::RecordExprField::for_field_name(name_ref)?; let initializer = record_field.expr()?; - if record_field.field_name()?.syntax().descendants().contains(name_ref.syntax()) { - Some((record_field, initializer)) - } else { - cov_mark::hit!(dont_overwrite_wrong_record_field); - None + if let Definition::Field(expected_field) = target_definition { + if got_field != expected_field { + return None; + } + } + + Some((record_field, initializer)) +} + +fn find_record_pat_field_usage(name: &ast::NameLike) -> Option { + let record_pat_field = name.syntax().parent().and_then(ast::RecordPatField::cast)?; + let pat = record_pat_field.pat()?; + + match pat { + ast::Pat::IdentPat(_) | ast::Pat::LiteralPat(_) | ast::Pat::WildcardPat(_) => Some(pat), + _ => None, } } @@ -317,7 +427,7 @@ fn add_enum_def( .filter_map(|FileReference { name, .. }| { ctx.sema.scope(name.syntax()).map(|scope| scope.module()) }) - .any(|module| &module != target_module); + .any(|module| module.nearest_non_block_module(ctx.db()) != *target_module); let enum_def = make_bool_enum(make_enum_pub); let indent = IndentLevel::from_node(&target_node); @@ -646,7 +756,7 @@ fn main() { } #[test] - fn field_basic() { + fn field_struct_basic() { cov_mark::check!(replaces_record_expr); check_assist( bool_to_enum, @@ -684,6 +794,263 @@ fn main() { ) } + #[test] + fn field_enum_basic() { + cov_mark::check!(replaces_record_pat); + check_assist( + bool_to_enum, + r#" +enum Foo { + Foo, + Bar { $0bar: bool }, +} + +fn main() { + let foo = Foo::Bar { bar: true }; + + if let Foo::Bar { bar: baz } = foo { + if baz { + println!("foo"); + } + } +} +"#, + r#" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +enum Foo { + Foo, + Bar { bar: Bool }, +} + +fn main() { + let foo = Foo::Bar { bar: Bool::True }; + + if let Foo::Bar { bar: baz } = foo { + if baz == Bool::True { + println!("foo"); + } + } +} +"#, + ) + } + + #[test] + fn field_enum_cross_file() { + check_assist( + bool_to_enum, + r#" +//- /foo.rs +pub enum Foo { + Foo, + Bar { $0bar: bool }, +} + +fn foo() { + let foo = Foo::Bar { bar: true }; +} + +//- /main.rs +use foo::Foo; + +mod foo; + +fn main() { + let foo = Foo::Bar { bar: false }; +} +"#, + r#" +//- /foo.rs +#[derive(PartialEq, Eq)] +pub enum Bool { True, False } + +pub enum Foo { + Foo, + Bar { bar: Bool }, +} + +fn foo() { + let foo = Foo::Bar { bar: Bool::True }; +} + +//- /main.rs +use foo::{Foo, Bool}; + +mod foo; + +fn main() { + let foo = Foo::Bar { bar: Bool::False }; +} +"#, + ) + } + + #[test] + fn field_enum_shorthand() { + cov_mark::check!(replaces_record_pat_shorthand); + check_assist( + bool_to_enum, + r#" +enum Foo { + Foo, + Bar { $0bar: bool }, +} + +fn main() { + let foo = Foo::Bar { bar: true }; + + match foo { + Foo::Bar { bar } => { + if bar { + println!("foo"); + } + } + _ => (), + } +} +"#, + r#" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +enum Foo { + Foo, + Bar { bar: Bool }, +} + +fn main() { + let foo = Foo::Bar { bar: Bool::True }; + + match foo { + Foo::Bar { bar } => { + if bar == Bool::True { + println!("foo"); + } + } + _ => (), + } +} +"#, + ) + } + + #[test] + fn field_enum_replaces_literal_patterns() { + cov_mark::check!(replaces_literal_pat); + check_assist( + bool_to_enum, + r#" +enum Foo { + Foo, + Bar { $0bar: bool }, +} + +fn main() { + let foo = Foo::Bar { bar: true }; + + if let Foo::Bar { bar: true } = foo { + println!("foo"); + } +} +"#, + r#" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +enum Foo { + Foo, + Bar { bar: Bool }, +} + +fn main() { + let foo = Foo::Bar { bar: Bool::True }; + + if let Foo::Bar { bar: Bool::True } = foo { + println!("foo"); + } +} +"#, + ) + } + + #[test] + fn field_enum_keeps_wildcard_patterns() { + check_assist( + bool_to_enum, + r#" +enum Foo { + Foo, + Bar { $0bar: bool }, +} + +fn main() { + let foo = Foo::Bar { bar: true }; + + if let Foo::Bar { bar: _ } = foo { + println!("foo"); + } +} +"#, + r#" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +enum Foo { + Foo, + Bar { bar: Bool }, +} + +fn main() { + let foo = Foo::Bar { bar: Bool::True }; + + if let Foo::Bar { bar: _ } = foo { + println!("foo"); + } +} +"#, + ) + } + + #[test] + fn field_union_basic() { + check_assist( + bool_to_enum, + r#" +union Foo { + $0foo: bool, + bar: usize, +} + +fn main() { + let foo = Foo { foo: true }; + + if unsafe { foo.foo } { + println!("foo"); + } +} +"#, + r#" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +union Foo { + foo: Bool, + bar: usize, +} + +fn main() { + let foo = Foo { foo: Bool::True }; + + if unsafe { foo.foo == Bool::True } { + println!("foo"); + } +} +"#, + ) + } + #[test] fn field_negated() { check_assist( @@ -841,7 +1208,6 @@ fn main() { #[test] fn field_initialized_with_other() { - cov_mark::check!(dont_overwrite_wrong_record_field); check_assist( bool_to_enum, r#" From 0863024b1a03b61dbdff518eca52e550efe67b8f Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Mon, 11 Sep 2023 13:31:42 +0200 Subject: [PATCH 027/435] Make assist lazy again --- .../src/handlers/convert_comment_block.rs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/crates/ide-assists/src/handlers/convert_comment_block.rs b/crates/ide-assists/src/handlers/convert_comment_block.rs index 1f048ac10fa5..ef914cdb2cdf 100644 --- a/crates/ide-assists/src/handlers/convert_comment_block.rs +++ b/crates/ide-assists/src/handlers/convert_comment_block.rs @@ -79,19 +79,21 @@ fn line_to_block(acc: &mut Assists, comment: ast::Comment) -> Option<()> { comments.last()?.syntax().text_range().end(), ); - // We pick a single indentation level for the whole block comment based on the - // comment where the assist was invoked. This will be prepended to the - // contents of each line comment when they're put into the block comment. - let indentation = IndentLevel::from_token(comment.syntax()); - - let cms = - comments.into_iter().map(|c| line_comment_text(indentation, c)).collect::>(); - acc.add( AssistId("line_to_block", AssistKind::RefactorRewrite), "Replace line comments with a single block comment", target, |edit| { + // We pick a single indentation level for the whole block comment based on the + // comment where the assist was invoked. This will be prepended to the + // contents of each line comment when they're put into the block comment. + let indentation = IndentLevel::from_token(comment.syntax()); + + let cms = comments + .into_iter() + .map(|c| line_comment_text(indentation, c)) + .collect::>(); + let block_comment_body = cms.into_iter().join("\n"); let block_prefix = From 893e19137e85e0fa11187a100b7fc716f7a99c76 Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Mon, 11 Sep 2023 13:33:26 +0200 Subject: [PATCH 028/435] Make assist lazy again --- crates/ide-assists/src/handlers/inline_call.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/ide-assists/src/handlers/inline_call.rs b/crates/ide-assists/src/handlers/inline_call.rs index 9b4ac8a02a35..3c5a0be775e2 100644 --- a/crates/ide-assists/src/handlers/inline_call.rs +++ b/crates/ide-assists/src/handlers/inline_call.rs @@ -218,12 +218,12 @@ pub(crate) fn inline_call(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option< } let syntax = call_info.node.syntax().clone(); - let replacement = inline(&ctx.sema, file_id, function, &fn_body, ¶ms, &call_info); acc.add( AssistId("inline_call", AssistKind::RefactorInline), label, syntax.text_range(), |builder| { + let replacement = inline(&ctx.sema, file_id, function, &fn_body, ¶ms, &call_info); builder.replace_ast( match call_info.node { ast::CallableExpr::Call(it) => ast::Expr::CallExpr(it), From 145a101fe86f570f4a7b236c8a4818f4ce7873c8 Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Mon, 11 Sep 2023 14:09:19 +0200 Subject: [PATCH 029/435] Deunwrap add_missing_match_arms --- .../src/handlers/add_missing_match_arms.rs | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/crates/ide-assists/src/handlers/add_missing_match_arms.rs b/crates/ide-assists/src/handlers/add_missing_match_arms.rs index 3b162d7c4d82..5376ece2f584 100644 --- a/crates/ide-assists/src/handlers/add_missing_match_arms.rs +++ b/crates/ide-assists/src/handlers/add_missing_match_arms.rs @@ -273,9 +273,10 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>) syntax::SyntaxElement::Token(it) => { // Don't have a way to make tokens mut, so instead make the parent mut // and find the token again - let parent = edit.make_syntax_mut(it.parent().unwrap()); + let parent = + edit.make_syntax_mut(it.parent().expect("Token must have a parent.")); let mut_token = - parent.covering_element(it.text_range()).into_token().unwrap(); + parent.covering_element(it.text_range()).into_token().expect("Covering element cannot be found. Range may be beyond the current node's range"); syntax::SyntaxElement::from(mut_token) } @@ -446,21 +447,23 @@ fn build_pat( mod_path_to_ast(&module.find_use_path(db, ModuleDef::from(var), prefer_no_std)?); // FIXME: use HIR for this; it doesn't currently expose struct vs. tuple vs. unit variants though - let pat: ast::Pat = match var.source(db)?.value.kind() { + Some(match var.source(db)?.value.kind() { ast::StructKind::Tuple(field_list) => { let pats = iter::repeat(make::wildcard_pat().into()).take(field_list.fields().count()); make::tuple_struct_pat(path, pats).into() } ast::StructKind::Record(field_list) => { - let pats = field_list - .fields() - .map(|f| make::ext::simple_ident_pat(f.name().unwrap()).into()); + let pats = field_list.fields().map(|f| { + make::ext::simple_ident_pat( + f.name().expect("Record field must have a name"), + ) + .into() + }); make::record_pat(path, pats).into() } ast::StructKind::Unit => make::path_pat(path), - }; - Some(pat) + }) } ExtendedVariant::True => Some(ast::Pat::from(make::literal_pat("true"))), ExtendedVariant::False => Some(ast::Pat::from(make::literal_pat("false"))), From d79486529e5f39216f202971c076997486a0b1c5 Mon Sep 17 00:00:00 2001 From: dfireBird Date: Sat, 22 Jul 2023 19:51:34 +0530 Subject: [PATCH 030/435] remove `as _` on auto importing on trait that is aliased with `_` --- crates/ide-db/src/imports/merge_imports.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/crates/ide-db/src/imports/merge_imports.rs b/crates/ide-db/src/imports/merge_imports.rs index 27b6321f3a7a..ff84e9ffaeec 100644 --- a/crates/ide-db/src/imports/merge_imports.rs +++ b/crates/ide-db/src/imports/merge_imports.rs @@ -78,6 +78,10 @@ fn try_merge_trees_mut(lhs: &ast::UseTree, rhs: &ast::UseTree, merge: MergeBehav { lhs.split_prefix(&lhs_prefix); rhs.split_prefix(&rhs_prefix); + } else { + ted::replace(lhs.syntax(), rhs.syntax()); + // we can safely return here, in this case `recursive_merge` doesn't do anything + return Some(()); } recursive_merge(lhs, rhs, merge) } @@ -123,6 +127,13 @@ fn recursive_merge(lhs: &ast::UseTree, rhs: &ast::UseTree, merge: MergeBehavior) // so they need to be handled explicitly .or_else(|| tree.star_token().map(|_| false)) }; + + if lhs_t.rename().and_then(|x| x.underscore_token()).is_some() { + ted::replace(lhs_t.syntax(), rhs_t.syntax()); + *lhs_t = rhs_t; + continue; + } + match (tree_contains_self(lhs_t), tree_contains_self(&rhs_t)) { (Some(true), None) => continue, (None, Some(true)) => { From df1239bf9246423f1006e4affb38ee504ef3dc79 Mon Sep 17 00:00:00 2001 From: dfireBird Date: Mon, 11 Sep 2023 17:36:09 +0530 Subject: [PATCH 031/435] add tests for insert use with renamed imports Tested for two cases: 1. Simple Use 2. Complex Use --- crates/ide-db/src/imports/insert_use/tests.rs | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/crates/ide-db/src/imports/insert_use/tests.rs b/crates/ide-db/src/imports/insert_use/tests.rs index b92e367f7e12..01d2f1970c38 100644 --- a/crates/ide-db/src/imports/insert_use/tests.rs +++ b/crates/ide-db/src/imports/insert_use/tests.rs @@ -993,6 +993,46 @@ use foo::bar::qux; ); } +#[test] +fn insert_with_renamed_import_simple_use() { + check_with_config( + "use self::foo::Foo", + r#" +use self::foo::Foo as _; +"#, + r#" +use self::foo::Foo; +"#, + &InsertUseConfig { + granularity: ImportGranularity::Crate, + prefix_kind: hir::PrefixKind::BySelf, + enforce_granularity: true, + group: true, + skip_glob_imports: true, + }, + ); +} + +#[test] +fn insert_with_renamed_import_complex_use() { + check_with_config( + "use self::foo::Foo;", + r#" +use self::foo::{self, Foo as _, Bar}; +"#, + r#" +use self::foo::{self, Foo, Bar}; +"#, + &InsertUseConfig { + granularity: ImportGranularity::Crate, + prefix_kind: hir::PrefixKind::BySelf, + enforce_granularity: true, + group: true, + skip_glob_imports: true, + }, + ); +} + fn check_with_config( path: &str, ra_fixture_before: &str, From 2974416a81a64d75e0dc1c394b75fecd96230713 Mon Sep 17 00:00:00 2001 From: David Barsky Date: Tue, 12 Sep 2023 14:35:24 -0400 Subject: [PATCH 032/435] fix: ensure `rustfmt` runs when configured with `./` --- crates/rust-analyzer/src/handlers/request.rs | 41 +++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/crates/rust-analyzer/src/handlers/request.rs b/crates/rust-analyzer/src/handlers/request.rs index b8a1a39be193..ad6319586cfe 100644 --- a/crates/rust-analyzer/src/handlers/request.rs +++ b/crates/rust-analyzer/src/handlers/request.rs @@ -4,6 +4,7 @@ use std::{ fs, io::Write as _, + path::PathBuf, process::{self, Stdio}, }; @@ -1995,7 +1996,43 @@ fn run_rustfmt( cmd } RustfmtConfig::CustomCommand { command, args } => { - let mut cmd = process::Command::new(command); + let cmd = PathBuf::from(&command); + let mut components = cmd.components(); + + // to support rustc's suggested, default configuration + let mut cmd = match components.next() { + Some(std::path::Component::CurDir) => { + let rest = components.as_path(); + + let roots = snap + .workspaces + .iter() + .flat_map(|ws| ws.workspace_definition_path()) + .collect::>(); + + let abs: Option = roots.into_iter().find_map(|base| { + let abs = base.join(rest); + std::fs::metadata(&abs).ok().map(|_| abs) + }); + + let command = match abs { + Some(cmd) => cmd, + None => { + tracing::error!( + rustfmt = ?command, + "Unable to make the format command an absolute path" + ); + anyhow::bail!( + "Unable to make the format command an absolute path: {}", + command + ); + } + }; + + process::Command::new(&command.as_os_str()) + } + _ => process::Command::new(command), + }; cmd.envs(snap.config.extra_env()); cmd.args(args); @@ -2003,6 +2040,8 @@ fn run_rustfmt( } }; + tracing::debug!(?command, "created format command"); + // try to chdir to the file so we can respect `rustfmt.toml` // FIXME: use `rustfmt --config-path` once // https://github.com/rust-lang/rustfmt/issues/4660 gets fixed From ebbbaaa90f4dd111b1bb9df7250925f612110925 Mon Sep 17 00:00:00 2001 From: shogo-nakano-desu <61229807+shogo-nakano-desu@users.noreply.github.com> Date: Fri, 15 Sep 2023 16:43:21 +0900 Subject: [PATCH 033/435] refactor: fix clippy lints --- crates/intern/src/lib.rs | 14 +++------- crates/parser/src/shortcuts.rs | 36 ++++++++++++-------------- crates/syntax/src/ast/edit_in_place.rs | 14 +++++++--- crates/syntax/src/lib.rs | 36 ++++++++++++-------------- crates/syntax/src/tests.rs | 4 +-- 5 files changed, 50 insertions(+), 54 deletions(-) diff --git a/crates/intern/src/lib.rs b/crates/intern/src/lib.rs index 2934d26674d7..d784321c7c7a 100644 --- a/crates/intern/src/lib.rs +++ b/crates/intern/src/lib.rs @@ -33,13 +33,10 @@ impl Interned { // - if not, box it up, insert it, and return a clone // This needs to be atomic (locking the shard) to avoid races with other thread, which could // insert the same object between us looking it up and inserting it. - match shard.raw_entry_mut().from_key_hashed_nocheck(hash as u64, &obj) { + match shard.raw_entry_mut().from_key_hashed_nocheck(hash, &obj) { RawEntryMut::Occupied(occ) => Self { arc: occ.key().clone() }, RawEntryMut::Vacant(vac) => Self { - arc: vac - .insert_hashed_nocheck(hash as u64, Arc::new(obj), SharedValue::new(())) - .0 - .clone(), + arc: vac.insert_hashed_nocheck(hash, Arc::new(obj), SharedValue::new(())).0.clone(), }, } } @@ -54,13 +51,10 @@ impl Interned { // - if not, box it up, insert it, and return a clone // This needs to be atomic (locking the shard) to avoid races with other thread, which could // insert the same object between us looking it up and inserting it. - match shard.raw_entry_mut().from_key_hashed_nocheck(hash as u64, s) { + match shard.raw_entry_mut().from_key_hashed_nocheck(hash, s) { RawEntryMut::Occupied(occ) => Self { arc: occ.key().clone() }, RawEntryMut::Vacant(vac) => Self { - arc: vac - .insert_hashed_nocheck(hash as u64, Arc::from(s), SharedValue::new(())) - .0 - .clone(), + arc: vac.insert_hashed_nocheck(hash, Arc::from(s), SharedValue::new(())).0.clone(), }, } } diff --git a/crates/parser/src/shortcuts.rs b/crates/parser/src/shortcuts.rs index 2c47e3d086d6..57005a6834c9 100644 --- a/crates/parser/src/shortcuts.rs +++ b/crates/parser/src/shortcuts.rs @@ -32,29 +32,27 @@ impl LexedStr<'_> { let kind = self.kind(i); if kind.is_trivia() { was_joint = false + } else if kind == SyntaxKind::IDENT { + let token_text = self.text(i); + let contextual_kw = + SyntaxKind::from_contextual_keyword(token_text).unwrap_or(SyntaxKind::IDENT); + res.push_ident(contextual_kw); } else { - if kind == SyntaxKind::IDENT { - let token_text = self.text(i); - let contextual_kw = SyntaxKind::from_contextual_keyword(token_text) - .unwrap_or(SyntaxKind::IDENT); - res.push_ident(contextual_kw); - } else { - if was_joint { + if was_joint { + res.was_joint(); + } + res.push(kind); + // Tag the token as joint if it is float with a fractional part + // we use this jointness to inform the parser about what token split + // event to emit when we encounter a float literal in a field access + if kind == SyntaxKind::FLOAT_NUMBER { + if !self.text(i).ends_with('.') { res.was_joint(); - } - res.push(kind); - // Tag the token as joint if it is float with a fractional part - // we use this jointness to inform the parser about what token split - // event to emit when we encounter a float literal in a field access - if kind == SyntaxKind::FLOAT_NUMBER { - if !self.text(i).ends_with('.') { - res.was_joint(); - } else { - was_joint = false; - } } else { - was_joint = true; + was_joint = false; } + } else { + was_joint = true; } } } diff --git a/crates/syntax/src/ast/edit_in_place.rs b/crates/syntax/src/ast/edit_in_place.rs index a150d9e6c07d..a85e1d1d9d0e 100644 --- a/crates/syntax/src/ast/edit_in_place.rs +++ b/crates/syntax/src/ast/edit_in_place.rs @@ -224,7 +224,7 @@ pub trait AttrsOwnerEdit: ast::HasAttrs { let after_attrs_and_comments = node .children_with_tokens() .find(|it| !matches!(it.kind(), WHITESPACE | COMMENT | ATTR)) - .map_or(Position::first_child_of(node), |it| Position::before(it)); + .map_or(Position::first_child_of(node), Position::before); ted::insert_all( after_attrs_and_comments, @@ -433,7 +433,9 @@ impl ast::UseTree { if &path == prefix && self.use_tree_list().is_none() { if self.star_token().is_some() { // path$0::* -> * - self.coloncolon_token().map(ted::remove); + if let Some(a) = self.coloncolon_token() { + ted::remove(a) + } ted::remove(prefix.syntax()); } else { // path$0 -> self @@ -460,7 +462,9 @@ impl ast::UseTree { for p in successors(parent.parent_path(), |it| it.parent_path()) { p.segment()?; } - prefix.parent_path().and_then(|p| p.coloncolon_token()).map(ted::remove); + if let Some(a) = prefix.parent_path().and_then(|p| p.coloncolon_token()) { + ted::remove(a) + } ted::remove(prefix.syntax()); Some(()) } @@ -976,7 +980,9 @@ enum Foo { fn check_add_variant(before: &str, expected: &str, variant: ast::Variant) { let enum_ = ast_mut_from_text::(before); - enum_.variant_list().map(|it| it.add_variant(variant)); + if let Some(it) = enum_.variant_list() { + it.add_variant(variant) + } let after = enum_.to_string(); assert_eq_text!(&trim_indent(expected.trim()), &trim_indent(after.trim())); } diff --git a/crates/syntax/src/lib.rs b/crates/syntax/src/lib.rs index 27c8a13e58d6..73eff358462a 100644 --- a/crates/syntax/src/lib.rs +++ b/crates/syntax/src/lib.rs @@ -181,29 +181,27 @@ impl ast::TokenTree { let kind = t.kind(); if kind.is_trivia() { was_joint = false + } else if kind == SyntaxKind::IDENT { + let token_text = t.text(); + let contextual_kw = + SyntaxKind::from_contextual_keyword(token_text).unwrap_or(SyntaxKind::IDENT); + parser_input.push_ident(contextual_kw); } else { - if kind == SyntaxKind::IDENT { - let token_text = t.text(); - let contextual_kw = SyntaxKind::from_contextual_keyword(token_text) - .unwrap_or(SyntaxKind::IDENT); - parser_input.push_ident(contextual_kw); - } else { - if was_joint { + if was_joint { + parser_input.was_joint(); + } + parser_input.push(kind); + // Tag the token as joint if it is float with a fractional part + // we use this jointness to inform the parser about what token split + // event to emit when we encounter a float literal in a field access + if kind == SyntaxKind::FLOAT_NUMBER { + if !t.text().ends_with('.') { parser_input.was_joint(); - } - parser_input.push(kind); - // Tag the token as joint if it is float with a fractional part - // we use this jointness to inform the parser about what token split - // event to emit when we encounter a float literal in a field access - if kind == SyntaxKind::FLOAT_NUMBER { - if !t.text().ends_with('.') { - parser_input.was_joint(); - } else { - was_joint = false; - } } else { - was_joint = true; + was_joint = false; } + } else { + was_joint = true; } } } diff --git a/crates/syntax/src/tests.rs b/crates/syntax/src/tests.rs index 168439053c27..3010d77d827e 100644 --- a/crates/syntax/src/tests.rs +++ b/crates/syntax/src/tests.rs @@ -17,11 +17,11 @@ use crate::{ast, fuzz, AstNode, SourceFile, SyntaxError}; #[test] fn parse_smoke_test() { - let code = r##" + let code = r#" fn main() { println!("Hello, world!") } - "##; + "#; let parse = SourceFile::parse(code); // eprintln!("{:#?}", parse.syntax_node()); From 0bb2298ac604e0654652418e63a9eb15a82f155c Mon Sep 17 00:00:00 2001 From: shogo-nakano-desu <61229807+shogo-nakano-desu@users.noreply.github.com> Date: Fri, 15 Sep 2023 16:43:31 +0900 Subject: [PATCH 034/435] refactor: remove TODO with no explanation --- crates/syntax/src/ast/make.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/syntax/src/ast/make.rs b/crates/syntax/src/ast/make.rs index 17e311c0c502..20cd6abb5a81 100644 --- a/crates/syntax/src/ast/make.rs +++ b/crates/syntax/src/ast/make.rs @@ -433,7 +433,6 @@ pub fn record_field( ast_from_text(&format!("struct S {{ {visibility}{name}: {ty}, }}")) } -// TODO pub fn block_expr( stmts: impl IntoIterator, tail_expr: Option, From 96c333262a51d98a11fb0fed949e5ef55e40cd87 Mon Sep 17 00:00:00 2001 From: shogo-nakano-desu <61229807+shogo-nakano-desu@users.noreply.github.com> Date: Fri, 15 Sep 2023 16:47:39 +0900 Subject: [PATCH 035/435] refactor: fix clippy lint --- crates/flycheck/src/lib.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/crates/flycheck/src/lib.rs b/crates/flycheck/src/lib.rs index 2de719af92ce..61433313921a 100644 --- a/crates/flycheck/src/lib.rs +++ b/crates/flycheck/src/lib.rs @@ -488,7 +488,9 @@ impl CargoActor { // Skip certain kinds of messages to only spend time on what's useful JsonMessage::Cargo(message) => match message { cargo_metadata::Message::CompilerArtifact(artifact) if !artifact.fresh => { - self.sender.send(CargoMessage::CompilerArtifact(artifact)).unwrap(); + self.sender + .send(CargoMessage::CompilerArtifact(Box::new(artifact))) + .unwrap(); } cargo_metadata::Message::CompilerMessage(msg) => { self.sender.send(CargoMessage::Diagnostic(msg.message)).unwrap(); @@ -533,7 +535,7 @@ impl CargoActor { } enum CargoMessage { - CompilerArtifact(cargo_metadata::Artifact), + CompilerArtifact(Box), Diagnostic(Diagnostic), } From f4704bc8ae92d150b2801e391692d9503f0c6126 Mon Sep 17 00:00:00 2001 From: hkalbasi Date: Fri, 15 Sep 2023 18:10:11 +0330 Subject: [PATCH 036/435] Switch to in-tree rustc dependencies with a cfg flag --- Cargo.lock | 22 ++++++++++----- Cargo.toml | 18 +++++-------- crates/hir-def/Cargo.toml | 8 +++--- crates/hir-def/src/data/adt.rs | 2 +- crates/hir-def/src/hir/format_args.rs | 2 +- crates/hir-def/src/lib.rs | 3 ++- crates/hir-ty/Cargo.toml | 5 +++- crates/hir-ty/src/layout.rs | 2 +- crates/parser/Cargo.toml | 5 +++- crates/parser/src/lexed_str.rs | 1 + crates/parser/src/lib.rs | 1 + crates/rust-analyzer/Cargo.toml | 12 ++++++++- crates/rustc-dependencies/Cargo.toml | 20 ++++++++++++++ crates/rustc-dependencies/src/lib.rs | 39 +++++++++++++++++++++++++++ crates/syntax/Cargo.toml | 4 +-- crates/syntax/src/ast/token_ext.rs | 2 ++ crates/syntax/src/lib.rs | 1 + crates/syntax/src/validation.rs | 2 +- 18 files changed, 118 insertions(+), 31 deletions(-) create mode 100644 crates/rustc-dependencies/Cargo.toml create mode 100644 crates/rustc-dependencies/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index bd6554bf8899..e506aa834eba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -531,8 +531,6 @@ dependencies = [ "fst", "hashbrown 0.12.3", "hir-expand", - "hkalbasi-rustc-ap-rustc_abi", - "hkalbasi-rustc-ap-rustc_index", "indexmap 2.0.0", "intern", "itertools", @@ -541,7 +539,7 @@ dependencies = [ "mbe", "once_cell", "profile", - "ra-ap-rustc_parse_format", + "rustc-dependencies", "rustc-hash", "smallvec", "stdx", @@ -594,7 +592,6 @@ dependencies = [ "expect-test", "hir-def", "hir-expand", - "hkalbasi-rustc-ap-rustc_index", "intern", "itertools", "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -604,6 +601,7 @@ dependencies = [ "oorandom", "profile", "project-model", + "rustc-dependencies", "rustc-hash", "scoped-tls", "smallvec", @@ -1277,7 +1275,7 @@ dependencies = [ "drop_bomb", "expect-test", "limit", - "ra-ap-rustc_lexer", + "rustc-dependencies", "sourcegen", "stdx", ] @@ -1594,10 +1592,12 @@ dependencies = [ "oorandom", "parking_lot 0.12.1", "parking_lot_core 0.9.6", + "parser", "proc-macro-api", "profile", "project-model", "rayon", + "rustc-dependencies", "rustc-hash", "scip", "serde", @@ -1626,6 +1626,16 @@ version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +[[package]] +name = "rustc-dependencies" +version = "0.0.0" +dependencies = [ + "hkalbasi-rustc-ap-rustc_abi", + "hkalbasi-rustc-ap-rustc_index", + "ra-ap-rustc_lexer", + "ra-ap-rustc_parse_format", +] + [[package]] name = "rustc-hash" version = "1.1.0" @@ -1853,9 +1863,9 @@ dependencies = [ "proc-macro2", "profile", "quote", - "ra-ap-rustc_lexer", "rayon", "rowan", + "rustc-dependencies", "rustc-hash", "smol_str", "sourcegen", diff --git a/Cargo.toml b/Cargo.toml index cab88fc18cec..ffac946b18f9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -79,6 +79,7 @@ toolchain = { path = "./crates/toolchain", version = "0.0.0" } tt = { path = "./crates/tt", version = "0.0.0" } vfs-notify = { path = "./crates/vfs-notify", version = "0.0.0" } vfs = { path = "./crates/vfs", version = "0.0.0" } +rustc-dependencies = { path = "./crates/rustc-dependencies", version = "0.0.0" } # local crates that aren't published to crates.io. These should not have versions. proc-macro-test = { path = "./crates/proc-macro-test" } @@ -90,9 +91,9 @@ lsp-server = { version = "0.7.4" } # non-local crates smallvec = { version = "1.10.0", features = [ - "const_new", - "union", - "const_generics", + "const_new", + "union", + "const_generics", ] } smol_str = "0.2.0" nohash-hasher = "0.2.0" @@ -101,11 +102,6 @@ serde = { version = "1.0.156", features = ["derive"] } serde_json = "1.0.96" triomphe = { version = "0.1.8", default-features = false, features = ["std"] } # can't upgrade due to dashmap depending on 0.12.3 currently -hashbrown = { version = "0.12.3", features = ["inline-more"], default-features = false } - -rustc_lexer = { version = "0.10.0", package = "ra-ap-rustc_lexer" } -rustc_parse_format = { version = "0.10.0", package = "ra-ap-rustc_parse_format", default-features = false } - -# Upstream broke this for us so we can't update it -rustc_abi = { version = "0.0.20221221", package = "hkalbasi-rustc-ap-rustc_abi", default-features = false } -rustc_index = { version = "0.0.20221221", package = "hkalbasi-rustc-ap-rustc_index", default-features = false } +hashbrown = { version = "0.12.3", features = [ + "inline-more", +], default-features = false } diff --git a/crates/hir-def/Cargo.toml b/crates/hir-def/Cargo.toml index 8cf61ee04d4e..092aab011205 100644 --- a/crates/hir-def/Cargo.toml +++ b/crates/hir-def/Cargo.toml @@ -31,10 +31,7 @@ smallvec.workspace = true hashbrown.workspace = true triomphe.workspace = true -rustc_abi.workspace = true -rustc_index.workspace = true -rustc_parse_format.workspace = true - +rustc-dependencies.workspace = true # local deps stdx.workspace = true @@ -53,3 +50,6 @@ expect-test = "1.4.0" # local deps test-utils.workspace = true + +[features] +in-rust-tree = ["rustc-dependencies/in-rust-tree"] diff --git a/crates/hir-def/src/data/adt.rs b/crates/hir-def/src/data/adt.rs index 224f7328f8cd..b163112db918 100644 --- a/crates/hir-def/src/data/adt.rs +++ b/crates/hir-def/src/data/adt.rs @@ -11,7 +11,7 @@ use hir_expand::{ }; use intern::Interned; use la_arena::{Arena, ArenaMap}; -use rustc_abi::{Align, Integer, IntegerType, ReprFlags, ReprOptions}; +use rustc_dependencies::abi::{Align, Integer, IntegerType, ReprFlags, ReprOptions}; use syntax::ast::{self, HasName, HasVisibility}; use triomphe::Arc; diff --git a/crates/hir-def/src/hir/format_args.rs b/crates/hir-def/src/hir/format_args.rs index 75025a984fcd..46d24bd4a614 100644 --- a/crates/hir-def/src/hir/format_args.rs +++ b/crates/hir-def/src/hir/format_args.rs @@ -2,7 +2,7 @@ use std::mem; use hir_expand::name::Name; -use rustc_parse_format as parse; +use rustc_dependencies::parse_format as parse; use syntax::{ ast::{self, IsString}, AstToken, SmolStr, TextRange, diff --git a/crates/hir-def/src/lib.rs b/crates/hir-def/src/lib.rs index 3f87fe62b83c..1abcb1835fd5 100644 --- a/crates/hir-def/src/lib.rs +++ b/crates/hir-def/src/lib.rs @@ -8,6 +8,7 @@ //! actually true. #![warn(rust_2018_idioms, unused_lifetimes, semicolon_in_expressions_from_macros)] +#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))] #[allow(unused)] macro_rules! eprintln { @@ -48,7 +49,7 @@ pub mod visibility; pub mod find_path; pub mod import_map; -pub use rustc_abi as layout; +pub use rustc_dependencies::abi as layout; use triomphe::Arc; #[cfg(test)] diff --git a/crates/hir-ty/Cargo.toml b/crates/hir-ty/Cargo.toml index b95ae05ccd45..6a0c26a8bc09 100644 --- a/crates/hir-ty/Cargo.toml +++ b/crates/hir-ty/Cargo.toml @@ -33,7 +33,7 @@ triomphe.workspace = true nohash-hasher.workspace = true typed-arena = "2.0.1" -rustc_index.workspace = true +rustc-dependencies.workspace = true # local deps stdx.workspace = true @@ -56,3 +56,6 @@ project-model = { path = "../project-model" } # local deps test-utils.workspace = true + +[features] +in-rust-tree = ["rustc-dependencies/in-rust-tree"] diff --git a/crates/hir-ty/src/layout.rs b/crates/hir-ty/src/layout.rs index 1a6106c0244c..ee558956a761 100644 --- a/crates/hir-ty/src/layout.rs +++ b/crates/hir-ty/src/layout.rs @@ -34,7 +34,7 @@ mod target; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct RustcEnumVariantIdx(pub LocalEnumVariantId); -impl rustc_index::vec::Idx for RustcEnumVariantIdx { +impl rustc_dependencies::index::vec::Idx for RustcEnumVariantIdx { fn new(idx: usize) -> Self { RustcEnumVariantIdx(Idx::from_raw(RawIdx::from(idx as u32))) } diff --git a/crates/parser/Cargo.toml b/crates/parser/Cargo.toml index 09e62c35278e..efb326323f91 100644 --- a/crates/parser/Cargo.toml +++ b/crates/parser/Cargo.toml @@ -13,7 +13,7 @@ doctest = false [dependencies] drop_bomb = "0.1.5" -rustc_lexer.workspace = true +rustc-dependencies.workspace = true limit.workspace = true @@ -22,3 +22,6 @@ expect-test = "1.4.0" stdx.workspace = true sourcegen.workspace = true + +[features] +in-rust-tree = ["rustc-dependencies/in-rust-tree"] diff --git a/crates/parser/src/lexed_str.rs b/crates/parser/src/lexed_str.rs index 36c52953a024..30c1c4f8c75b 100644 --- a/crates/parser/src/lexed_str.rs +++ b/crates/parser/src/lexed_str.rs @@ -8,6 +8,7 @@ //! Note that these tokens, unlike the tokens we feed into the parser, do //! include info about comments and whitespace. +use rustc_dependencies::lexer as rustc_lexer; use std::ops; use crate::{ diff --git a/crates/parser/src/lib.rs b/crates/parser/src/lib.rs index c155e8aaf67b..fcfd1a50719b 100644 --- a/crates/parser/src/lib.rs +++ b/crates/parser/src/lib.rs @@ -19,6 +19,7 @@ #![warn(rust_2018_idioms, unused_lifetimes, semicolon_in_expressions_from_macros)] #![allow(rustdoc::private_intra_doc_links)] +#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))] mod lexed_str; mod token_set; diff --git a/crates/rust-analyzer/Cargo.toml b/crates/rust-analyzer/Cargo.toml index 7410f0a3a668..0a5412c638c3 100644 --- a/crates/rust-analyzer/Cargo.toml +++ b/crates/rust-analyzer/Cargo.toml @@ -57,6 +57,7 @@ flycheck.workspace = true hir-def.workspace = true hir-ty.workspace = true hir.workspace = true +rustc-dependencies.workspace = true ide-db.workspace = true # This should only be used in CLI ide-ssr.workspace = true @@ -67,6 +68,7 @@ profile.workspace = true project-model.workspace = true stdx.workspace = true syntax.workspace = true +parser.workspace = true toolchain.workspace = true vfs-notify.workspace = true vfs.workspace = true @@ -89,4 +91,12 @@ mbe.workspace = true jemalloc = ["jemallocator", "profile/jemalloc"] force-always-assert = ["always-assert/force"] sysroot-abi = [] -in-rust-tree = ["sysroot-abi", "ide/in-rust-tree", "syntax/in-rust-tree"] +in-rust-tree = [ + "sysroot-abi", + "ide/in-rust-tree", + "syntax/in-rust-tree", + "parser/in-rust-tree", + "rustc-dependencies/in-rust-tree", + "hir-def/in-rust-tree", + "hir-ty/in-rust-tree", +] diff --git a/crates/rustc-dependencies/Cargo.toml b/crates/rustc-dependencies/Cargo.toml new file mode 100644 index 000000000000..901706d3d95f --- /dev/null +++ b/crates/rustc-dependencies/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "rustc-dependencies" +version = "0.0.0" +rust-version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +ra-ap-rustc_lexer = { version = "0.10.0" } +ra-ap-rustc_parse_format = { version = "0.10.0", default-features = false } + +# Upstream broke this for us so we can't update it +hkalbasi-rustc-ap-rustc_abi = { version = "0.0.20221221", default-features = false } +hkalbasi-rustc-ap-rustc_index = { version = "0.0.20221221", default-features = false } + +[features] +in-rust-tree = [] diff --git a/crates/rustc-dependencies/src/lib.rs b/crates/rustc-dependencies/src/lib.rs new file mode 100644 index 000000000000..c1d3f05f34e7 --- /dev/null +++ b/crates/rustc-dependencies/src/lib.rs @@ -0,0 +1,39 @@ +//! A wrapper around rustc internal crates, which enables switching between compiler provided +//! ones and stable ones published in crates.io + +#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))] + +#[cfg(feature = "in-rust-tree")] +extern crate rustc_lexer; + +#[cfg(feature = "in-rust-tree")] +pub mod lexer { + pub use ::rustc_lexer::*; +} + +#[cfg(not(feature = "in-rust-tree"))] +pub mod lexer { + pub use ::ra_ap_rustc_lexer::*; +} + +#[cfg(feature = "in-rust-tree")] +extern crate rustc_parse_format; + +#[cfg(feature = "in-rust-tree")] +pub mod parse_format { + pub use ::rustc_parse_format::*; +} + +#[cfg(not(feature = "in-rust-tree"))] +pub mod parse_format { + pub use ::ra_ap_rustc_parse_format::*; +} + +// Upstream broke this for us so we can't update it +pub mod abi { + pub use ::hkalbasi_rustc_ap_rustc_abi::*; +} + +pub mod index { + pub use ::hkalbasi_rustc_ap_rustc_index::*; +} diff --git a/crates/syntax/Cargo.toml b/crates/syntax/Cargo.toml index 5ee0c4792846..dc92366d1c7a 100644 --- a/crates/syntax/Cargo.toml +++ b/crates/syntax/Cargo.toml @@ -23,7 +23,7 @@ indexmap = "2.0.0" smol_str.workspace = true triomphe.workspace = true -rustc_lexer.workspace = true +rustc-dependencies.workspace = true parser.workspace = true profile.workspace = true @@ -41,4 +41,4 @@ test-utils.workspace = true sourcegen.workspace = true [features] -in-rust-tree = [] +in-rust-tree = ["rustc-dependencies/in-rust-tree"] diff --git a/crates/syntax/src/ast/token_ext.rs b/crates/syntax/src/ast/token_ext.rs index 87fd51d703cf..8cc271d226c4 100644 --- a/crates/syntax/src/ast/token_ext.rs +++ b/crates/syntax/src/ast/token_ext.rs @@ -2,6 +2,8 @@ use std::borrow::Cow; +use rustc_dependencies::lexer as rustc_lexer; + use rustc_lexer::unescape::{ unescape_byte, unescape_c_string, unescape_char, unescape_literal, CStrUnit, Mode, }; diff --git a/crates/syntax/src/lib.rs b/crates/syntax/src/lib.rs index 27c8a13e58d6..2cd82e3762e6 100644 --- a/crates/syntax/src/lib.rs +++ b/crates/syntax/src/lib.rs @@ -19,6 +19,7 @@ //! [RFC]: //! [Swift]: +#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))] #![warn(rust_2018_idioms, unused_lifetimes, semicolon_in_expressions_from_macros)] #[allow(unused)] diff --git a/crates/syntax/src/validation.rs b/crates/syntax/src/validation.rs index e0ec6a242ffa..2b1bbac08e52 100644 --- a/crates/syntax/src/validation.rs +++ b/crates/syntax/src/validation.rs @@ -5,7 +5,7 @@ mod block; use rowan::Direction; -use rustc_lexer::unescape::{self, unescape_literal, Mode}; +use rustc_dependencies::lexer::unescape::{self, unescape_literal, Mode}; use crate::{ algo, From 24b6922957dbe0b9f887c69508fc1192663019ca Mon Sep 17 00:00:00 2001 From: Peter Jaszkowiak Date: Sat, 16 Sep 2023 10:58:53 -0600 Subject: [PATCH 037/435] triagebot exclude_labels -> exclude_titles --- triagebot.toml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/triagebot.toml b/triagebot.toml index f0cd35399752..95eed3ee172c 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -11,5 +11,10 @@ allow-unauthenticated = [ new_pr = true [no-merges] -exclude_labels = ["sync"] +exclude_titles = [ # exclude syncs from subtree in rust-lang/rust + "Sync from downstream", + "sync from downstream", + "Sync from rust", + "sync from rust", +] labels = ["has-merge-commits", "S-waiting-on-author"] From cac796acb30d3af9a2eb9aff02acfae43a6da537 Mon Sep 17 00:00:00 2001 From: Kevin Reid Date: Sat, 16 Sep 2023 12:59:17 -0700 Subject: [PATCH 038/435] Give `unmerge_use` a label explaining what it will affect. --- .../ide-assists/src/handlers/unmerge_use.rs | 36 +++++++++---------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/crates/ide-assists/src/handlers/unmerge_use.rs b/crates/ide-assists/src/handlers/unmerge_use.rs index dac216b69b72..52df30d9623f 100644 --- a/crates/ide-assists/src/handlers/unmerge_use.rs +++ b/crates/ide-assists/src/handlers/unmerge_use.rs @@ -36,29 +36,25 @@ pub(crate) fn unmerge_use(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option< let old_parent_range = use_.syntax().parent()?.text_range(); let new_parent = use_.syntax().parent()?; + // If possible, explain what is going to be done. + let label = match tree.path().and_then(|path| path.first_segment()) { + Some(name) => format!("Unmerge use of `{name}`"), + None => "Unmerge use".into(), + }; + let target = tree.syntax().text_range(); - acc.add( - AssistId("unmerge_use", AssistKind::RefactorRewrite), - "Unmerge use", - target, - |builder| { - let new_use = make::use_( - use_.visibility(), - make::use_tree( - path, - tree.use_tree_list(), - tree.rename(), - tree.star_token().is_some(), - ), - ) - .clone_for_update(); + acc.add(AssistId("unmerge_use", AssistKind::RefactorRewrite), label, target, |builder| { + let new_use = make::use_( + use_.visibility(), + make::use_tree(path, tree.use_tree_list(), tree.rename(), tree.star_token().is_some()), + ) + .clone_for_update(); - tree.remove(); - ted::insert(Position::after(use_.syntax()), new_use.syntax()); + tree.remove(); + ted::insert(Position::after(use_.syntax()), new_use.syntax()); - builder.replace(old_parent_range, new_parent.to_string()); - }, - ) + builder.replace(old_parent_range, new_parent.to_string()); + }) } fn resolve_full_path(tree: &ast::UseTree) -> Option { From 2a929813016946dd671a9b01a5cefdda168dcc0b Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sat, 16 Sep 2023 21:39:58 -0700 Subject: [PATCH 039/435] rustdoc: stop preloading Source Serif 4 Bold According to 4198fac7390509128c42757fcfb89a0effde4a8e, italic fonts are not preloaded because they're rarely used, but bold fonts are. This seems to be true of bold Source Code Pro and bold Fira Sans, but bold and italic Source Serif Pro seem to be equally heavily used. This is, I assume, the result of using Fira Sans Bold and Source Code Bold headings, so you only get bold Serif text when the doc author uses strong `**` emphasis (or within certain kinds of tooltip, which shouldn't be preloaded because they only show up long after the page is loaded). To check this, run these two commands in the browser console to measure how much they're used. The measurement is extremely rough, but it gets the idea across: the two styles are about equally popular. // count bold elements Array.prototype.slice.call(document.querySelectorAll("*")).filter(x => { const y = document.defaultView.getComputedStyle(x); return y.fontFamily.indexOf("Source Serif 4") !== -1 && y.fontWeight > 400 }).length // count italic elements Array.prototype.slice.call(document.querySelectorAll("*")).filter(x => { const y = document.defaultView.getComputedStyle(x); return y.fontFamily.indexOf("Source Serif 4") !== -1 && y.fontStyle == "italic" }).length | URL | Bold | Italic | |---------|-----:|-------:| | [std] | 2 | 9 | | [Vec] | 8 | 89 | | [regex] | 33 | 17 | [std]: https://doc.rust-lang.org/nightly/std/index.html [Vec]: https://doc.rust-lang.org/nightly/std/vec/struct.Vec.html [regex]: https://docs.rs/regex/1.9.5/regex/index.html --- src/librustdoc/html/templates/page.html | 1 - 1 file changed, 1 deletion(-) diff --git a/src/librustdoc/html/templates/page.html b/src/librustdoc/html/templates/page.html index b4b9c3191653..370d392a39ea 100644 --- a/src/librustdoc/html/templates/page.html +++ b/src/librustdoc/html/templates/page.html @@ -10,7 +10,6 @@ {# #} {# #} {# #} - {# #} {# #} {# #} From c3724311236916264adaaede2e05bf4ebbf08f5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Tue, 19 Sep 2023 13:48:05 +0200 Subject: [PATCH 040/435] scip: Use load_workspace_at. This honors the build script config, and is also simpler. --- crates/rust-analyzer/src/cli/scip.rs | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/crates/rust-analyzer/src/cli/scip.rs b/crates/rust-analyzer/src/cli/scip.rs index 8c056fff000e..875b724bd892 100644 --- a/crates/rust-analyzer/src/cli/scip.rs +++ b/crates/rust-analyzer/src/cli/scip.rs @@ -11,10 +11,9 @@ use ide::{ TokenStaticData, }; use ide_db::LineIndexDatabase; -use load_cargo::{load_workspace, LoadCargoConfig, ProcMacroServerChoice}; -use project_model::{CargoConfig, ProjectManifest, ProjectWorkspace, RustLibSource}; +use load_cargo::{load_workspace_at, LoadCargoConfig, ProcMacroServerChoice}; +use project_model::{CargoConfig, RustLibSource}; use scip::types as scip_types; -use std::env; use crate::{ cli::flags, @@ -34,14 +33,13 @@ impl flags::Scip { with_proc_macro_server: ProcMacroServerChoice::Sysroot, prefill_caches: true, }; - let path = vfs::AbsPathBuf::assert(env::current_dir()?.join(&self.path)); - let rootpath = path.normalize(); - let manifest = ProjectManifest::discover_single(&path)?; - - let workspace = ProjectWorkspace::load(manifest, &cargo_config, no_progress)?; - - let (host, vfs, _) = - load_workspace(workspace, &cargo_config.extra_env, &load_cargo_config)?; + let root = vfs::AbsPathBuf::assert(std::env::current_dir()?.join(&self.path)).normalize(); + let (host, vfs, _) = load_workspace_at( + root.as_path().as_ref(), + &cargo_config, + &load_cargo_config, + &no_progress, + )?; let db = host.raw_database(); let analysis = host.analysis(); @@ -58,8 +56,7 @@ impl flags::Scip { .into(), project_root: format!( "file://{}", - path.normalize() - .as_os_str() + root.as_os_str() .to_str() .ok_or(anyhow::format_err!("Unable to normalize project_root path"))? ), @@ -80,7 +77,7 @@ impl flags::Scip { new_symbol }; - let relative_path = match get_relative_filepath(&vfs, &rootpath, file_id) { + let relative_path = match get_relative_filepath(&vfs, &root, file_id) { Some(relative_path) => relative_path, None => continue, }; From 184119258e256b656f30d89ea5e1512fe1d927db Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Tue, 19 Sep 2023 21:34:43 +0300 Subject: [PATCH 041/435] Do not resolve inlayHint.textEdit for VSCode client VSCode behaves strangely, allowing to navigate into label location, but not allowing to apply hint's text edit, after hint is resolved. See https://github.com/microsoft/vscode/issues/193124 for details. For now, stub hint resolution for VSCode specifically. --- crates/rust-analyzer/src/bin/main.rs | 12 ++++--- crates/rust-analyzer/src/config.rs | 33 +++++++++++++++---- .../rust-analyzer/src/diagnostics/to_proto.rs | 7 +++- crates/rust-analyzer/src/lsp/to_proto.rs | 3 +- .../rust-analyzer/tests/slow-tests/support.rs | 1 + 5 files changed, 43 insertions(+), 13 deletions(-) diff --git a/crates/rust-analyzer/src/bin/main.rs b/crates/rust-analyzer/src/bin/main.rs index 2fa14fc7e283..c1d0d24b96d2 100644 --- a/crates/rust-analyzer/src/bin/main.rs +++ b/crates/rust-analyzer/src/bin/main.rs @@ -190,6 +190,12 @@ fn run_server() -> anyhow::Result<()> { } }; + let mut is_visual_studio = false; + if let Some(client_info) = client_info { + tracing::info!("Client '{}' {}", client_info.name, client_info.version.unwrap_or_default()); + is_visual_studio = client_info.name == "Visual Studio Code"; + } + let workspace_roots = workspace_folders .map(|workspaces| { workspaces @@ -201,7 +207,7 @@ fn run_server() -> anyhow::Result<()> { }) .filter(|workspaces| !workspaces.is_empty()) .unwrap_or_else(|| vec![root_path.clone()]); - let mut config = Config::new(root_path, capabilities, workspace_roots); + let mut config = Config::new(root_path, capabilities, workspace_roots, is_visual_studio); if let Some(json) = initialization_options { if let Err(e) = config.update(json) { use lsp_types::{ @@ -231,10 +237,6 @@ fn run_server() -> anyhow::Result<()> { connection.initialize_finish(initialize_id, initialize_result)?; - if let Some(client_info) = client_info { - tracing::info!("Client '{}' {}", client_info.name, client_info.version.unwrap_or_default()); - } - if !config.has_linked_projects() && config.detached_files().is_empty() { config.rediscover_workspaces(); } diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index ea3a21241cb6..683b3deb6ee6 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -565,6 +565,7 @@ pub struct Config { data: ConfigData, detached_files: Vec, snippets: Vec, + is_visual_studio: bool, } type ParallelCachePrimingNumThreads = u8; @@ -760,6 +761,7 @@ impl Config { root_path: AbsPathBuf, caps: ClientCapabilities, workspace_roots: Vec, + is_visual_studio: bool, ) -> Self { Config { caps, @@ -769,6 +771,7 @@ impl Config { root_path, snippets: Default::default(), workspace_roots, + is_visual_studio, } } @@ -1667,6 +1670,12 @@ impl Config { pub fn typing_autoclose_angle(&self) -> bool { self.data.typing_autoClosingAngleBrackets_enable } + + // FIXME: VSCode seems to work wrong sometimes, see https://github.com/microsoft/vscode/issues/193124 + // hence, distinguish it for now. + pub fn is_visual_studio(&self) -> bool { + self.is_visual_studio + } } // Deserialization definitions @@ -2555,8 +2564,12 @@ mod tests { #[test] fn proc_macro_srv_null() { - let mut config = - Config::new(AbsPathBuf::try_from(project_root()).unwrap(), Default::default(), vec![]); + let mut config = Config::new( + AbsPathBuf::try_from(project_root()).unwrap(), + Default::default(), + vec![], + false, + ); config .update(serde_json::json!({ "procMacro_server": null, @@ -2567,8 +2580,12 @@ mod tests { #[test] fn proc_macro_srv_abs() { - let mut config = - Config::new(AbsPathBuf::try_from(project_root()).unwrap(), Default::default(), vec![]); + let mut config = Config::new( + AbsPathBuf::try_from(project_root()).unwrap(), + Default::default(), + vec![], + false, + ); config .update(serde_json::json!({ "procMacro": {"server": project_root().display().to_string()} @@ -2579,8 +2596,12 @@ mod tests { #[test] fn proc_macro_srv_rel() { - let mut config = - Config::new(AbsPathBuf::try_from(project_root()).unwrap(), Default::default(), vec![]); + let mut config = Config::new( + AbsPathBuf::try_from(project_root()).unwrap(), + Default::default(), + vec![], + false, + ); config .update(serde_json::json!({ "procMacro": {"server": "./server"} diff --git a/crates/rust-analyzer/src/diagnostics/to_proto.rs b/crates/rust-analyzer/src/diagnostics/to_proto.rs index 731580557c29..f8bc66ff8e74 100644 --- a/crates/rust-analyzer/src/diagnostics/to_proto.rs +++ b/crates/rust-analyzer/src/diagnostics/to_proto.rs @@ -538,7 +538,12 @@ mod tests { let (sender, _) = crossbeam_channel::unbounded(); let state = GlobalState::new( sender, - Config::new(workspace_root.to_path_buf(), ClientCapabilities::default(), Vec::new()), + Config::new( + workspace_root.to_path_buf(), + ClientCapabilities::default(), + Vec::new(), + false, + ), ); let snap = state.snapshot(); let mut actual = map_rust_diagnostic_to_lsp(&config, &diagnostic, workspace_root, &snap); diff --git a/crates/rust-analyzer/src/lsp/to_proto.rs b/crates/rust-analyzer/src/lsp/to_proto.rs index 23074493aeee..9190c203146e 100644 --- a/crates/rust-analyzer/src/lsp/to_proto.rs +++ b/crates/rust-analyzer/src/lsp/to_proto.rs @@ -443,10 +443,11 @@ pub(crate) fn inlay_hint( file_id: FileId, inlay_hint: InlayHint, ) -> Cancellable { + let is_visual_studio = snap.config.is_visual_studio(); let needs_resolve = inlay_hint.needs_resolve; let (label, tooltip, mut something_to_resolve) = inlay_hint_label(snap, fields_to_resolve, needs_resolve, inlay_hint.label)?; - let text_edits = if needs_resolve && fields_to_resolve.resolve_text_edits { + let text_edits = if !is_visual_studio && needs_resolve && fields_to_resolve.resolve_text_edits { something_to_resolve |= inlay_hint.text_edit.is_some(); None } else { diff --git a/crates/rust-analyzer/tests/slow-tests/support.rs b/crates/rust-analyzer/tests/slow-tests/support.rs index e49b5768fa46..106b99cb9352 100644 --- a/crates/rust-analyzer/tests/slow-tests/support.rs +++ b/crates/rust-analyzer/tests/slow-tests/support.rs @@ -150,6 +150,7 @@ impl Project<'_> { ..Default::default() }, roots, + false, ); config.update(self.config).expect("invalid config"); config.rediscover_workspaces(); From f9fac02c571a4f5520246ab80f5c4b825ca492a5 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Tue, 19 Sep 2023 23:34:43 +0300 Subject: [PATCH 042/435] Use proper editor name --- crates/rust-analyzer/src/bin/main.rs | 6 +++--- crates/rust-analyzer/src/config.rs | 10 +++++----- crates/rust-analyzer/src/lsp/to_proto.rs | 15 ++++++++------- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/crates/rust-analyzer/src/bin/main.rs b/crates/rust-analyzer/src/bin/main.rs index c1d0d24b96d2..b8875ef87a4c 100644 --- a/crates/rust-analyzer/src/bin/main.rs +++ b/crates/rust-analyzer/src/bin/main.rs @@ -190,10 +190,10 @@ fn run_server() -> anyhow::Result<()> { } }; - let mut is_visual_studio = false; + let mut is_visual_studio_code = false; if let Some(client_info) = client_info { tracing::info!("Client '{}' {}", client_info.name, client_info.version.unwrap_or_default()); - is_visual_studio = client_info.name == "Visual Studio Code"; + is_visual_studio_code = client_info.name == "Visual Studio Code"; } let workspace_roots = workspace_folders @@ -207,7 +207,7 @@ fn run_server() -> anyhow::Result<()> { }) .filter(|workspaces| !workspaces.is_empty()) .unwrap_or_else(|| vec![root_path.clone()]); - let mut config = Config::new(root_path, capabilities, workspace_roots, is_visual_studio); + let mut config = Config::new(root_path, capabilities, workspace_roots, is_visual_studio_code); if let Some(json) = initialization_options { if let Err(e) = config.update(json) { use lsp_types::{ diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 683b3deb6ee6..af2a8436efb9 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -565,7 +565,7 @@ pub struct Config { data: ConfigData, detached_files: Vec, snippets: Vec, - is_visual_studio: bool, + is_visual_studio_code: bool, } type ParallelCachePrimingNumThreads = u8; @@ -761,7 +761,7 @@ impl Config { root_path: AbsPathBuf, caps: ClientCapabilities, workspace_roots: Vec, - is_visual_studio: bool, + is_visual_studio_code: bool, ) -> Self { Config { caps, @@ -771,7 +771,7 @@ impl Config { root_path, snippets: Default::default(), workspace_roots, - is_visual_studio, + is_visual_studio_code, } } @@ -1673,8 +1673,8 @@ impl Config { // FIXME: VSCode seems to work wrong sometimes, see https://github.com/microsoft/vscode/issues/193124 // hence, distinguish it for now. - pub fn is_visual_studio(&self) -> bool { - self.is_visual_studio + pub fn is_visual_studio_code(&self) -> bool { + self.is_visual_studio_code } } // Deserialization definitions diff --git a/crates/rust-analyzer/src/lsp/to_proto.rs b/crates/rust-analyzer/src/lsp/to_proto.rs index 9190c203146e..aca91570f7c2 100644 --- a/crates/rust-analyzer/src/lsp/to_proto.rs +++ b/crates/rust-analyzer/src/lsp/to_proto.rs @@ -443,16 +443,17 @@ pub(crate) fn inlay_hint( file_id: FileId, inlay_hint: InlayHint, ) -> Cancellable { - let is_visual_studio = snap.config.is_visual_studio(); + let is_visual_studio_code = snap.config.is_visual_studio_code(); let needs_resolve = inlay_hint.needs_resolve; let (label, tooltip, mut something_to_resolve) = inlay_hint_label(snap, fields_to_resolve, needs_resolve, inlay_hint.label)?; - let text_edits = if !is_visual_studio && needs_resolve && fields_to_resolve.resolve_text_edits { - something_to_resolve |= inlay_hint.text_edit.is_some(); - None - } else { - inlay_hint.text_edit.map(|it| text_edit_vec(line_index, it)) - }; + let text_edits = + if !is_visual_studio_code && needs_resolve && fields_to_resolve.resolve_text_edits { + something_to_resolve |= inlay_hint.text_edit.is_some(); + None + } else { + inlay_hint.text_edit.map(|it| text_edit_vec(line_index, it)) + }; let data = if needs_resolve && something_to_resolve { Some(to_value(lsp_ext::InlayHintResolveData { file_id: file_id.0 }).unwrap()) } else { From 3a63255d2a16fd56e08915da0dbaa7228a41cb8f Mon Sep 17 00:00:00 2001 From: Wilfred Hughes Date: Tue, 19 Sep 2023 16:56:59 -0700 Subject: [PATCH 043/435] Update chalk version --- Cargo.lock | 16 ++++++++-------- crates/hir-ty/Cargo.toml | 8 ++++---- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e506aa834eba..fa7b6a2fa378 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -177,9 +177,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chalk-derive" -version = "0.92.0" +version = "0.93.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff5053a8a42dbff5279a82423946fc56dc1253b76cf211b2b3c14b3aad4e1281" +checksum = "264726159011fc7f22c23eb51f49021ece6e71bc358b96e7f2e842db0b14162b" dependencies = [ "proc-macro2", "quote", @@ -189,9 +189,9 @@ dependencies = [ [[package]] name = "chalk-ir" -version = "0.92.0" +version = "0.93.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a56de2146a8ed0fcd54f4bd50db852f1de4eac9e1efe568494f106c21b77d2a" +checksum = "d65c17407d4c756b8f7f84344acb0fb96364d0298822743219bb25769b6d00df" dependencies = [ "bitflags 1.3.2", "chalk-derive", @@ -200,9 +200,9 @@ dependencies = [ [[package]] name = "chalk-recursive" -version = "0.92.0" +version = "0.93.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc09e6e9531f3544989ef89b189e80fbc7ad9e2f73f1c5e03ddc9ffb0527463" +checksum = "80e2cf7b70bedaaf3a8cf3c93b6120c2bb65be89389124028e724d19e209686e" dependencies = [ "chalk-derive", "chalk-ir", @@ -213,9 +213,9 @@ dependencies = [ [[package]] name = "chalk-solve" -version = "0.92.0" +version = "0.93.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b392e02b4c81ec76d3748da839fc70a5539b83d27c9030668463d34d5110b860" +checksum = "afc67c548d3854f64e97e67dc5b7c88513425c5bfa347cff96b7992ae6379288" dependencies = [ "chalk-derive", "chalk-ir", diff --git a/crates/hir-ty/Cargo.toml b/crates/hir-ty/Cargo.toml index 6a0c26a8bc09..c30807ad8849 100644 --- a/crates/hir-ty/Cargo.toml +++ b/crates/hir-ty/Cargo.toml @@ -23,10 +23,10 @@ oorandom = "11.1.3" tracing = "0.1.35" rustc-hash = "1.1.0" scoped-tls = "1.0.0" -chalk-solve = { version = "0.92.0", default-features = false } -chalk-ir = "0.92.0" -chalk-recursive = { version = "0.92.0", default-features = false } -chalk-derive = "0.92.0" +chalk-solve = { version = "0.93.0", default-features = false } +chalk-ir = "0.93.0" +chalk-recursive = { version = "0.93.0", default-features = false } +chalk-derive = "0.93.0" la-arena.workspace = true once_cell = "1.17.0" triomphe.workspace = true From 4b3257a365b7e61f5a868fd039165f0365934b5c Mon Sep 17 00:00:00 2001 From: shogo-nakano-desu <61229807+shogo-nakano-desu@users.noreply.github.com> Date: Sat, 16 Sep 2023 11:54:06 +0900 Subject: [PATCH 044/435] refactor: port anymap --- Cargo.lock | 28 +- Cargo.toml | 16 +- crates/anymap/Cargo.toml | 20 ++ crates/anymap/src/any.rs | 134 +++++++++ crates/anymap/src/lib.rs | 275 ++++++++++++++++++ crates/hir-def/Cargo.toml | 3 +- crates/rust-analyzer/tests/slow-tests/tidy.rs | 1 - 7 files changed, 468 insertions(+), 9 deletions(-) create mode 100644 crates/anymap/Cargo.toml create mode 100644 crates/anymap/src/any.rs create mode 100644 crates/anymap/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index e506aa834eba..6b0f7efc6ca6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,23 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "ahash" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", +] + +[[package]] +name = "allocator-api2" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" + [[package]] name = "always-assert" version = "0.1.3" @@ -34,9 +51,10 @@ checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" [[package]] name = "anymap" -version = "1.0.0-beta.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f1f8f5a6f3d50d89e3797d7593a50f96bb2aaa20ca0cc7be1fb673232c91d72" +version = "0.0.0" +dependencies = [ + "hashbrown 0.14.0", +] [[package]] name = "arbitrary" @@ -464,6 +482,10 @@ name = "hashbrown" version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" +dependencies = [ + "ahash", + "allocator-api2", +] [[package]] name = "heck" diff --git a/Cargo.toml b/Cargo.toml index ffac946b18f9..0b3ec8ed0004 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,6 +46,7 @@ debug = 0 [workspace.dependencies] # local crates +anymap = { path = "./crates/anymap", version = "0.0.0" } base-db = { path = "./crates/base-db", version = "0.0.0" } cfg = { path = "./crates/cfg", version = "0.0.0" } flycheck = { path = "./crates/flycheck", version = "0.0.0" } @@ -91,9 +92,9 @@ lsp-server = { version = "0.7.4" } # non-local crates smallvec = { version = "1.10.0", features = [ - "const_new", - "union", - "const_generics", + "const_new", + "union", + "const_generics", ] } smol_str = "0.2.0" nohash-hasher = "0.2.0" @@ -103,5 +104,12 @@ serde_json = "1.0.96" triomphe = { version = "0.1.8", default-features = false, features = ["std"] } # can't upgrade due to dashmap depending on 0.12.3 currently hashbrown = { version = "0.12.3", features = [ - "inline-more", + "inline-more", ], default-features = false } + +rustc_lexer = { version = "0.10.0", package = "ra-ap-rustc_lexer" } +rustc_parse_format = { version = "0.10.0", package = "ra-ap-rustc_parse_format", default-features = false } + +# Upstream broke this for us so we can't update it +rustc_abi = { version = "0.0.20221221", package = "hkalbasi-rustc-ap-rustc_abi", default-features = false } +rustc_index = { version = "0.0.20221221", package = "hkalbasi-rustc-ap-rustc_index", default-features = false } diff --git a/crates/anymap/Cargo.toml b/crates/anymap/Cargo.toml new file mode 100644 index 000000000000..5f3976edcbd3 --- /dev/null +++ b/crates/anymap/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "anymap" +version = "0.0.0" +description = "This crate is a port of only the necessary features from https://github.com/chris-morgan/anymap for use within rust-analyzer. Copyright © 2014–2022 Chris Morgan. COPYING: https://github.com/chris-morgan/anymap/blob/master/COPYING" + +authors.workspace = true +edition.workspace = true +license.workspace = true +rust-version.workspace = true + +[package.metadata.docs.rs] +all-features = true + +[features] +default = ["std"] +std = [] + +[dependencies] +# The hashbrown feature, disabled by default, is exposed under different stability guarantees than the usual SemVer ones: by preference the version range will only be extended, but it may be shrunk in a MINOR release. See README.md. +hashbrown = { version = "0.14.0", optional = true } diff --git a/crates/anymap/src/any.rs b/crates/anymap/src/any.rs new file mode 100644 index 000000000000..1e205e7c9d1e --- /dev/null +++ b/crates/anymap/src/any.rs @@ -0,0 +1,134 @@ +//! Copyright © 2014–2022 Chris Morgan +//! https://github.com/chris-morgan/anymap/blob/master/COPYING +//! impl some traits for dyn Any +use core::any::{Any, TypeId}; +use core::fmt; + +#[doc(hidden)] +pub trait CloneToAny { + /// Clone `self` into a new `Box` object. + fn clone_to_any(&self) -> Box; +} + +impl CloneToAny for T { + #[inline] + fn clone_to_any(&self) -> Box { + Box::new(self.clone()) + } +} + +macro_rules! impl_clone { + ($t:ty) => { + impl Clone for Box<$t> { + #[inline] + fn clone(&self) -> Box<$t> { + // SAFETY: this dance is to reapply any Send/Sync marker. I’m not happy about this + // approach, given that I used to do it in safe code, but then came a dodgy + // future-compatibility warning where_clauses_object_safety, which is spurious for + // auto traits but still super annoying (future-compatibility lints seem to mean + // your bin crate needs a corresponding allow!). Although I explained my plight¹ + // and it was all explained and agreed upon, no action has been taken. So I finally + // caved and worked around it by doing it this way, which matches what’s done for + // core::any², so it’s probably not *too* bad. + // + // ¹ https://github.com/rust-lang/rust/issues/51443#issuecomment-421988013 + // ² https://github.com/rust-lang/rust/blob/e7825f2b690c9a0d21b6f6d84c404bb53b151b38/library/alloc/src/boxed.rs#L1613-L1616 + let clone: Box = (**self).clone_to_any(); + let raw: *mut dyn CloneAny = Box::into_raw(clone); + unsafe { Box::from_raw(raw as *mut $t) } + } + } + + impl fmt::Debug for $t { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad(stringify!($t)) + } + } + }; +} + +/// Methods for downcasting from an `Any`-like trait object. +/// +/// This should only be implemented on trait objects for subtraits of `Any`, though you can +/// implement it for other types and it’ll work fine, so long as your implementation is correct. +pub trait Downcast { + /// Gets the `TypeId` of `self`. + fn type_id(&self) -> TypeId; + + // Note the bound through these downcast methods is 'static, rather than the inexpressible + // concept of Self-but-as-a-trait (where Self is `dyn Trait`). This is sufficient, exceeding + // TypeId’s requirements. Sure, you *can* do CloneAny.downcast_unchecked::() and the + // type system won’t protect you, but that doesn’t introduce any unsafety: the method is + // already unsafe because you can specify the wrong type, and if this were exposing safe + // downcasting, CloneAny.downcast::() would just return an error, which is just as + // correct. + // + // Now in theory we could also add T: ?Sized, but that doesn’t play nicely with the common + // implementation, so I’m doing without it. + + /// Downcast from `&Any` to `&T`, without checking the type matches. + /// + /// # Safety + /// + /// The caller must ensure that `T` matches the trait object, on pain of *undefined behaviour*. + unsafe fn downcast_ref_unchecked(&self) -> &T; + + /// Downcast from `&mut Any` to `&mut T`, without checking the type matches. + /// + /// # Safety + /// + /// The caller must ensure that `T` matches the trait object, on pain of *undefined behaviour*. + unsafe fn downcast_mut_unchecked(&mut self) -> &mut T; +} + +/// A trait for the conversion of an object into a boxed trait object. +pub trait IntoBox: Any { + /// Convert self into the appropriate boxed form. + fn into_box(self) -> Box; +} + +macro_rules! implement { + ($any_trait:ident $(+ $auto_traits:ident)*) => { + impl Downcast for dyn $any_trait $(+ $auto_traits)* { + #[inline] + fn type_id(&self) -> TypeId { + self.type_id() + } + + #[inline] + unsafe fn downcast_ref_unchecked(&self) -> &T { + &*(self as *const Self as *const T) + } + + #[inline] + unsafe fn downcast_mut_unchecked(&mut self) -> &mut T { + &mut *(self as *mut Self as *mut T) + } + } + + impl IntoBox for T { + #[inline] + fn into_box(self) -> Box { + Box::new(self) + } + } + } +} + +implement!(Any); +implement!(Any + Send); +implement!(Any + Send + Sync); + +/// [`Any`], but with cloning. +/// +/// Every type with no non-`'static` references that implements `Clone` implements `CloneAny`. +/// See [`core::any`] for more details on `Any` in general. +pub trait CloneAny: Any + CloneToAny {} +impl CloneAny for T {} +implement!(CloneAny); +implement!(CloneAny + Send); +implement!(CloneAny + Send + Sync); +impl_clone!(dyn CloneAny); +impl_clone!(dyn CloneAny + Send); +impl_clone!(dyn CloneAny + Send + Sync); diff --git a/crates/anymap/src/lib.rs b/crates/anymap/src/lib.rs new file mode 100644 index 000000000000..967c3769ec63 --- /dev/null +++ b/crates/anymap/src/lib.rs @@ -0,0 +1,275 @@ +//! Copyright © 2014–2022 Chris Morgan +//! https://github.com/chris-morgan/anymap/blob/master/COPYING +//! +//! This crate provides a safe and convenient store for one value of each type. +//! +//! Your starting point is [`Map`]. It has an example. +//! +//! # Cargo features +//! +//! This crate has two independent features, each of which provides an implementation providing +//! types `Map`, `AnyMap`, `OccupiedEntry`, `VacantEntry`, `Entry` and `RawMap`: +//! +#![cfg_attr(feature = "std", doc = " - **std** (default, *enabled* in this build):")] +#![cfg_attr(not(feature = "std"), doc = " - **std** (default, *disabled* in this build):")] +//! an implementation using `std::collections::hash_map`, placed in the crate root +//! (e.g. `anymap::AnyMap`). +//! +#![cfg_attr(feature = "hashbrown", doc = " - **hashbrown** (optional; *enabled* in this build):")] +#![cfg_attr( + not(feature = "hashbrown"), + doc = " - **hashbrown** (optional; *disabled* in this build):" +)] +//! an implementation using `alloc` and `hashbrown::hash_map`, placed in a module `hashbrown` +//! (e.g. `anymap::hashbrown::AnyMap`). + +#![warn(missing_docs, unused_results)] +#![cfg_attr(not(feature = "std"), no_std)] + +use core::convert::TryInto; +use core::hash::Hasher; + +pub use crate::any::CloneAny; + +mod any; + +/// A hasher designed to eke a little more speed out, given `TypeId`’s known characteristics. +/// +/// Specifically, this is a no-op hasher that expects to be fed a u64’s worth of +/// randomly-distributed bits. It works well for `TypeId` (eliminating start-up time, so that my +/// get_missing benchmark is ~30ns rather than ~900ns, and being a good deal faster after that, so +/// that my insert_and_get_on_260_types benchmark is ~12μs instead of ~21.5μs), but will +/// panic in debug mode and always emit zeros in release mode for any other sorts of inputs, so +/// yeah, don’t use it! 😀 +#[derive(Default)] +pub struct TypeIdHasher { + value: u64, +} + +impl Hasher for TypeIdHasher { + #[inline] + fn write(&mut self, bytes: &[u8]) { + // This expects to receive exactly one 64-bit value, and there’s no realistic chance of + // that changing, but I don’t want to depend on something that isn’t expressly part of the + // contract for safety. But I’m OK with release builds putting everything in one bucket + // if it *did* change (and debug builds panicking). + debug_assert_eq!(bytes.len(), 8); + let _ = bytes.try_into().map(|array| self.value = u64::from_ne_bytes(array)); + } + + #[inline] + fn finish(&self) -> u64 { + self.value + } +} + +#[cfg(any(feature = "std", feature = "hashbrown"))] +macro_rules! everything { + ($example_init:literal, $($parent:ident)::+ $(, $entry_generics:ty)?) => { + use core::any::{Any, TypeId}; + use core::hash::BuildHasherDefault; + use core::marker::PhantomData; + + #[cfg(not(feature = "std"))] + use alloc::boxed::Box; + + use ::$($parent)::+::hash_map::{self, HashMap}; + + use crate::any::{Downcast, IntoBox}; + + /// Raw access to the underlying `HashMap`. + /// + /// This alias is provided for convenience because of the ugly third generic parameter. + pub type RawMap = HashMap, BuildHasherDefault>; + + /// A collection containing zero or one values for any given type and allowing convenient, + /// type-safe access to those values. + /// + /// The type parameter `A` allows you to use a different value type; normally you will want + /// it to be `core::any::Any` (also known as `std::any::Any`), but there are other choices: + /// + /// - If you want the entire map to be cloneable, use `CloneAny` instead of `Any`; with + /// that, you can only add types that implement `Clone` to the map. + /// - You can add on `+ Send` or `+ Send + Sync` (e.g. `Map`) to add those + /// auto traits. + /// + /// Cumulatively, there are thus six forms of map: + /// + /// - [Map]<dyn [core::any::Any]>, + /// also spelled [`AnyMap`] for convenience. + /// - [Map]<dyn [core::any::Any] + Send> + /// - [Map]<dyn [core::any::Any] + Send + Sync> + /// - [Map]<dyn [CloneAny]> + /// - [Map]<dyn [CloneAny] + Send> + /// - [Map]<dyn [CloneAny] + Send + Sync> + /// + /// ## Example + /// + /// (Here using the [`AnyMap`] convenience alias; the first line could use + /// [anymap::Map][Map]::<[core::any::Any]>::new() instead if desired.) + /// + /// ```rust + #[doc = $example_init] + /// assert_eq!(data.get(), None::<&i32>); + /// ``` + /// + /// Values containing non-static references are not permitted. + #[derive(Debug)] + pub struct Map { + raw: RawMap, + } + + /// The most common type of `Map`: just using `Any`; [Map]<dyn [Any]>. + /// + /// Why is this a separate type alias rather than a default value for `Map`? + /// `Map::new()` doesn’t seem to be happy to infer that it should go with the default + /// value. It’s a bit sad, really. Ah well, I guess this approach will do. + pub type AnyMap = Map; + impl Default for Map { + #[inline] + fn default() -> Map { + Map::new() + } + } + + impl Map { + /// Create an empty collection. + #[inline] + pub fn new() -> Map { + Map { + raw: RawMap::with_hasher(Default::default()), + } + } + + /// Returns a reference to the value stored in the collection for the type `T`, + /// if it exists. + #[inline] + pub fn get>(&self) -> Option<&T> { + self.raw.get(&TypeId::of::()) + .map(|any| unsafe { any.downcast_ref_unchecked::() }) + } + + /// Gets the entry for the given type in the collection for in-place manipulation + #[inline] + pub fn entry>(&mut self) -> Entry { + match self.raw.entry(TypeId::of::()) { + hash_map::Entry::Occupied(e) => Entry::Occupied(OccupiedEntry { + inner: e, + type_: PhantomData, + }), + hash_map::Entry::Vacant(e) => Entry::Vacant(VacantEntry { + inner: e, + type_: PhantomData, + }), + } + } + + } + + /// A view into a single occupied location in an `Map`. + pub struct OccupiedEntry<'a, A: ?Sized + Downcast, V: 'a> { + inner: hash_map::OccupiedEntry<'a, TypeId, Box, $($entry_generics)?>, + type_: PhantomData, + } + + /// A view into a single empty location in an `Map`. + pub struct VacantEntry<'a, A: ?Sized + Downcast, V: 'a> { + inner: hash_map::VacantEntry<'a, TypeId, Box, $($entry_generics)?>, + type_: PhantomData, + } + + /// A view into a single location in an `Map`, which may be vacant or occupied. + pub enum Entry<'a, A: ?Sized + Downcast, V: 'a> { + /// An occupied Entry + Occupied(OccupiedEntry<'a, A, V>), + /// A vacant Entry + Vacant(VacantEntry<'a, A, V>), + } + + impl<'a, A: ?Sized + Downcast, V: IntoBox> Entry<'a, A, V> { + + + /// Ensures a value is in the entry by inserting the result of the default function if + /// empty, and returns a mutable reference to the value in the entry. + #[inline] + pub fn or_insert_with V>(self, default: F) -> &'a mut V { + match self { + Entry::Occupied(inner) => inner.into_mut(), + Entry::Vacant(inner) => inner.insert(default()), + } + } + } + + impl<'a, A: ?Sized + Downcast, V: IntoBox> OccupiedEntry<'a, A, V> { + /// Converts the OccupiedEntry into a mutable reference to the value in the entry + /// with a lifetime bound to the collection itself + #[inline] + pub fn into_mut(self) -> &'a mut V { + unsafe { self.inner.into_mut().downcast_mut_unchecked() } + } + } + + impl<'a, A: ?Sized + Downcast, V: IntoBox> VacantEntry<'a, A, V> { + /// Sets the value of the entry with the VacantEntry's key, + /// and returns a mutable reference to it + #[inline] + pub fn insert(self, value: V) -> &'a mut V { + unsafe { self.inner.insert(value.into_box()).downcast_mut_unchecked() } + } + } + + #[cfg(test)] + mod tests { + use crate::CloneAny; + use super::*; + + #[derive(Clone, Debug, PartialEq)] struct A(i32); + #[derive(Clone, Debug, PartialEq)] struct B(i32); + #[derive(Clone, Debug, PartialEq)] struct C(i32); + #[derive(Clone, Debug, PartialEq)] struct D(i32); + #[derive(Clone, Debug, PartialEq)] struct E(i32); + #[derive(Clone, Debug, PartialEq)] struct F(i32); + #[derive(Clone, Debug, PartialEq)] struct J(i32); + + #[test] + fn test_varieties() { + fn assert_send() { } + fn assert_sync() { } + fn assert_debug() { } + assert_send::>(); + assert_send::>(); + assert_sync::>(); + assert_debug::>(); + assert_debug::>(); + assert_debug::>(); + assert_send::>(); + assert_send::>(); + assert_sync::>(); + assert_debug::>(); + assert_debug::>(); + assert_debug::>(); + } + } + }; +} + +#[test] +fn type_id_hasher() { + use core::any::TypeId; + use core::hash::Hash; + fn verify_hashing_with(type_id: TypeId) { + let mut hasher = TypeIdHasher::default(); + type_id.hash(&mut hasher); + // SAFETY: u64 is valid for all bit patterns. + let _ = hasher.finish(); + } + // Pick a variety of types, just to demonstrate it’s all sane. Normal, zero-sized, unsized, &c. + verify_hashing_with(TypeId::of::()); + verify_hashing_with(TypeId::of::<()>()); + verify_hashing_with(TypeId::of::()); + verify_hashing_with(TypeId::of::<&str>()); + verify_hashing_with(TypeId::of::>()); +} + +#[cfg(feature = "std")] +everything!("let mut data = anymap::AnyMap::new();", std::collections); diff --git a/crates/hir-def/Cargo.toml b/crates/hir-def/Cargo.toml index 092aab011205..261172ad9468 100644 --- a/crates/hir-def/Cargo.toml +++ b/crates/hir-def/Cargo.toml @@ -12,7 +12,6 @@ rust-version.workspace = true doctest = false [dependencies] -anymap = "1.0.0-beta.2" arrayvec = "0.7.2" bitflags = "2.1.0" cov-mark = "2.0.0-pre.1" @@ -34,6 +33,7 @@ triomphe.workspace = true rustc-dependencies.workspace = true # local deps +anymap.workspace = true stdx.workspace = true intern.workspace = true base-db.workspace = true @@ -45,6 +45,7 @@ cfg.workspace = true tt.workspace = true limit.workspace = true + [dev-dependencies] expect-test = "1.4.0" diff --git a/crates/rust-analyzer/tests/slow-tests/tidy.rs b/crates/rust-analyzer/tests/slow-tests/tidy.rs index 8b5c92c66023..fdc710f7c840 100644 --- a/crates/rust-analyzer/tests/slow-tests/tidy.rs +++ b/crates/rust-analyzer/tests/slow-tests/tidy.rs @@ -157,7 +157,6 @@ Apache-2.0 OR MIT Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT Apache-2.0/MIT BSD-3-Clause -BlueOak-1.0.0 OR MIT OR Apache-2.0 CC0-1.0 ISC MIT From 00e238e99bdd0f2f8ed285fbb160b3755164cbbf Mon Sep 17 00:00:00 2001 From: shogo-nakano-desu <61229807+shogo-nakano-desu@users.noreply.github.com> Date: Wed, 20 Sep 2023 08:34:14 +0900 Subject: [PATCH 045/435] refactor: remove unnecesary cfg_attr and inline macro --- crates/anymap/src/lib.rs | 400 +++++++++++++++++++-------------------- 1 file changed, 191 insertions(+), 209 deletions(-) diff --git a/crates/anymap/src/lib.rs b/crates/anymap/src/lib.rs index 967c3769ec63..d8c6c889f78d 100644 --- a/crates/anymap/src/lib.rs +++ b/crates/anymap/src/lib.rs @@ -10,21 +10,15 @@ //! This crate has two independent features, each of which provides an implementation providing //! types `Map`, `AnyMap`, `OccupiedEntry`, `VacantEntry`, `Entry` and `RawMap`: //! -#![cfg_attr(feature = "std", doc = " - **std** (default, *enabled* in this build):")] -#![cfg_attr(not(feature = "std"), doc = " - **std** (default, *disabled* in this build):")] +//! - **std** (default, *enabled* in this build): //! an implementation using `std::collections::hash_map`, placed in the crate root //! (e.g. `anymap::AnyMap`). //! -#![cfg_attr(feature = "hashbrown", doc = " - **hashbrown** (optional; *enabled* in this build):")] -#![cfg_attr( - not(feature = "hashbrown"), - doc = " - **hashbrown** (optional; *disabled* in this build):" -)] +//! - **hashbrown** (optional; *enabled* in this build): //! an implementation using `alloc` and `hashbrown::hash_map`, placed in a module `hashbrown` //! (e.g. `anymap::hashbrown::AnyMap`). #![warn(missing_docs, unused_results)] -#![cfg_attr(not(feature = "std"), no_std)] use core::convert::TryInto; use core::hash::Hasher; @@ -63,213 +57,201 @@ impl Hasher for TypeIdHasher { } } -#[cfg(any(feature = "std", feature = "hashbrown"))] -macro_rules! everything { - ($example_init:literal, $($parent:ident)::+ $(, $entry_generics:ty)?) => { - use core::any::{Any, TypeId}; - use core::hash::BuildHasherDefault; - use core::marker::PhantomData; +use core::any::{Any, TypeId}; +use core::hash::BuildHasherDefault; +use core::marker::PhantomData; - #[cfg(not(feature = "std"))] - use alloc::boxed::Box; +use ::std::collections::hash_map::{self, HashMap}; - use ::$($parent)::+::hash_map::{self, HashMap}; +use crate::any::{Downcast, IntoBox}; - use crate::any::{Downcast, IntoBox}; +/// Raw access to the underlying `HashMap`. +/// +/// This alias is provided for convenience because of the ugly third generic parameter. +pub type RawMap = HashMap, BuildHasherDefault>; - /// Raw access to the underlying `HashMap`. - /// - /// This alias is provided for convenience because of the ugly third generic parameter. - pub type RawMap = HashMap, BuildHasherDefault>; - - /// A collection containing zero or one values for any given type and allowing convenient, - /// type-safe access to those values. - /// - /// The type parameter `A` allows you to use a different value type; normally you will want - /// it to be `core::any::Any` (also known as `std::any::Any`), but there are other choices: - /// - /// - If you want the entire map to be cloneable, use `CloneAny` instead of `Any`; with - /// that, you can only add types that implement `Clone` to the map. - /// - You can add on `+ Send` or `+ Send + Sync` (e.g. `Map`) to add those - /// auto traits. - /// - /// Cumulatively, there are thus six forms of map: - /// - /// - [Map]<dyn [core::any::Any]>, - /// also spelled [`AnyMap`] for convenience. - /// - [Map]<dyn [core::any::Any] + Send> - /// - [Map]<dyn [core::any::Any] + Send + Sync> - /// - [Map]<dyn [CloneAny]> - /// - [Map]<dyn [CloneAny] + Send> - /// - [Map]<dyn [CloneAny] + Send + Sync> - /// - /// ## Example - /// - /// (Here using the [`AnyMap`] convenience alias; the first line could use - /// [anymap::Map][Map]::<[core::any::Any]>::new() instead if desired.) - /// - /// ```rust - #[doc = $example_init] - /// assert_eq!(data.get(), None::<&i32>); - /// ``` - /// - /// Values containing non-static references are not permitted. - #[derive(Debug)] - pub struct Map { - raw: RawMap, - } - - /// The most common type of `Map`: just using `Any`; [Map]<dyn [Any]>. - /// - /// Why is this a separate type alias rather than a default value for `Map`? - /// `Map::new()` doesn’t seem to be happy to infer that it should go with the default - /// value. It’s a bit sad, really. Ah well, I guess this approach will do. - pub type AnyMap = Map; - impl Default for Map { - #[inline] - fn default() -> Map { - Map::new() - } - } - - impl Map { - /// Create an empty collection. - #[inline] - pub fn new() -> Map { - Map { - raw: RawMap::with_hasher(Default::default()), - } - } - - /// Returns a reference to the value stored in the collection for the type `T`, - /// if it exists. - #[inline] - pub fn get>(&self) -> Option<&T> { - self.raw.get(&TypeId::of::()) - .map(|any| unsafe { any.downcast_ref_unchecked::() }) - } - - /// Gets the entry for the given type in the collection for in-place manipulation - #[inline] - pub fn entry>(&mut self) -> Entry { - match self.raw.entry(TypeId::of::()) { - hash_map::Entry::Occupied(e) => Entry::Occupied(OccupiedEntry { - inner: e, - type_: PhantomData, - }), - hash_map::Entry::Vacant(e) => Entry::Vacant(VacantEntry { - inner: e, - type_: PhantomData, - }), - } - } - - } - - /// A view into a single occupied location in an `Map`. - pub struct OccupiedEntry<'a, A: ?Sized + Downcast, V: 'a> { - inner: hash_map::OccupiedEntry<'a, TypeId, Box, $($entry_generics)?>, - type_: PhantomData, - } - - /// A view into a single empty location in an `Map`. - pub struct VacantEntry<'a, A: ?Sized + Downcast, V: 'a> { - inner: hash_map::VacantEntry<'a, TypeId, Box, $($entry_generics)?>, - type_: PhantomData, - } - - /// A view into a single location in an `Map`, which may be vacant or occupied. - pub enum Entry<'a, A: ?Sized + Downcast, V: 'a> { - /// An occupied Entry - Occupied(OccupiedEntry<'a, A, V>), - /// A vacant Entry - Vacant(VacantEntry<'a, A, V>), - } - - impl<'a, A: ?Sized + Downcast, V: IntoBox> Entry<'a, A, V> { - - - /// Ensures a value is in the entry by inserting the result of the default function if - /// empty, and returns a mutable reference to the value in the entry. - #[inline] - pub fn or_insert_with V>(self, default: F) -> &'a mut V { - match self { - Entry::Occupied(inner) => inner.into_mut(), - Entry::Vacant(inner) => inner.insert(default()), - } - } - } - - impl<'a, A: ?Sized + Downcast, V: IntoBox> OccupiedEntry<'a, A, V> { - /// Converts the OccupiedEntry into a mutable reference to the value in the entry - /// with a lifetime bound to the collection itself - #[inline] - pub fn into_mut(self) -> &'a mut V { - unsafe { self.inner.into_mut().downcast_mut_unchecked() } - } - } - - impl<'a, A: ?Sized + Downcast, V: IntoBox> VacantEntry<'a, A, V> { - /// Sets the value of the entry with the VacantEntry's key, - /// and returns a mutable reference to it - #[inline] - pub fn insert(self, value: V) -> &'a mut V { - unsafe { self.inner.insert(value.into_box()).downcast_mut_unchecked() } - } - } - - #[cfg(test)] - mod tests { - use crate::CloneAny; - use super::*; - - #[derive(Clone, Debug, PartialEq)] struct A(i32); - #[derive(Clone, Debug, PartialEq)] struct B(i32); - #[derive(Clone, Debug, PartialEq)] struct C(i32); - #[derive(Clone, Debug, PartialEq)] struct D(i32); - #[derive(Clone, Debug, PartialEq)] struct E(i32); - #[derive(Clone, Debug, PartialEq)] struct F(i32); - #[derive(Clone, Debug, PartialEq)] struct J(i32); - - #[test] - fn test_varieties() { - fn assert_send() { } - fn assert_sync() { } - fn assert_debug() { } - assert_send::>(); - assert_send::>(); - assert_sync::>(); - assert_debug::>(); - assert_debug::>(); - assert_debug::>(); - assert_send::>(); - assert_send::>(); - assert_sync::>(); - assert_debug::>(); - assert_debug::>(); - assert_debug::>(); - } - } - }; +/// A collection containing zero or one values for any given type and allowing convenient, +/// type-safe access to those values. +/// +/// The type parameter `A` allows you to use a different value type; normally you will want +/// it to be `core::any::Any` (also known as `std::any::Any`), but there are other choices: +/// +/// - If you want the entire map to be cloneable, use `CloneAny` instead of `Any`; with +/// that, you can only add types that implement `Clone` to the map. +/// - You can add on `+ Send` or `+ Send + Sync` (e.g. `Map`) to add those +/// auto traits. +/// +/// Cumulatively, there are thus six forms of map: +/// +/// - [Map]<dyn [core::any::Any]>, +/// also spelled [`AnyMap`] for convenience. +/// - [Map]<dyn [core::any::Any] + Send> +/// - [Map]<dyn [core::any::Any] + Send + Sync> +/// - [Map]<dyn [CloneAny]> +/// - [Map]<dyn [CloneAny] + Send> +/// - [Map]<dyn [CloneAny] + Send + Sync> +/// +/// ## Example +/// +/// (Here using the [`AnyMap`] convenience alias; the first line could use +/// [anymap::Map][Map]::<[core::any::Any]>::new() instead if desired.) +/// +/// ```rust +#[doc = "let mut data = anymap::AnyMap::new();"] +/// assert_eq!(data.get(), None::<&i32>); +/// ``` +/// +/// Values containing non-static references are not permitted. +#[derive(Debug)] +pub struct Map { + raw: RawMap, } -#[test] -fn type_id_hasher() { - use core::any::TypeId; - use core::hash::Hash; - fn verify_hashing_with(type_id: TypeId) { - let mut hasher = TypeIdHasher::default(); - type_id.hash(&mut hasher); - // SAFETY: u64 is valid for all bit patterns. - let _ = hasher.finish(); +/// The most common type of `Map`: just using `Any`; [Map]<dyn [Any]>. +/// +/// Why is this a separate type alias rather than a default value for `Map`? +/// `Map::new()` doesn’t seem to be happy to infer that it should go with the default +/// value. It’s a bit sad, really. Ah well, I guess this approach will do. +pub type AnyMap = Map; +impl Default for Map { + #[inline] + fn default() -> Map { + Map::new() } - // Pick a variety of types, just to demonstrate it’s all sane. Normal, zero-sized, unsized, &c. - verify_hashing_with(TypeId::of::()); - verify_hashing_with(TypeId::of::<()>()); - verify_hashing_with(TypeId::of::()); - verify_hashing_with(TypeId::of::<&str>()); - verify_hashing_with(TypeId::of::>()); } -#[cfg(feature = "std")] -everything!("let mut data = anymap::AnyMap::new();", std::collections); +impl Map { + /// Create an empty collection. + #[inline] + pub fn new() -> Map { + Map { raw: RawMap::with_hasher(Default::default()) } + } + + /// Returns a reference to the value stored in the collection for the type `T`, + /// if it exists. + #[inline] + pub fn get>(&self) -> Option<&T> { + self.raw.get(&TypeId::of::()).map(|any| unsafe { any.downcast_ref_unchecked::() }) + } + + /// Gets the entry for the given type in the collection for in-place manipulation + #[inline] + pub fn entry>(&mut self) -> Entry { + match self.raw.entry(TypeId::of::()) { + hash_map::Entry::Occupied(e) => { + Entry::Occupied(OccupiedEntry { inner: e, type_: PhantomData }) + } + hash_map::Entry::Vacant(e) => { + Entry::Vacant(VacantEntry { inner: e, type_: PhantomData }) + } + } + } +} + +/// A view into a single occupied location in an `Map`. +pub struct OccupiedEntry<'a, A: ?Sized + Downcast, V: 'a> { + inner: hash_map::OccupiedEntry<'a, TypeId, Box>, + type_: PhantomData, +} + +/// A view into a single empty location in an `Map`. +pub struct VacantEntry<'a, A: ?Sized + Downcast, V: 'a> { + inner: hash_map::VacantEntry<'a, TypeId, Box>, + type_: PhantomData, +} + +/// A view into a single location in an `Map`, which may be vacant or occupied. +pub enum Entry<'a, A: ?Sized + Downcast, V: 'a> { + /// An occupied Entry + Occupied(OccupiedEntry<'a, A, V>), + /// A vacant Entry + Vacant(VacantEntry<'a, A, V>), +} + +impl<'a, A: ?Sized + Downcast, V: IntoBox> Entry<'a, A, V> { + /// Ensures a value is in the entry by inserting the result of the default function if + /// empty, and returns a mutable reference to the value in the entry. + #[inline] + pub fn or_insert_with V>(self, default: F) -> &'a mut V { + match self { + Entry::Occupied(inner) => inner.into_mut(), + Entry::Vacant(inner) => inner.insert(default()), + } + } +} + +impl<'a, A: ?Sized + Downcast, V: IntoBox> OccupiedEntry<'a, A, V> { + /// Converts the OccupiedEntry into a mutable reference to the value in the entry + /// with a lifetime bound to the collection itself + #[inline] + pub fn into_mut(self) -> &'a mut V { + unsafe { self.inner.into_mut().downcast_mut_unchecked() } + } +} + +impl<'a, A: ?Sized + Downcast, V: IntoBox> VacantEntry<'a, A, V> { + /// Sets the value of the entry with the VacantEntry's key, + /// and returns a mutable reference to it + #[inline] + pub fn insert(self, value: V) -> &'a mut V { + unsafe { self.inner.insert(value.into_box()).downcast_mut_unchecked() } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::CloneAny; + + #[derive(Clone, Debug, PartialEq)] + struct A(i32); + #[derive(Clone, Debug, PartialEq)] + struct B(i32); + #[derive(Clone, Debug, PartialEq)] + struct C(i32); + #[derive(Clone, Debug, PartialEq)] + struct D(i32); + #[derive(Clone, Debug, PartialEq)] + struct E(i32); + #[derive(Clone, Debug, PartialEq)] + struct F(i32); + #[derive(Clone, Debug, PartialEq)] + struct J(i32); + + #[test] + fn test_varieties() { + fn assert_send() {} + fn assert_sync() {} + fn assert_debug() {} + assert_send::>(); + assert_send::>(); + assert_sync::>(); + assert_debug::>(); + assert_debug::>(); + assert_debug::>(); + assert_send::>(); + assert_send::>(); + assert_sync::>(); + assert_debug::>(); + assert_debug::>(); + assert_debug::>(); + } + + #[test] + fn type_id_hasher() { + use core::any::TypeId; + use core::hash::Hash; + fn verify_hashing_with(type_id: TypeId) { + let mut hasher = TypeIdHasher::default(); + type_id.hash(&mut hasher); + // SAFETY: u64 is valid for all bit patterns. + let _ = hasher.finish(); + } + // Pick a variety of types, just to demonstrate it’s all sane. Normal, zero-sized, unsized, &c. + verify_hashing_with(TypeId::of::()); + verify_hashing_with(TypeId::of::<()>()); + verify_hashing_with(TypeId::of::()); + verify_hashing_with(TypeId::of::<&str>()); + verify_hashing_with(TypeId::of::>()); + } +} From f671b0b8644aff682616025af5e1a1780ffab0c3 Mon Sep 17 00:00:00 2001 From: shogo-nakano-desu <61229807+shogo-nakano-desu@users.noreply.github.com> Date: Wed, 20 Sep 2023 08:48:15 +0900 Subject: [PATCH 046/435] refactor: move implementation inside anymap crate into stdx crate --- Cargo.lock | 9 +- Cargo.toml | 1 - crates/anymap/Cargo.toml | 20 --- crates/anymap/src/any.rs | 134 ---------------- crates/hir-def/Cargo.toml | 1 - crates/hir-def/src/dyn_map.rs | 2 +- crates/stdx/Cargo.toml | 1 + .../{anymap/src/lib.rs => stdx/src/anymap.rs} | 145 ++++++++++++++++-- crates/stdx/src/lib.rs | 1 + 9 files changed, 140 insertions(+), 174 deletions(-) delete mode 100644 crates/anymap/Cargo.toml delete mode 100644 crates/anymap/src/any.rs rename crates/{anymap/src/lib.rs => stdx/src/anymap.rs} (63%) diff --git a/Cargo.lock b/Cargo.lock index 6b0f7efc6ca6..5dcf68e0ce76 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -49,13 +49,6 @@ version = "1.0.71" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" -[[package]] -name = "anymap" -version = "0.0.0" -dependencies = [ - "hashbrown 0.14.0", -] - [[package]] name = "arbitrary" version = "1.3.0" @@ -540,7 +533,6 @@ dependencies = [ name = "hir-def" version = "0.0.0" dependencies = [ - "anymap", "arrayvec", "base-db", "bitflags 2.3.2", @@ -1831,6 +1823,7 @@ dependencies = [ "always-assert", "backtrace", "crossbeam-channel", + "hashbrown 0.14.0", "jod-thread", "libc", "miow", diff --git a/Cargo.toml b/Cargo.toml index 0b3ec8ed0004..dd4348785df7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,7 +46,6 @@ debug = 0 [workspace.dependencies] # local crates -anymap = { path = "./crates/anymap", version = "0.0.0" } base-db = { path = "./crates/base-db", version = "0.0.0" } cfg = { path = "./crates/cfg", version = "0.0.0" } flycheck = { path = "./crates/flycheck", version = "0.0.0" } diff --git a/crates/anymap/Cargo.toml b/crates/anymap/Cargo.toml deleted file mode 100644 index 5f3976edcbd3..000000000000 --- a/crates/anymap/Cargo.toml +++ /dev/null @@ -1,20 +0,0 @@ -[package] -name = "anymap" -version = "0.0.0" -description = "This crate is a port of only the necessary features from https://github.com/chris-morgan/anymap for use within rust-analyzer. Copyright © 2014–2022 Chris Morgan. COPYING: https://github.com/chris-morgan/anymap/blob/master/COPYING" - -authors.workspace = true -edition.workspace = true -license.workspace = true -rust-version.workspace = true - -[package.metadata.docs.rs] -all-features = true - -[features] -default = ["std"] -std = [] - -[dependencies] -# The hashbrown feature, disabled by default, is exposed under different stability guarantees than the usual SemVer ones: by preference the version range will only be extended, but it may be shrunk in a MINOR release. See README.md. -hashbrown = { version = "0.14.0", optional = true } diff --git a/crates/anymap/src/any.rs b/crates/anymap/src/any.rs deleted file mode 100644 index 1e205e7c9d1e..000000000000 --- a/crates/anymap/src/any.rs +++ /dev/null @@ -1,134 +0,0 @@ -//! Copyright © 2014–2022 Chris Morgan -//! https://github.com/chris-morgan/anymap/blob/master/COPYING -//! impl some traits for dyn Any -use core::any::{Any, TypeId}; -use core::fmt; - -#[doc(hidden)] -pub trait CloneToAny { - /// Clone `self` into a new `Box` object. - fn clone_to_any(&self) -> Box; -} - -impl CloneToAny for T { - #[inline] - fn clone_to_any(&self) -> Box { - Box::new(self.clone()) - } -} - -macro_rules! impl_clone { - ($t:ty) => { - impl Clone for Box<$t> { - #[inline] - fn clone(&self) -> Box<$t> { - // SAFETY: this dance is to reapply any Send/Sync marker. I’m not happy about this - // approach, given that I used to do it in safe code, but then came a dodgy - // future-compatibility warning where_clauses_object_safety, which is spurious for - // auto traits but still super annoying (future-compatibility lints seem to mean - // your bin crate needs a corresponding allow!). Although I explained my plight¹ - // and it was all explained and agreed upon, no action has been taken. So I finally - // caved and worked around it by doing it this way, which matches what’s done for - // core::any², so it’s probably not *too* bad. - // - // ¹ https://github.com/rust-lang/rust/issues/51443#issuecomment-421988013 - // ² https://github.com/rust-lang/rust/blob/e7825f2b690c9a0d21b6f6d84c404bb53b151b38/library/alloc/src/boxed.rs#L1613-L1616 - let clone: Box = (**self).clone_to_any(); - let raw: *mut dyn CloneAny = Box::into_raw(clone); - unsafe { Box::from_raw(raw as *mut $t) } - } - } - - impl fmt::Debug for $t { - #[inline] - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.pad(stringify!($t)) - } - } - }; -} - -/// Methods for downcasting from an `Any`-like trait object. -/// -/// This should only be implemented on trait objects for subtraits of `Any`, though you can -/// implement it for other types and it’ll work fine, so long as your implementation is correct. -pub trait Downcast { - /// Gets the `TypeId` of `self`. - fn type_id(&self) -> TypeId; - - // Note the bound through these downcast methods is 'static, rather than the inexpressible - // concept of Self-but-as-a-trait (where Self is `dyn Trait`). This is sufficient, exceeding - // TypeId’s requirements. Sure, you *can* do CloneAny.downcast_unchecked::() and the - // type system won’t protect you, but that doesn’t introduce any unsafety: the method is - // already unsafe because you can specify the wrong type, and if this were exposing safe - // downcasting, CloneAny.downcast::() would just return an error, which is just as - // correct. - // - // Now in theory we could also add T: ?Sized, but that doesn’t play nicely with the common - // implementation, so I’m doing without it. - - /// Downcast from `&Any` to `&T`, without checking the type matches. - /// - /// # Safety - /// - /// The caller must ensure that `T` matches the trait object, on pain of *undefined behaviour*. - unsafe fn downcast_ref_unchecked(&self) -> &T; - - /// Downcast from `&mut Any` to `&mut T`, without checking the type matches. - /// - /// # Safety - /// - /// The caller must ensure that `T` matches the trait object, on pain of *undefined behaviour*. - unsafe fn downcast_mut_unchecked(&mut self) -> &mut T; -} - -/// A trait for the conversion of an object into a boxed trait object. -pub trait IntoBox: Any { - /// Convert self into the appropriate boxed form. - fn into_box(self) -> Box; -} - -macro_rules! implement { - ($any_trait:ident $(+ $auto_traits:ident)*) => { - impl Downcast for dyn $any_trait $(+ $auto_traits)* { - #[inline] - fn type_id(&self) -> TypeId { - self.type_id() - } - - #[inline] - unsafe fn downcast_ref_unchecked(&self) -> &T { - &*(self as *const Self as *const T) - } - - #[inline] - unsafe fn downcast_mut_unchecked(&mut self) -> &mut T { - &mut *(self as *mut Self as *mut T) - } - } - - impl IntoBox for T { - #[inline] - fn into_box(self) -> Box { - Box::new(self) - } - } - } -} - -implement!(Any); -implement!(Any + Send); -implement!(Any + Send + Sync); - -/// [`Any`], but with cloning. -/// -/// Every type with no non-`'static` references that implements `Clone` implements `CloneAny`. -/// See [`core::any`] for more details on `Any` in general. -pub trait CloneAny: Any + CloneToAny {} -impl CloneAny for T {} -implement!(CloneAny); -implement!(CloneAny + Send); -implement!(CloneAny + Send + Sync); -impl_clone!(dyn CloneAny); -impl_clone!(dyn CloneAny + Send); -impl_clone!(dyn CloneAny + Send + Sync); diff --git a/crates/hir-def/Cargo.toml b/crates/hir-def/Cargo.toml index 261172ad9468..99b8e9bf0e14 100644 --- a/crates/hir-def/Cargo.toml +++ b/crates/hir-def/Cargo.toml @@ -33,7 +33,6 @@ triomphe.workspace = true rustc-dependencies.workspace = true # local deps -anymap.workspace = true stdx.workspace = true intern.workspace = true base-db.workspace = true diff --git a/crates/hir-def/src/dyn_map.rs b/crates/hir-def/src/dyn_map.rs index 63138aa6ad78..a59bbf7e2211 100644 --- a/crates/hir-def/src/dyn_map.rs +++ b/crates/hir-def/src/dyn_map.rs @@ -29,8 +29,8 @@ use std::{ ops::{Index, IndexMut}, }; -use anymap::Map; use rustc_hash::FxHashMap; +use stdx::anymap::Map; pub struct Key { _phantom: PhantomData<(K, V, P)>, diff --git a/crates/stdx/Cargo.toml b/crates/stdx/Cargo.toml index 536f000a44b7..fae16fa2e428 100644 --- a/crates/stdx/Cargo.toml +++ b/crates/stdx/Cargo.toml @@ -17,6 +17,7 @@ backtrace = { version = "0.3.67", optional = true } always-assert = { version = "0.1.2", features = ["log"] } jod-thread = "0.1.2" crossbeam-channel = "0.5.5" +hashbrown = { version = "0.14.0" } # Think twice before adding anything here [target.'cfg(windows)'.dependencies] diff --git a/crates/anymap/src/lib.rs b/crates/stdx/src/anymap.rs similarity index 63% rename from crates/anymap/src/lib.rs rename to crates/stdx/src/anymap.rs index d8c6c889f78d..0f4ae0a440cc 100644 --- a/crates/anymap/src/lib.rs +++ b/crates/stdx/src/anymap.rs @@ -1,5 +1,7 @@ //! Copyright © 2014–2022 Chris Morgan //! https://github.com/chris-morgan/anymap/blob/master/COPYING +//! Copyright © 2014–2022 Chris Morgan +//! https://github.com/chris-morgan/anymap/blob/master/COPYING //! //! This crate provides a safe and convenient store for one value of each type. //! @@ -23,10 +25,6 @@ use core::convert::TryInto; use core::hash::Hasher; -pub use crate::any::CloneAny; - -mod any; - /// A hasher designed to eke a little more speed out, given `TypeId`’s known characteristics. /// /// Specifically, this is a no-op hasher that expects to be fed a u64’s worth of @@ -63,8 +61,6 @@ use core::marker::PhantomData; use ::std::collections::hash_map::{self, HashMap}; -use crate::any::{Downcast, IntoBox}; - /// Raw access to the underlying `HashMap`. /// /// This alias is provided for convenience because of the ugly third generic parameter. @@ -136,7 +132,7 @@ impl Map { /// Gets the entry for the given type in the collection for in-place manipulation #[inline] - pub fn entry>(&mut self) -> Entry { + pub fn entry>(&mut self) -> Entry<'_, A, T> { match self.raw.entry(TypeId::of::()) { hash_map::Entry::Occupied(e) => { Entry::Occupied(OccupiedEntry { inner: e, type_: PhantomData }) @@ -161,7 +157,7 @@ pub struct VacantEntry<'a, A: ?Sized + Downcast, V: 'a> { } /// A view into a single location in an `Map`, which may be vacant or occupied. -pub enum Entry<'a, A: ?Sized + Downcast, V: 'a> { +pub enum Entry<'a, A: ?Sized + Downcast, V> { /// An occupied Entry Occupied(OccupiedEntry<'a, A, V>), /// A vacant Entry @@ -201,7 +197,6 @@ impl<'a, A: ?Sized + Downcast, V: IntoBox> VacantEntry<'a, A, V> { #[cfg(test)] mod tests { use super::*; - use crate::CloneAny; #[derive(Clone, Debug, PartialEq)] struct A(i32); @@ -255,3 +250,135 @@ mod tests { verify_hashing_with(TypeId::of::>()); } } + +// impl some traits for dyn Any +use core::fmt; + +#[doc(hidden)] +pub trait CloneToAny { + /// Clone `self` into a new `Box` object. + fn clone_to_any(&self) -> Box; +} + +impl CloneToAny for T { + #[inline] + fn clone_to_any(&self) -> Box { + Box::new(self.clone()) + } +} + +macro_rules! impl_clone { + ($t:ty) => { + impl Clone for Box<$t> { + #[inline] + fn clone(&self) -> Box<$t> { + // SAFETY: this dance is to reapply any Send/Sync marker. I’m not happy about this + // approach, given that I used to do it in safe code, but then came a dodgy + // future-compatibility warning where_clauses_object_safety, which is spurious for + // auto traits but still super annoying (future-compatibility lints seem to mean + // your bin crate needs a corresponding allow!). Although I explained my plight¹ + // and it was all explained and agreed upon, no action has been taken. So I finally + // caved and worked around it by doing it this way, which matches what’s done for + // core::any², so it’s probably not *too* bad. + // + // ¹ https://github.com/rust-lang/rust/issues/51443#issuecomment-421988013 + // ² https://github.com/rust-lang/rust/blob/e7825f2b690c9a0d21b6f6d84c404bb53b151b38/library/alloc/src/boxed.rs#L1613-L1616 + let clone: Box = (**self).clone_to_any(); + let raw: *mut dyn CloneAny = Box::into_raw(clone); + unsafe { Box::from_raw(raw as *mut $t) } + } + } + + impl fmt::Debug for $t { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.pad(stringify!($t)) + } + } + }; +} + +/// Methods for downcasting from an `Any`-like trait object. +/// +/// This should only be implemented on trait objects for subtraits of `Any`, though you can +/// implement it for other types and it’ll work fine, so long as your implementation is correct. +pub trait Downcast { + /// Gets the `TypeId` of `self`. + fn type_id(&self) -> TypeId; + + // Note the bound through these downcast methods is 'static, rather than the inexpressible + // concept of Self-but-as-a-trait (where Self is `dyn Trait`). This is sufficient, exceeding + // TypeId’s requirements. Sure, you *can* do CloneAny.downcast_unchecked::() and the + // type system won’t protect you, but that doesn’t introduce any unsafety: the method is + // already unsafe because you can specify the wrong type, and if this were exposing safe + // downcasting, CloneAny.downcast::() would just return an error, which is just as + // correct. + // + // Now in theory we could also add T: ?Sized, but that doesn’t play nicely with the common + // implementation, so I’m doing without it. + + /// Downcast from `&Any` to `&T`, without checking the type matches. + /// + /// # Safety + /// + /// The caller must ensure that `T` matches the trait object, on pain of *undefined behaviour*. + unsafe fn downcast_ref_unchecked(&self) -> &T; + + /// Downcast from `&mut Any` to `&mut T`, without checking the type matches. + /// + /// # Safety + /// + /// The caller must ensure that `T` matches the trait object, on pain of *undefined behaviour*. + unsafe fn downcast_mut_unchecked(&mut self) -> &mut T; +} + +/// A trait for the conversion of an object into a boxed trait object. +pub trait IntoBox: Any { + /// Convert self into the appropriate boxed form. + fn into_box(self) -> Box; +} + +macro_rules! implement { + ($any_trait:ident $(+ $auto_traits:ident)*) => { + impl Downcast for dyn $any_trait $(+ $auto_traits)* { + #[inline] + fn type_id(&self) -> TypeId { + self.type_id() + } + + #[inline] + unsafe fn downcast_ref_unchecked(&self) -> &T { + &*(self as *const Self as *const T) + } + + #[inline] + unsafe fn downcast_mut_unchecked(&mut self) -> &mut T { + &mut *(self as *mut Self as *mut T) + } + } + + impl IntoBox for T { + #[inline] + fn into_box(self) -> Box { + Box::new(self) + } + } + } +} + +implement!(Any); +implement!(Any + Send); +implement!(Any + Send + Sync); + +/// [`Any`], but with cloning. +/// +/// Every type with no non-`'static` references that implements `Clone` implements `CloneAny`. +/// See [`core::any`] for more details on `Any` in general. +pub trait CloneAny: Any + CloneToAny {} +impl CloneAny for T {} +implement!(CloneAny); +implement!(CloneAny + Send); +implement!(CloneAny + Send + Sync); +impl_clone!(dyn CloneAny); +impl_clone!(dyn CloneAny + Send); +impl_clone!(dyn CloneAny + Send + Sync); diff --git a/crates/stdx/src/lib.rs b/crates/stdx/src/lib.rs index 24990d6a0e71..1e9a54e996b7 100644 --- a/crates/stdx/src/lib.rs +++ b/crates/stdx/src/lib.rs @@ -12,6 +12,7 @@ pub mod panic_context; pub mod non_empty_vec; pub mod rand; pub mod thread; +pub mod anymap; pub use always_assert::{always, never}; From 62121827390ae06bd8af9594459629cfc5a49f8d Mon Sep 17 00:00:00 2001 From: shogo-nakano-desu <61229807+shogo-nakano-desu@users.noreply.github.com> Date: Wed, 20 Sep 2023 08:59:07 +0900 Subject: [PATCH 047/435] refactor: remove hashbrown deps since we can use std --- Cargo.lock | 22 ---------------------- crates/stdx/Cargo.toml | 1 - crates/stdx/src/anymap.rs | 4 ---- 3 files changed, 27 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5dcf68e0ce76..72aaefb32759 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,23 +17,6 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" -[[package]] -name = "ahash" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" -dependencies = [ - "cfg-if", - "once_cell", - "version_check", -] - -[[package]] -name = "allocator-api2" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" - [[package]] name = "always-assert" version = "0.1.3" @@ -475,10 +458,6 @@ name = "hashbrown" version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" -dependencies = [ - "ahash", - "allocator-api2", -] [[package]] name = "heck" @@ -1823,7 +1802,6 @@ dependencies = [ "always-assert", "backtrace", "crossbeam-channel", - "hashbrown 0.14.0", "jod-thread", "libc", "miow", diff --git a/crates/stdx/Cargo.toml b/crates/stdx/Cargo.toml index fae16fa2e428..536f000a44b7 100644 --- a/crates/stdx/Cargo.toml +++ b/crates/stdx/Cargo.toml @@ -17,7 +17,6 @@ backtrace = { version = "0.3.67", optional = true } always-assert = { version = "0.1.2", features = ["log"] } jod-thread = "0.1.2" crossbeam-channel = "0.5.5" -hashbrown = { version = "0.14.0" } # Think twice before adding anything here [target.'cfg(windows)'.dependencies] diff --git a/crates/stdx/src/anymap.rs b/crates/stdx/src/anymap.rs index 0f4ae0a440cc..0165235009af 100644 --- a/crates/stdx/src/anymap.rs +++ b/crates/stdx/src/anymap.rs @@ -15,10 +15,6 @@ //! - **std** (default, *enabled* in this build): //! an implementation using `std::collections::hash_map`, placed in the crate root //! (e.g. `anymap::AnyMap`). -//! -//! - **hashbrown** (optional; *enabled* in this build): -//! an implementation using `alloc` and `hashbrown::hash_map`, placed in a module `hashbrown` -//! (e.g. `anymap::hashbrown::AnyMap`). #![warn(missing_docs, unused_results)] From 2b891ca084f38aa88842cd8c568913adbf0e88a2 Mon Sep 17 00:00:00 2001 From: shogo-nakano-desu <61229807+shogo-nakano-desu@users.noreply.github.com> Date: Wed, 20 Sep 2023 09:07:58 +0900 Subject: [PATCH 048/435] chore: add comments to mention anymap is a port from another repo --- crates/stdx/src/anymap.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/crates/stdx/src/anymap.rs b/crates/stdx/src/anymap.rs index 0165235009af..fd44e6c6d0f4 100644 --- a/crates/stdx/src/anymap.rs +++ b/crates/stdx/src/anymap.rs @@ -1,15 +1,14 @@ -//! Copyright © 2014–2022 Chris Morgan -//! https://github.com/chris-morgan/anymap/blob/master/COPYING -//! Copyright © 2014–2022 Chris Morgan -//! https://github.com/chris-morgan/anymap/blob/master/COPYING +//! This file is a port of only the necessary features from https://github.com/chris-morgan/anymap version 1.0.0-beta.2 for use within rust-analyzer. +//! Copyright © 2014–2022 Chris Morgan. COPYING: https://github.com/chris-morgan/anymap/blob/master/COPYING" +//! Note that the license is changed from Blue Oak Model 1.0.0 or MIT or Apache-2.0 to MIT OR Apache-2.0 //! -//! This crate provides a safe and convenient store for one value of each type. +//! This implementation provides a safe and convenient store for one value of each type. //! //! Your starting point is [`Map`]. It has an example. //! //! # Cargo features //! -//! This crate has two independent features, each of which provides an implementation providing +//! This implementation has two independent features, each of which provides an implementation providing //! types `Map`, `AnyMap`, `OccupiedEntry`, `VacantEntry`, `Entry` and `RawMap`: //! //! - **std** (default, *enabled* in this build): From 1e11a55f98d9b3f1f7ac2a6779e10b060fe3c896 Mon Sep 17 00:00:00 2001 From: shogo-nakano-desu <61229807+shogo-nakano-desu@users.noreply.github.com> Date: Wed, 20 Sep 2023 22:55:52 +0900 Subject: [PATCH 049/435] refactor: remove unnecesary deps that are blended in when rebase --- Cargo.toml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index dd4348785df7..c382a5a37d23 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -105,10 +105,3 @@ triomphe = { version = "0.1.8", default-features = false, features = ["std"] } hashbrown = { version = "0.12.3", features = [ "inline-more", ], default-features = false } - -rustc_lexer = { version = "0.10.0", package = "ra-ap-rustc_lexer" } -rustc_parse_format = { version = "0.10.0", package = "ra-ap-rustc_parse_format", default-features = false } - -# Upstream broke this for us so we can't update it -rustc_abi = { version = "0.0.20221221", package = "hkalbasi-rustc-ap-rustc_abi", default-features = false } -rustc_index = { version = "0.0.20221221", package = "hkalbasi-rustc-ap-rustc_index", default-features = false } From dd843060f9ebff3862dc48c033c3ddbabb3b6a84 Mon Sep 17 00:00:00 2001 From: shogo-nakano-desu <61229807+shogo-nakano-desu@users.noreply.github.com> Date: Wed, 20 Sep 2023 23:02:52 +0900 Subject: [PATCH 050/435] refactor: remove boxing --- crates/flycheck/src/lib.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/crates/flycheck/src/lib.rs b/crates/flycheck/src/lib.rs index 61433313921a..2de719af92ce 100644 --- a/crates/flycheck/src/lib.rs +++ b/crates/flycheck/src/lib.rs @@ -488,9 +488,7 @@ impl CargoActor { // Skip certain kinds of messages to only spend time on what's useful JsonMessage::Cargo(message) => match message { cargo_metadata::Message::CompilerArtifact(artifact) if !artifact.fresh => { - self.sender - .send(CargoMessage::CompilerArtifact(Box::new(artifact))) - .unwrap(); + self.sender.send(CargoMessage::CompilerArtifact(artifact)).unwrap(); } cargo_metadata::Message::CompilerMessage(msg) => { self.sender.send(CargoMessage::Diagnostic(msg.message)).unwrap(); @@ -535,7 +533,7 @@ impl CargoActor { } enum CargoMessage { - CompilerArtifact(Box), + CompilerArtifact(cargo_metadata::Artifact), Diagnostic(Diagnostic), } From 91b012f91d625eeedd3831e8968174a3f2d33a63 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Thu, 21 Sep 2023 14:58:24 -0400 Subject: [PATCH 051/435] Documentation: Add parenthesis to the list of on-typing assists. --- crates/ide/src/typing.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/ide/src/typing.rs b/crates/ide/src/typing.rs index b40509715baf..d21850bcff3e 100644 --- a/crates/ide/src/typing.rs +++ b/crates/ide/src/typing.rs @@ -47,7 +47,7 @@ struct ExtendedTextEdit { // - typing `=` between two expressions adds `;` when in statement position // - typing `=` to turn an assignment into an equality comparison removes `;` when in expression position // - typing `.` in a chain method call auto-indents -// - typing `{` in front of an expression inserts a closing `}` after the expression +// - typing `{` or `(` in front of an expression inserts a closing `}` or `)` after the expression // - typing `{` in a use item adds a closing `}` in the right place // // VS Code:: From 60f7473c997a33cd59d8530f8aa1588bd622d296 Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Thu, 21 Sep 2023 21:31:15 -0700 Subject: [PATCH 052/435] fix parens when inlining closure local variables --- .../src/handlers/inline_local_variable.rs | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/crates/ide-assists/src/handlers/inline_local_variable.rs b/crates/ide-assists/src/handlers/inline_local_variable.rs index e69d1a29677a..49dcde75d2b3 100644 --- a/crates/ide-assists/src/handlers/inline_local_variable.rs +++ b/crates/ide-assists/src/handlers/inline_local_variable.rs @@ -96,8 +96,7 @@ pub(crate) fn inline_local_variable(acc: &mut Assists, ctx: &AssistContext<'_>) ); let parent = matches!( usage_parent, - ast::Expr::CallExpr(_) - | ast::Expr::TupleExpr(_) + ast::Expr::TupleExpr(_) | ast::Expr::ArrayExpr(_) | ast::Expr::ParenExpr(_) | ast::Expr::ForExpr(_) @@ -949,6 +948,24 @@ fn f() { let S$0 = S; S; } +"#, + ); + } + + #[test] + fn test_inline_closure() { + check_assist( + inline_local_variable, + r#" +fn main() { + let $0f = || 2; + let _ = f(); +} +"#, + r#" +fn main() { + let _ = (|| 2)(); +} "#, ); } From ea118464908589db0293b7ba458a58db2f13db83 Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Thu, 21 Sep 2023 21:55:10 -0700 Subject: [PATCH 053/435] fix parens when inlining closure in body of function --- .../ide-assists/src/handlers/inline_call.rs | 31 ++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/crates/ide-assists/src/handlers/inline_call.rs b/crates/ide-assists/src/handlers/inline_call.rs index ffab58509b18..a80c1e23941f 100644 --- a/crates/ide-assists/src/handlers/inline_call.rs +++ b/crates/ide-assists/src/handlers/inline_call.rs @@ -481,8 +481,12 @@ fn inline( }; body.reindent_to(original_indentation); + let no_stmts = body.statements().next().is_none(); match body.tail_expr() { - Some(expr) if !is_async_fn && body.statements().next().is_none() => expr, + Some(expr) if matches!(expr, ast::Expr::ClosureExpr(_)) && no_stmts => { + make::expr_paren(expr).clone_for_update() + } + Some(expr) if !is_async_fn && no_stmts => expr, _ => match node .syntax() .parent() @@ -1471,6 +1475,31 @@ fn main() { } }); } +"#, + ); + } + + #[test] + fn inline_call_closure_body() { + check_assist( + inline_call, + r#" +fn f() -> impl Fn() -> i32 { + || 2 +} + +fn main() { + let _ = $0f()(); +} +"#, + r#" +fn f() -> impl Fn() -> i32 { + || 2 +} + +fn main() { + let _ = (|| 2)(); +} "#, ); } From 93562dd5bdec82c70b8eff05c59badb4314c90c8 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 22 Sep 2023 08:53:24 +0200 Subject: [PATCH 054/435] Use parent + and_then instead of ancestors --- crates/ide-assists/src/handlers/bool_to_enum.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/ide-assists/src/handlers/bool_to_enum.rs b/crates/ide-assists/src/handlers/bool_to_enum.rs index b9dbd6e98fcb..85b0b87d0c95 100644 --- a/crates/ide-assists/src/handlers/bool_to_enum.rs +++ b/crates/ide-assists/src/handlers/bool_to_enum.rs @@ -111,7 +111,7 @@ fn find_bool_node(ctx: &AssistContext<'_>) -> Option { initializer: let_stmt.initializer(), definition: Definition::Local(def), }) - } else if let Some(const_) = name.syntax().ancestors().find_map(ast::Const::cast) { + } else if let Some(const_) = name.syntax().parent().and_then(ast::Const::cast) { let def = ctx.sema.to_def(&const_)?; if !def.ty(ctx.db()).is_bool() { cov_mark::hit!(not_applicable_non_bool_const); @@ -125,7 +125,7 @@ fn find_bool_node(ctx: &AssistContext<'_>) -> Option { initializer: const_.body(), definition: Definition::Const(def), }) - } else if let Some(static_) = name.syntax().ancestors().find_map(ast::Static::cast) { + } else if let Some(static_) = name.syntax().parent().and_then(ast::Static::cast) { let def = ctx.sema.to_def(&static_)?; if !def.ty(ctx.db()).is_bool() { cov_mark::hit!(not_applicable_non_bool_static); @@ -140,7 +140,7 @@ fn find_bool_node(ctx: &AssistContext<'_>) -> Option { definition: Definition::Static(def), }) } else { - let field = name.syntax().ancestors().find_map(ast::RecordField::cast)?; + let field = name.syntax().parent().and_then(ast::RecordField::cast)?; if field.name()? != name { return None; } From 556f0c67049517c98e89ca26055b513f5a35746b Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 22 Sep 2023 08:08:00 +0200 Subject: [PATCH 055/435] Various small fixes --- crates/hir-def/src/body/scope.rs | 11 +++++------ crates/hir-def/src/import_map.rs | 13 +++++++------ crates/hir-def/src/lib.rs | 5 +---- crates/hir/src/source_analyzer.rs | 4 ++-- crates/stdx/src/macros.rs | 7 ++++++- crates/stdx/src/process.rs | 2 +- 6 files changed, 22 insertions(+), 20 deletions(-) diff --git a/crates/hir-def/src/body/scope.rs b/crates/hir-def/src/body/scope.rs index 2a90a09f25e8..f69466631355 100644 --- a/crates/hir-def/src/body/scope.rs +++ b/crates/hir-def/src/body/scope.rs @@ -1,7 +1,6 @@ //! Name resolution for expressions. use hir_expand::name::Name; -use la_arena::{Arena, Idx, IdxRange, RawIdx}; -use rustc_hash::FxHashMap; +use la_arena::{Arena, ArenaMap, Idx, IdxRange, RawIdx}; use triomphe::Arc; use crate::{ @@ -17,7 +16,7 @@ pub type ScopeId = Idx; pub struct ExprScopes { scopes: Arena, scope_entries: Arena, - scope_by_expr: FxHashMap, + scope_by_expr: ArenaMap, } #[derive(Debug, PartialEq, Eq)] @@ -77,10 +76,10 @@ impl ExprScopes { } pub fn scope_for(&self, expr: ExprId) -> Option { - self.scope_by_expr.get(&expr).copied() + self.scope_by_expr.get(expr).copied() } - pub fn scope_by_expr(&self) -> &FxHashMap { + pub fn scope_by_expr(&self) -> &ArenaMap { &self.scope_by_expr } } @@ -94,7 +93,7 @@ impl ExprScopes { let mut scopes = ExprScopes { scopes: Arena::default(), scope_entries: Arena::default(), - scope_by_expr: FxHashMap::default(), + scope_by_expr: ArenaMap::with_capacity(body.exprs.len()), }; let mut root = scopes.root_scope(); scopes.add_params_bindings(body, root, &body.params); diff --git a/crates/hir-def/src/import_map.rs b/crates/hir-def/src/import_map.rs index eb32c76b066d..90763d4c3dfe 100644 --- a/crates/hir-def/src/import_map.rs +++ b/crates/hir-def/src/import_map.rs @@ -1,7 +1,6 @@ //! A map of all publicly exported items in a crate. -use std::collections::hash_map::Entry; -use std::{fmt, hash::BuildHasherDefault}; +use std::{collections::hash_map::Entry, fmt, hash::BuildHasherDefault}; use base_db::CrateId; use fst::{self, Streamer}; @@ -11,10 +10,12 @@ use itertools::Itertools; use rustc_hash::{FxHashMap, FxHashSet, FxHasher}; use triomphe::Arc; -use crate::item_scope::ImportOrExternCrate; use crate::{ - db::DefDatabase, item_scope::ItemInNs, nameres::DefMap, visibility::Visibility, AssocItemId, - ModuleDefId, ModuleId, TraitId, + db::DefDatabase, + item_scope::{ImportOrExternCrate, ItemInNs}, + nameres::DefMap, + visibility::Visibility, + AssocItemId, ModuleDefId, ModuleId, TraitId, }; type FxIndexMap = IndexMap>; @@ -94,7 +95,7 @@ fn collect_import_map(db: &dyn DefDatabase, krate: CrateId) -> FxIndexMap bool { - match self { - MacroId::ProcMacroId(it) => it.lookup(db).kind == ProcMacroKind::Attr, - _ => false, - } + matches!(self, MacroId::ProcMacroId(it) if it.lookup(db).kind == ProcMacroKind::Attr) } } diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs index f29fb1edf00b..8d8ba48ad923 100644 --- a/crates/hir/src/source_analyzer.rs +++ b/crates/hir/src/source_analyzer.rs @@ -888,7 +888,7 @@ fn scope_for_offset( .scope_by_expr() .iter() .filter_map(|(id, scope)| { - let InFile { file_id, value } = source_map.expr_syntax(*id).ok()?; + let InFile { file_id, value } = source_map.expr_syntax(id).ok()?; if from_file == file_id { return Some((value.text_range(), scope)); } @@ -923,7 +923,7 @@ fn adjust( .scope_by_expr() .iter() .filter_map(|(id, scope)| { - let source = source_map.expr_syntax(*id).ok()?; + let source = source_map.expr_syntax(id).ok()?; // FIXME: correctly handle macro expansion if source.file_id != from_file { return None; diff --git a/crates/stdx/src/macros.rs b/crates/stdx/src/macros.rs index 1a9982fa8b2a..d71e418c89bc 100644 --- a/crates/stdx/src/macros.rs +++ b/crates/stdx/src/macros.rs @@ -15,7 +15,12 @@ macro_rules! eprintln { macro_rules! format_to { ($buf:expr) => (); ($buf:expr, $lit:literal $($arg:tt)*) => { - { use ::std::fmt::Write as _; let _ = ::std::write!($buf, $lit $($arg)*); } + { + use ::std::fmt::Write as _; + // We can't do ::std::fmt::Write::write_fmt($buf, format_args!($lit $($arg)*)) + // unfortunately, as that loses out on autoref behavior. + _ = $buf.write_fmt(format_args!($lit $($arg)*)) + } }; } diff --git a/crates/stdx/src/process.rs b/crates/stdx/src/process.rs index e5aa34365187..bca0cbc36d1a 100644 --- a/crates/stdx/src/process.rs +++ b/crates/stdx/src/process.rs @@ -23,7 +23,7 @@ pub fn streaming_output( let idx = if eof { data.len() } else { - match data.iter().rposition(|b| *b == b'\n') { + match data.iter().rposition(|&b| b == b'\n') { Some(i) => i + 1, None => return, } From 8ad536f2d12846684fed51dd95d95a4c56e5be62 Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Fri, 15 Sep 2023 23:26:45 +0200 Subject: [PATCH 056/435] Make path start with a QualifiedPathType --- .../src/handlers/into_to_qualified_from.rs | 84 +++++++++++++++++-- 1 file changed, 75 insertions(+), 9 deletions(-) diff --git a/crates/ide-assists/src/handlers/into_to_qualified_from.rs b/crates/ide-assists/src/handlers/into_to_qualified_from.rs index 663df266b6f8..32d30e6b18d8 100644 --- a/crates/ide-assists/src/handlers/into_to_qualified_from.rs +++ b/crates/ide-assists/src/handlers/into_to_qualified_from.rs @@ -52,18 +52,24 @@ pub(crate) fn into_to_qualified_from(acc: &mut Assists, ctx: &AssistContext<'_>) == FamousDefs(sema, scope.krate()).core_convert_Into()? { let type_call = sema.type_of_expr(&method_call.clone().into())?; - let type_call_disp = - type_call.adjusted().display_source_code(db, scope.module().into(), true).ok()?; + let adjusted_tc = type_call.adjusted(); + + if adjusted_tc.is_unknown() && adjusted_tc.contains_unknown() { + return None; + } + + let qualified_from = format!( + "<{}>::from({})", + adjusted_tc.display_source_code(db, scope.module().into(), true).ok()?, + receiver + ); acc.add( AssistId("into_to_qualified_from", AssistKind::Generate), "Convert `into` to fully qualified `from`", nameref.syntax().text_range(), |edit| { - edit.replace( - method_call.syntax().text_range(), - format!("{}::from({})", type_call_disp, receiver), - ); + edit.replace(method_call.syntax().text_range(), qualified_from); }, ); } @@ -106,7 +112,7 @@ impl From for B { fn main() -> () { let a: A = A; - let b: B = B::from(a); + let b: B = ::from(a); }"#, ) } @@ -154,7 +160,7 @@ mod C { fn main() -> () { let a: A = A; - let b: B = B::from(a); + let b: B = ::from(a); }"#, ) } @@ -198,7 +204,67 @@ mod C { fn main() -> () { let a: A = A; - let b: C::B = C::B::from(a); + let b: C::B = ::from(a); +}"#, + ) + } + + #[test] + fn preceding_type_qualifier() { + check_assist( + into_to_qualified_from, + r#" +//- minicore: from +impl From<(i32,i32)> for [i32;2] { + fn from(value: (i32,i32)) -> Self { + [value.0, value.1] + } +} + +fn tuple_to_array() -> [i32; 2] { + (0,1).in$0to() +}"#, + r#" +impl From<(i32,i32)> for [i32;2] { + fn from(value: (i32,i32)) -> Self { + [value.0, value.1] + } +} + +fn tuple_to_array() -> [i32; 2] { + <[i32; 2]>::from((0,1)) +}"#, + ) + } + + #[test] + fn type_with_gens() { + check_assist( + into_to_qualified_from, + r#" +//- minicore: from +struct StructA(Gen); + +impl From for StructA { + fn from(value: i32) -> Self { + StructA(value + 1) + } +} + +fn main() -> () { + let a: StructA = 3.in$0to(); +}"#, + r#" +struct StructA(Gen); + +impl From for StructA { + fn from(value: i32) -> Self { + StructA(value + 1) + } +} + +fn main() -> () { + let a: StructA = >::from(3); }"#, ) } From 695a1349fa1c41333e079381e4ec06bb6539f2f1 Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Wed, 20 Sep 2023 19:43:02 +0200 Subject: [PATCH 057/435] Fix doctest --- crates/ide-assists/src/handlers/into_to_qualified_from.rs | 2 +- crates/ide-assists/src/tests/generated.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/ide-assists/src/handlers/into_to_qualified_from.rs b/crates/ide-assists/src/handlers/into_to_qualified_from.rs index 32d30e6b18d8..640883b1bc15 100644 --- a/crates/ide-assists/src/handlers/into_to_qualified_from.rs +++ b/crates/ide-assists/src/handlers/into_to_qualified_from.rs @@ -36,7 +36,7 @@ use crate::assist_context::{AssistContext, Assists}; // // fn main() -> () { // let a = 3; -// let b: B = B::from(a); +// let b: B = ::from(a); // } // ``` pub(crate) fn into_to_qualified_from(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { diff --git a/crates/ide-assists/src/tests/generated.rs b/crates/ide-assists/src/tests/generated.rs index 63a08a0e5697..e65058f70b54 100644 --- a/crates/ide-assists/src/tests/generated.rs +++ b/crates/ide-assists/src/tests/generated.rs @@ -1812,7 +1812,7 @@ impl From for B { fn main() -> () { let a = 3; - let b: B = B::from(a); + let b: B = ::from(a); } "#####, ) From 0a91a54794cfd45bc927de4760332c6ac5559ac8 Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Fri, 22 Sep 2023 13:32:20 +0200 Subject: [PATCH 058/435] v4 --- .../src/handlers/convert_comment_block.rs | 8 ++--- .../src/handlers/desugar_doc_comment.rs | 32 +++++++++---------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/crates/ide-assists/src/handlers/convert_comment_block.rs b/crates/ide-assists/src/handlers/convert_comment_block.rs index ef914cdb2cdf..3f478ee7d39a 100644 --- a/crates/ide-assists/src/handlers/convert_comment_block.rs +++ b/crates/ide-assists/src/handlers/convert_comment_block.rs @@ -89,12 +89,12 @@ fn line_to_block(acc: &mut Assists, comment: ast::Comment) -> Option<()> { // contents of each line comment when they're put into the block comment. let indentation = IndentLevel::from_token(comment.syntax()); - let cms = comments + let block_comment_body = comments .into_iter() .map(|c| line_comment_text(indentation, c)) - .collect::>(); - - let block_comment_body = cms.into_iter().join("\n"); + .collect::>() + .into_iter() + .join("\n"); let block_prefix = CommentKind { shape: CommentShape::Block, ..comment.kind() }.prefix(); diff --git a/crates/ide-assists/src/handlers/desugar_doc_comment.rs b/crates/ide-assists/src/handlers/desugar_doc_comment.rs index b7919bd1502c..c859e98524e8 100644 --- a/crates/ide-assists/src/handlers/desugar_doc_comment.rs +++ b/crates/ide-assists/src/handlers/desugar_doc_comment.rs @@ -55,27 +55,27 @@ pub(crate) fn desugar_doc_comment(acc: &mut Assists, ctx: &AssistContext<'_>) -> } }; - let text = match comments { - Either::Left(comment) => { - let text = comment.text(); - text[comment.prefix().len()..(text.len() - "*/".len())] - .trim() - .lines() - .map(|l| l.strip_prefix(&indentation).unwrap_or(l)) - .join("\n") - } - Either::Right(comments) => comments - .into_iter() - .map(|cm| line_comment_text(IndentLevel(0), cm)) - .collect::>() - .join("\n"), - }; - acc.add( AssistId("desugar_doc_comment", AssistKind::RefactorRewrite), "Desugar doc-comment to attribute macro", target, |edit| { + let text = match comments { + Either::Left(comment) => { + let text = comment.text(); + text[comment.prefix().len()..(text.len() - "*/".len())] + .trim() + .lines() + .map(|l| l.strip_prefix(&indentation).unwrap_or(l)) + .join("\n") + } + Either::Right(comments) => comments + .into_iter() + .map(|cm| line_comment_text(IndentLevel(0), cm)) + .collect::>() + .join("\n"), + }; + let hashes = "#".repeat(required_hashes(&text)); let prefix = match placement { From 622e1a8d882204601d8e12c464d27cf3a7d96d44 Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Fri, 22 Sep 2023 13:51:19 +0200 Subject: [PATCH 059/435] Add a test case to `add_missing_match_arms` Although it doesn't panic now, further changes to how we recover from incomplete syntax may cause this assist to panic. To mitigate this a test case has been added. --- .../src/handlers/add_missing_match_arms.rs | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/crates/ide-assists/src/handlers/add_missing_match_arms.rs b/crates/ide-assists/src/handlers/add_missing_match_arms.rs index 5376ece2f584..c8b78b094169 100644 --- a/crates/ide-assists/src/handlers/add_missing_match_arms.rs +++ b/crates/ide-assists/src/handlers/add_missing_match_arms.rs @@ -1944,4 +1944,35 @@ fn main() { "#, ); } + + /// See [`discussion`](https://github.com/rust-lang/rust-analyzer/pull/15594#discussion_r1322960614) + #[test] + fn missing_field_name() { + check_assist( + add_missing_match_arms, + r#" +enum A { + A, + Missing { a: u32, : u32, c: u32 } +} + +fn a() { + let b = A::A; + match b$0 {} +}"#, + r#" +enum A { + A, + Missing { a: u32, : u32, c: u32 } +} + +fn a() { + let b = A::A; + match b { + $0A::A => todo!(), + A::Missing { a, u32, c } => todo!(), + } +}"#, + ) + } } From 132a6ce8fc20ccf56d29334fecf978a9ceec2a55 Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Fri, 22 Sep 2023 13:21:38 +0200 Subject: [PATCH 060/435] Omit QualPathTy when possible --- .../src/handlers/into_to_qualified_from.rs | 26 ++++++++++--------- crates/ide-assists/src/tests/generated.rs | 2 +- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/crates/ide-assists/src/handlers/into_to_qualified_from.rs b/crates/ide-assists/src/handlers/into_to_qualified_from.rs index 640883b1bc15..0589cbaf8a76 100644 --- a/crates/ide-assists/src/handlers/into_to_qualified_from.rs +++ b/crates/ide-assists/src/handlers/into_to_qualified_from.rs @@ -36,7 +36,7 @@ use crate::assist_context::{AssistContext, Assists}; // // fn main() -> () { // let a = 3; -// let b: B = ::from(a); +// let b: B = B::from(a); // } // ``` pub(crate) fn into_to_qualified_from(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { @@ -54,22 +54,24 @@ pub(crate) fn into_to_qualified_from(acc: &mut Assists, ctx: &AssistContext<'_>) let type_call = sema.type_of_expr(&method_call.clone().into())?; let adjusted_tc = type_call.adjusted(); - if adjusted_tc.is_unknown() && adjusted_tc.contains_unknown() { + if adjusted_tc.contains_unknown() { return None; } - let qualified_from = format!( - "<{}>::from({})", - adjusted_tc.display_source_code(db, scope.module().into(), true).ok()?, - receiver - ); - + let sc = adjusted_tc.display_source_code(db, scope.module().into(), true).ok()?; acc.add( AssistId("into_to_qualified_from", AssistKind::Generate), "Convert `into` to fully qualified `from`", nameref.syntax().text_range(), |edit| { - edit.replace(method_call.syntax().text_range(), qualified_from); + edit.replace( + method_call.syntax().text_range(), + if sc.chars().find(|c| !c.is_alphanumeric() && c != &':').is_some() { + format!("<{}>::from({})", sc, receiver) + } else { + format!("{}::from({})", sc, receiver) + }, + ); }, ); } @@ -112,7 +114,7 @@ impl From for B { fn main() -> () { let a: A = A; - let b: B = ::from(a); + let b: B = B::from(a); }"#, ) } @@ -160,7 +162,7 @@ mod C { fn main() -> () { let a: A = A; - let b: B = ::from(a); + let b: B = B::from(a); }"#, ) } @@ -204,7 +206,7 @@ mod C { fn main() -> () { let a: A = A; - let b: C::B = ::from(a); + let b: C::B = C::B::from(a); }"#, ) } diff --git a/crates/ide-assists/src/tests/generated.rs b/crates/ide-assists/src/tests/generated.rs index e65058f70b54..63a08a0e5697 100644 --- a/crates/ide-assists/src/tests/generated.rs +++ b/crates/ide-assists/src/tests/generated.rs @@ -1812,7 +1812,7 @@ impl From for B { fn main() -> () { let a = 3; - let b: B = ::from(a); + let b: B = B::from(a); } "#####, ) From ba7f2bfb85dffb0d300fedf8f9adcebb6666c8a0 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 22 Sep 2023 17:46:17 +0200 Subject: [PATCH 061/435] Update config docs --- docs/user/generated_config.adoc | 14 +++++++++++--- editors/code/package.json | 4 ++-- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc index 71feed0f72ca..bde1c03bef7f 100644 --- a/docs/user/generated_config.adoc +++ b/docs/user/generated_config.adoc @@ -57,6 +57,12 @@ build procedural macros. The command is required to output json and should therefore include `--message-format=json` or a similar option. +If there are multiple linked projects/workspaces, this command is invoked for +each of them, with the working directory being the workspace root +(i.e., the folder containing the `Cargo.toml`). This can be overwritten +by changing `#rust-analyzer.cargo.buildScripts.invocationStrategy#` and +`#rust-analyzer.cargo.buildScripts.invocationLocation#`. + By default, a cargo invocation will be constructed for the configured targets and features, with the following base command line: @@ -206,9 +212,11 @@ If you're changing this because you're using some tool wrapping Cargo, you might also want to change `#rust-analyzer.cargo.buildScripts.overrideCommand#`. -If there are multiple linked projects, this command is invoked for -each of them, with the working directory being the project root -(i.e., the folder containing the `Cargo.toml`). +If there are multiple linked projects/workspaces, this command is invoked for +each of them, with the working directory being the workspace root +(i.e., the folder containing the `Cargo.toml`). This can be overwritten +by changing `#rust-analyzer.cargo.check.invocationStrategy#` and +`#rust-analyzer.cargo.check.invocationLocation#`. An example command would be: diff --git a/editors/code/package.json b/editors/code/package.json index 44f1b81675a5..406846fa59dc 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -560,7 +560,7 @@ ] }, "rust-analyzer.cargo.buildScripts.overrideCommand": { - "markdownDescription": "Override the command rust-analyzer uses to run build scripts and\nbuild procedural macros. The command is required to output json\nand should therefore include `--message-format=json` or a similar\noption.\n\nBy default, a cargo invocation will be constructed for the configured\ntargets and features, with the following base command line:\n\n```bash\ncargo check --quiet --workspace --message-format=json --all-targets\n```\n.", + "markdownDescription": "Override the command rust-analyzer uses to run build scripts and\nbuild procedural macros. The command is required to output json\nand should therefore include `--message-format=json` or a similar\noption.\n\nIf there are multiple linked projects/workspaces, this command is invoked for\neach of them, with the working directory being the workspace root\n(i.e., the folder containing the `Cargo.toml`). This can be overwritten\nby changing `#rust-analyzer.cargo.buildScripts.invocationStrategy#` and\n`#rust-analyzer.cargo.buildScripts.invocationLocation#`.\n\nBy default, a cargo invocation will be constructed for the configured\ntargets and features, with the following base command line:\n\n```bash\ncargo check --quiet --workspace --message-format=json --all-targets\n```\n.", "default": null, "type": [ "null", @@ -749,7 +749,7 @@ ] }, "rust-analyzer.check.overrideCommand": { - "markdownDescription": "Override the command rust-analyzer uses instead of `cargo check` for\ndiagnostics on save. The command is required to output json and\nshould therefore include `--message-format=json` or a similar option\n(if your client supports the `colorDiagnosticOutput` experimental\ncapability, you can use `--message-format=json-diagnostic-rendered-ansi`).\n\nIf you're changing this because you're using some tool wrapping\nCargo, you might also want to change\n`#rust-analyzer.cargo.buildScripts.overrideCommand#`.\n\nIf there are multiple linked projects, this command is invoked for\neach of them, with the working directory being the project root\n(i.e., the folder containing the `Cargo.toml`).\n\nAn example command would be:\n\n```bash\ncargo check --workspace --message-format=json --all-targets\n```\n.", + "markdownDescription": "Override the command rust-analyzer uses instead of `cargo check` for\ndiagnostics on save. The command is required to output json and\nshould therefore include `--message-format=json` or a similar option\n(if your client supports the `colorDiagnosticOutput` experimental\ncapability, you can use `--message-format=json-diagnostic-rendered-ansi`).\n\nIf you're changing this because you're using some tool wrapping\nCargo, you might also want to change\n`#rust-analyzer.cargo.buildScripts.overrideCommand#`.\n\nIf there are multiple linked projects/workspaces, this command is invoked for\neach of them, with the working directory being the workspace root\n(i.e., the folder containing the `Cargo.toml`). This can be overwritten\nby changing `#rust-analyzer.cargo.check.invocationStrategy#` and\n`#rust-analyzer.cargo.check.invocationLocation#`.\n\nAn example command would be:\n\n```bash\ncargo check --workspace --message-format=json --all-targets\n```\n.", "default": null, "type": [ "null", From fc258de5a3ae7a40b8625b862295d5bca00a8c7b Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Fri, 22 Sep 2023 21:22:22 +0200 Subject: [PATCH 062/435] Make QualPathTy case readable --- crates/ide-assists/src/handlers/into_to_qualified_from.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/ide-assists/src/handlers/into_to_qualified_from.rs b/crates/ide-assists/src/handlers/into_to_qualified_from.rs index 0589cbaf8a76..965e4aa786e7 100644 --- a/crates/ide-assists/src/handlers/into_to_qualified_from.rs +++ b/crates/ide-assists/src/handlers/into_to_qualified_from.rs @@ -66,10 +66,10 @@ pub(crate) fn into_to_qualified_from(acc: &mut Assists, ctx: &AssistContext<'_>) |edit| { edit.replace( method_call.syntax().text_range(), - if sc.chars().find(|c| !c.is_alphanumeric() && c != &':').is_some() { - format!("<{}>::from({})", sc, receiver) - } else { + if sc.chars().all(|c| c.is_alphanumeric() || c == ':') { format!("{}::from({})", sc, receiver) + } else { + format!("<{}>::from({})", sc, receiver) }, ); }, From 9f3d627681e069ea313076ce65cbd28a8dfe0974 Mon Sep 17 00:00:00 2001 From: vxpm Date: Sat, 23 Sep 2023 19:39:42 -0300 Subject: [PATCH 063/435] add tests for full signatures --- crates/ide-completion/src/tests/special.rs | 73 +++++++++++++++++++++- 1 file changed, 71 insertions(+), 2 deletions(-) diff --git a/crates/ide-completion/src/tests/special.rs b/crates/ide-completion/src/tests/special.rs index e80a289049f1..83888e08f1c7 100644 --- a/crates/ide-completion/src/tests/special.rs +++ b/crates/ide-completion/src/tests/special.rs @@ -2,10 +2,15 @@ use expect_test::{expect, Expect}; -use crate::tests::{ - check_edit, completion_list, completion_list_no_kw, completion_list_with_trigger_character, +use crate::{ + tests::{ + check_edit, completion_list, completion_list_no_kw, completion_list_with_trigger_character, + }, + CompletionItemKind, }; +use super::{do_completion_with_config, TEST_CONFIG}; + fn check_no_kw(ra_fixture: &str, expect: Expect) { let actual = completion_list_no_kw(ra_fixture); expect.assert_eq(&actual) @@ -1303,3 +1308,67 @@ struct Foo(x: &'x mut T) -> u8 where T: Clone, { 0u8 } +fn main() { fo$0 } +"#, + CompletionItemKind::SymbolKind(ide_db::SymbolKind::Function), + expect!("fn(&mut T) -> u8"), + expect!("pub fn foo<'x, T>(x: &'x mut T) -> u8 where T: Clone,"), + ); + + check_signatures( + r#" +struct Foo; +struct Bar; +impl Bar { + pub const fn baz(x: Foo) -> ! { loop {} }; +} + +fn main() { Bar::b$0 } +"#, + CompletionItemKind::SymbolKind(ide_db::SymbolKind::Function), + expect!("const fn(Foo) -> !"), + expect!("pub const fn baz(x: Foo) -> !"), + ); + + check_signatures( + r#" +struct Foo; +struct Bar; +impl Bar { + pub const fn baz<'foo>(&'foo mut self, x: &'foo Foo) -> ! { loop {} }; +} + +fn main() { + let mut bar = Bar; + bar.b$0 +} +"#, + CompletionItemKind::Method, + expect!("const fn(&'foo mut self, &Foo) -> !"), + expect!("pub const fn baz<'foo>(&'foo mut self, x: &'foo Foo) -> !"), + ); +} From 10fae6282070945531853901cc19155f59758bbc Mon Sep 17 00:00:00 2001 From: vxpm Date: Sat, 23 Sep 2023 19:43:19 -0300 Subject: [PATCH 064/435] split detail function --- crates/ide-completion/src/render/function.rs | 39 +++++++++++--------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/crates/ide-completion/src/render/function.rs b/crates/ide-completion/src/render/function.rs index dd7de72190d1..dfae715afe36 100644 --- a/crates/ide-completion/src/render/function.rs +++ b/crates/ide-completion/src/render/function.rs @@ -98,9 +98,14 @@ fn render( _ => (), } + let detail = if ctx.completion.config.full_function_signatures { + detail_full(db, func) + } else { + detail(db, func) + }; item.set_documentation(ctx.docs(func)) .set_deprecated(ctx.is_deprecated(func) || ctx.is_deprecated_assoc_item(func)) - .detail(detail(db, func, ctx.completion.config.full_function_signatures)) + .detail(detail) .lookup_by(name.unescaped().to_smol_str()); match ctx.completion.config.snippet_cap { @@ -239,22 +244,7 @@ fn ref_of_param(ctx: &CompletionContext<'_>, arg: &str, ty: &hir::Type) -> &'sta "" } -fn detail(db: &dyn HirDatabase, func: hir::Function, full_function_signature: bool) -> String { - if full_function_signature { - let signature = format!("{}", func.display(db)); - let mut singleline = String::with_capacity(signature.len()); - - for segment in signature.split_whitespace() { - if !singleline.is_empty() { - singleline.push(' '); - } - - singleline.push_str(segment); - } - - return singleline; - } - +fn detail(db: &dyn HirDatabase, func: hir::Function) -> String { let mut ret_ty = func.ret_type(db); let mut detail = String::new(); @@ -278,6 +268,21 @@ fn detail(db: &dyn HirDatabase, func: hir::Function, full_function_signature: bo detail } +fn detail_full(db: &dyn HirDatabase, func: hir::Function) -> String { + let signature = format!("{}", func.display(db)); + let mut detail = String::with_capacity(signature.len()); + + for segment in signature.split_whitespace() { + if !detail.is_empty() { + detail.push(' '); + } + + detail.push_str(segment); + } + + detail +} + fn params_display(db: &dyn HirDatabase, func: hir::Function) -> String { if let Some(self_param) = func.self_param(db) { let assoc_fn_params = func.assoc_fn_params(db); From 7834b8fadb769815264305177bf969db8240632d Mon Sep 17 00:00:00 2001 From: hkalbasi Date: Sun, 24 Sep 2023 21:29:15 +0330 Subject: [PATCH 065/435] Add `unused_variables` native diagnostic --- crates/hir-ty/src/layout/tests/closure.rs | 4 +- crates/hir-ty/src/mir.rs | 8 +- crates/hir-ty/src/mir/borrowck.rs | 88 +++++++++++--- crates/hir-ty/src/mir/eval.rs | 1 + crates/hir-ty/src/mir/lower.rs | 14 +++ crates/hir-ty/src/mir/monomorphization.rs | 1 + crates/hir-ty/src/mir/pretty.rs | 5 + crates/hir/src/diagnostics.rs | 6 + crates/hir/src/lib.rs | 15 ++- .../src/handlers/mutability_errors.rs | 66 ++++++++--- .../src/handlers/unused_variables.rs | 110 ++++++++++++++++++ crates/ide-diagnostics/src/lib.rs | 2 + 12 files changed, 282 insertions(+), 38 deletions(-) create mode 100644 crates/ide-diagnostics/src/handlers/unused_variables.rs diff --git a/crates/hir-ty/src/layout/tests/closure.rs b/crates/hir-ty/src/layout/tests/closure.rs index bbe855a14de7..939025461f36 100644 --- a/crates/hir-ty/src/layout/tests/closure.rs +++ b/crates/hir-ty/src/layout/tests/closure.rs @@ -186,9 +186,9 @@ fn capture_specific_fields() { fn match_pattern() { size_and_align_expr! { struct X(i64, i32, (u8, i128)); - let y: X = X(2, 5, (7, 3)); + let _y: X = X(2, 5, (7, 3)); move |x: i64| { - match y { + match _y { _ => x, } } diff --git a/crates/hir-ty/src/mir.rs b/crates/hir-ty/src/mir.rs index e953058ccca4..797f4c1248d6 100644 --- a/crates/hir-ty/src/mir.rs +++ b/crates/hir-ty/src/mir.rs @@ -280,7 +280,7 @@ impl ProjectionId { } } -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct Place { pub local: LocalId, pub projection: ProjectionId, @@ -1007,7 +1007,7 @@ pub enum Rvalue { #[derive(Debug, PartialEq, Eq, Clone)] pub enum StatementKind { Assign(Place, Rvalue), - //FakeRead(Box<(FakeReadCause, Place)>), + FakeRead(Place), //SetDiscriminant { // place: Box, // variant_index: VariantIdx, @@ -1109,7 +1109,9 @@ impl MirBody { } } } - StatementKind::Deinit(p) => f(p, &mut self.projection_store), + StatementKind::FakeRead(p) | StatementKind::Deinit(p) => { + f(p, &mut self.projection_store) + } StatementKind::StorageLive(_) | StatementKind::StorageDead(_) | StatementKind::Nop => (), diff --git a/crates/hir-ty/src/mir/borrowck.rs b/crates/hir-ty/src/mir/borrowck.rs index 41fb129652a1..74c5efd6c3f4 100644 --- a/crates/hir-ty/src/mir/borrowck.rs +++ b/crates/hir-ty/src/mir/borrowck.rs @@ -24,6 +24,7 @@ use super::{ pub enum MutabilityReason { Mut { spans: Vec }, Not, + Unused, } #[derive(Debug, Clone, PartialEq, Eq)] @@ -144,7 +145,8 @@ fn moved_out_of_ref(db: &dyn HirDatabase, body: &MirBody) -> Vec } } }, - StatementKind::Deinit(_) + StatementKind::FakeRead(_) + | StatementKind::Deinit(_) | StatementKind::StorageLive(_) | StatementKind::StorageDead(_) | StatementKind::Nop => (), @@ -264,7 +266,10 @@ fn ever_initialized_map( is_ever_initialized = false; } } - StatementKind::Deinit(_) | StatementKind::Nop | StatementKind::StorageLive(_) => (), + StatementKind::Deinit(_) + | StatementKind::FakeRead(_) + | StatementKind::Nop + | StatementKind::StorageLive(_) => (), } } let Some(terminator) = &block.terminator else { @@ -331,16 +336,37 @@ fn ever_initialized_map( result } +fn push_mut_span(local: LocalId, span: MirSpan, result: &mut ArenaMap) { + match &mut result[local] { + MutabilityReason::Mut { spans } => spans.push(span), + it @ (MutabilityReason::Not | MutabilityReason::Unused) => { + *it = MutabilityReason::Mut { spans: vec![span] } + } + }; +} + +fn record_usage(local: LocalId, result: &mut ArenaMap) { + match &mut result[local] { + it @ MutabilityReason::Unused => { + *it = MutabilityReason::Not; + } + _ => (), + }; +} + +fn record_usage_for_operand(arg: &Operand, result: &mut ArenaMap) { + if let Operand::Copy(p) | Operand::Move(p) = arg { + record_usage(p.local, result); + } +} + fn mutability_of_locals( db: &dyn HirDatabase, body: &MirBody, ) -> ArenaMap { let mut result: ArenaMap = - body.locals.iter().map(|it| (it.0, MutabilityReason::Not)).collect(); - let mut push_mut_span = |local, span| match &mut result[local] { - MutabilityReason::Mut { spans } => spans.push(span), - it @ MutabilityReason::Not => *it = MutabilityReason::Mut { spans: vec![span] }, - }; + body.locals.iter().map(|it| (it.0, MutabilityReason::Unused)).collect(); + let ever_init_maps = ever_initialized_map(db, body); for (block_id, mut ever_init_map) in ever_init_maps.into_iter() { let block = &body.basic_blocks[block_id]; @@ -350,23 +376,51 @@ fn mutability_of_locals( match place_case(db, body, place) { ProjectionCase::Direct => { if ever_init_map.get(place.local).copied().unwrap_or_default() { - push_mut_span(place.local, statement.span); + push_mut_span(place.local, statement.span, &mut result); } else { ever_init_map.insert(place.local, true); } } ProjectionCase::DirectPart => { // Partial initialization is not supported, so it is definitely `mut` - push_mut_span(place.local, statement.span); + push_mut_span(place.local, statement.span, &mut result); } - ProjectionCase::Indirect => (), + ProjectionCase::Indirect => { + record_usage(place.local, &mut result); + } + } + match value { + Rvalue::CopyForDeref(p) + | Rvalue::Discriminant(p) + | Rvalue::Len(p) + | Rvalue::Ref(_, p) => { + record_usage(p.local, &mut result); + } + Rvalue::Use(o) + | Rvalue::Repeat(o, _) + | Rvalue::Cast(_, o, _) + | Rvalue::UnaryOp(_, o) => record_usage_for_operand(o, &mut result), + Rvalue::CheckedBinaryOp(_, o1, o2) => { + for o in [o1, o2] { + record_usage_for_operand(o, &mut result); + } + } + Rvalue::Aggregate(_, args) => { + for arg in args.iter() { + record_usage_for_operand(arg, &mut result); + } + } + Rvalue::ShallowInitBox(_, _) | Rvalue::ShallowInitBoxWithAlloc(_) => (), } if let Rvalue::Ref(BorrowKind::Mut { .. }, p) = value { if place_case(db, body, p) != ProjectionCase::Indirect { - push_mut_span(p.local, statement.span); + push_mut_span(p.local, statement.span, &mut result); } } } + StatementKind::FakeRead(p) => { + record_usage(p.local, &mut result); + } StatementKind::StorageDead(p) => { ever_init_map.insert(*p, false); } @@ -386,15 +440,21 @@ fn mutability_of_locals( | TerminatorKind::FalseEdge { .. } | TerminatorKind::FalseUnwind { .. } | TerminatorKind::GeneratorDrop - | TerminatorKind::SwitchInt { .. } | TerminatorKind::Drop { .. } | TerminatorKind::DropAndReplace { .. } | TerminatorKind::Assert { .. } | TerminatorKind::Yield { .. } => (), - TerminatorKind::Call { destination, .. } => { + TerminatorKind::SwitchInt { discr, targets: _ } => { + record_usage_for_operand(discr, &mut result); + } + TerminatorKind::Call { destination, args, func, .. } => { + record_usage_for_operand(func, &mut result); + for arg in args.iter() { + record_usage_for_operand(arg, &mut result); + } if destination.projection.lookup(&body.projection_store).len() == 0 { if ever_init_map.get(destination.local).copied().unwrap_or_default() { - push_mut_span(destination.local, MirSpan::Unknown); + push_mut_span(destination.local, MirSpan::Unknown, &mut result); } else { ever_init_map.insert(destination.local, true); } diff --git a/crates/hir-ty/src/mir/eval.rs b/crates/hir-ty/src/mir/eval.rs index 4364e0d323bb..98c78f7f3051 100644 --- a/crates/hir-ty/src/mir/eval.rs +++ b/crates/hir-ty/src/mir/eval.rs @@ -842,6 +842,7 @@ impl Evaluator<'_> { } StatementKind::Deinit(_) => not_supported!("de-init statement"), StatementKind::StorageLive(_) + | StatementKind::FakeRead(_) | StatementKind::StorageDead(_) | StatementKind::Nop => (), } diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs index dd2dba717f95..a5c6983f95cc 100644 --- a/crates/hir-ty/src/mir/lower.rs +++ b/crates/hir-ty/src/mir/lower.rs @@ -529,6 +529,7 @@ impl<'ctx> MirLowerCtx<'ctx> { else { return Ok(None); }; + self.push_fake_read(current, cond_place, expr_id.into()); let (then_target, else_target) = self.pattern_match(current, None, cond_place, *pat)?; self.write_bytes_to_place( @@ -668,6 +669,7 @@ impl<'ctx> MirLowerCtx<'ctx> { else { return Ok(None); }; + self.push_fake_read(current, cond_place, expr_id.into()); let mut end = None; for MatchArm { pat, guard, expr } in arms.iter() { let (then, mut otherwise) = @@ -1299,6 +1301,7 @@ impl<'ctx> MirLowerCtx<'ctx> { return Ok(None); }; if matches!(&self.body.exprs[lhs], Expr::Underscore) { + self.push_fake_read_for_operand(current, rhs_op, span); return Ok(Some(current)); } if matches!( @@ -1575,6 +1578,16 @@ impl<'ctx> MirLowerCtx<'ctx> { self.result.basic_blocks[block].statements.push(statement); } + fn push_fake_read(&mut self, block: BasicBlockId, p: Place, span: MirSpan) { + self.push_statement(block, StatementKind::FakeRead(p).with_span(span)); + } + + fn push_fake_read_for_operand(&mut self, block: BasicBlockId, operand: Operand, span: MirSpan) { + if let Operand::Move(p) | Operand::Copy(p) = operand { + self.push_fake_read(block, p, span); + } + } + fn push_assignment( &mut self, block: BasicBlockId, @@ -1733,6 +1746,7 @@ impl<'ctx> MirLowerCtx<'ctx> { return Ok(None); }; current = c; + self.push_fake_read(current, init_place, span); (current, else_block) = self.pattern_match(current, None, init_place, *pat)?; match (else_block, else_branch) { diff --git a/crates/hir-ty/src/mir/monomorphization.rs b/crates/hir-ty/src/mir/monomorphization.rs index df16d0d82015..7d2bb95d931c 100644 --- a/crates/hir-ty/src/mir/monomorphization.rs +++ b/crates/hir-ty/src/mir/monomorphization.rs @@ -248,6 +248,7 @@ impl Filler<'_> { | Rvalue::CopyForDeref(_) => (), }, StatementKind::Deinit(_) + | StatementKind::FakeRead(_) | StatementKind::StorageLive(_) | StatementKind::StorageDead(_) | StatementKind::Nop => (), diff --git a/crates/hir-ty/src/mir/pretty.rs b/crates/hir-ty/src/mir/pretty.rs index 0108859ff32e..6e42bee97f79 100644 --- a/crates/hir-ty/src/mir/pretty.rs +++ b/crates/hir-ty/src/mir/pretty.rs @@ -233,6 +233,11 @@ impl<'a> MirPrettyCtx<'a> { this.place(p); wln!(this, ");"); } + StatementKind::FakeRead(p) => { + w!(this, "FakeRead("); + this.place(p); + wln!(this, ");"); + } StatementKind::Nop => wln!(this, "Nop;"), } } diff --git a/crates/hir/src/diagnostics.rs b/crates/hir/src/diagnostics.rs index 479138b67f82..66ad95c5597c 100644 --- a/crates/hir/src/diagnostics.rs +++ b/crates/hir/src/diagnostics.rs @@ -66,6 +66,7 @@ diagnostics![ UnresolvedModule, UnresolvedProcMacro, UnusedMut, + UnusedVariable, ]; #[derive(Debug)] @@ -270,6 +271,11 @@ pub struct UnusedMut { pub local: Local, } +#[derive(Debug)] +pub struct UnusedVariable { + pub local: Local, +} + #[derive(Debug)] pub struct MovedOutOfRef { pub ty: Type, diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index b215ed38f28b..a6c6c0dbb8bf 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -98,7 +98,7 @@ pub use crate::{ ReplaceFilterMapNextWithFindMap, TypeMismatch, TypedHole, UndeclaredLabel, UnimplementedBuiltinMacro, UnreachableLabel, UnresolvedExternCrate, UnresolvedField, UnresolvedImport, UnresolvedMacroCall, UnresolvedMethodCall, UnresolvedModule, - UnresolvedProcMacro, UnusedMut, + UnresolvedProcMacro, UnusedMut, UnusedVariable, }, has_source::HasSource, semantics::{PathResolution, Semantics, SemanticsScope, TypeInfo, VisibleTraits}, @@ -1697,9 +1697,20 @@ impl DefWithBody { // Skip synthetic bindings continue; } - let need_mut = &mol[local]; + let mut need_mut = &mol[local]; + if body[binding_id].name.as_str() == Some("self") + && need_mut == &mir::MutabilityReason::Unused + { + need_mut = &mir::MutabilityReason::Not; + } let local = Local { parent: self.into(), binding_id }; match (need_mut, local.is_mut(db)) { + (mir::MutabilityReason::Unused, _) => { + let should_ignore = matches!(body[binding_id].name.as_str(), Some(it) if it.starts_with("_")); + if !should_ignore { + acc.push(UnusedVariable { local }.into()) + } + } (mir::MutabilityReason::Mut { .. }, true) | (mir::MutabilityReason::Not, false) => (), (mir::MutabilityReason::Mut { spans }, false) => { diff --git a/crates/ide-diagnostics/src/handlers/mutability_errors.rs b/crates/ide-diagnostics/src/handlers/mutability_errors.rs index d056e5c85cc0..ee096a100aaa 100644 --- a/crates/ide-diagnostics/src/handlers/mutability_errors.rs +++ b/crates/ide-diagnostics/src/handlers/mutability_errors.rs @@ -324,6 +324,7 @@ fn main() { let x_own = 2; let ref mut x_ref = x_own; //^^^^^^^^^^^^^ 💡 error: cannot mutate immutable variable `x_own` + _ = x_ref; } "#, ); @@ -331,7 +332,7 @@ fn main() { r#" struct Foo; impl Foo { - fn method(&mut self, x: i32) {} + fn method(&mut self, _x: i32) {} } fn main() { let x = Foo; @@ -391,6 +392,7 @@ fn main() { //^^^^^ 💡 warn: variable does not need to be mutable x = 7; //^^^^^ 💡 error: cannot mutate immutable variable `x` + _ = y; } } } @@ -404,12 +406,14 @@ fn main() { // there would be no mutability error for locals in dead code. Rustc tries to // not emit `unused_mut` in this case, but since it works without `mut`, and // special casing it is not trivial, we emit it. + + // Update: now MIR based `unused-variable` is taking over `unused-mut` for the same reason. check_diagnostics( r#" fn main() { return; let mut x = 2; - //^^^^^ 💡 warn: variable does not need to be mutable + //^^^^^ warn: unused variable &mut x; } "#, @@ -419,7 +423,7 @@ fn main() { fn main() { loop {} let mut x = 2; - //^^^^^ 💡 warn: variable does not need to be mutable + //^^^^^ warn: unused variable &mut x; } "#, @@ -440,7 +444,7 @@ fn main(b: bool) { g(); } let mut x = 2; - //^^^^^ 💡 warn: variable does not need to be mutable + //^^^^^ warn: unused variable &mut x; } "#, @@ -454,7 +458,7 @@ fn main(b: bool) { return; } let mut x = 2; - //^^^^^ 💡 warn: variable does not need to be mutable + //^^^^^ warn: unused variable &mut x; } "#, @@ -536,6 +540,7 @@ fn main() { (k @ 5, ref mut t) if { continue; } => { //^^^^^^^^^ 💡 error: cannot mutate immutable variable `z` *t = 5; + _ = k; } _ => { let y = (1, 2); @@ -588,6 +593,7 @@ fn main() { b = 1; c = (2, 3); d = 3; + _ = (c, b, d); } } "#, @@ -600,6 +606,7 @@ fn main() { r#" fn f(mut x: i32) { //^^^^^ 💡 warn: variable does not need to be mutable + f(x + 2); } "#, ); @@ -615,8 +622,11 @@ fn f(x: i32) { r#" fn f((x, y): (i32, i32)) { let t = [0; 2]; - x = 5; - //^^^^^ 💡 error: cannot mutate immutable variable `x` + x = 5; + //^^^^^ 💡 error: cannot mutate immutable variable `x` + _ = x; + _ = y; + _ = t; } "#, ); @@ -645,6 +655,7 @@ fn f(x: [(i32, u8); 10]) { //^^^^^ 💡 warn: variable does not need to be mutable a = 2; //^^^^^ 💡 error: cannot mutate immutable variable `a` + _ = b; } } "#, @@ -666,6 +677,7 @@ fn f(x: [(i32, u8); 10]) { //^^^^^ 💡 error: cannot mutate immutable variable `a` c = 2; //^^^^^ 💡 error: cannot mutate immutable variable `c` + _ = (b, d); } } } @@ -696,18 +708,18 @@ fn f() { fn overloaded_index() { check_diagnostics( r#" -//- minicore: index +//- minicore: index, copy use core::ops::{Index, IndexMut}; struct Foo; impl Index for Foo { type Output = (i32, u8); - fn index(&self, index: usize) -> &(i32, u8) { + fn index(&self, _index: usize) -> &(i32, u8) { &(5, 2) } } impl IndexMut for Foo { - fn index_mut(&mut self, index: usize) -> &mut (i32, u8) { + fn index_mut(&mut self, _index: usize) -> &mut (i32, u8) { &mut (5, 2) } } @@ -715,26 +727,32 @@ fn f() { let mut x = Foo; //^^^^^ 💡 warn: variable does not need to be mutable let y = &x[2]; + _ = (x, y); let x = Foo; let y = &mut x[2]; //^💡 error: cannot mutate immutable variable `x` + _ = (x, y); let mut x = &mut Foo; //^^^^^ 💡 warn: variable does not need to be mutable let y: &mut (i32, u8) = &mut x[2]; + _ = (x, y); let x = Foo; let ref mut y = x[7]; //^ 💡 error: cannot mutate immutable variable `x` + _ = (x, y); let (ref mut y, _) = x[3]; //^ 💡 error: cannot mutate immutable variable `x` + _ = y; match x[10] { //^ 💡 error: cannot mutate immutable variable `x` - (ref y, _) => (), - (_, ref mut y) => (), + (ref y, 5) => _ = y, + (_, ref mut y) => _ = y, } let mut x = Foo; let mut i = 5; //^^^^^ 💡 warn: variable does not need to be mutable let y = &mut x[i]; + _ = y; } "#, ); @@ -744,7 +762,7 @@ fn f() { fn overloaded_deref() { check_diagnostics( r#" -//- minicore: deref_mut +//- minicore: deref_mut, copy use core::ops::{Deref, DerefMut}; struct Foo; @@ -763,21 +781,27 @@ fn f() { let mut x = Foo; //^^^^^ 💡 warn: variable does not need to be mutable let y = &*x; + _ = (x, y); let x = Foo; let y = &mut *x; //^^ 💡 error: cannot mutate immutable variable `x` + _ = (x, y); let x = Foo; + //^ warn: unused variable let x = Foo; let y: &mut (i32, u8) = &mut x; //^^^^^^ 💡 error: cannot mutate immutable variable `x` + _ = (x, y); let ref mut y = *x; //^^ 💡 error: cannot mutate immutable variable `x` + _ = y; let (ref mut y, _) = *x; //^^ 💡 error: cannot mutate immutable variable `x` + _ = y; match *x { //^^ 💡 error: cannot mutate immutable variable `x` - (ref y, _) => (), - (_, ref mut y) => (), + (ref y, 5) => _ = y, + (_, ref mut y) => _ = y, } } "#, @@ -866,6 +890,7 @@ pub fn test() { data: 0 } ); + _ = tree; } "#, ); @@ -925,6 +950,7 @@ fn fn_once(mut x: impl FnOnce(u8) -> u8) -> u8 { let x = X; let closure4 = || { x.mutate(); }; //^ 💡 error: cannot mutate immutable variable `x` + _ = (closure2, closure3, closure4); } "#, ); @@ -941,7 +967,9 @@ fn fn_once(mut x: impl FnOnce(u8) -> u8) -> u8 { z = 3; let mut k = z; //^^^^^ 💡 warn: variable does not need to be mutable + _ = k; }; + _ = (x, closure); } "#, ); @@ -958,6 +986,7 @@ fn f() { } } }; + _ = closure; } "#, ); @@ -972,7 +1001,8 @@ fn f() { let mut x = X; let c2 = || { x = X; x }; let mut x = X; - let c2 = move || { x = X; }; + let c3 = move || { x = X; }; + _ = (c1, c2, c3); } "#, ); @@ -1023,7 +1053,7 @@ fn x(t: &[u8]) { a = 2; //^^^^^ 💡 error: cannot mutate immutable variable `a` - + _ = b; } _ => {} } @@ -1079,6 +1109,7 @@ fn f() { let x = Box::new(5); let closure = || *x = 2; //^ 💡 error: cannot mutate immutable variable `x` + _ = closure; } "#, ); @@ -1156,6 +1187,7 @@ macro_rules! mac { fn main2() { let mut x = mac![]; //^^^^^ 💡 warn: variable does not need to be mutable + _ = x; } "#, ); diff --git a/crates/ide-diagnostics/src/handlers/unused_variables.rs b/crates/ide-diagnostics/src/handlers/unused_variables.rs new file mode 100644 index 000000000000..2658f12f8ad3 --- /dev/null +++ b/crates/ide-diagnostics/src/handlers/unused_variables.rs @@ -0,0 +1,110 @@ +use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext}; + +// Diagnostic: unused-variables +// +// This diagnostic is triggered when a local variable is not used. +pub(crate) fn unused_variables( + ctx: &DiagnosticsContext<'_>, + d: &hir::UnusedVariable, +) -> Diagnostic { + let ast = d.local.primary_source(ctx.sema.db).syntax_ptr(); + Diagnostic::new_with_syntax_node_ptr( + ctx, + DiagnosticCode::RustcLint("unused_variables"), + "unused variable", + ast, + ) +} + +#[cfg(test)] +mod tests { + use crate::tests::check_diagnostics; + + #[test] + fn unused_variables_simple() { + check_diagnostics( + r#" +//- minicore: fn +struct Foo { f1: i32, f2: i64 } + +fn f(kkk: i32) {} + //^^^ warn: unused variable +fn main() { + let a = 2; + //^ warn: unused variable + let b = 5; + // note: `unused variable` implies `unused mut`, so we should not emit both at the same time. + let mut c = f(b); + //^^^^^ warn: unused variable + let (d, e) = (3, 5); + //^ warn: unused variable + let _ = e; + let f1 = 2; + let f2 = 5; + let f = Foo { f1, f2 }; + match f { + Foo { f1, f2 } => { + //^^ warn: unused variable + _ = f2; + } + } + let g = false; + if g {} + let h: fn() -> i32 = || 2; + let i = h(); + //^ warn: unused variable +} +"#, + ); + } + + #[test] + fn unused_self() { + check_diagnostics( + r#" +struct S { +} +impl S { + fn owned_self(self, u: i32) {} + //^ warn: unused variable + fn ref_self(&self, u: i32) {} + //^ warn: unused variable + fn ref_mut_self(&mut self, u: i32) {} + //^ warn: unused variable + fn owned_mut_self(mut self) {} + //^^^^^^^^ 💡 warn: variable does not need to be mutable + +} +"#, + ); + } + + #[test] + fn allow_unused_variables_for_identifiers_starting_with_underline() { + check_diagnostics( + r#" +fn main() { + let _x = 2; +} +"#, + ); + } + + #[test] + fn respect_lint_attributes_for_unused_variables() { + check_diagnostics( + r#" +fn main() { + #[allow(unused_variables)] + let x = 2; +} + +#[deny(unused)] +fn main2() { + let x = 2; + //^ error: unused variable +} +"#, + ); + } +} diff --git a/crates/ide-diagnostics/src/lib.rs b/crates/ide-diagnostics/src/lib.rs index ebe197a6790e..fe5567544e83 100644 --- a/crates/ide-diagnostics/src/lib.rs +++ b/crates/ide-diagnostics/src/lib.rs @@ -56,6 +56,7 @@ mod handlers { pub(crate) mod unresolved_proc_macro; pub(crate) mod undeclared_label; pub(crate) mod unreachable_label; + pub(crate) mod unused_variables; // The handlers below are unusual, the implement the diagnostics as well. pub(crate) mod field_shorthand; @@ -368,6 +369,7 @@ pub fn diagnostics( AnyDiagnostic::UnresolvedModule(d) => handlers::unresolved_module::unresolved_module(&ctx, &d), AnyDiagnostic::UnresolvedProcMacro(d) => handlers::unresolved_proc_macro::unresolved_proc_macro(&ctx, &d, config.proc_macros_enabled, config.proc_attr_macros_enabled), AnyDiagnostic::UnusedMut(d) => handlers::mutability_errors::unused_mut(&ctx, &d), + AnyDiagnostic::UnusedVariable(d) => handlers::unused_variables::unused_variables(&ctx, &d), AnyDiagnostic::BreakOutsideOfLoop(d) => handlers::break_outside_of_loop::break_outside_of_loop(&ctx, &d), AnyDiagnostic::MismatchedTupleStructPatArgCount(d) => handlers::mismatched_arg_count::mismatched_tuple_struct_pat_arg_count(&ctx, &d), }; From ab52ba2de7108453a1f69fe7c1d1045aa2ee02ce Mon Sep 17 00:00:00 2001 From: hkalbasi Date: Sun, 24 Sep 2023 23:45:36 +0330 Subject: [PATCH 066/435] Fix unused_variables in tests --- crates/hir-ty/src/mir/lower.rs | 5 +- .../src/handlers/field_shorthand.rs | 6 ++- .../src/handlers/incorrect_case.rs | 18 +++++-- .../src/handlers/mismatched_arg_count.rs | 22 ++++----- .../src/handlers/missing_fields.rs | 3 +- .../src/handlers/missing_match_arms.rs | 6 ++- .../src/handlers/missing_unsafe.rs | 48 +++++++++---------- .../src/handlers/moved_out_of_ref.rs | 8 ++-- .../replace_filter_map_next_with_find_map.rs | 20 ++++---- .../src/handlers/type_mismatch.rs | 36 +++++++------- .../src/handlers/typed_hole.rs | 4 +- crates/ide/src/inlay_hints/chaining.rs | 12 ++--- crates/test-utils/src/minicore.rs | 38 +++++++-------- 13 files changed, 122 insertions(+), 104 deletions(-) diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs index a5c6983f95cc..9905d522146c 100644 --- a/crates/hir-ty/src/mir/lower.rs +++ b/crates/hir-ty/src/mir/lower.rs @@ -1774,13 +1774,14 @@ impl<'ctx> MirLowerCtx<'ctx> { } } } - hir_def::hir::Statement::Expr { expr, has_semi: _ } => { + &hir_def::hir::Statement::Expr { expr, has_semi: _ } => { let scope2 = self.push_drop_scope(); - let Some((_, c)) = self.lower_expr_as_place(current, *expr, true)? else { + let Some((p, c)) = self.lower_expr_as_place(current, expr, true)? else { scope2.pop_assume_dropped(self); scope.pop_assume_dropped(self); return Ok(None); }; + self.push_fake_read(c, p, expr.into()); current = scope2.pop_and_drop(self, c); } } diff --git a/crates/ide-diagnostics/src/handlers/field_shorthand.rs b/crates/ide-diagnostics/src/handlers/field_shorthand.rs index 3b69640af9b8..9ed8199ae4d0 100644 --- a/crates/ide-diagnostics/src/handlers/field_shorthand.rs +++ b/crates/ide-diagnostics/src/handlers/field_shorthand.rs @@ -166,7 +166,7 @@ fn main() { check_diagnostics( r#" struct A { a: &'static str } -fn f(a: A) { let A { a: hello } = a; } +fn f(a: A) { let A { a: _hello } = a; } "#, ); check_diagnostics( @@ -181,12 +181,14 @@ fn f(a: A) { let A { 0: 0 } = a; } struct A { a: &'static str } fn f(a: A) { let A { a$0: a } = a; + _ = a; } "#, r#" struct A { a: &'static str } fn f(a: A) { let A { a } = a; + _ = a; } "#, ); @@ -196,12 +198,14 @@ fn f(a: A) { struct A { a: &'static str, b: &'static str } fn f(a: A) { let A { a$0: a, b } = a; + _ = (a, b); } "#, r#" struct A { a: &'static str, b: &'static str } fn f(a: A) { let A { a, b } = a; + _ = (a, b); } "#, ); diff --git a/crates/ide-diagnostics/src/handlers/incorrect_case.rs b/crates/ide-diagnostics/src/handlers/incorrect_case.rs index 235062bf531f..7824011db67a 100644 --- a/crates/ide-diagnostics/src/handlers/incorrect_case.rs +++ b/crates/ide-diagnostics/src/handlers/incorrect_case.rs @@ -175,10 +175,10 @@ fn NonSnakeCaseName() {} fn incorrect_function_params() { check_diagnostics( r#" -fn foo(SomeParam: u8) {} +fn foo(SomeParam: u8) { _ = SomeParam; } // ^^^^^^^^^ 💡 warn: Parameter `SomeParam` should have snake_case name, e.g. `some_param` -fn foo2(ok_param: &str, CAPS_PARAM: u8) {} +fn foo2(ok_param: &str, CAPS_PARAM: u8) { _ = (ok_param, CAPS_PARAM); } // ^^^^^^^^^^ 💡 warn: Parameter `CAPS_PARAM` should have snake_case name, e.g. `caps_param` "#, ); @@ -188,6 +188,7 @@ fn foo2(ok_param: &str, CAPS_PARAM: u8) {} fn incorrect_variable_names() { check_diagnostics( r#" +#[allow(unused)] fn foo() { let SOME_VALUE = 10; // ^^^^^^^^^^ 💡 warn: Variable `SOME_VALUE` should have snake_case name, e.g. `some_value` @@ -294,6 +295,7 @@ impl someStruct { // ^^^^^^^^ 💡 warn: Function `SomeFunc` should have snake_case name, e.g. `some_func` let WHY_VAR_IS_CAPS = 10; // ^^^^^^^^^^^^^^^ 💡 warn: Variable `WHY_VAR_IS_CAPS` should have snake_case name, e.g. `why_var_is_caps` + _ = WHY_VAR_IS_CAPS; } } "#, @@ -306,6 +308,7 @@ impl someStruct { r#" enum Option { Some, None } +#[allow(unused)] fn main() { match Option::None { None => (), @@ -322,6 +325,7 @@ fn main() { r#" enum Option { Some, None } +#[allow(unused)] fn main() { match Option::None { SOME_VAR @ None => (), @@ -349,7 +353,9 @@ enum E { } mod F { - fn CheckItWorksWithCrateAttr(BAD_NAME_HI: u8) {} + fn CheckItWorksWithCrateAttr(BAD_NAME_HI: u8) { + _ = BAD_NAME_HI; + } } "#, ); @@ -395,7 +401,7 @@ fn qualify() { #[test] // Issue #8809. fn parenthesized_parameter() { - check_diagnostics(r#"fn f((O): _) {}"#) + check_diagnostics(r#"fn f((O): _) { _ = O; }"#) } #[test] @@ -472,7 +478,9 @@ mod CheckBadStyle { mod F { #![allow(non_snake_case)] - fn CheckItWorksWithModAttr(BAD_NAME_HI: u8) {} + fn CheckItWorksWithModAttr(BAD_NAME_HI: u8) { + _ = BAD_NAME_HI; + } } #[allow(non_snake_case, non_camel_case_types)] diff --git a/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs b/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs index 8265e0b1c117..ede9858c7265 100644 --- a/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs +++ b/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs @@ -131,7 +131,7 @@ fn f() { zero(); } fn simple_free_fn_one() { check_diagnostics( r#" -fn one(arg: u8) {} +fn one(_arg: u8) {} fn f() { one(); } //^^ error: expected 1 argument, found 0 "#, @@ -139,7 +139,7 @@ fn f() { one(); } check_diagnostics( r#" -fn one(arg: u8) {} +fn one(_arg: u8) {} fn f() { one(1); } "#, ); @@ -176,7 +176,7 @@ fn f() { check_diagnostics( r#" struct S; -impl S { fn method(&self, arg: u8) {} } +impl S { fn method(&self, _arg: u8) {} } fn f() { S.method(); @@ -187,7 +187,7 @@ impl S { fn method(&self, arg: u8) {} } check_diagnostics( r#" struct S; -impl S { fn method(&self, arg: u8) {} } +impl S { fn method(&self, _arg: u8) {} } fn f() { S::method(&S, 0); @@ -335,8 +335,8 @@ struct S; impl S { fn method(#[cfg(NEVER)] self) {} - fn method2(#[cfg(NEVER)] self, arg: u8) {} - fn method3(self, #[cfg(NEVER)] arg: u8) {} + fn method2(#[cfg(NEVER)] self, _arg: u8) {} + fn method3(self, #[cfg(NEVER)] _arg: u8) {} } extern "C" { @@ -365,8 +365,8 @@ fn main() { r#" #[rustc_legacy_const_generics(1, 3)] fn mixed( - a: u8, - b: i8, + _a: u8, + _b: i8, ) {} fn f() { @@ -376,8 +376,8 @@ fn f() { #[rustc_legacy_const_generics(1, 3)] fn b( - a: u8, - b: u8, + _a: u8, + _b: u8, ) {} fn g() { @@ -403,7 +403,7 @@ fn f( // ^^ error: this pattern has 0 fields, but the corresponding tuple struct has 2 fields S(e, f, .., g, d): S // ^^^^^^^^^ error: this pattern has 4 fields, but the corresponding tuple struct has 2 fields -) {} +) { _ = (a, b, c, d, e, f, g); } "#, ) } diff --git a/crates/ide-diagnostics/src/handlers/missing_fields.rs b/crates/ide-diagnostics/src/handlers/missing_fields.rs index acc31cd117ad..3178c7fa2bc7 100644 --- a/crates/ide-diagnostics/src/handlers/missing_fields.rs +++ b/crates/ide-diagnostics/src/handlers/missing_fields.rs @@ -290,6 +290,7 @@ fn x(a: S) { struct S { s: u32 } fn x(a: S) { let S { ref s } = a; + _ = s; } ", ) @@ -626,7 +627,7 @@ struct TestStruct { one: i32, two: i64 } fn test_fn() { let one = 1; - let s = TestStruct{ one, two: 2 }; + let _s = TestStruct{ one, two: 2 }; } "#, ); diff --git a/crates/ide-diagnostics/src/handlers/missing_match_arms.rs b/crates/ide-diagnostics/src/handlers/missing_match_arms.rs index 06b03d3d1989..84267d3d9069 100644 --- a/crates/ide-diagnostics/src/handlers/missing_match_arms.rs +++ b/crates/ide-diagnostics/src/handlers/missing_match_arms.rs @@ -19,6 +19,7 @@ pub(crate) fn missing_match_arms( mod tests { use crate::tests::check_diagnostics; + #[track_caller] fn check_diagnostics_no_bails(ra_fixture: &str) { cov_mark::check_count!(validate_match_bailed_out, 0); crate::tests::check_diagnostics(ra_fixture) @@ -564,6 +565,7 @@ fn bang(never: !) { r#" enum Option { Some(T), None } +#[allow(unused)] fn main() { // `Never` is deliberately not defined so that it's an uninferred type. match Option::::None { @@ -719,7 +721,7 @@ fn main() { r#" struct S { a: char} fn main(v: S) { - match v { S{ a } => {} } + match v { S{ a } => { _ = a; } } match v { S{ a: _x } => {} } match v { S{ a: 'a' } => {} } match v { S{..} => {} } @@ -901,7 +903,7 @@ enum E{ A, B } fn foo() { match &E::A { E::A => {} - x => {} + _x => {} } }", ); diff --git a/crates/ide-diagnostics/src/handlers/missing_unsafe.rs b/crates/ide-diagnostics/src/handlers/missing_unsafe.rs index 70b26009bae0..0f695b2745a8 100644 --- a/crates/ide-diagnostics/src/handlers/missing_unsafe.rs +++ b/crates/ide-diagnostics/src/handlers/missing_unsafe.rs @@ -100,9 +100,9 @@ mod tests { r#" fn main() { let x = &5 as *const usize; - unsafe { let y = *x; } - let z = *x; -} //^^💡 error: this operation is unsafe and requires an unsafe function or block + unsafe { let _y = *x; } + let _z = *x; +} //^^💡 error: this operation is unsafe and requires an unsafe function or block "#, ) } @@ -116,13 +116,13 @@ struct HasUnsafe; impl HasUnsafe { unsafe fn unsafe_fn(&self) { let x = &5 as *const usize; - let y = *x; + let _y = *x; } } unsafe fn unsafe_fn() { let x = &5 as *const usize; - let y = *x; + let _y = *x; } fn main() { @@ -152,10 +152,10 @@ struct Ty { static mut STATIC_MUT: Ty = Ty { a: 0 }; fn main() { - let x = STATIC_MUT.a; - //^^^^^^^^^^💡 error: this operation is unsafe and requires an unsafe function or block + let _x = STATIC_MUT.a; + //^^^^^^^^^^💡 error: this operation is unsafe and requires an unsafe function or block unsafe { - let x = STATIC_MUT.a; + let _x = STATIC_MUT.a; } } "#, @@ -187,13 +187,13 @@ fn main() { r#" fn main() { let x = &5 as *const usize; - let z = *x$0; + let _z = *x$0; } "#, r#" fn main() { let x = &5 as *const usize; - let z = unsafe { *x }; + let _z = unsafe { *x }; } "#, ); @@ -231,7 +231,7 @@ struct S(usize); impl S { unsafe fn func(&self) { let x = &self.0 as *const usize; - let z = *x; + let _z = *x; } } fn main() { @@ -244,7 +244,7 @@ struct S(usize); impl S { unsafe fn func(&self) { let x = &self.0 as *const usize; - let z = *x; + let _z = *x; } } fn main() { @@ -267,7 +267,7 @@ struct Ty { static mut STATIC_MUT: Ty = Ty { a: 0 }; fn main() { - let x = STATIC_MUT$0.a; + let _x = STATIC_MUT$0.a; } "#, r#" @@ -278,7 +278,7 @@ struct Ty { static mut STATIC_MUT: Ty = Ty { a: 0 }; fn main() { - let x = unsafe { STATIC_MUT.a }; + let _x = unsafe { STATIC_MUT.a }; } "#, ) @@ -382,16 +382,16 @@ fn main() { static mut STATIC_MUT: u8 = 0; fn main() { - let x; - x = STATIC_MUT$0; + let _x; + _x = STATIC_MUT$0; } "#, r#" static mut STATIC_MUT: u8 = 0; fn main() { - let x; - x = unsafe { STATIC_MUT }; + let _x; + _x = unsafe { STATIC_MUT }; } "#, ) @@ -405,14 +405,14 @@ fn main() { static mut STATIC_MUT: u8 = 0; fn main() { - let x = STATIC_MUT$0 + 1; + let _x = STATIC_MUT$0 + 1; } "#, r#" static mut STATIC_MUT: u8 = 0; fn main() { - let x = unsafe { STATIC_MUT } + 1; + let _x = unsafe { STATIC_MUT } + 1; } "#, ) @@ -425,14 +425,14 @@ fn main() { static mut STATIC_MUT: u8 = 0; fn main() { - let x = &STATIC_MUT$0; + let _x = &STATIC_MUT$0; } "#, r#" static mut STATIC_MUT: u8 = 0; fn main() { - let x = unsafe { &STATIC_MUT }; + let _x = unsafe { &STATIC_MUT }; } "#, ) @@ -445,14 +445,14 @@ fn main() { static mut STATIC_MUT: u8 = 0; fn main() { - let x = &&STATIC_MUT$0; + let _x = &&STATIC_MUT$0; } "#, r#" static mut STATIC_MUT: u8 = 0; fn main() { - let x = unsafe { &&STATIC_MUT }; + let _x = unsafe { &&STATIC_MUT }; } "#, ) diff --git a/crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs b/crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs index 3aa4aa97026a..20175b3fd535 100644 --- a/crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs +++ b/crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs @@ -29,6 +29,7 @@ fn main() { let a = &X; let b = *a; //^ error: cannot move `X` out of reference + _ = b; } "#, ); @@ -46,6 +47,7 @@ fn main() { let b = a.0; //^ error: cannot move `X` out of reference let y = a.1; + _ = (b, y); } "#, ); @@ -59,8 +61,8 @@ fn main() { struct X; fn main() { static S: X = X; - let s = S; - //^ error: cannot move `X` out of reference + let _s = S; + //^^ error: cannot move `X` out of reference } "#, ); @@ -165,7 +167,7 @@ enum X { fn main() { let x = &X::Bar; - let c = || match *x { + let _c = || match *x { X::Foo(t) => t, _ => 5, }; diff --git a/crates/ide-diagnostics/src/handlers/replace_filter_map_next_with_find_map.rs b/crates/ide-diagnostics/src/handlers/replace_filter_map_next_with_find_map.rs index 083ef3e8dc16..d15233d15c2c 100644 --- a/crates/ide-diagnostics/src/handlers/replace_filter_map_next_with_find_map.rs +++ b/crates/ide-diagnostics/src/handlers/replace_filter_map_next_with_find_map.rs @@ -74,8 +74,8 @@ mod tests { r#" //- minicore: iterators fn foo() { - let m = core::iter::repeat(()).filter_map(|()| Some(92)).next(); -} //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 💡 weak: replace filter_map(..).next() with find_map(..) + let _m = core::iter::repeat(()).filter_map(|()| Some(92)).next(); +} //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 💡 weak: replace filter_map(..).next() with find_map(..) "#, ); } @@ -117,7 +117,7 @@ fn foo() { fn foo() { let mut m = core::iter::repeat(()) .filter_map(|()| Some(92)); - let n = m.next(); + let _n = m.next(); } "#, ); @@ -148,22 +148,22 @@ fn foo() { fn foo() { #[allow(clippy::filter_map_next)] - let m = core::iter::repeat(()).filter_map(|()| Some(92)).next(); + let _m = core::iter::repeat(()).filter_map(|()| Some(92)).next(); } #[deny(clippy::filter_map_next)] fn foo() { - let m = core::iter::repeat(()).filter_map(|()| Some(92)).next(); -} //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 💡 error: replace filter_map(..).next() with find_map(..) + let _m = core::iter::repeat(()).filter_map(|()| Some(92)).next(); +} //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 💡 error: replace filter_map(..).next() with find_map(..) fn foo() { - let m = core::iter::repeat(()).filter_map(|()| Some(92)).next(); -} //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 💡 weak: replace filter_map(..).next() with find_map(..) + let _m = core::iter::repeat(()).filter_map(|()| Some(92)).next(); +} //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 💡 weak: replace filter_map(..).next() with find_map(..) #[warn(clippy::filter_map_next)] fn foo() { - let m = core::iter::repeat(()).filter_map(|()| Some(92)).next(); -} //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 💡 warn: replace filter_map(..).next() with find_map(..) + let _m = core::iter::repeat(()).filter_map(|()| Some(92)).next(); +} //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 💡 warn: replace filter_map(..).next() with find_map(..) "#, ); diff --git a/crates/ide-diagnostics/src/handlers/type_mismatch.rs b/crates/ide-diagnostics/src/handlers/type_mismatch.rs index 15bd28c00dfd..1f400bb42dde 100644 --- a/crates/ide-diagnostics/src/handlers/type_mismatch.rs +++ b/crates/ide-diagnostics/src/handlers/type_mismatch.rs @@ -205,7 +205,7 @@ fn main() { test(123); //^^^ 💡 error: expected &i32, found i32 } -fn test(arg: &i32) {} +fn test(_arg: &i32) {} "#, ); } @@ -217,13 +217,13 @@ fn test(arg: &i32) {} fn main() { test(123$0); } -fn test(arg: &i32) {} +fn test(_arg: &i32) {} "#, r#" fn main() { test(&123); } -fn test(arg: &i32) {} +fn test(_arg: &i32) {} "#, ); } @@ -235,13 +235,13 @@ fn test(arg: &i32) {} fn main() { test($0123); } -fn test(arg: &mut i32) {} +fn test(_arg: &mut i32) {} "#, r#" fn main() { test(&mut 123); } -fn test(arg: &mut i32) {} +fn test(_arg: &mut i32) {} "#, ); } @@ -254,13 +254,13 @@ fn test(arg: &mut i32) {} fn main() { test($0[1, 2, 3]); } -fn test(arg: &[i32]) {} +fn test(_arg: &[i32]) {} "#, r#" fn main() { test(&[1, 2, 3]); } -fn test(arg: &[i32]) {} +fn test(_arg: &[i32]) {} "#, ); } @@ -279,7 +279,7 @@ impl core::ops::Deref for Foo { fn main() { test($0Foo); } -fn test(arg: &Bar) {} +fn test(_arg: &Bar) {} "#, r#" struct Foo; @@ -291,7 +291,7 @@ impl core::ops::Deref for Foo { fn main() { test(&Foo); } -fn test(arg: &Bar) {} +fn test(_arg: &Bar) {} "#, ); } @@ -305,7 +305,7 @@ fn main() { } struct Test; impl Test { - fn call_by_ref(&self, arg: &i32) {} + fn call_by_ref(&self, _arg: &i32) {} } "#, r#" @@ -314,7 +314,7 @@ fn main() { } struct Test; impl Test { - fn call_by_ref(&self, arg: &i32) {} + fn call_by_ref(&self, _arg: &i32) {} } "#, ); @@ -345,7 +345,7 @@ macro_rules! thousand { 1000_u64 }; } -fn test(foo: &u64) {} +fn test(_foo: &u64) {} fn main() { test($0thousand!()); } @@ -356,7 +356,7 @@ macro_rules! thousand { 1000_u64 }; } -fn test(foo: &u64) {} +fn test(_foo: &u64) {} fn main() { test(&thousand!()); } @@ -369,12 +369,12 @@ fn main() { check_fix( r#" fn main() { - let test: &mut i32 = $0123; + let _test: &mut i32 = $0123; } "#, r#" fn main() { - let test: &mut i32 = &mut 123; + let _test: &mut i32 = &mut 123; } "#, ); @@ -411,7 +411,7 @@ fn div(x: i32, y: i32) -> Option { fn f() -> Rate { // FIXME: add some error loop {} } - fn run(t: Rate<5>) { + fn run(_t: Rate<5>) { } fn main() { run(f()) // FIXME: remove this error @@ -426,7 +426,7 @@ fn div(x: i32, y: i32) -> Option { check_diagnostics( r#" pub struct Rate(T); - fn run(t: Rate) { + fn run(_t: Rate) { } fn main() { run(Rate::<_, _, _>(5)); @@ -650,7 +650,7 @@ fn h() { r#" struct X(T); -fn foo(x: X) {} +fn foo(_x: X) {} fn test1() { // Unknown might be `i32`, so we should not emit type mismatch here. foo(X(42)); diff --git a/crates/ide-diagnostics/src/handlers/typed_hole.rs b/crates/ide-diagnostics/src/handlers/typed_hole.rs index 4af67227115d..4e215a89d793 100644 --- a/crates/ide-diagnostics/src/handlers/typed_hole.rs +++ b/crates/ide-diagnostics/src/handlers/typed_hole.rs @@ -142,8 +142,8 @@ fn t() -> T { loop {} } check_diagnostics( r#" fn main() { - let x = [(); _]; - let y: [(); 10] = [(); _]; + let _x = [(); _]; + let _y: [(); 10] = [(); _]; _ = 0; (_,) = (1,); } diff --git a/crates/ide/src/inlay_hints/chaining.rs b/crates/ide/src/inlay_hints/chaining.rs index 12e46c0f8837..4152e6067551 100644 --- a/crates/ide/src/inlay_hints/chaining.rs +++ b/crates/ide/src/inlay_hints/chaining.rs @@ -484,7 +484,7 @@ fn main() { file_id: FileId( 1, ), - range: 10739..10747, + range: 10752..10760, }, ), tooltip: "", @@ -497,7 +497,7 @@ fn main() { file_id: FileId( 1, ), - range: 10771..10775, + range: 10784..10788, }, ), tooltip: "", @@ -522,7 +522,7 @@ fn main() { file_id: FileId( 1, ), - range: 10739..10747, + range: 10752..10760, }, ), tooltip: "", @@ -535,7 +535,7 @@ fn main() { file_id: FileId( 1, ), - range: 10771..10775, + range: 10784..10788, }, ), tooltip: "", @@ -560,7 +560,7 @@ fn main() { file_id: FileId( 1, ), - range: 10739..10747, + range: 10752..10760, }, ), tooltip: "", @@ -573,7 +573,7 @@ fn main() { file_id: FileId( 1, ), - range: 10771..10775, + range: 10784..10788, }, ), tooltip: "", diff --git a/crates/test-utils/src/minicore.rs b/crates/test-utils/src/minicore.rs index 573f56b003af..cc41d87f5d97 100644 --- a/crates/test-utils/src/minicore.rs +++ b/crates/test-utils/src/minicore.rs @@ -489,7 +489,7 @@ pub mod ops { I: SliceIndex<[T]>, { type Output = I::Output; - fn index(&self, index: I) -> &I::Output { + fn index(&self, _index: I) -> &I::Output { loop {} } } @@ -497,7 +497,7 @@ pub mod ops { where I: SliceIndex<[T]>, { - fn index_mut(&mut self, index: I) -> &mut I::Output { + fn index_mut(&mut self, _index: I) -> &mut I::Output { loop {} } } @@ -507,7 +507,7 @@ pub mod ops { I: SliceIndex<[T]>, { type Output = I::Output; - fn index(&self, index: I) -> &I::Output { + fn index(&self, _index: I) -> &I::Output { loop {} } } @@ -515,7 +515,7 @@ pub mod ops { where I: SliceIndex<[T]>, { - fn index_mut(&mut self, index: I) -> &mut I::Output { + fn index_mut(&mut self, _index: I) -> &mut I::Output { loop {} } } @@ -863,17 +863,17 @@ pub mod fmt { pub struct DebugTuple; pub struct DebugStruct; impl Formatter<'_> { - pub fn debug_tuple(&mut self, name: &str) -> DebugTuple { + pub fn debug_tuple(&mut self, _name: &str) -> DebugTuple { DebugTuple } - pub fn debug_struct(&mut self, name: &str) -> DebugStruct { + pub fn debug_struct(&mut self, _name: &str) -> DebugStruct { DebugStruct } } impl DebugTuple { - pub fn field(&mut self, value: &dyn Debug) -> &mut Self { + pub fn field(&mut self, _value: &dyn Debug) -> &mut Self { self } @@ -883,7 +883,7 @@ pub mod fmt { } impl DebugStruct { - pub fn field(&mut self, name: &str, value: &dyn Debug) -> &mut Self { + pub fn field(&mut self, _name: &str, _value: &dyn Debug) -> &mut Self { self } @@ -996,7 +996,7 @@ pub mod fmt { ($($t:ty)*) => { $( impl const Debug for $t { - fn fmt(&self, f: &mut Formatter<'_>) -> Result { + fn fmt(&self, _f: &mut Formatter<'_>) -> Result { Ok(()) } } @@ -1012,7 +1012,7 @@ pub mod fmt { } impl Debug for [T] { - fn fmt(&self, f: &mut Formatter<'_>) -> Result { + fn fmt(&self, _f: &mut Formatter<'_>) -> Result { Ok(()) } } @@ -1062,7 +1062,7 @@ pub mod option { } } - pub fn and(self, optb: Option) -> Option { + pub fn and(self, _optb: Option) -> Option { loop {} } pub fn unwrap_or(self, default: T) -> T { @@ -1080,25 +1080,25 @@ pub mod option { } // endregion:result // region:fn - pub fn and_then(self, f: F) -> Option + pub fn and_then(self, _f: F) -> Option where F: FnOnce(T) -> Option, { loop {} } - pub fn unwrap_or_else(self, f: F) -> T + pub fn unwrap_or_else(self, _f: F) -> T where F: FnOnce() -> T, { loop {} } - pub fn map_or(self, default: U, f: F) -> U + pub fn map_or(self, _default: U, _f: F) -> U where F: FnOnce(T) -> U, { loop {} } - pub fn map_or_else(self, default: D, f: F) -> U + pub fn map_or_else(self, _default: D, _f: F) -> U where D: FnOnce() -> U, F: FnOnce(T) -> U, @@ -1129,7 +1129,7 @@ pub mod pin { pointer: P, } impl

Pin

{ - pub fn new(pointer: P) -> Pin

{ + pub fn new(_pointer: P) -> Pin

{ loop {} } } @@ -1226,7 +1226,7 @@ pub mod iter { mod sources { mod repeat { - pub fn repeat(elt: T) -> Repeat { + pub fn repeat(_elt: T) -> Repeat { loop {} } @@ -1266,7 +1266,7 @@ pub mod iter { fn take(self, n: usize) -> crate::iter::Take { loop {} } - fn filter_map(self, f: F) -> crate::iter::FilterMap + fn filter_map(self, _f: F) -> crate::iter::FilterMap where Self: Sized, F: FnMut(Self::Item) -> Option, @@ -1337,7 +1337,7 @@ mod panic { mod panicking { #[lang = "panic_fmt"] - pub const fn panic_fmt(fmt: crate::fmt::Arguments<'_>) -> ! { + pub const fn panic_fmt(_fmt: crate::fmt::Arguments<'_>) -> ! { loop {} } } From 588c7d9182de9748f87d99f5f26c0f840fe59e16 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Sun, 24 Sep 2023 22:47:29 +0200 Subject: [PATCH 067/435] minor: hover_simple refactor --- crates/base-db/src/input.rs | 1 + crates/ide-db/src/defs.rs | 4 ++-- crates/ide/src/hover.rs | 32 +++++++++++++++----------------- 3 files changed, 18 insertions(+), 19 deletions(-) diff --git a/crates/base-db/src/input.rs b/crates/base-db/src/input.rs index b75c7079be78..65db5c0fc7d3 100644 --- a/crates/base-db/src/input.rs +++ b/crates/base-db/src/input.rs @@ -257,6 +257,7 @@ pub trait ProcMacroExpander: fmt::Debug + Send + Sync + RefUnwindSafe { ) -> Result; } +#[derive(Debug)] pub enum ProcMacroExpansionError { Panic(String), /// Things like "proc macro server was killed by OOM". diff --git a/crates/ide-db/src/defs.rs b/crates/ide-db/src/defs.rs index 4ce80532e8ef..ef72fc3861a7 100644 --- a/crates/ide-db/src/defs.rs +++ b/crates/ide-db/src/defs.rs @@ -161,8 +161,8 @@ impl IdentClass { ast::AwaitExpr(await_expr) => OperatorClass::classify_await(sema, &await_expr).map(IdentClass::Operator), ast::BinExpr(bin_expr) => OperatorClass::classify_bin(sema, &bin_expr).map(IdentClass::Operator), ast::IndexExpr(index_expr) => OperatorClass::classify_index(sema, &index_expr).map(IdentClass::Operator), - ast::PrefixExpr(prefix_expr) => OperatorClass::classify_prefix(sema,&prefix_expr).map(IdentClass::Operator), - ast::TryExpr(try_expr) => OperatorClass::classify_try(sema,&try_expr).map(IdentClass::Operator), + ast::PrefixExpr(prefix_expr) => OperatorClass::classify_prefix(sema, &prefix_expr).map(IdentClass::Operator), + ast::TryExpr(try_expr) => OperatorClass::classify_try(sema, &try_expr).map(IdentClass::Operator), _ => None, } } diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index 21934b9480ef..e0b64fe7988e 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs @@ -180,26 +180,24 @@ fn hover_simple( descended() .filter_map(|token| { let node = token.parent()?; - let class = IdentClass::classify_token(sema, token)?; - if let IdentClass::Operator(OperatorClass::Await(_)) = class { + match IdentClass::classify_node(sema, &node)? { // It's better for us to fall back to the keyword hover here, // rendering poll is very confusing - return None; + IdentClass::Operator(OperatorClass::Await(_)) => None, + + IdentClass::NameRefClass(NameRefClass::ExternCrateShorthand { + decl, + .. + }) => Some(vec![(Definition::ExternCrateDecl(decl), node)]), + + class => Some( + class + .definitions() + .into_iter() + .zip(iter::repeat(node)) + .collect::>(), + ), } - if let IdentClass::NameRefClass(NameRefClass::ExternCrateShorthand { - decl, - .. - }) = class - { - return Some(vec![(Definition::ExternCrateDecl(decl), node)]); - } - Some( - class - .definitions() - .into_iter() - .zip(iter::once(node).cycle()) - .collect::>(), - ) }) .flatten() .unique_by(|&(def, _)| def) From 7306504b82cfc1d39f44c3bd59aceca483e37eac Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Sun, 24 Sep 2023 15:39:12 -0700 Subject: [PATCH 068/435] fix panic with wrapping/unwrapping result return type assists --- .../src/handlers/unwrap_result_return_type.rs | 24 +++++++++++++++---- .../handlers/wrap_return_type_in_result.rs | 24 +++++++++++++++---- 2 files changed, 40 insertions(+), 8 deletions(-) diff --git a/crates/ide-assists/src/handlers/unwrap_result_return_type.rs b/crates/ide-assists/src/handlers/unwrap_result_return_type.rs index f235b554e61f..03e6dfebebfb 100644 --- a/crates/ide-assists/src/handlers/unwrap_result_return_type.rs +++ b/crates/ide-assists/src/handlers/unwrap_result_return_type.rs @@ -123,10 +123,8 @@ fn tail_cb_impl(acc: &mut Vec, e: &ast::Expr) { for_each_tail_expr(&break_expr_arg, &mut |e| tail_cb_impl(acc, e)) } } - Expr::ReturnExpr(ret_expr) => { - if let Some(ret_expr_arg) = &ret_expr.expr() { - for_each_tail_expr(ret_expr_arg, &mut |e| tail_cb_impl(acc, e)); - } + Expr::ReturnExpr(_) => { + // all return expressions have already been handled by the walk loop } e => acc.push(e.clone()), } @@ -800,6 +798,24 @@ fn foo() -> i32 { ); } + #[test] + fn wrap_return_in_tail_position() { + check_assist( + unwrap_result_return_type, + r#" +//- minicore: result +fn foo(num: i32) -> $0Result { + return Ok(num) +} +"#, + r#" +fn foo(num: i32) -> i32 { + return num +} +"#, + ); + } + #[test] fn unwrap_result_return_type_simple_with_closure() { check_assist( diff --git a/crates/ide-assists/src/handlers/wrap_return_type_in_result.rs b/crates/ide-assists/src/handlers/wrap_return_type_in_result.rs index 61e9bcdcc516..b68ed00f7721 100644 --- a/crates/ide-assists/src/handlers/wrap_return_type_in_result.rs +++ b/crates/ide-assists/src/handlers/wrap_return_type_in_result.rs @@ -98,10 +98,8 @@ fn tail_cb_impl(acc: &mut Vec, e: &ast::Expr) { for_each_tail_expr(&break_expr_arg, &mut |e| tail_cb_impl(acc, e)) } } - Expr::ReturnExpr(ret_expr) => { - if let Some(ret_expr_arg) = &ret_expr.expr() { - for_each_tail_expr(ret_expr_arg, &mut |e| tail_cb_impl(acc, e)); - } + Expr::ReturnExpr(_) => { + // all return expressions have already been handled by the walk loop } e => acc.push(e.clone()), } @@ -732,6 +730,24 @@ fn foo() -> Result { ); } + #[test] + fn wrap_return_in_tail_position() { + check_assist( + wrap_return_type_in_result, + r#" +//- minicore: result +fn foo(num: i32) -> $0i32 { + return num +} +"#, + r#" +fn foo(num: i32) -> Result { + return Ok(num) +} +"#, + ); + } + #[test] fn wrap_return_type_in_result_simple_with_closure() { check_assist( From 963ba5957971d2adeceedbe3fa8a4df3ff95bb6b Mon Sep 17 00:00:00 2001 From: Henry Chen Date: Mon, 25 Sep 2023 10:13:25 +0800 Subject: [PATCH 069/435] minor: update libc to 0.2.148 `cargo update -p libc` --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fa7b6a2fa378..7eac6267b8b5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -916,9 +916,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.146" +version = "0.2.148" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b" +checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" [[package]] name = "libloading" From f64eecd2e255b33e7f6944d0f6abde44e04e3326 Mon Sep 17 00:00:00 2001 From: Milo <50248166+Milo123459@users.noreply.github.com> Date: Mon, 25 Sep 2023 11:30:21 +0000 Subject: [PATCH 070/435] fix one --- crates/ide-assists/src/handlers/generate_function.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/ide-assists/src/handlers/generate_function.rs b/crates/ide-assists/src/handlers/generate_function.rs index 5b13e01b1330..7949e176531b 100644 --- a/crates/ide-assists/src/handlers/generate_function.rs +++ b/crates/ide-assists/src/handlers/generate_function.rs @@ -683,7 +683,7 @@ where { // This function should be only called with `Impl`, `Trait`, or `Function`, for which it's // infallible to get source ast. - let node = ctx.sema.source(def).unwrap().value; + let node = ctx.sema.source(def).expect("definition's source couldn't be found").value; let generic_params = node.generic_param_list().into_iter().flat_map(|it| it.generic_params()); let where_clauses = node.where_clause().into_iter().flat_map(|it| it.predicates()); (generic_params, where_clauses) From 85ead6ec278c7bb99173189d5baba00429c0b32e Mon Sep 17 00:00:00 2001 From: Milo <50248166+Milo123459@users.noreply.github.com> Date: Mon, 25 Sep 2023 11:48:23 +0000 Subject: [PATCH 071/435] remove other unwraps --- crates/ide-assists/src/handlers/generate_function.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/ide-assists/src/handlers/generate_function.rs b/crates/ide-assists/src/handlers/generate_function.rs index 7949e176531b..f74fc5df4bd2 100644 --- a/crates/ide-assists/src/handlers/generate_function.rs +++ b/crates/ide-assists/src/handlers/generate_function.rs @@ -404,7 +404,11 @@ impl FunctionBuilder { leading_ws, ret_type: fn_def.ret_type(), // PANIC: we guarantee we always create a function body with a tail expr - tail_expr: fn_def.body().unwrap().tail_expr().unwrap(), + tail_expr: fn_def + .body() + .expect("generated function should have a body") + .tail_expr() + .expect("function body should have a tail expression"), should_focus_return_type: self.should_focus_return_type, fn_def, trailing_ws, From bce4be9478f18eded9412bb064d5ef193189d9aa Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Mon, 25 Sep 2023 21:01:54 -0700 Subject: [PATCH 072/435] fix: make bool_to_enum assist create enum at top-level --- .../ide-assists/src/handlers/bool_to_enum.rs | 193 +++++++++++++++--- crates/ide-assists/src/tests/generated.rs | 6 +- 2 files changed, 163 insertions(+), 36 deletions(-) diff --git a/crates/ide-assists/src/handlers/bool_to_enum.rs b/crates/ide-assists/src/handlers/bool_to_enum.rs index 85b0b87d0c95..3303a2dd3c7d 100644 --- a/crates/ide-assists/src/handlers/bool_to_enum.rs +++ b/crates/ide-assists/src/handlers/bool_to_enum.rs @@ -16,7 +16,7 @@ use syntax::{ edit_in_place::{AttrsOwnerEdit, Indent}, make, HasName, }, - ted, AstNode, NodeOrToken, SyntaxNode, T, + match_ast, ted, AstNode, NodeOrToken, SyntaxNode, T, }; use text_edit::TextRange; @@ -40,10 +40,10 @@ use crate::assist_context::{AssistContext, Assists}; // ``` // -> // ``` -// fn main() { -// #[derive(PartialEq, Eq)] -// enum Bool { True, False } +// #[derive(PartialEq, Eq)] +// enum Bool { True, False } // +// fn main() { // let bool = Bool::True; // // if bool == Bool::True { @@ -270,6 +270,10 @@ fn replace_usages( } _ => (), } + } else if let Some((ty_annotation, initializer)) = find_assoc_const_usage(&new_name) + { + edit.replace(ty_annotation.syntax().text_range(), "Bool"); + replace_bool_expr(edit, initializer); } else if new_name.syntax().ancestors().find_map(ast::UseTree::cast).is_none() { // for any other usage in an expression, replace it with a check that it is the true variant if let Some((record_field, expr)) = new_name @@ -413,6 +417,15 @@ fn find_record_pat_field_usage(name: &ast::NameLike) -> Option { } } +fn find_assoc_const_usage(name: &ast::NameLike) -> Option<(ast::Type, ast::Expr)> { + let const_ = name.syntax().parent().and_then(ast::Const::cast)?; + if const_.syntax().parent().and_then(ast::AssocItemList::cast).is_none() { + return None; + } + + Some((const_.ty()?, const_.body()?)) +} + /// Adds the definition of the new enum before the target node. fn add_enum_def( edit: &mut SourceChangeBuilder, @@ -430,11 +443,12 @@ fn add_enum_def( .any(|module| module.nearest_non_block_module(ctx.db()) != *target_module); let enum_def = make_bool_enum(make_enum_pub); - let indent = IndentLevel::from_node(&target_node); + let insert_before = node_to_insert_before(target_node); + let indent = IndentLevel::from_node(&insert_before); enum_def.reindent_to(indent); ted::insert_all( - ted::Position::before(&edit.make_syntax_mut(target_node)), + ted::Position::before(&edit.make_syntax_mut(insert_before)), vec![ enum_def.syntax().clone().into(), make::tokens::whitespace(&format!("\n\n{indent}")).into(), @@ -442,6 +456,35 @@ fn add_enum_def( ); } +/// Finds where to put the new enum definition, at the nearest module or at top-level. +fn node_to_insert_before(mut target_node: SyntaxNode) -> SyntaxNode { + let mut ancestors = target_node.ancestors(); + + while let Some(ancestor) = ancestors.next() { + match_ast! { + match ancestor { + ast::Item(item) => { + if item + .syntax() + .parent() + .and_then(|item_list| item_list.parent()) + .and_then(ast::Module::cast) + .is_some() + { + return ancestor; + } + }, + ast::SourceFile(_) => break, + _ => (), + } + } + + target_node = ancestor; + } + + target_node +} + fn make_bool_enum(make_pub: bool) -> ast::Enum { let enum_def = make::enum_( if make_pub { Some(make::visibility_pub()) } else { None }, @@ -491,10 +534,10 @@ fn main() { } "#, r#" -fn main() { - #[derive(PartialEq, Eq)] - enum Bool { True, False } +#[derive(PartialEq, Eq)] +enum Bool { True, False } +fn main() { let foo = Bool::True; if foo == Bool::True { @@ -520,10 +563,10 @@ fn main() { } "#, r#" -fn main() { - #[derive(PartialEq, Eq)] - enum Bool { True, False } +#[derive(PartialEq, Eq)] +enum Bool { True, False } +fn main() { let foo = Bool::True; if foo == Bool::False { @@ -545,10 +588,10 @@ fn main() { } "#, r#" -fn main() { - #[derive(PartialEq, Eq)] - enum Bool { True, False } +#[derive(PartialEq, Eq)] +enum Bool { True, False } +fn main() { let foo: Bool = Bool::False; } "#, @@ -565,10 +608,10 @@ fn main() { } "#, r#" -fn main() { - #[derive(PartialEq, Eq)] - enum Bool { True, False } +#[derive(PartialEq, Eq)] +enum Bool { True, False } +fn main() { let foo = if 1 == 2 { Bool::True } else { Bool::False }; } "#, @@ -590,10 +633,10 @@ fn main() { } "#, r#" -fn main() { - #[derive(PartialEq, Eq)] - enum Bool { True, False } +#[derive(PartialEq, Eq)] +enum Bool { True, False } +fn main() { let foo = Bool::False; let bar = true; @@ -619,10 +662,10 @@ fn main() { } "#, r#" -fn main() { - #[derive(PartialEq, Eq)] - enum Bool { True, False } +#[derive(PartialEq, Eq)] +enum Bool { True, False } +fn main() { let foo = Bool::True; if *&foo == Bool::True { @@ -645,10 +688,10 @@ fn main() { } "#, r#" -fn main() { - #[derive(PartialEq, Eq)] - enum Bool { True, False } +#[derive(PartialEq, Eq)] +enum Bool { True, False } +fn main() { let foo: Bool; foo = Bool::True; } @@ -671,10 +714,10 @@ fn main() { } "#, r#" -fn main() { - #[derive(PartialEq, Eq)] - enum Bool { True, False } +#[derive(PartialEq, Eq)] +enum Bool { True, False } +fn main() { let foo = Bool::True; let bar = foo == Bool::False; @@ -702,11 +745,11 @@ fn main() { } "#, r#" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + fn main() { if !"foo".chars().any(|c| { - #[derive(PartialEq, Eq)] - enum Bool { True, False } - let foo = Bool::True; foo == Bool::True }) { @@ -1445,6 +1488,90 @@ pub mod bar { ) } + #[test] + fn const_in_impl_cross_file() { + check_assist( + bool_to_enum, + r#" +//- /main.rs +mod foo; + +struct Foo; + +impl Foo { + pub const $0BOOL: bool = true; +} + +//- /foo.rs +use crate::Foo; + +fn foo() -> bool { + Foo::BOOL +} +"#, + r#" +//- /main.rs +mod foo; + +struct Foo; + +#[derive(PartialEq, Eq)] +pub enum Bool { True, False } + +impl Foo { + pub const BOOL: Bool = Bool::True; +} + +//- /foo.rs +use crate::{Foo, Bool}; + +fn foo() -> bool { + Foo::BOOL == Bool::True +} +"#, + ) + } + + #[test] + fn const_in_trait() { + check_assist( + bool_to_enum, + r#" +trait Foo { + const $0BOOL: bool; +} + +impl Foo for usize { + const BOOL: bool = true; +} + +fn main() { + if ::BOOL { + println!("foo"); + } +} +"#, + r#" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +trait Foo { + const BOOL: Bool; +} + +impl Foo for usize { + const BOOL: Bool = Bool::True; +} + +fn main() { + if ::BOOL == Bool::True { + println!("foo"); + } +} +"#, + ) + } + #[test] fn const_non_bool() { cov_mark::check!(not_applicable_non_bool_const); diff --git a/crates/ide-assists/src/tests/generated.rs b/crates/ide-assists/src/tests/generated.rs index 63a08a0e5697..5a815d5c6a18 100644 --- a/crates/ide-assists/src/tests/generated.rs +++ b/crates/ide-assists/src/tests/generated.rs @@ -294,10 +294,10 @@ fn main() { } "#####, r#####" -fn main() { - #[derive(PartialEq, Eq)] - enum Bool { True, False } +#[derive(PartialEq, Eq)] +enum Bool { True, False } +fn main() { let bool = Bool::True; if bool == Bool::True { From 73150c3f360d399126c1ce9ce2f9846b9f0b5293 Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Mon, 25 Sep 2023 21:44:16 -0700 Subject: [PATCH 073/435] fix: wrap method call exprs in parens --- .../ide-assists/src/handlers/bool_to_enum.rs | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/crates/ide-assists/src/handlers/bool_to_enum.rs b/crates/ide-assists/src/handlers/bool_to_enum.rs index 3303a2dd3c7d..1c0cbb9dfdac 100644 --- a/crates/ide-assists/src/handlers/bool_to_enum.rs +++ b/crates/ide-assists/src/handlers/bool_to_enum.rs @@ -274,6 +274,11 @@ fn replace_usages( { edit.replace(ty_annotation.syntax().text_range(), "Bool"); replace_bool_expr(edit, initializer); + } else if let Some(receiver) = find_method_call_expr_usage(&new_name) { + edit.replace( + receiver.syntax().text_range(), + format!("({} == Bool::True)", receiver), + ); } else if new_name.syntax().ancestors().find_map(ast::UseTree::cast).is_none() { // for any other usage in an expression, replace it with a check that it is the true variant if let Some((record_field, expr)) = new_name @@ -426,6 +431,17 @@ fn find_assoc_const_usage(name: &ast::NameLike) -> Option<(ast::Type, ast::Expr) Some((const_.ty()?, const_.body()?)) } +fn find_method_call_expr_usage(name: &ast::NameLike) -> Option { + let method_call = name.syntax().ancestors().find_map(ast::MethodCallExpr::cast)?; + let receiver = method_call.receiver()?; + + if !receiver.syntax().descendants().contains(name.syntax()) { + return None; + } + + Some(receiver) +} + /// Adds the definition of the new enum before the target node. fn add_enum_def( edit: &mut SourceChangeBuilder, @@ -1287,6 +1303,38 @@ fn main() { ) } + #[test] + fn field_method_chain_usage() { + check_assist( + bool_to_enum, + r#" +struct Foo { + $0bool: bool, +} + +fn main() { + let foo = Foo { bool: true }; + + foo.bool.then(|| 2); +} +"#, + r#" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +struct Foo { + bool: Bool, +} + +fn main() { + let foo = Foo { bool: Bool::True }; + + (foo.bool == Bool::True).then(|| 2); +} +"#, + ) + } + #[test] fn field_non_bool() { cov_mark::check!(not_applicable_non_bool_field); From 6ca48d98c46885b27e04ac9bcfbb3b563282ac6c Mon Sep 17 00:00:00 2001 From: Connor Skees Date: Tue, 26 Sep 2023 06:31:16 +0000 Subject: [PATCH 074/435] feat: add backtick to surrounding and auto-closing pairs --- editors/code/language-configuration.json | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/editors/code/language-configuration.json b/editors/code/language-configuration.json index 51f0e65f4fd3..1c348b63f1a2 100644 --- a/editors/code/language-configuration.json +++ b/editors/code/language-configuration.json @@ -18,7 +18,8 @@ { "open": "[", "close": "]" }, { "open": "(", "close": ")" }, { "open": "\"", "close": "\"", "notIn": ["string"] }, - { "open": "/*", "close": " */" } + { "open": "/*", "close": " */" }, + { "open": "`", "close": "`", "notIn": ["string"] } ], "autoCloseBefore": ";:.,=}])> \n\t", "surroundingPairs": [ @@ -27,7 +28,8 @@ ["(", ")"], ["<", ">"], ["\"", "\""], - ["'", "'"] + ["'", "'"], + ["`", "`"] ], "indentationRules": { "increaseIndentPattern": "^.*\\{[^}\"']*$|^.*\\([^\\)\"']*$", From 0dbde71159c72e9502689766e731b396a4bf15f8 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 26 Sep 2023 12:25:59 +0200 Subject: [PATCH 075/435] Simplify --- crates/syntax/src/lib.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/syntax/src/lib.rs b/crates/syntax/src/lib.rs index a5044911c918..4939ab39049c 100644 --- a/crates/syntax/src/lib.rs +++ b/crates/syntax/src/lib.rs @@ -75,7 +75,7 @@ pub use smol_str::SmolStr; #[derive(Debug, PartialEq, Eq)] pub struct Parse { green: GreenNode, - errors: Arc>, + errors: Arc<[SyntaxError]>, _ty: PhantomData T>, } @@ -87,7 +87,7 @@ impl Clone for Parse { impl Parse { fn new(green: GreenNode, errors: Vec) -> Parse { - Parse { green, errors: Arc::new(errors), _ty: PhantomData } + Parse { green, errors: errors.into(), _ty: PhantomData } } pub fn syntax_node(&self) -> SyntaxNode { @@ -107,7 +107,7 @@ impl Parse { T::cast(self.syntax_node()).unwrap() } - pub fn ok(self) -> Result>> { + pub fn ok(self) -> Result> { if self.errors.is_empty() { Ok(self.tree()) } else { @@ -144,7 +144,7 @@ impl Parse { parsing::incremental_reparse(self.tree().syntax(), indel, self.errors.to_vec()).map( |(green_node, errors, _reparsed_range)| Parse { green: green_node, - errors: Arc::new(errors), + errors: errors.into(), _ty: PhantomData, }, ) @@ -168,7 +168,7 @@ impl SourceFile { errors.extend(validation::validate(&root)); assert_eq!(root.kind(), SyntaxKind::SOURCE_FILE); - Parse { green, errors: Arc::new(errors), _ty: PhantomData } + Parse { green, errors: errors.into(), _ty: PhantomData } } } @@ -275,7 +275,7 @@ impl ast::TokenTree { let (green, errors) = builder.finish_raw(); - Parse { green, errors: Arc::new(errors), _ty: PhantomData } + Parse { green, errors: errors.into(), _ty: PhantomData } } } From 6c907e1e207cd4fc4a60432c7f2c05394efe63e8 Mon Sep 17 00:00:00 2001 From: Alex Veber Date: Wed, 27 Sep 2023 02:19:50 +0300 Subject: [PATCH 076/435] Improve useRustcErrorCode description --- editors/code/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/editors/code/package.json b/editors/code/package.json index 856d69d7eb86..5b6572dd867c 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -467,7 +467,7 @@ "type": "boolean" }, "rust-analyzer.diagnostics.useRustcErrorCode": { - "markdownDescription": "Whether to use the rustc error code.", + "markdownDescription": "Whether to show diagnostics using the original rustc error code. If this is false all rustc diagnostics will have the code 'rustc(Click for full compiler diagnostics)'", "default": false, "type": "boolean" }, From 5b04a7d338045fc2f0bbf0f8fd852cc70cf9869b Mon Sep 17 00:00:00 2001 From: Alex Veber Date: Wed, 27 Sep 2023 18:33:22 +0300 Subject: [PATCH 077/435] Update editors/code/package.json MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Laurențiu Nicola --- editors/code/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/editors/code/package.json b/editors/code/package.json index 5b6572dd867c..639588566344 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -467,7 +467,7 @@ "type": "boolean" }, "rust-analyzer.diagnostics.useRustcErrorCode": { - "markdownDescription": "Whether to show diagnostics using the original rustc error code. If this is false all rustc diagnostics will have the code 'rustc(Click for full compiler diagnostics)'", + "markdownDescription": "Whether to show diagnostics using the original rustc error code. If this is false, all rustc diagnostics will have the code 'rustc(Click for full compiler diagnostics)'", "default": false, "type": "boolean" }, From 2b9dde14abfd523c2dd4e848bad62844d009009e Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 28 Sep 2023 13:16:11 +0200 Subject: [PATCH 078/435] Allocate ast ids for parameters --- crates/hir-def/src/data.rs | 11 +++-------- crates/hir-def/src/item_tree.rs | 15 +++++++++++---- crates/hir-def/src/item_tree/lower.rs | 20 ++++++++++++++++---- crates/hir-def/src/item_tree/pretty.rs | 6 +++--- crates/hir-expand/src/ast_id_map.rs | 2 +- 5 files changed, 34 insertions(+), 20 deletions(-) diff --git a/crates/hir-def/src/data.rs b/crates/hir-def/src/data.rs index 68defa3858fc..718f241cf780 100644 --- a/crates/hir-def/src/data.rs +++ b/crates/hir-def/src/data.rs @@ -15,9 +15,7 @@ use crate::{ attr::Attrs, db::DefDatabase, expander::{Expander, Mark}, - item_tree::{ - self, AssocItem, FnFlags, ItemTree, ItemTreeId, MacroCall, ModItem, Param, TreeId, - }, + item_tree::{self, AssocItem, FnFlags, ItemTree, ItemTreeId, MacroCall, ModItem, TreeId}, macro_call_as_call_id, macro_id_to_def_id, nameres::{ attr_resolution::ResolvedAttr, @@ -69,7 +67,7 @@ impl FunctionData { let is_varargs = enabled_params .clone() .next_back() - .map_or(false, |param| matches!(item_tree[param], Param::Varargs)); + .map_or(false, |param| item_tree[param].type_ref.is_none()); let mut flags = func.flags; if is_varargs { @@ -105,10 +103,7 @@ impl FunctionData { name: func.name.clone(), params: enabled_params .clone() - .filter_map(|id| match &item_tree[id] { - Param::Normal(ty) => Some(ty.clone()), - Param::Varargs => None, - }) + .filter_map(|id| item_tree[id].type_ref.clone()) .collect(), ret_type: func.ret_type.clone(), attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()), diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs index 4c812b62a46a..3c4f21d5c69b 100644 --- a/crates/hir-def/src/item_tree.rs +++ b/crates/hir-def/src/item_tree.rs @@ -613,10 +613,17 @@ pub struct Function { pub(crate) flags: FnFlags, } -#[derive(Debug, Clone, Eq, PartialEq)] -pub enum Param { - Normal(Interned), - Varargs, +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct Param { + /// This is [`None`] for varargs + pub type_ref: Option>, + pub ast_id: ParamAstId, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum ParamAstId { + Param(FileAstId), + SelfParam(FileAstId), } bitflags::bitflags! { diff --git a/crates/hir-def/src/item_tree/lower.rs b/crates/hir-def/src/item_tree/lower.rs index e4702c113b85..c0a880a64bb6 100644 --- a/crates/hir-def/src/item_tree/lower.rs +++ b/crates/hir-def/src/item_tree/lower.rs @@ -295,8 +295,12 @@ impl<'a> Ctx<'a> { } } }; - let ty = Interned::new(self_type); - let idx = self.data().params.alloc(Param::Normal(ty)); + let type_ref = Interned::new(self_type); + let ast_id = self.source_ast_id_map.ast_id(&self_param); + let idx = self.data().params.alloc(Param { + type_ref: Some(type_ref), + ast_id: ParamAstId::SelfParam(ast_id), + }); self.add_attrs( idx.into(), RawAttrs::new(self.db.upcast(), &self_param, self.hygiene()), @@ -305,11 +309,19 @@ impl<'a> Ctx<'a> { } for param in param_list.params() { let idx = match param.dotdotdot_token() { - Some(_) => self.data().params.alloc(Param::Varargs), + Some(_) => { + let ast_id = self.source_ast_id_map.ast_id(¶m); + self.data() + .params + .alloc(Param { type_ref: None, ast_id: ParamAstId::Param(ast_id) }) + } None => { let type_ref = TypeRef::from_ast_opt(&self.body_ctx, param.ty()); let ty = Interned::new(type_ref); - self.data().params.alloc(Param::Normal(ty)) + let ast_id = self.source_ast_id_map.ast_id(¶m); + self.data() + .params + .alloc(Param { type_ref: Some(ty), ast_id: ParamAstId::Param(ast_id) }) } }; self.add_attrs(idx.into(), RawAttrs::new(self.db.upcast(), ¶m, self.hygiene())); diff --git a/crates/hir-def/src/item_tree/pretty.rs b/crates/hir-def/src/item_tree/pretty.rs index 417bd37c8a9b..5036c2b88297 100644 --- a/crates/hir-def/src/item_tree/pretty.rs +++ b/crates/hir-def/src/item_tree/pretty.rs @@ -261,15 +261,15 @@ impl Printer<'_> { self.indented(|this| { for param in params.clone() { this.print_attrs_of(param, "\n"); - match &this.tree[param] { - Param::Normal(ty) => { + match &this.tree[param].type_ref { + Some(ty) => { if flags.contains(FnFlags::HAS_SELF_PARAM) { w!(this, "self: "); } this.print_type_ref(ty); wln!(this, ","); } - Param::Varargs => { + None => { wln!(this, "..."); } }; diff --git a/crates/hir-expand/src/ast_id_map.rs b/crates/hir-expand/src/ast_id_map.rs index 1906ed15baec..40726505491b 100644 --- a/crates/hir-expand/src/ast_id_map.rs +++ b/crates/hir-expand/src/ast_id_map.rs @@ -99,7 +99,7 @@ register_ast_id_node! { TraitAlias, TypeAlias, Use, - AssocItem, BlockExpr, Variant, RecordField, TupleField, ConstArg + AssocItem, BlockExpr, Variant, RecordField, TupleField, ConstArg, Param, SelfParam } /// Maps items' `SyntaxNode`s to `ErasedFileAstId`s and back. From 791e6c8b1b48e1e9e051cc05443ff65f8ecc0f92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Tue, 19 Sep 2023 14:17:39 +0200 Subject: [PATCH 079/435] scip: Allow customizing cargo config. Re-use the LSP config json for simplicity. --- crates/rust-analyzer/src/cli/flags.rs | 4 ++++ crates/rust-analyzer/src/cli/scip.rs | 17 ++++++++++++++--- crates/rust-analyzer/src/config.rs | 2 ++ 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/crates/rust-analyzer/src/cli/flags.rs b/crates/rust-analyzer/src/cli/flags.rs index 419440b6df7b..fe5022f8606d 100644 --- a/crates/rust-analyzer/src/cli/flags.rs +++ b/crates/rust-analyzer/src/cli/flags.rs @@ -131,6 +131,9 @@ xflags::xflags! { /// The output path where the SCIP file will be written to. Defaults to `index.scip`. optional --output path: PathBuf + + /// A path to an json configuration file that can be used to customize cargo behavior. + optional --config-path config_path: PathBuf } } } @@ -239,6 +242,7 @@ pub struct Scip { pub path: PathBuf, pub output: Option, + pub config_path: Option, } impl RustAnalyzer { diff --git a/crates/rust-analyzer/src/cli/scip.rs b/crates/rust-analyzer/src/cli/scip.rs index 875b724bd892..b058e6d153f0 100644 --- a/crates/rust-analyzer/src/cli/scip.rs +++ b/crates/rust-analyzer/src/cli/scip.rs @@ -12,7 +12,6 @@ use ide::{ }; use ide_db::LineIndexDatabase; use load_cargo::{load_workspace_at, LoadCargoConfig, ProcMacroServerChoice}; -use project_model::{CargoConfig, RustLibSource}; use scip::types as scip_types; use crate::{ @@ -24,8 +23,6 @@ impl flags::Scip { pub fn run(self) -> anyhow::Result<()> { eprintln!("Generating SCIP start..."); let now = Instant::now(); - let mut cargo_config = CargoConfig::default(); - cargo_config.sysroot = Some(RustLibSource::Discover); let no_progress = &|s| (eprintln!("rust-analyzer: Loading {s}")); let load_cargo_config = LoadCargoConfig { @@ -34,6 +31,20 @@ impl flags::Scip { prefill_caches: true, }; let root = vfs::AbsPathBuf::assert(std::env::current_dir()?.join(&self.path)).normalize(); + + let mut config = crate::config::Config::new( + root.clone(), + lsp_types::ClientCapabilities::default(), + /* workspace_roots = */ vec![], + /* is_visual_studio_code = */ false, + ); + + if let Some(p) = self.config_path { + let mut file = std::io::BufReader::new(std::fs::File::open(p)?); + let json = serde_json::from_reader(&mut file)?; + config.update(json)?; + } + let cargo_config = config.cargo(); let (host, vfs, _) = load_workspace_at( root.as_path().as_ref(), &cargo_config, diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index cc7f2da532c3..8e780baa36dd 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -766,6 +766,8 @@ impl fmt::Display for ConfigError { } } +impl std::error::Error for ConfigError {} + impl Config { pub fn new( root_path: AbsPathBuf, From 1b3e5b2105b20b3237efaac17c4a9761890f6597 Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Thu, 28 Sep 2023 10:09:13 -0700 Subject: [PATCH 080/435] style: simplify node_to_insert_before --- .../ide-assists/src/handlers/bool_to_enum.rs | 37 +++++-------------- 1 file changed, 10 insertions(+), 27 deletions(-) diff --git a/crates/ide-assists/src/handlers/bool_to_enum.rs b/crates/ide-assists/src/handlers/bool_to_enum.rs index 1c0cbb9dfdac..082839118c58 100644 --- a/crates/ide-assists/src/handlers/bool_to_enum.rs +++ b/crates/ide-assists/src/handlers/bool_to_enum.rs @@ -16,7 +16,7 @@ use syntax::{ edit_in_place::{AttrsOwnerEdit, Indent}, make, HasName, }, - match_ast, ted, AstNode, NodeOrToken, SyntaxNode, T, + ted, AstNode, NodeOrToken, SyntaxKind, SyntaxNode, T, }; use text_edit::TextRange; @@ -472,33 +472,16 @@ fn add_enum_def( ); } -/// Finds where to put the new enum definition, at the nearest module or at top-level. -fn node_to_insert_before(mut target_node: SyntaxNode) -> SyntaxNode { - let mut ancestors = target_node.ancestors(); - - while let Some(ancestor) = ancestors.next() { - match_ast! { - match ancestor { - ast::Item(item) => { - if item - .syntax() - .parent() - .and_then(|item_list| item_list.parent()) - .and_then(ast::Module::cast) - .is_some() - { - return ancestor; - } - }, - ast::SourceFile(_) => break, - _ => (), - } - } - - target_node = ancestor; - } - +/// Finds where to put the new enum definition. +/// Tries to find the ast node at the nearest module or at top-level, otherwise just +/// returns the input node. +fn node_to_insert_before(target_node: SyntaxNode) -> SyntaxNode { target_node + .ancestors() + .take_while(|it| !matches!(it.kind(), SyntaxKind::MODULE | SyntaxKind::SOURCE_FILE)) + .filter(|it| ast::Item::can_cast(it.kind())) + .last() + .unwrap_or(target_node) } fn make_bool_enum(make_pub: bool) -> ast::Enum { From a382e649ca090b3ef9a6fe2f823d1a4282580f86 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 29 Sep 2023 12:48:46 +0200 Subject: [PATCH 081/435] Recover better on missing parameter in param list --- crates/parser/src/grammar/params.rs | 9 +++- .../inline/err/0023_empty_param_slot.rast | 41 +++++++++++++++++++ .../inline/err/0023_empty_param_slot.rs | 1 + 3 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 crates/parser/test_data/parser/inline/err/0023_empty_param_slot.rast create mode 100644 crates/parser/test_data/parser/inline/err/0023_empty_param_slot.rs diff --git a/crates/parser/src/grammar/params.rs b/crates/parser/src/grammar/params.rs index 74eae9151a26..846da28cb016 100644 --- a/crates/parser/src/grammar/params.rs +++ b/crates/parser/src/grammar/params.rs @@ -7,6 +7,9 @@ use super::*; // fn b(x: i32) {} // fn c(x: i32, ) {} // fn d(x: i32, y: ()) {} + +// test_err empty_param_slot +// fn f(y: i32, ,t: i32) {} pub(super) fn param_list_fn_def(p: &mut Parser<'_>) { list_(p, Flavor::FnDef); } @@ -71,7 +74,11 @@ fn list_(p: &mut Parser<'_>, flavor: Flavor) { if !p.at_ts(PARAM_FIRST.union(ATTRIBUTE_FIRST)) { p.error("expected value parameter"); m.abandon(p); - break; + if p.eat(T![,]) { + continue; + } else { + break; + } } param(p, m, flavor); if !p.at(T![,]) { diff --git a/crates/parser/test_data/parser/inline/err/0023_empty_param_slot.rast b/crates/parser/test_data/parser/inline/err/0023_empty_param_slot.rast new file mode 100644 index 000000000000..39e35a81ee27 --- /dev/null +++ b/crates/parser/test_data/parser/inline/err/0023_empty_param_slot.rast @@ -0,0 +1,41 @@ +SOURCE_FILE + FN + FN_KW "fn" + WHITESPACE " " + NAME + IDENT "f" + PARAM_LIST + L_PAREN "(" + PARAM + IDENT_PAT + NAME + IDENT "y" + COLON ":" + WHITESPACE " " + PATH_TYPE + PATH + PATH_SEGMENT + NAME_REF + IDENT "i32" + COMMA "," + WHITESPACE " " + COMMA "," + PARAM + IDENT_PAT + NAME + IDENT "t" + COLON ":" + WHITESPACE " " + PATH_TYPE + PATH + PATH_SEGMENT + NAME_REF + IDENT "i32" + R_PAREN ")" + WHITESPACE " " + BLOCK_EXPR + STMT_LIST + L_CURLY "{" + R_CURLY "}" + WHITESPACE "\n" +error 12: expected value parameter diff --git a/crates/parser/test_data/parser/inline/err/0023_empty_param_slot.rs b/crates/parser/test_data/parser/inline/err/0023_empty_param_slot.rs new file mode 100644 index 000000000000..0adf7b8d2f02 --- /dev/null +++ b/crates/parser/test_data/parser/inline/err/0023_empty_param_slot.rs @@ -0,0 +1 @@ +fn f(y: i32, ,t: i32) {} From dfeff9f40b77c2a08ea5b454028f2380269f77bf Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 29 Sep 2023 13:34:19 +0200 Subject: [PATCH 082/435] Only run tests on linux in pull requests --- .github/workflows/ci.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index fb7b4b07f984..6dc339eddf34 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -84,6 +84,7 @@ jobs: run: cargo build --quiet ${{ env.USE_SYSROOT_ABI }} - name: Test + if: matrix.os == 'ubuntu-latest' || github.event_name == 'push' run: cargo test ${{ env.USE_SYSROOT_ABI }} -- --nocapture --quiet - name: Switch to stable toolchain From 53f5c1c13f77f0b159e0022e92b0451d63939a1c Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Fri, 29 Sep 2023 02:44:40 +0200 Subject: [PATCH 083/435] internal: re-generate lints.rs --- crates/ide-completion/src/item.rs | 2 +- crates/ide-db/src/generated/lints.rs | 3261 ++++++++++------- crates/ide-db/src/tests/sourcegen_lints.rs | 21 +- crates/ide/src/hover/tests.rs | 54 +- crates/rust-analyzer/tests/slow-tests/tidy.rs | 2 + 5 files changed, 2057 insertions(+), 1283 deletions(-) diff --git a/crates/ide-completion/src/item.rs b/crates/ide-completion/src/item.rs index c45cc8d7b37e..ed74ef7b667b 100644 --- a/crates/ide-completion/src/item.rs +++ b/crates/ide-completion/src/item.rs @@ -89,7 +89,7 @@ impl fmt::Debug for CompletionItem { let mut s = f.debug_struct("CompletionItem"); s.field("label", &self.label).field("source_range", &self.source_range); if self.text_edit.len() == 1 { - let atom = &self.text_edit.iter().next().unwrap(); + let atom = self.text_edit.iter().next().unwrap(); s.field("delete", &atom.delete); s.field("insert", &atom.insert); } else { diff --git a/crates/ide-db/src/generated/lints.rs b/crates/ide-db/src/generated/lints.rs index 57563a174833..52321d5bf1d7 100644 --- a/crates/ide-db/src/generated/lints.rs +++ b/crates/ide-db/src/generated/lints.rs @@ -15,6 +15,11 @@ pub const DEFAULT_LINTS: &[Lint] = &[ description: r##"fully qualified paths that start with a module name instead of `crate`, `self`, or an extern crate name"##, }, Lint { label: "ambiguous_associated_items", description: r##"ambiguous associated items"## }, + Lint { + label: "ambiguous_glob_imports", + description: r##"detects certain glob imports that require reporting an ambiguity error"##, + }, + Lint { label: "ambiguous_glob_reexports", description: r##"ambiguous glob re-exports"## }, Lint { label: "anonymous_parameters", description: r##"detects anonymous parameters"## }, Lint { label: "arithmetic_overflow", description: r##"arithmetic operation overflows"## }, Lint { @@ -39,6 +44,10 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "break_with_label_and_loop", description: r##"`break` expression with label and unlabeled loop as value expression"##, }, + Lint { + label: "byte_slice_in_packed_struct_with_derive", + description: r##"`[u8]` or `str` used in a packed struct with `derive`"##, + }, Lint { label: "cenum_impl_drop_cast", description: r##"a C-like enum implementing Drop is cast"##, @@ -51,6 +60,10 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "coherence_leak_check", description: r##"distinct impls distinguished only by the leak-check code"##, }, + Lint { + label: "coinductive_overlap_in_coherence", + description: r##"impls that are not considered to overlap may be considered to overlap in the future"##, + }, Lint { label: "conflicting_repr_hints", description: r##"conflicts between `#[repr(..)]` hints that were previously accepted and used in practice"##, @@ -59,10 +72,6 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "confusable_idents", description: r##"detects visually confusable pairs between identifiers"##, }, - Lint { - label: "const_err", - description: r##"constant evaluation encountered erroneous expression"##, - }, Lint { label: "const_evaluatable_unchecked", description: r##"detects a generic constant is used in a type without a emitting a warning"##, @@ -73,10 +82,18 @@ pub const DEFAULT_LINTS: &[Lint] = &[ }, Lint { label: "dead_code", description: r##"detect unused, unexported items"## }, Lint { label: "deprecated", description: r##"detects use of deprecated items"## }, + Lint { + label: "deprecated_cfg_attr_crate_type_name", + description: r##"detects usage of `#![cfg_attr(..., crate_type/crate_name = "...")]`"##, + }, Lint { label: "deprecated_in_future", description: r##"detects use of items that will be deprecated in a future version"##, }, + Lint { + label: "deprecated_where_clause_location", + description: r##"deprecated where clause location"##, + }, Lint { label: "deref_into_dyn_supertrait", description: r##"`Deref` implementation usage with a supertrait trait object for output might be shadowed in the future"##, @@ -89,10 +106,23 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "drop_bounds", description: r##"bounds of the form `T: Drop` are most likely incorrect"##, }, + Lint { + label: "dropping_copy_types", + description: r##"calls to `std::mem::drop` with a value that implements Copy"##, + }, + Lint { + label: "dropping_references", + description: r##"calls to `std::mem::drop` with a reference instead of an owned value"##, + }, + Lint { label: "duplicate_macro_attributes", description: r##"duplicated attribute"## }, Lint { label: "dyn_drop", description: r##"trait objects of the form `dyn Drop` are useless"##, }, + Lint { + label: "elided_lifetimes_in_associated_constant", + description: r##"elided lifetimes cannot be used in associated constants in impls"##, + }, Lint { label: "elided_lifetimes_in_paths", description: r##"hidden lifetime parameters in types are deprecated"##, @@ -113,14 +143,38 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "exported_private_dependencies", description: r##"public interface leaks type from a private dependency"##, }, + Lint { + label: "ffi_unwind_calls", + description: r##"call to foreign functions or function pointers with FFI-unwind ABI"##, + }, + Lint { + label: "for_loops_over_fallibles", + description: r##"for-looping over an `Option` or a `Result`, which is more clearly expressed as an `if let`"##, + }, Lint { label: "forbidden_lint_groups", description: r##"applying forbid to lint-groups"## }, + Lint { + label: "forgetting_copy_types", + description: r##"calls to `std::mem::forget` with a value that implements Copy"##, + }, + Lint { + label: "forgetting_references", + description: r##"calls to `std::mem::forget` with a reference instead of an owned value"##, + }, Lint { label: "function_item_references", description: r##"suggest casting to a function pointer when attempting to take references to function items"##, }, Lint { label: "future_incompatible", - description: r##"lint group for: forbidden-lint-groups, illegal-floating-point-literal-pattern, private-in-public, pub-use-of-private-extern-crate, invalid-type-param-default, const-err, unaligned-references, patterns-in-fns-without-body, missing-fragment-specifier, late-bound-lifetime-arguments, order-dependent-trait-objects, coherence-leak-check, unstable-name-collisions, where-clauses-object-safety, proc-macro-derive-resolution-fallback, macro-expanded-macro-exports-accessed-by-absolute-paths, ill-formed-attribute-input, conflicting-repr-hints, ambiguous-associated-items, mutable-borrow-reservation-conflict, indirect-structural-match, pointer-structural-match, nontrivial-structural-match, soft-unstable, cenum-impl-drop-cast, const-evaluatable-unchecked, uninhabited-static, unsupported-naked-functions, invalid-doc-attributes, semicolon-in-expressions-from-macros, legacy-derive-helpers, proc-macro-back-compat, unsupported-calling-conventions, deref-into-dyn-supertrait"##, + description: r##"lint group for: deref-into-dyn-supertrait, ambiguous-associated-items, ambiguous-glob-imports, byte-slice-in-packed-struct-with-derive, cenum-impl-drop-cast, coherence-leak-check, coinductive-overlap-in-coherence, conflicting-repr-hints, const-evaluatable-unchecked, deprecated-cfg-attr-crate-type-name, elided-lifetimes-in-associated-constant, forbidden-lint-groups, ill-formed-attribute-input, illegal-floating-point-literal-pattern, implied-bounds-entailment, indirect-structural-match, invalid-alignment, invalid-doc-attributes, invalid-type-param-default, late-bound-lifetime-arguments, legacy-derive-helpers, macro-expanded-macro-exports-accessed-by-absolute-paths, missing-fragment-specifier, nontrivial-structural-match, order-dependent-trait-objects, patterns-in-fns-without-body, pointer-structural-match, proc-macro-back-compat, proc-macro-derive-resolution-fallback, pub-use-of-private-extern-crate, repr-transparent-external-private-fields, semicolon-in-expressions-from-macros, soft-unstable, suspicious-auto-trait-impls, uninhabited-static, unstable-name-collisions, unstable-syntax-pre-expansion, unsupported-calling-conventions, where-clauses-object-safety"##, + }, + Lint { + label: "fuzzy_provenance_casts", + description: r##"a fuzzy integer to pointer cast is used"##, + }, + Lint { + label: "hidden_glob_reexports", + description: r##"name introduced by a private item shadows a name introduced by a public glob re-export"##, }, Lint { label: "ill_formed_attribute_input", @@ -130,6 +184,10 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "illegal_floating_point_literal_pattern", description: r##"floating-point literals cannot be used in patterns"##, }, + Lint { + label: "implied_bounds_entailment", + description: r##"impl method assumes more implied bounds than its corresponding trait method"##, + }, Lint { label: "improper_ctypes", description: r##"proper use of libc types in foreign modules"##, @@ -155,6 +213,14 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "inline_no_sanitize", description: r##"detects incompatible use of `#[inline(always)]` and `#[no_sanitize(...)]`"##, }, + Lint { + label: "internal_features", + description: r##"internal features are not supposed to be used"##, + }, + Lint { + label: "invalid_alignment", + description: r##"raw pointers must be aligned before dereferencing"##, + }, Lint { label: "invalid_atomic_ordering", description: r##"usage of invalid atomic ordering in atomic operations and memory fences"##, @@ -163,6 +229,26 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "invalid_doc_attributes", description: r##"detects invalid `#[doc(...)]` attributes"##, }, + Lint { + label: "invalid_from_utf8", + description: r##"using a non UTF-8 literal in `std::str::from_utf8`"##, + }, + Lint { + label: "invalid_from_utf8_unchecked", + description: r##"using a non UTF-8 literal in `std::str::from_utf8_unchecked`"##, + }, + Lint { + label: "invalid_macro_export_arguments", + description: r##""invalid_parameter" isn't a valid argument for `#[macro_export]`"##, + }, + Lint { + label: "invalid_nan_comparisons", + description: r##"detects invalid floating point NaN comparisons"##, + }, + Lint { + label: "invalid_reference_casting", + description: r##"casts of `&T` to `&mut T` without interior mutability"##, + }, Lint { label: "invalid_type_param_default", description: r##"type parameter default erroneously allowed in invalid location"##, @@ -188,6 +274,26 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "legacy_derive_helpers", description: r##"detects derive helper attributes that are used before they are introduced"##, }, + Lint { + label: "let_underscore", + description: r##"lint group for: let-underscore-drop, let-underscore-lock"##, + }, + Lint { + label: "let_underscore_drop", + description: r##"non-binding let on a type that implements `Drop`"##, + }, + Lint { + label: "let_underscore_lock", + description: r##"non-binding let on a synchronization lock"##, + }, + Lint { + label: "long_running_const_eval", + description: r##"detects long const eval operations"##, + }, + Lint { + label: "lossy_provenance_casts", + description: r##"a lossy pointer to integer cast is used"##, + }, Lint { label: "macro_expanded_macro_exports_accessed_by_absolute_paths", description: r##"macro-expanded `macro_export` macros from the current crate cannot be referred to by absolute paths"##, @@ -196,6 +302,10 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "macro_use_extern_crate", description: r##"the `#[macro_use]` attribute is now deprecated in favor of using macros via the module system"##, }, + Lint { + label: "map_unit_fn", + description: r##"`Iterator::map` call that discard the iterator's values"##, + }, Lint { label: "meta_variable_misuse", description: r##"possible meta-variable misuse at macro definition"##, @@ -221,17 +331,21 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "mixed_script_confusables", description: r##"detects Unicode scripts whose mixed script confusables codepoints are solely used"##, }, + Lint { + label: "multiple_supertrait_upcastable", + description: r##"detect when an object-safe trait has multiple supertraits"##, + }, Lint { label: "must_not_suspend", description: r##"use of a `#[must_not_suspend]` value across a yield point"##, }, Lint { - label: "mutable_borrow_reservation_conflict", - description: r##"reservation of a two-phased borrow conflicts with other shared borrows"##, + label: "mutable_transmutes", + description: r##"transmuting &T to &mut T is undefined behavior, even if the reference is unused"##, }, Lint { - label: "mutable_transmutes", - description: r##"mutating transmuted &mut T from &T may cause undefined behavior"##, + label: "named_arguments_used_positionally", + description: r##"named arguments in format used positionally"##, }, Lint { label: "named_asm_labels", description: r##"named labels in inline assembly"## }, Lint { @@ -276,6 +390,10 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "noop_method_call", description: r##"detects the use of well-known noop methods"##, }, + Lint { + label: "opaque_hidden_inferred_bound", + description: r##"detects the use of nested `impl Trait` types in associated type bounds that are not general enough"##, + }, Lint { label: "order_dependent_trait_objects", description: r##"trait-object types were treated as different depending on marker-trait order"##, @@ -295,8 +413,12 @@ pub const DEFAULT_LINTS: &[Lint] = &[ description: r##"pointers are not structural-match"##, }, Lint { - label: "private_in_public", - description: r##"detect private items in public interfaces not caught by the old implementation"##, + label: "private_bounds", + description: r##"private type in secondary interface of an item"##, + }, + Lint { + label: "private_interfaces", + description: r##"private type in primary interface of an item"##, }, Lint { label: "proc_macro_back_compat", @@ -314,13 +436,21 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "redundant_semicolons", description: r##"detects unnecessary trailing semicolons"##, }, + Lint { + label: "refining_impl_trait", + description: r##"impl trait in impl method signature does not match trait method signature"##, + }, Lint { label: "renamed_and_removed_lints", description: r##"lints that have been renamed or removed"##, }, + Lint { + label: "repr_transparent_external_private_fields", + description: r##"transparent type contains an external ZST that is marked #[non_exhaustive] or contains private fields"##, + }, Lint { label: "rust_2018_compatibility", - description: r##"lint group for: keyword-idents, anonymous-parameters, tyvar-behind-raw-pointer, absolute-paths-not-starting-with-crate"##, + description: r##"lint group for: keyword-idents, anonymous-parameters, absolute-paths-not-starting-with-crate, tyvar-behind-raw-pointer"##, }, Lint { label: "rust_2018_idioms", @@ -328,7 +458,7 @@ pub const DEFAULT_LINTS: &[Lint] = &[ }, Lint { label: "rust_2021_compatibility", - description: r##"lint group for: ellipsis-inclusive-range-patterns, bare-trait-objects, rust-2021-incompatible-closure-captures, rust-2021-incompatible-or-patterns, rust-2021-prelude-collisions, rust-2021-prefixes-incompatible-syntax, array-into-iter, non-fmt-panics"##, + description: r##"lint group for: ellipsis-inclusive-range-patterns, bare-trait-objects, rust-2021-incompatible-closure-captures, rust-2021-incompatible-or-patterns, rust-2021-prefixes-incompatible-syntax, rust-2021-prelude-collisions, array-into-iter, non-fmt-panics"##, }, Lint { label: "rust_2021_incompatible_closure_captures", @@ -358,14 +488,30 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "soft_unstable", description: r##"a feature gate that doesn't break dependent crates"##, }, + Lint { + label: "special_module_name", + description: r##"module declarations for files with a special meaning"##, + }, Lint { label: "stable_features", description: r##"stable features found in `#[feature]` directive"##, }, + Lint { + label: "suspicious_auto_trait_impls", + description: r##"the rules governing auto traits have recently changed resulting in potential breakage"##, + }, + Lint { + label: "suspicious_double_ref_op", + description: r##"suspicious call of trait method on `&&T`"##, + }, Lint { label: "temporary_cstring_as_ptr", description: r##"detects getting the inner pointer of a temporary `CString`"##, }, + Lint { + label: "test_unstable_lint", + description: r##"this unstable lint is only for testing"##, + }, Lint { label: "text_direction_codepoint_in_comment", description: r##"invisible directionality-changing codepoints in comment"##, @@ -394,10 +540,6 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "tyvar_behind_raw_pointer", description: r##"raw pointer to an inference variable"##, }, - Lint { - label: "unaligned_references", - description: r##"detects unaligned references to fields of packed structs"##, - }, Lint { label: "uncommon_codepoints", description: r##"detects uncommon Unicode codepoints in identifiers"##, @@ -410,23 +552,54 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "unconditional_recursion", description: r##"functions that cannot return without calling themselves"##, }, + Lint { + label: "undefined_naked_function_abi", + description: r##"undefined naked function ABI"##, + }, + Lint { + label: "undropped_manually_drops", + description: r##"calls to `std::mem::drop` with `std::mem::ManuallyDrop` instead of it's inner value"##, + }, + Lint { + label: "unexpected_cfgs", + description: r##"detects unexpected names and values in `#[cfg]` conditions"##, + }, + Lint { + label: "unfulfilled_lint_expectations", + description: r##"unfulfilled lint expectation"##, + }, + Lint { + label: "ungated_async_fn_track_caller", + description: r##"enabling track_caller on an async fn is a no-op unless the async_fn_track_caller feature is enabled"##, + }, Lint { label: "uninhabited_static", description: r##"uninhabited static"## }, Lint { label: "unknown_crate_types", description: r##"unknown crate type found in `#[crate_type]` directive"##, }, Lint { label: "unknown_lints", description: r##"unrecognized lint attribute"## }, + Lint { + label: "unknown_or_malformed_diagnostic_attributes", + description: r##"unrecognized or malformed diagnostic attribute"##, + }, Lint { label: "unnameable_test_items", description: r##"detects an item that cannot be named being marked as `#[test_case]`"##, }, + Lint { + label: "unnameable_types", + description: r##"effective visibility of a type is larger than the area in which it can be named"##, + }, Lint { label: "unreachable_code", description: r##"detects unreachable code paths"## }, Lint { label: "unreachable_patterns", description: r##"detects unreachable patterns"## }, Lint { label: "unreachable_pub", description: r##"`pub` items not reachable from crate root"##, }, - Lint { label: "unsafe_code", description: r##"usage of `unsafe` code"## }, + Lint { + label: "unsafe_code", + description: r##"usage of `unsafe` code and other potentially unsound constructs"##, + }, Lint { label: "unsafe_op_in_unsafe_fn", description: r##"unsafe operations in unsafe functions without an explicit unsafe block are deprecated"##, @@ -439,17 +612,17 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "unstable_name_collisions", description: r##"detects name collision with an existing but unstable method"##, }, + Lint { + label: "unstable_syntax_pre_expansion", + description: r##"unstable syntax can change at any point in the future, causing a hard error!"##, + }, Lint { label: "unsupported_calling_conventions", description: r##"use of unsupported calling convention"##, }, - Lint { - label: "unsupported_naked_functions", - description: r##"unsupported naked function definitions"##, - }, Lint { label: "unused", - description: r##"lint group for: unused-imports, unused-variables, unused-assignments, dead-code, unused-mut, unreachable-code, unreachable-patterns, unused-must-use, unused-unsafe, path-statements, unused-attributes, unused-macros, unused-allocation, unused-doc-comments, unused-extern-crates, unused-features, unused-labels, unused-parens, unused-braces, redundant-semicolons"##, + description: r##"lint group for: unused-imports, unused-variables, unused-assignments, dead-code, unused-mut, unreachable-code, unreachable-patterns, unused-must-use, unused-unsafe, path-statements, unused-attributes, unused-macros, unused-macro-rules, unused-allocation, unused-doc-comments, unused-extern-crates, unused-features, unused-labels, unused-parens, unused-braces, redundant-semicolons, map-unit-fn"##, }, Lint { label: "unused_allocation", @@ -459,6 +632,10 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "unused_assignments", description: r##"detect assignments that will never be read"##, }, + Lint { + label: "unused_associated_type_bounds", + description: r##"detects unused `Foo = Bar` bounds in `dyn Trait`"##, + }, Lint { label: "unused_attributes", description: r##"detects attributes that were not used by the compiler"##, @@ -491,6 +668,10 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "unused_lifetimes", description: r##"detects lifetime parameters that are never used"##, }, + Lint { + label: "unused_macro_rules", + description: r##"detects macro rules that were not used"##, + }, Lint { label: "unused_macros", description: r##"detects macros that were not used"## }, Lint { label: "unused_must_use", @@ -512,6 +693,10 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "unused_results", description: r##"unused result of an expression in a statement"##, }, + Lint { + label: "unused_tuple_struct_fields", + description: r##"detects tuple struct fields that are never read"##, + }, Lint { label: "unused_unsafe", description: r##"unnecessary use of an `unsafe` block"## }, Lint { label: "unused_variables", @@ -521,6 +706,10 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "useless_deprecated", description: r##"detects deprecation attributes with no effect"##, }, + Lint { + label: "useless_ptr_null_checks", + description: r##"useless checking of non-null-typed pointer"##, + }, Lint { label: "variant_size_differences", description: r##"detects enums with widely varying variant sizes"##, @@ -546,45 +735,57 @@ pub const DEFAULT_LINT_GROUPS: &[LintGroup] = &[ LintGroup { lint: Lint { label: "future_incompatible", - description: r##"lint group for: forbidden-lint-groups, illegal-floating-point-literal-pattern, private-in-public, pub-use-of-private-extern-crate, invalid-type-param-default, const-err, unaligned-references, patterns-in-fns-without-body, missing-fragment-specifier, late-bound-lifetime-arguments, order-dependent-trait-objects, coherence-leak-check, unstable-name-collisions, where-clauses-object-safety, proc-macro-derive-resolution-fallback, macro-expanded-macro-exports-accessed-by-absolute-paths, ill-formed-attribute-input, conflicting-repr-hints, ambiguous-associated-items, mutable-borrow-reservation-conflict, indirect-structural-match, pointer-structural-match, nontrivial-structural-match, soft-unstable, cenum-impl-drop-cast, const-evaluatable-unchecked, uninhabited-static, unsupported-naked-functions, invalid-doc-attributes, semicolon-in-expressions-from-macros, legacy-derive-helpers, proc-macro-back-compat, unsupported-calling-conventions, deref-into-dyn-supertrait"##, + description: r##"lint group for: deref-into-dyn-supertrait, ambiguous-associated-items, ambiguous-glob-imports, byte-slice-in-packed-struct-with-derive, cenum-impl-drop-cast, coherence-leak-check, coinductive-overlap-in-coherence, conflicting-repr-hints, const-evaluatable-unchecked, deprecated-cfg-attr-crate-type-name, elided-lifetimes-in-associated-constant, forbidden-lint-groups, ill-formed-attribute-input, illegal-floating-point-literal-pattern, implied-bounds-entailment, indirect-structural-match, invalid-alignment, invalid-doc-attributes, invalid-type-param-default, late-bound-lifetime-arguments, legacy-derive-helpers, macro-expanded-macro-exports-accessed-by-absolute-paths, missing-fragment-specifier, nontrivial-structural-match, order-dependent-trait-objects, patterns-in-fns-without-body, pointer-structural-match, proc-macro-back-compat, proc-macro-derive-resolution-fallback, pub-use-of-private-extern-crate, repr-transparent-external-private-fields, semicolon-in-expressions-from-macros, soft-unstable, suspicious-auto-trait-impls, uninhabited-static, unstable-name-collisions, unstable-syntax-pre-expansion, unsupported-calling-conventions, where-clauses-object-safety"##, }, children: &[ - "forbidden_lint_groups", - "illegal_floating_point_literal_pattern", - "private_in_public", - "pub_use_of_private_extern_crate", - "invalid_type_param_default", - "const_err", - "unaligned_references", - "patterns_in_fns_without_body", - "missing_fragment_specifier", - "late_bound_lifetime_arguments", - "order_dependent_trait_objects", - "coherence_leak_check", - "unstable_name_collisions", - "where_clauses_object_safety", - "proc_macro_derive_resolution_fallback", - "macro_expanded_macro_exports_accessed_by_absolute_paths", - "ill_formed_attribute_input", - "conflicting_repr_hints", - "ambiguous_associated_items", - "mutable_borrow_reservation_conflict", - "indirect_structural_match", - "pointer_structural_match", - "nontrivial_structural_match", - "soft_unstable", - "cenum_impl_drop_cast", - "const_evaluatable_unchecked", - "uninhabited_static", - "unsupported_naked_functions", - "invalid_doc_attributes", - "semicolon_in_expressions_from_macros", - "legacy_derive_helpers", - "proc_macro_back_compat", - "unsupported_calling_conventions", "deref_into_dyn_supertrait", + "ambiguous_associated_items", + "ambiguous_glob_imports", + "byte_slice_in_packed_struct_with_derive", + "cenum_impl_drop_cast", + "coherence_leak_check", + "coinductive_overlap_in_coherence", + "conflicting_repr_hints", + "const_evaluatable_unchecked", + "deprecated_cfg_attr_crate_type_name", + "elided_lifetimes_in_associated_constant", + "forbidden_lint_groups", + "ill_formed_attribute_input", + "illegal_floating_point_literal_pattern", + "implied_bounds_entailment", + "indirect_structural_match", + "invalid_alignment", + "invalid_doc_attributes", + "invalid_type_param_default", + "late_bound_lifetime_arguments", + "legacy_derive_helpers", + "macro_expanded_macro_exports_accessed_by_absolute_paths", + "missing_fragment_specifier", + "nontrivial_structural_match", + "order_dependent_trait_objects", + "patterns_in_fns_without_body", + "pointer_structural_match", + "proc_macro_back_compat", + "proc_macro_derive_resolution_fallback", + "pub_use_of_private_extern_crate", + "repr_transparent_external_private_fields", + "semicolon_in_expressions_from_macros", + "soft_unstable", + "suspicious_auto_trait_impls", + "uninhabited_static", + "unstable_name_collisions", + "unstable_syntax_pre_expansion", + "unsupported_calling_conventions", + "where_clauses_object_safety", ], }, + LintGroup { + lint: Lint { + label: "let_underscore", + description: r##"lint group for: let-underscore-drop, let-underscore-lock"##, + }, + children: &["let_underscore_drop", "let_underscore_lock"], + }, LintGroup { lint: Lint { label: "nonstandard_style", @@ -595,13 +796,13 @@ pub const DEFAULT_LINT_GROUPS: &[LintGroup] = &[ LintGroup { lint: Lint { label: "rust_2018_compatibility", - description: r##"lint group for: keyword-idents, anonymous-parameters, tyvar-behind-raw-pointer, absolute-paths-not-starting-with-crate"##, + description: r##"lint group for: keyword-idents, anonymous-parameters, absolute-paths-not-starting-with-crate, tyvar-behind-raw-pointer"##, }, children: &[ "keyword_idents", "anonymous_parameters", - "tyvar_behind_raw_pointer", "absolute_paths_not_starting_with_crate", + "tyvar_behind_raw_pointer", ], }, LintGroup { @@ -620,15 +821,15 @@ pub const DEFAULT_LINT_GROUPS: &[LintGroup] = &[ LintGroup { lint: Lint { label: "rust_2021_compatibility", - description: r##"lint group for: ellipsis-inclusive-range-patterns, bare-trait-objects, rust-2021-incompatible-closure-captures, rust-2021-incompatible-or-patterns, rust-2021-prelude-collisions, rust-2021-prefixes-incompatible-syntax, array-into-iter, non-fmt-panics"##, + description: r##"lint group for: ellipsis-inclusive-range-patterns, bare-trait-objects, rust-2021-incompatible-closure-captures, rust-2021-incompatible-or-patterns, rust-2021-prefixes-incompatible-syntax, rust-2021-prelude-collisions, array-into-iter, non-fmt-panics"##, }, children: &[ "ellipsis_inclusive_range_patterns", "bare_trait_objects", "rust_2021_incompatible_closure_captures", "rust_2021_incompatible_or_patterns", - "rust_2021_prelude_collisions", "rust_2021_prefixes_incompatible_syntax", + "rust_2021_prelude_collisions", "array_into_iter", "non_fmt_panics", ], @@ -636,7 +837,7 @@ pub const DEFAULT_LINT_GROUPS: &[LintGroup] = &[ LintGroup { lint: Lint { label: "unused", - description: r##"lint group for: unused-imports, unused-variables, unused-assignments, dead-code, unused-mut, unreachable-code, unreachable-patterns, unused-must-use, unused-unsafe, path-statements, unused-attributes, unused-macros, unused-allocation, unused-doc-comments, unused-extern-crates, unused-features, unused-labels, unused-parens, unused-braces, redundant-semicolons"##, + description: r##"lint group for: unused-imports, unused-variables, unused-assignments, dead-code, unused-mut, unreachable-code, unreachable-patterns, unused-must-use, unused-unsafe, path-statements, unused-attributes, unused-macros, unused-macro-rules, unused-allocation, unused-doc-comments, unused-extern-crates, unused-features, unused-labels, unused-parens, unused-braces, redundant-semicolons, map-unit-fn"##, }, children: &[ "unused_imports", @@ -651,6 +852,7 @@ pub const DEFAULT_LINT_GROUPS: &[LintGroup] = &[ "path_statements", "unused_attributes", "unused_macros", + "unused_macro_rules", "unused_allocation", "unused_doc_comments", "unused_extern_crates", @@ -659,6 +861,7 @@ pub const DEFAULT_LINT_GROUPS: &[LintGroup] = &[ "unused_parens", "unused_braces", "redundant_semicolons", + "map_unit_fn", ], }, LintGroup { @@ -671,9 +874,13 @@ pub const DEFAULT_LINT_GROUPS: &[LintGroup] = &[ ]; pub const RUSTDOC_LINTS: &[Lint] = &[ + Lint { label: "____", description: r##"-------"## }, + Lint { label: "____", description: r##"lint group for: ---------"## }, + Lint { label: "name", description: r##"meaning"## }, + Lint { label: "name", description: r##"lint group for: sub-lints"## }, Lint { label: "rustdoc::all", - description: r##"lint group for: rustdoc::broken-intra-doc-links, rustdoc::private-intra-doc-links, rustdoc::missing-doc-code-examples, rustdoc::private-doc-tests, rustdoc::invalid-codeblock-attributes, rustdoc::invalid-rust-codeblocks, rustdoc::invalid-html-tags, rustdoc::bare-urls, rustdoc::missing-crate-level-docs"##, + description: r##"lint group for: rustdoc::broken-intra-doc-links, rustdoc::private-intra-doc-links, rustdoc::private-doc-tests, rustdoc::invalid-codeblock-attributes, rustdoc::invalid-rust-codeblocks, rustdoc::invalid-html-tags, rustdoc::bare-urls, rustdoc::missing-crate-level-docs, rustdoc::unescaped-backticks, rustdoc::redundant-explicit-links"##, }, Lint { label: "rustdoc::bare_urls", description: r##"detects URLs that are not hyperlinks"## }, Lint { @@ -708,24 +915,43 @@ pub const RUSTDOC_LINTS: &[Lint] = &[ label: "rustdoc::private_intra_doc_links", description: r##"linking from a public item to a private one"##, }, -]; -pub const RUSTDOC_LINT_GROUPS: &[LintGroup] = &[LintGroup { - lint: Lint { - label: "rustdoc::all", - description: r##"lint group for: rustdoc::broken-intra-doc-links, rustdoc::private-intra-doc-links, rustdoc::missing-doc-code-examples, rustdoc::private-doc-tests, rustdoc::invalid-codeblock-attributes, rustdoc::invalid-rust-codeblocks, rustdoc::invalid-html-tags, rustdoc::bare-urls, rustdoc::missing-crate-level-docs"##, + Lint { + label: "rustdoc::redundant_explicit_links", + description: r##"detects redundant explicit links in doc comments"##, }, - children: &[ - "rustdoc::broken_intra_doc_links", - "rustdoc::private_intra_doc_links", - "rustdoc::missing_doc_code_examples", - "rustdoc::private_doc_tests", - "rustdoc::invalid_codeblock_attributes", - "rustdoc::invalid_rust_codeblocks", - "rustdoc::invalid_html_tags", - "rustdoc::bare_urls", - "rustdoc::missing_crate_level_docs", - ], -}]; + Lint { + label: "rustdoc::unescaped_backticks", + description: r##"detects unescaped backticks in doc comments"##, + }, +]; +pub const RUSTDOC_LINT_GROUPS: &[LintGroup] = &[ + LintGroup { + lint: Lint { label: "____", description: r##"lint group for: ---------"## }, + children: &["_________"], + }, + LintGroup { + lint: Lint { label: "name", description: r##"lint group for: sub-lints"## }, + children: &["sub_lints"], + }, + LintGroup { + lint: Lint { + label: "rustdoc::all", + description: r##"lint group for: rustdoc::broken-intra-doc-links, rustdoc::private-intra-doc-links, rustdoc::private-doc-tests, rustdoc::invalid-codeblock-attributes, rustdoc::invalid-rust-codeblocks, rustdoc::invalid-html-tags, rustdoc::bare-urls, rustdoc::missing-crate-level-docs, rustdoc::unescaped-backticks, rustdoc::redundant-explicit-links"##, + }, + children: &[ + "rustdoc::broken_intra_doc_links", + "rustdoc::private_intra_doc_links", + "rustdoc::private_doc_tests", + "rustdoc::invalid_codeblock_attributes", + "rustdoc::invalid_rust_codeblocks", + "rustdoc::invalid_html_tags", + "rustdoc::bare_urls", + "rustdoc::missing_crate_level_docs", + "rustdoc::unescaped_backticks", + "rustdoc::redundant_explicit_links", + ], + }, +]; pub const FEATURES: &[Lint] = &[ Lint { @@ -958,56 +1184,15 @@ detail of the `global_allocator` feature not intended for use outside the compiler. ------------------------ -"##, - }, - Lint { - label: "arbitrary_enum_discriminant", - description: r##"# `arbitrary_enum_discriminant` - -The tracking issue for this feature is: [#60553] - -[#60553]: https://github.com/rust-lang/rust/issues/60553 - ------------------------- - -The `arbitrary_enum_discriminant` feature permits tuple-like and -struct-like enum variants with `#[repr()]` to have explicit discriminants. - -## Examples - -```rust -#![feature(arbitrary_enum_discriminant)] - -#[allow(dead_code)] -#[repr(u8)] -enum Enum { - Unit = 3, - Tuple(u16) = 2, - Struct { - a: u8, - b: u16, - } = 1, -} - -impl Enum { - fn tag(&self) -> u8 { - unsafe { *(self as *const Self as *const u8) } - } -} - -assert_eq!(3, Enum::Unit.tag()); -assert_eq!(2, Enum::Tuple(5).tag()); -assert_eq!(1, Enum::Struct{a: 7, b: 11}.tag()); -``` "##, }, Lint { label: "asm_const", description: r##"# `asm_const` -The tracking issue for this feature is: [#72016] +The tracking issue for this feature is: [#93332] -[#72016]: https://github.com/rust-lang/rust/issues/72016 +[#93332]: https://github.com/rust-lang/rust/issues/93332 ------------------------ @@ -1020,9 +1205,9 @@ This feature adds a `const ` operand type to `asm!` and `global_asm!`. label: "asm_experimental_arch", description: r##"# `asm_experimental_arch` -The tracking issue for this feature is: [#72016] +The tracking issue for this feature is: [#93335] -[#72016]: https://github.com/rust-lang/rust/issues/72016 +[#93335]: https://github.com/rust-lang/rust/issues/93335 ------------------------ @@ -1035,6 +1220,10 @@ This feature tracks `asm!` and `global_asm!` support for the following architect - BPF - SPIR-V - AVR +- MSP430 +- M68k +- CSKY +- s390x ## Register classes @@ -1059,6 +1248,14 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | AVR | `reg_pair` | `r3r2` .. `r25r24`, `X`, `Z` | `r` | | AVR | `reg_iw` | `r25r24`, `X`, `Z` | `w` | | AVR | `reg_ptr` | `X`, `Z` | `e` | +| MSP430 | `reg` | `r[0-15]` | `r` | +| M68k | `reg` | `d[0-7]`, `a[0-7]` | `r` | +| M68k | `reg_data` | `d[0-7]` | `d` | +| M68k | `reg_addr` | `a[0-3]` | `a` | +| CSKY | `reg` | `r[0-31]` | `r` | +| CSKY | `freg` | `f[0-31]` | `f` | +| s390x | `reg` | `r[0-10]`, `r[12-14]` | `r` | +| s390x | `freg` | `f[0-15]` | `f` | > **Notes**: > - NVPTX doesn't have a fixed register set, so named registers are not supported. @@ -1087,6 +1284,13 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | BPF | `wreg` | `alu32` | `i8` `i16` `i32` | | AVR | `reg`, `reg_upper` | None | `i8` | | AVR | `reg_pair`, `reg_iw`, `reg_ptr` | None | `i16` | +| MSP430 | `reg` | None | `i8`, `i16` | +| M68k | `reg`, `reg_addr` | None | `i16`, `i32` | +| M68k | `reg_data` | None | `i8`, `i16`, `i32` | +| CSKY | `reg` | None | `i8`, `i16`, `i32` | +| CSKY | `freg` | None | `f32`, | +| s390x | `reg` | None | `i8`, `i16`, `i32`, `i64` | +| s390x | `freg` | None | `f32`, `f64` | ## Register aliases @@ -1100,13 +1304,36 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | AVR | `XL` | `r26` | | AVR | `ZH` | `r31` | | AVR | `ZL` | `r30` | +| MSP430 | `r0` | `pc` | +| MSP430 | `r1` | `sp` | +| MSP430 | `r2` | `sr` | +| MSP430 | `r3` | `cg` | +| MSP430 | `r4` | `fp` | +| M68k | `a5` | `bp` | +| M68k | `a6` | `fp` | +| M68k | `a7` | `sp`, `usp`, `ssp`, `isp` | +| CSKY | `r[0-3]` | `a[0-3]` | +| CSKY | `r[4-11]` | `l[0-7]` | +| CSKY | `r[12-13]` | `t[0-1]` | +| CSKY | `r14` | `sp` | +| CSKY | `r15` | `lr` | +| CSKY | `r[16-17]` | `l[8-9]` | +| CSKY | `r[18-25]` | `t[2-9]` | +| CSKY | `r28` | `rgb` | +| CSKY | `r29` | `rtb` | +| CSKY | `r30` | `svbr` | +| CSKY | `r31` | `tls` | + +> **Notes**: +> - TI does not mandate a frame pointer for MSP430, but toolchains are allowed + to use one; LLVM uses `r4`. ## Unsupported registers | Architecture | Unsupported register | Reason | | ------------ | --------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| All | `sp` | The stack pointer must be restored to its original value at the end of an asm code block. | -| All | `fr` (Hexagon), `$fp` (MIPS), `Y` (AVR) | The frame pointer cannot be used as an input or output. | +| All | `sp`, `r15` (s390x) | The stack pointer must be restored to its original value at the end of an asm code block. | +| All | `fr` (Hexagon), `$fp` (MIPS), `Y` (AVR), `r4` (MSP430), `a6` (M68k), `r11` (s390x) | The frame pointer cannot be used as an input or output. | | All | `r19` (Hexagon) | This is used internally by LLVM as a "base pointer" for functions with complex stack frames. | | MIPS | `$0` or `$zero` | This is a constant zero register which can't be modified. | | MIPS | `$1` or `$at` | Reserved for assembler. | @@ -1115,6 +1342,15 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | MIPS | `$ra` | Return address cannot be used as inputs or outputs. | | Hexagon | `lr` | This is the link register which cannot be used as an input or output. | | AVR | `r0`, `r1`, `r1r0` | Due to an issue in LLVM, the `r0` and `r1` registers cannot be used as inputs or outputs. If modified, they must be restored to their original values before the end of the block. | +|MSP430 | `r0`, `r2`, `r3` | These are the program counter, status register, and constant generator respectively. Neither the status register nor constant generator can be written to. | +| M68k | `a4`, `a5` | Used internally by LLVM for the base pointer and global base pointer. | +| CSKY | `r7`, `r28` | Used internally by LLVM for the base pointer and global base pointer. | +| CSKY | `r8` | Used internally by LLVM for the frame pointer. | +| CSKY | `r14` | Used internally by LLVM for the stack pointer. | +| CSKY | `r15` | This is the link register. | +| CSKY | `r[26-30]` | Reserved by its ABI. | +| CSKY | `r31` | This is the TLS register. | + ## Template modifiers @@ -1129,38 +1365,31 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | PowerPC | `reg` | None | `0` | None | | PowerPC | `reg_nonzero` | None | `3` | `b` | | PowerPC | `freg` | None | `0` | None | +| s390x | `reg` | None | `%r0` | None | +| s390x | `freg` | None | `%f0` | None | +| CSKY | `reg` | None | `r0` | None | +| CSKY | `freg` | None | `f0` | None | # Flags covered by `preserves_flags` These flags registers must be restored upon exiting the asm block if the `preserves_flags` option is set: - AVR - The status register `SREG`. -"##, - }, - Lint { - label: "asm_sym", - description: r##"# `asm_sym` - -The tracking issue for this feature is: [#72016] - -[#72016]: https://github.com/rust-lang/rust/issues/72016 - ------------------------- - -This feature adds a `sym ` operand type to `asm!` and `global_asm!`. -- `` must refer to a `fn` or `static`. -- A mangled symbol name referring to the item is substituted into the asm template string. -- The substituted string does not include any modifiers (e.g. GOT, PLT, relocations, etc). -- `` is allowed to point to a `#[thread_local]` static, in which case the asm code can combine the symbol with relocations (e.g. `@plt`, `@TPOFF`) to read from thread-local data. +- MSP430 + - The status register `r2`. +- M68k + - The condition code register `ccr`. +- s390x + - The condition code register `cc`. "##, }, Lint { label: "asm_unwind", description: r##"# `asm_unwind` -The tracking issue for this feature is: [#72016] +The tracking issue for this feature is: [#93334] -[#72016]: https://github.com/rust-lang/rust/issues/72016 +[#93334]: https://github.com/rust-lang/rust/issues/93334 ------------------------ @@ -1184,8 +1413,8 @@ that are automatically implemented for every type, unless the type, or a type it has explicitly opted out via a negative impl. (Negative impls are separately controlled by the `negative_impls` feature.) -[`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html -[`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html +[`Send`]: ../../std/marker/trait.Send.html +[`Sync`]: ../../std/marker/trait.Sync.html ```rust,ignore (partial-example) impl !Trait for Type {} @@ -1285,8 +1514,6 @@ The tracking issue for this feature is: [#29641] [#29641]: https://github.com/rust-lang/rust/issues/29641 -See also [`box_syntax`](box-syntax.md) - ------------------------ Box patterns let you match on `Box`s: @@ -1299,10 +1526,10 @@ fn main() { let b = Some(Box::new(5)); match b { Some(box n) if n < 0 => { - println!("Box contains negative number {}", n); + println!("Box contains negative number {n}"); }, Some(box n) if n >= 0 => { - println!("Box contains non-negative number {}", n); + println!("Box contains non-negative number {n}"); }, None => { println!("No box"); @@ -1311,32 +1538,6 @@ fn main() { } } ``` -"##, - }, - Lint { - label: "box_syntax", - description: r##"# `box_syntax` - -The tracking issue for this feature is: [#49733] - -[#49733]: https://github.com/rust-lang/rust/issues/49733 - -See also [`box_patterns`](box-patterns.md) - ------------------------- - -Currently the only stable way to create a `Box` is via the `Box::new` method. -Also it is not possible in stable Rust to destructure a `Box` in a match -pattern. The unstable `box` keyword can be used to create a `Box`. An example -usage would be: - -```rust -#![feature(box_syntax)] - -fn main() { - let b = box 5; -} -``` "##, }, Lint { @@ -1349,9 +1550,20 @@ The tracking issue for this feature is: [#74990] ------------------------ -Introduces four new ABI strings: "C-unwind", "stdcall-unwind", -"thiscall-unwind", and "system-unwind". These enable unwinding from other -languages (such as C++) into Rust frames and from Rust into other languages. +Introduces new ABI strings: +- "C-unwind" +- "cdecl-unwind" +- "stdcall-unwind" +- "fastcall-unwind" +- "vectorcall-unwind" +- "thiscall-unwind" +- "aapcs-unwind" +- "win64-unwind" +- "sysv64-unwind" +- "system-unwind" + +These enable unwinding from other languages (such as C++) into Rust frames and +from Rust into other languages. See [RFC 2945] for more information. @@ -1369,7 +1581,7 @@ The tracking issue for this feature is: [#44930] ------------------------ The `c_variadic` language feature enables C-variadic functions to be -defined in Rust. The may be called both from within Rust and via FFI. +defined in Rust. They may be called both from within Rust and via FFI. ## Examples @@ -1423,48 +1635,6 @@ pub unsafe extern "C" fn vadd(n: usize, mut args: VaList) -> usize { This feature is internal to the Rust compiler and is not intended for general use. ------------------------ -"##, - }, - Lint { - label: "cfg_panic", - description: r##"# `cfg_panic` - -The tracking issue for this feature is: [#77443] - -[#77443]: https://github.com/rust-lang/rust/issues/77443 - ------------------------- - -The `cfg_panic` feature makes it possible to execute different code -depending on the panic strategy. - -Possible values at the moment are `"unwind"` or `"abort"`, although -it is possible that new panic strategies may be added to Rust in the -future. - -## Examples - -```rust -#![feature(cfg_panic)] - -#[cfg(panic = "unwind")] -fn a() { - // ... -} - -#[cfg(not(panic = "unwind"))] -fn a() { - // ... -} - -fn b() { - if cfg!(panic = "abort") { - // ... - } else { - // ... - } -} -``` "##, }, Lint { @@ -1545,12 +1715,32 @@ fn b() { "##, }, Lint { - label: "char_error_internals", - description: r##"# `char_error_internals` + label: "cfi_encoding", + description: r##"# `cfi_encoding` -This feature is internal to the Rust compiler and is not intended for general use. +The tracking issue for this feature is: [#89653] + +[#89653]: https://github.com/rust-lang/rust/issues/89653 ------------------------ + +The `cfi_encoding` feature allows the user to define a CFI encoding for a type. +It allows the user to use a different names for types that otherwise would be +required to have the same name as used in externally defined C functions. + +## Examples + +```rust +#![feature(cfi_encoding, extern_types)] + +#[cfi_encoding = "3Foo"] +pub struct Type1(i32); + +extern { + #[cfi_encoding = "3Bar"] + type Type2; +} +``` "##, }, Lint { @@ -1687,17 +1877,6 @@ fn main() { assert_eq!(f(), 23); } ``` -"##, - }, - Lint { - label: "const_eval_limit", - description: r##"# `const_eval_limit` - -The tracking issue for this feature is: [#67217] - -[#67217]: https://github.com/rust-lang/rust/issues/67217 - -The `const_eval_limit` allows someone to limit the evaluation steps the CTFE undertakes to evaluate a `const fn`. "##, }, Lint { @@ -1737,25 +1916,35 @@ This feature is internal to the Rust compiler and is not intended for general us "##, }, Lint { - label: "crate_visibility_modifier", - description: r##"# `crate_visibility_modifier` + label: "coverage_attribute", + description: r##"# `coverage_attribute` -The tracking issue for this feature is: [#53120] +The tracking issue for this feature is: [#84605] -[#53120]: https://github.com/rust-lang/rust/issues/53120 +[#84605]: https://github.com/rust-lang/rust/issues/84605 ------ +--- -The `crate_visibility_modifier` feature allows the `crate` keyword to be used -as a visibility modifier synonymous to `pub(crate)`, indicating that a type -(function, _&c._) is to be visible to the entire enclosing crate, but not to -other crates. +The `coverage` attribute can be used to selectively disable coverage +instrumentation in an annotated function. This might be useful to: + +- Avoid instrumentation overhead in a performance critical function +- Avoid generating coverage for a function that is not meant to be executed, + but still target 100% coverage for the rest of the program. + +## Example ```rust -#![feature(crate_visibility_modifier)] +#![feature(coverage_attribute)] -crate struct Foo { - bar: usize, +// `foo()` will get coverage instrumentation (by default) +fn foo() { + // ... +} + +#[coverage(off)] +fn bar() { + // ... } ``` "##, @@ -1803,57 +1992,6 @@ const WILL_FAIL: i32 = 4; This feature is internal to the Rust compiler and is not intended for general use. ------------------------ -"##, - }, - Lint { - label: "default_free_fn", - description: r##"# `default_free_fn` - -The tracking issue for this feature is: [#73014] - -[#73014]: https://github.com/rust-lang/rust/issues/73014 - ------------------------- - -Adds a free `default()` function to the `std::default` module. This function -just forwards to [`Default::default()`], but may remove repetition of the word -"default" from the call site. - -[`Default::default()`]: https://doc.rust-lang.org/nightly/std/default/trait.Default.html#tymethod.default - -Here is an example: - -```rust -#![feature(default_free_fn)] -use std::default::default; - -#[derive(Default)] -struct AppConfig { - foo: FooConfig, - bar: BarConfig, -} - -#[derive(Default)] -struct FooConfig { - foo: i32, -} - -#[derive(Default)] -struct BarConfig { - bar: f32, - baz: u8, -} - -fn main() { - let options = AppConfig { - foo: default(), - bar: BarConfig { - bar: 10.1, - ..default() - }, - }; -} -``` "##, }, Lint { @@ -1885,7 +2023,7 @@ The tracking issue for this feature is: [#43781] The `doc_cfg` feature allows an API be documented as only available in some specific platforms. This attribute has two effects: -1. In the annotated item's documentation, there will be a message saying "This is supported on +1. In the annotated item's documentation, there will be a message saying "Available on (platform) only". 2. The item's doc-tests will only run on the specific platform. @@ -2020,60 +2158,17 @@ stabilized. "##, }, Lint { - label: "explicit_generic_args_with_impl_trait", - description: r##"# `explicit_generic_args_with_impl_trait` + label: "extended_varargs_abi_support", + description: r##"# `extended_varargs_abi_support` -The tracking issue for this feature is: [#83701] +The tracking issue for this feature is: [#100189] -[#83701]: https://github.com/rust-lang/rust/issues/83701 +[#100189]: https://github.com/rust-lang/rust/issues/100189 ------------------------ -The `explicit_generic_args_with_impl_trait` feature gate lets you specify generic arguments even -when `impl Trait` is used in argument position. - -A simple example is: - -```rust -#![feature(explicit_generic_args_with_impl_trait)] - -fn foo(_f: impl AsRef) {} - -fn main() { - foo::("".to_string()); -} -``` - -This is currently rejected: - -```text -error[E0632]: cannot provide explicit generic arguments when `impl Trait` is used in argument position - --> src/main.rs:6:11 - | -6 | foo::("".to_string()); - | ^^^ explicit generic argument not allowed - -``` - -However it would compile if `explicit_generic_args_with_impl_trait` is enabled. - -Note that the synthetic type parameters from `impl Trait` are still implicit and you -cannot explicitly specify these: - -```rust,compile_fail -#![feature(explicit_generic_args_with_impl_trait)] - -fn foo(_f: impl AsRef) {} -fn bar>(_f: F) {} - -fn main() { - bar::("".to_string()); // Okay - bar::("".to_string()); // Okay - - foo::("".to_string()); // Okay - foo::("".to_string()); // Error, you cannot specify `impl Trait` explicitly -} -``` +This feature adds the possibility of using `sysv64`, `win64` or `efiapi` calling +conventions on functions with varargs. "##, }, Lint { @@ -2243,7 +2338,7 @@ See Also: [`unboxed_closures`](../language-features/unboxed-closures.md) The `fn_traits` feature allows for implementation of the [`Fn*`] traits for creating custom closure-like types. -[`Fn*`]: https://doc.rust-lang.org/std/ops/trait.Fn.html +[`Fn*`]: ../../std/ops/trait.Fn.html ```rust #![feature(unboxed_closures)] @@ -2518,80 +2613,35 @@ does. "##, }, Lint { - label: "half_open_range_patterns", - description: r##"# `half_open_range_patterns` + label: "half_open_range_patterns_in_slices", + description: r##"# `half_open_range_patterns_in_slices` The tracking issue for this feature is: [#67264] -It is part of the `#![exclusive_range_pattern]` feature, +It is part of the `exclusive_range_pattern` feature, tracked at [#37854]. [#67264]: https://github.com/rust-lang/rust/issues/67264 [#37854]: https://github.com/rust-lang/rust/issues/37854 ----- -The `half_open_range_patterns` feature allows RangeTo patterns -(`..10`) to be used in appropriate pattern matching contexts. -This requires also enabling the `exclusive_range_pattern` feature. - -It also enabled RangeFrom patterns but that has since been -stabilized. +This feature allow using top-level half-open range patterns in slices. ```rust -#![feature(half_open_range_patterns)] +#![feature(half_open_range_patterns_in_slices)] #![feature(exclusive_range_pattern)] - let x = 5; - match x { - ..0 => println!("negative!"), // "RangeTo" pattern. Unstable. - 0 => println!("zero!"), - 1.. => println!("positive!"), // "RangeFrom" pattern. Stable. - } -``` -"##, - }, - Lint { - label: "infer_static_outlives_requirements", - description: r##"# `infer_static_outlives_requirements` -The tracking issue for this feature is: [#54185] - -[#54185]: https://github.com/rust-lang/rust/issues/54185 - ------------------------- -The `infer_static_outlives_requirements` feature indicates that certain -`'static` outlives requirements can be inferred by the compiler rather than -stating them explicitly. - -Note: It is an accompanying feature to `infer_outlives_requirements`, -which must be enabled to infer outlives requirements. - -For example, currently generic struct definitions that contain -references, require where-clauses of the form T: 'static. By using -this feature the outlives predicates will be inferred, although -they may still be written explicitly. - -```rust,ignore (pseudo-Rust) -struct Foo where U: 'static { // <-- currently required - bar: Bar -} -struct Bar { - x: T, +fn main() { + let xs = [13, 1, 5, 2, 3, 1, 21, 8]; + let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs else { return; }; } ``` +Note that this feature is not required if the patterns are wrapped between parenthesis. -## Examples: - -```rust,ignore (pseudo-Rust) -#![feature(infer_outlives_requirements)] -#![feature(infer_static_outlives_requirements)] - -#[rustc_outlives] -// Implicitly infer U: 'static -struct Foo { - bar: Bar -} -struct Bar { - x: T, +```rust +fn main() { + let xs = [13, 1]; + let [(a @ 3..), c] = xs else { return; }; } ``` "##, @@ -2658,15 +2708,6 @@ match some_int { ``` [#76001]: https://github.com/rust-lang/rust/issues/76001 -"##, - }, - Lint { - label: "int_error_internals", - description: r##"# `int_error_internals` - -This feature is internal to the Rust compiler and is not intended for general use. - ------------------------- "##, }, Lint { @@ -2718,12 +2759,13 @@ via a declaration like ```rust #![feature(intrinsics)] +#![allow(internal_features)] # fn main() {} extern "rust-intrinsic" { fn transmute(x: T) -> U; - fn offset(dst: *const T, offset: isize) -> *const T; + fn arith_offset(dst: *const T, offset: isize) -> *const T; } ``` @@ -2758,290 +2800,110 @@ functionality that isn't hard-coded into the language, but is implemented in libraries, with a special marker to tell the compiler it exists. The marker is the attribute `#[lang = "..."]` and there are various different values of `...`, i.e. various different 'lang -items'. +items'. Most of them can only be defined once. -For example, `Box` pointers require two lang items, one for allocation -and one for deallocation. A freestanding program that uses the `Box` -sugar for dynamic allocations via `malloc` and `free`: +Lang items are loaded lazily by the compiler; e.g. if one never uses `Box` +then there is no need to define a function for `exchange_malloc`. +`rustc` will emit an error when an item is needed but not found in the current +crate or any that it depends on. + +Some features provided by lang items: + +- overloadable operators via traits: the traits corresponding to the + `==`, `<`, dereferencing (`*`) and `+` (etc.) operators are all + marked with lang items; those specific four are `eq`, `partial_ord`, + `deref`/`deref_mut`, and `add` respectively. +- panicking: the `panic` and `panic_impl` lang items, among others. +- stack unwinding: the lang item `eh_personality` is a function used by the + failure mechanisms of the compiler. This is often mapped to GCC's personality + function (see the [`std` implementation][personality] for more information), + but programs which don't trigger a panic can be assured that this function is + never called. Additionally, a `eh_catch_typeinfo` static is needed for certain + targets which implement Rust panics on top of C++ exceptions. +- the traits in `core::marker` used to indicate types of + various kinds; e.g. lang items `sized`, `sync` and `copy`. +- memory allocation, see below. + +Most lang items are defined by `core`, but if you're trying to build +an executable without the `std` crate, you might run into the need +for lang item definitions. + +[personality]: https://github.com/rust-lang/rust/blob/master/library/std/src/sys/personality/gcc.rs + +## Example: Implementing a `Box` + +`Box` pointers require two lang items: one for the type itself and one for +allocation. A freestanding program that uses the `Box` sugar for dynamic +allocations via `malloc` and `free`: ```rust,ignore (libc-is-finicky) -#![feature(lang_items, box_syntax, start, libc, core_intrinsics, rustc_private)] +#![feature(lang_items, start, core_intrinsics, rustc_private, panic_unwind, rustc_attrs)] +#![allow(internal_features)] #![no_std] -use core::intrinsics; -use core::panic::PanicInfo; extern crate libc; +extern crate unwind; + +use core::ffi::c_void; +use core::intrinsics; +use core::panic::PanicInfo; +use core::ptr::NonNull; + +pub struct Global; // the global allocator +struct Unique(NonNull); #[lang = "owned_box"] -pub struct Box(*mut T); +pub struct Box(Unique, A); + +impl Box { + pub fn new(x: T) -> Self { + #[rustc_box] + Box::new(x) + } +} + +impl Drop for Box { + fn drop(&mut self) { + unsafe { + libc::free(self.0.0.as_ptr() as *mut c_void); + } + } +} #[lang = "exchange_malloc"] unsafe fn allocate(size: usize, _align: usize) -> *mut u8 { - let p = libc::malloc(size as libc::size_t) as *mut u8; + let p = libc::malloc(size) as *mut u8; // Check if `malloc` failed: - if p as usize == 0 { + if p.is_null() { intrinsics::abort(); } p } -#[lang = "box_free"] -unsafe fn box_free(ptr: *mut T) { - libc::free(ptr as *mut libc::c_void) -} - #[start] fn main(_argc: isize, _argv: *const *const u8) -> isize { - let _x = box 1; + let _x = Box::new(1); 0 } -#[lang = "eh_personality"] extern fn rust_eh_personality() {} -#[lang = "panic_impl"] extern fn rust_begin_panic(info: &PanicInfo) -> ! { unsafe { intrinsics::abort() } } -#[no_mangle] pub extern fn rust_eh_register_frames () {} -#[no_mangle] pub extern fn rust_eh_unregister_frames () {} +#[lang = "eh_personality"] +fn rust_eh_personality() {} + +#[panic_handler] +fn panic_handler(_info: &PanicInfo) -> ! { intrinsics::abort() } ``` Note the use of `abort`: the `exchange_malloc` lang item is assumed to return a valid pointer, and so needs to do the check internally. -Other features provided by lang items include: - -- overloadable operators via traits: the traits corresponding to the - `==`, `<`, dereferencing (`*`) and `+` (etc.) operators are all - marked with lang items; those specific four are `eq`, `ord`, - `deref`, and `add` respectively. -- stack unwinding and general failure; the `eh_personality`, - `panic` and `panic_bounds_check` lang items. -- the traits in `std::marker` used to indicate types of - various kinds; lang items `send`, `sync` and `copy`. -- the marker types and variance indicators found in - `std::marker`; lang items `covariant_type`, - `contravariant_lifetime`, etc. - -Lang items are loaded lazily by the compiler; e.g. if one never uses -`Box` then there is no need to define functions for `exchange_malloc` -and `box_free`. `rustc` will emit an error when an item is needed -but not found in the current crate or any that it depends on. - -Most lang items are defined by `libcore`, but if you're trying to build -an executable without the standard library, you'll run into the need -for lang items. The rest of this page focuses on this use-case, even though -lang items are a bit broader than that. - -### Using libc - -In order to build a `#[no_std]` executable we will need libc as a dependency. -We can specify this using our `Cargo.toml` file: - -```toml -[dependencies] -libc = { version = "0.2.14", default-features = false } -``` - -Note that the default features have been disabled. This is a critical step - -**the default features of libc include the standard library and so must be -disabled.** - -### Writing an executable without stdlib - -Controlling the entry point is possible in two ways: the `#[start]` attribute, -or overriding the default shim for the C `main` function with your own. - -The function marked `#[start]` is passed the command line parameters -in the same format as C: - -```rust,ignore (libc-is-finicky) -#![feature(lang_items, core_intrinsics, rustc_private)] -#![feature(start)] -#![no_std] -use core::intrinsics; -use core::panic::PanicInfo; - -// Pull in the system libc library for what crt0.o likely requires. -extern crate libc; - -// Entry point for this program. -#[start] -fn start(_argc: isize, _argv: *const *const u8) -> isize { - 0 -} - -// These functions are used by the compiler, but not -// for a bare-bones hello world. These are normally -// provided by libstd. -#[lang = "eh_personality"] -#[no_mangle] -pub extern fn rust_eh_personality() { -} - -#[lang = "panic_impl"] -#[no_mangle] -pub extern fn rust_begin_panic(info: &PanicInfo) -> ! { - unsafe { intrinsics::abort() } -} -``` - -To override the compiler-inserted `main` shim, one has to disable it -with `#![no_main]` and then create the appropriate symbol with the -correct ABI and the correct name, which requires overriding the -compiler's name mangling too: - -```rust,ignore (libc-is-finicky) -#![feature(lang_items, core_intrinsics, rustc_private)] -#![feature(start)] -#![no_std] -#![no_main] -use core::intrinsics; -use core::panic::PanicInfo; - -// Pull in the system libc library for what crt0.o likely requires. -extern crate libc; - -// Entry point for this program. -#[no_mangle] // ensure that this symbol is called `main` in the output -pub extern fn main(_argc: i32, _argv: *const *const u8) -> i32 { - 0 -} - -// These functions are used by the compiler, but not -// for a bare-bones hello world. These are normally -// provided by libstd. -#[lang = "eh_personality"] -#[no_mangle] -pub extern fn rust_eh_personality() { -} - -#[lang = "panic_impl"] -#[no_mangle] -pub extern fn rust_begin_panic(info: &PanicInfo) -> ! { - unsafe { intrinsics::abort() } -} -``` - -In many cases, you may need to manually link to the `compiler_builtins` crate -when building a `no_std` binary. You may observe this via linker error messages -such as "```undefined reference to `__rust_probestack'```". - -## More about the language items - -The compiler currently makes a few assumptions about symbols which are -available in the executable to call. Normally these functions are provided by -the standard library, but without it you must define your own. These symbols -are called "language items", and they each have an internal name, and then a -signature that an implementation must conform to. - -The first of these functions, `rust_eh_personality`, is used by the failure -mechanisms of the compiler. This is often mapped to GCC's personality function -(see the [libstd implementation][unwind] for more information), but crates -which do not trigger a panic can be assured that this function is never -called. The language item's name is `eh_personality`. - -[unwind]: https://github.com/rust-lang/rust/blob/master/library/panic_unwind/src/gcc.rs - -The second function, `rust_begin_panic`, is also used by the failure mechanisms of the -compiler. When a panic happens, this controls the message that's displayed on -the screen. While the language item's name is `panic_impl`, the symbol name is -`rust_begin_panic`. - -Finally, a `eh_catch_typeinfo` static is needed for certain targets which -implement Rust panics on top of C++ exceptions. - ## List of all language items -This is a list of all language items in Rust along with where they are located in -the source code. +An up-to-date list of all language items can be found [here] in the compiler code. -- Primitives - - `i8`: `libcore/num/mod.rs` - - `i16`: `libcore/num/mod.rs` - - `i32`: `libcore/num/mod.rs` - - `i64`: `libcore/num/mod.rs` - - `i128`: `libcore/num/mod.rs` - - `isize`: `libcore/num/mod.rs` - - `u8`: `libcore/num/mod.rs` - - `u16`: `libcore/num/mod.rs` - - `u32`: `libcore/num/mod.rs` - - `u64`: `libcore/num/mod.rs` - - `u128`: `libcore/num/mod.rs` - - `usize`: `libcore/num/mod.rs` - - `f32`: `libstd/f32.rs` - - `f64`: `libstd/f64.rs` - - `char`: `libcore/char.rs` - - `slice`: `liballoc/slice.rs` - - `str`: `liballoc/str.rs` - - `const_ptr`: `libcore/ptr.rs` - - `mut_ptr`: `libcore/ptr.rs` - - `unsafe_cell`: `libcore/cell.rs` -- Runtime - - `start`: `libstd/rt.rs` - - `eh_personality`: `libpanic_unwind/emcc.rs` (EMCC) - - `eh_personality`: `libpanic_unwind/gcc.rs` (GNU) - - `eh_personality`: `libpanic_unwind/seh.rs` (SEH) - - `eh_catch_typeinfo`: `libpanic_unwind/emcc.rs` (EMCC) - - `panic`: `libcore/panicking.rs` - - `panic_bounds_check`: `libcore/panicking.rs` - - `panic_impl`: `libcore/panicking.rs` - - `panic_impl`: `libstd/panicking.rs` -- Allocations - - `owned_box`: `liballoc/boxed.rs` - - `exchange_malloc`: `liballoc/heap.rs` - - `box_free`: `liballoc/heap.rs` -- Operands - - `not`: `libcore/ops/bit.rs` - - `bitand`: `libcore/ops/bit.rs` - - `bitor`: `libcore/ops/bit.rs` - - `bitxor`: `libcore/ops/bit.rs` - - `shl`: `libcore/ops/bit.rs` - - `shr`: `libcore/ops/bit.rs` - - `bitand_assign`: `libcore/ops/bit.rs` - - `bitor_assign`: `libcore/ops/bit.rs` - - `bitxor_assign`: `libcore/ops/bit.rs` - - `shl_assign`: `libcore/ops/bit.rs` - - `shr_assign`: `libcore/ops/bit.rs` - - `deref`: `libcore/ops/deref.rs` - - `deref_mut`: `libcore/ops/deref.rs` - - `index`: `libcore/ops/index.rs` - - `index_mut`: `libcore/ops/index.rs` - - `add`: `libcore/ops/arith.rs` - - `sub`: `libcore/ops/arith.rs` - - `mul`: `libcore/ops/arith.rs` - - `div`: `libcore/ops/arith.rs` - - `rem`: `libcore/ops/arith.rs` - - `neg`: `libcore/ops/arith.rs` - - `add_assign`: `libcore/ops/arith.rs` - - `sub_assign`: `libcore/ops/arith.rs` - - `mul_assign`: `libcore/ops/arith.rs` - - `div_assign`: `libcore/ops/arith.rs` - - `rem_assign`: `libcore/ops/arith.rs` - - `eq`: `libcore/cmp.rs` - - `ord`: `libcore/cmp.rs` -- Functions - - `fn`: `libcore/ops/function.rs` - - `fn_mut`: `libcore/ops/function.rs` - - `fn_once`: `libcore/ops/function.rs` - - `generator_state`: `libcore/ops/generator.rs` - - `generator`: `libcore/ops/generator.rs` -- Other - - `coerce_unsized`: `libcore/ops/unsize.rs` - - `drop`: `libcore/ops/drop.rs` - - `drop_in_place`: `libcore/ptr.rs` - - `clone`: `libcore/clone.rs` - - `copy`: `libcore/marker.rs` - - `send`: `libcore/marker.rs` - - `sized`: `libcore/marker.rs` - - `unsize`: `libcore/marker.rs` - - `sync`: `libcore/marker.rs` - - `phantom_data`: `libcore/marker.rs` - - `discriminant_kind`: `libcore/marker.rs` - - `freeze`: `libcore/marker.rs` - - `debug_trait`: `libcore/fmt/mod.rs` - - `non_zero`: `libcore/nonzero.rs` - - `arc`: `liballoc/sync.rs` - - `rc`: `liballoc/rc.rs` +[here]: https://github.com/rust-lang/rust/blob/master/compiler/rustc_hir/src/lang_items.rs "##, }, Lint { @@ -3050,15 +2912,6 @@ the source code. This feature is internal to the Rust compiler and is not intended for general use. ------------------------- -"##, - }, - Lint { - label: "libstd_thread_internals", - description: r##"# `libstd_thread_internals` - -This feature is internal to the Rust compiler and is not intended for general use. - ------------------------ "##, }, @@ -3069,200 +2922,6 @@ This feature is internal to the Rust compiler and is not intended for general us This feature is internal to the Rust compiler and is not intended for general use. ------------------------ -"##, - }, - Lint { - label: "llvm_asm", - description: r##"# `llvm_asm` - -The tracking issue for this feature is: [#70173] - -[#70173]: https://github.com/rust-lang/rust/issues/70173 - ------------------------- - -For extremely low-level manipulations and performance reasons, one -might wish to control the CPU directly. Rust supports using inline -assembly to do this via the `llvm_asm!` macro. - -```rust,ignore (pseudo-code) -llvm_asm!(assembly template - : output operands - : input operands - : clobbers - : options - ); -``` - -Any use of `llvm_asm` is feature gated (requires `#![feature(llvm_asm)]` on the -crate to allow) and of course requires an `unsafe` block. - -> **Note**: the examples here are given in x86/x86-64 assembly, but -> all platforms are supported. - -## Assembly template - -The `assembly template` is the only required parameter and must be a -literal string (i.e. `""`) - -```rust -#![feature(llvm_asm)] - -#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -fn foo() { - unsafe { - llvm_asm!("NOP"); - } -} - -// Other platforms: -#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] -fn foo() { /* ... */ } - -fn main() { - // ... - foo(); - // ... -} -``` - -(The `feature(llvm_asm)` and `#[cfg]`s are omitted from now on.) - -Output operands, input operands, clobbers and options are all optional -but you must add the right number of `:` if you skip them: - -```rust -# #![feature(llvm_asm)] -# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -# fn main() { unsafe { -llvm_asm!("xor %eax, %eax" - : - : - : "eax" - ); -# } } -# #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] -# fn main() {} -``` - -Whitespace also doesn't matter: - -```rust -# #![feature(llvm_asm)] -# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -# fn main() { unsafe { -llvm_asm!("xor %eax, %eax" ::: "eax"); -# } } -# #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] -# fn main() {} -``` - -## Operands - -Input and output operands follow the same format: `: -"constraints1"(expr1), "constraints2"(expr2), ..."`. Output operand -expressions must be mutable place, or not yet assigned: - -```rust -# #![feature(llvm_asm)] -# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -fn add(a: i32, b: i32) -> i32 { - let c: i32; - unsafe { - llvm_asm!("add $2, $0" - : "=r"(c) - : "0"(a), "r"(b) - ); - } - c -} -# #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] -# fn add(a: i32, b: i32) -> i32 { a + b } - -fn main() { - assert_eq!(add(3, 14159), 14162) -} -``` - -If you would like to use real operands in this position, however, -you are required to put curly braces `{}` around the register that -you want, and you are required to put the specific size of the -operand. This is useful for very low level programming, where -which register you use is important: - -```rust -# #![feature(llvm_asm)] -# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -# unsafe fn read_byte_in(port: u16) -> u8 { -let result: u8; -llvm_asm!("in %dx, %al" : "={al}"(result) : "{dx}"(port)); -result -# } -``` - -## Clobbers - -Some instructions modify registers which might otherwise have held -different values so we use the clobbers list to indicate to the -compiler not to assume any values loaded into those registers will -stay valid. - -```rust -# #![feature(llvm_asm)] -# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -# fn main() { unsafe { -// Put the value 0x200 in eax: -llvm_asm!("mov $$0x200, %eax" : /* no outputs */ : /* no inputs */ : "eax"); -# } } -# #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] -# fn main() {} -``` - -Input and output registers need not be listed since that information -is already communicated by the given constraints. Otherwise, any other -registers used either implicitly or explicitly should be listed. - -If the assembly changes the condition code register `cc` should be -specified as one of the clobbers. Similarly, if the assembly modifies -memory, `memory` should also be specified. - -## Options - -The last section, `options` is specific to Rust. The format is comma -separated literal strings (i.e. `:"foo", "bar", "baz"`). It's used to -specify some extra info about the inline assembly: - -Current valid options are: - -1. `volatile` - specifying this is analogous to - `__asm__ __volatile__ (...)` in gcc/clang. -2. `alignstack` - certain instructions expect the stack to be - aligned a certain way (i.e. SSE) and specifying this indicates to - the compiler to insert its usual stack alignment code -3. `intel` - use intel syntax instead of the default AT&T. - -```rust -# #![feature(llvm_asm)] -# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -# fn main() { -let result: i32; -unsafe { - llvm_asm!("mov eax, 2" : "={eax}"(result) : : : "intel") -} -println!("eax is currently {}", result); -# } -# #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] -# fn main() {} -``` - -## More Information - -The current implementation of the `llvm_asm!` macro is a direct binding to [LLVM's -inline assembler expressions][llvm-docs], so be sure to check out [their -documentation as well][llvm-docs] for more information about clobbers, -constraints, etc. - -[llvm-docs]: http://llvm.org/docs/LangRef.html#inline-assembler-expressions "##, }, Lint { @@ -3335,21 +2994,6 @@ impl A for Foo { type Assoc = StructStruct; } ``` -"##, - }, - Lint { - label: "native_link_modifiers", - description: r##"# `native_link_modifiers` - -The tracking issue for this feature is: [#81490] - -[#81490]: https://github.com/rust-lang/rust/issues/81490 - ------------------------- - -The `native_link_modifiers` feature allows you to use the `modifiers` syntax with the `#[link(..)]` attribute. - -Modifiers are specified as a comma-delimited string with each modifier prefixed with either a `+` or `-` to indicate that the modifier is enabled or disabled, respectively. The last boolean value specified for a given modifier wins. "##, }, Lint { @@ -3372,75 +3016,6 @@ This modifier translates to `--as-needed` for ld-like linkers, and to `-dead_str The modifier does nothing for linkers that don't support it (e.g. `link.exe`). The default for this modifier is unclear, some targets currently specify it as `+as-needed`, some do not. We may want to try making `+as-needed` a default for all targets. -"##, - }, - Lint { - label: "native_link_modifiers_bundle", - description: r##"# `native_link_modifiers_bundle` - -The tracking issue for this feature is: [#81490] - -[#81490]: https://github.com/rust-lang/rust/issues/81490 - ------------------------- - -The `native_link_modifiers_bundle` feature allows you to use the `bundle` modifier. - -Only compatible with the `static` linking kind. Using any other kind will result in a compiler error. - -`+bundle` means objects from the static library are bundled into the produced crate (a rlib, for example) and are used from this crate later during linking of the final binary. - -`-bundle` means the static library is included into the produced rlib "by name" and object files from it are included only during linking of the final binary, the file search by that name is also performed during final linking. - -This modifier is supposed to supersede the `static-nobundle` linking kind defined by [RFC 1717](https://github.com/rust-lang/rfcs/pull/1717). - -The default for this modifier is currently `+bundle`, but it could be changed later on some future edition boundary. -"##, - }, - Lint { - label: "native_link_modifiers_verbatim", - description: r##"# `native_link_modifiers_verbatim` - -The tracking issue for this feature is: [#81490] - -[#81490]: https://github.com/rust-lang/rust/issues/81490 - ------------------------- - -The `native_link_modifiers_verbatim` feature allows you to use the `verbatim` modifier. - -`+verbatim` means that rustc itself won't add any target-specified library prefixes or suffixes (like `lib` or `.a`) to the library name, and will try its best to ask for the same thing from the linker. - -For `ld`-like linkers rustc will use the `-l:filename` syntax (note the colon) when passing the library, so the linker won't add any prefixes or suffixes as well. -See [`-l namespec`](https://sourceware.org/binutils/docs/ld/Options.html) in ld documentation for more details. -For linkers not supporting any verbatim modifiers (e.g. `link.exe` or `ld64`) the library name will be passed as is. - -The default for this modifier is `-verbatim`. - -This RFC changes the behavior of `raw-dylib` linking kind specified by [RFC 2627](https://github.com/rust-lang/rfcs/pull/2627). The `.dll` suffix (or other target-specified suffixes for other targets) is now added automatically. -If your DLL doesn't have the `.dll` suffix, it can be specified with `+verbatim`. -"##, - }, - Lint { - label: "native_link_modifiers_whole_archive", - description: r##"# `native_link_modifiers_whole_archive` - -The tracking issue for this feature is: [#81490] - -[#81490]: https://github.com/rust-lang/rust/issues/81490 - ------------------------- - -The `native_link_modifiers_whole_archive` feature allows you to use the `whole-archive` modifier. - -Only compatible with the `static` linking kind. Using any other kind will result in a compiler error. - -`+whole-archive` means that the static library is linked as a whole archive without throwing any object files away. - -This modifier translates to `--whole-archive` for `ld`-like linkers, to `/WHOLEARCHIVE` for `link.exe`, and to `-force_load` for `ld64`. -The modifier does nothing for linkers that don't support it. - -The default for this modifier is `-whole-archive`. "##, }, Lint { @@ -3502,40 +3077,6 @@ This serves two purposes: * For proving the correctness of unsafe code, we can use that impl as evidence that no `DerefMut` or `Clone` impl exists. * It prevents downstream crates from creating such impls. -"##, - }, - Lint { - label: "coverage", - description: r##"# `coverage` - -The tracking issue for this feature is: [#84605] - -[#84605]: https://github.com/rust-lang/rust/issues/84605 - ---- - -The `coverage` attribute can be used to selectively disable coverage -instrumentation in an annotated function. This might be useful to: - -- Avoid instrumentation overhead in a performance critical function -- Avoid generating coverage for a function that is not meant to be executed, - but still target 100% coverage for the rest of the program. - -## Example - -```rust -#![feature(coverage)] - -// `foo()` will get coverage instrumentation (by default) -fn foo() { - // ... -} - -#[coverage(off)] -fn bar() { - // ... -} -``` "##, }, Lint { @@ -3612,7 +3153,7 @@ additional checks for code style, safety, etc. Now let's write a plugin that warns about any item named `lintme`. ```rust,ignore (requires-stage-2) -#![feature(box_syntax, rustc_private)] +#![feature(rustc_private)] extern crate rustc_ast; @@ -3643,7 +3184,7 @@ impl EarlyLintPass for Pass { #[no_mangle] fn __rustc_plugin_registrar(reg: &mut Registry) { reg.lint_store.register_lints(&[&TEST_LINT]); - reg.lint_store.register_early_pass(|| box Pass); + reg.lint_store.register_early_pass(|| Box::new(Pass)); } ``` @@ -3677,7 +3218,7 @@ The components of a lint plugin are: Lint passes are syntax traversals, but they run at a late stage of compilation where type information is available. `rustc`'s [built-in -lints](https://github.com/rust-lang/rust/blob/master/src/librustc_session/lint/builtin.rs) +lints](https://github.com/rust-lang/rust/blob/master/compiler/rustc_lint_defs/src/builtin.rs) mostly use the same infrastructure as lint plugins, and provide examples of how to access type information. @@ -3716,44 +3257,6 @@ The tracking issue for this feature is: [#42524](https://github.com/rust-lang/ru This feature is internal to the Rust compiler and is not intended for general use. ------------------------ -"##, - }, - Lint { - label: "raw_dylib", - description: r##"# `raw_dylib` - -The tracking issue for this feature is: [#58713] - -[#58713]: https://github.com/rust-lang/rust/issues/58713 - ------------------------- - -The `raw_dylib` feature allows you to link against the implementations of functions in an `extern` -block without, on Windows, linking against an import library. - -```rust,ignore (partial-example) -#![feature(raw_dylib)] - -#[link(name="library", kind="raw-dylib")] -extern { - fn extern_function(x: i32); -} - -fn main() { - unsafe { - extern_function(14); - } -} -``` - -## Limitations - -Currently, this feature is only supported on `-windows-msvc` targets. Non-Windows platforms don't have import -libraries, and an incompatibility between LLVM and the BFD linker means that it is not currently supported on -`-windows-gnu` targets. - -On the `i686-pc-windows-msvc` target, this feature supports only the `cdecl`, `stdcall`, `system`, and `fastcall` -calling conventions. "##, }, Lint { @@ -3851,6 +3354,69 @@ error: aborting due to 2 previous errors This feature is internal to the Rust compiler and is not intended for general use. ------------------------ +"##, + }, + Lint { + label: "start", + description: r##"# `start` + +The tracking issue for this feature is: [#29633] + +[#29633]: https://github.com/rust-lang/rust/issues/29633 + +------------------------ + +Allows you to mark a function as the entry point of the executable, which is +necessary in `#![no_std]` environments. + +The function marked `#[start]` is passed the command line parameters in the same +format as the C main function (aside from the integer types being used). +It has to be non-generic and have the following signature: + +```rust,ignore (only-for-syntax-highlight) +# let _: +fn(isize, *const *const u8) -> isize +# ; +``` + +This feature should not be confused with the `start` *lang item* which is +defined by the `std` crate and is written `#[lang = "start"]`. + +## Usage together with the `std` crate + +`#[start]` can be used in combination with the `std` crate, in which case the +normal `main` function (which would get called from the `std` crate) won't be +used as an entry point. +The initialization code in `std` will be skipped this way. + +Example: + +```rust +#![feature(start)] + +#[start] +fn start(_argc: isize, _argv: *const *const u8) -> isize { + 0 +} +``` + +Unwinding the stack past the `#[start]` function is currently considered +Undefined Behavior (for any unwinding implementation): + +```rust,ignore (UB) +#![feature(start)] + +#[start] +fn start(_argc: isize, _argv: *const *const u8) -> isize { + std::panic::catch_unwind(|| { + panic!(); // panic safely gets caught or safely aborts execution + }); + + panic!(); // UB! + + 0 +} +``` "##, }, Lint { @@ -3860,6 +3426,32 @@ This feature is internal to the Rust compiler and is not intended for general us This feature is internal to the Rust compiler and is not intended for general use. ------------------------ +"##, + }, + Lint { + label: "strict_provenance", + description: r##"# `strict_provenance` + +The tracking issue for this feature is: [#95228] + +[#95228]: https://github.com/rust-lang/rust/issues/95228 +----- + +The `strict_provenance` feature allows to enable the `fuzzy_provenance_casts` and `lossy_provenance_casts` lints. +These lint on casts between integers and pointers, that are recommended against or invalid in the strict provenance model. +The same feature gate is also used for the experimental strict provenance API in `std` (actually `core`). + +## Example + +```rust +#![feature(strict_provenance)] +#![warn(fuzzy_provenance_casts)] + +fn main() { + let _dangling = 16_usize as *const u8; + //~^ WARNING: strict provenance disallows casting integer `usize` to pointer `*const u8` +} +``` "##, }, Lint { @@ -4319,7 +3911,7 @@ The `unboxed_closures` feature allows you to write functions using the `"rust-ca required for implementing the [`Fn*`] family of traits. `"rust-call"` functions must have exactly one (non self) argument, a tuple representing the argument list. -[`Fn*`]: https://doc.rust-lang.org/std/ops/trait.Fn.html +[`Fn*`]: ../../std/ops/trait.Fn.html ```rust #![feature(unboxed_closures)] @@ -4330,6 +3922,72 @@ extern "rust-call" fn add_args(args: (u32, u32)) -> u32 { fn main() {} ``` +"##, + }, + Lint { + label: "unix_sigpipe", + description: r##"# `unix_sigpipe` + +The tracking issue for this feature is: [#97889] + +[#97889]: https://github.com/rust-lang/rust/issues/97889 + +--- + +The `#[unix_sigpipe = "..."]` attribute on `fn main()` can be used to specify how libstd shall setup `SIGPIPE` on Unix platforms before invoking `fn main()`. This attribute is ignored on non-Unix targets. There are three variants: +* `#[unix_sigpipe = "inherit"]` +* `#[unix_sigpipe = "sig_dfl"]` +* `#[unix_sigpipe = "sig_ign"]` + +## `#[unix_sigpipe = "inherit"]` + +Leave `SIGPIPE` untouched before entering `fn main()`. Unless the parent process has changed the default `SIGPIPE` handler from `SIG_DFL` to something else, this will behave the same as `#[unix_sigpipe = "sig_dfl"]`. + +## `#[unix_sigpipe = "sig_dfl"]` + +Set the `SIGPIPE` handler to `SIG_DFL`. This will result in your program getting killed if it tries to write to a closed pipe. This is normally what you want if your program produces textual output. + +### Example + +```rust,no_run +#![feature(unix_sigpipe)] +#[unix_sigpipe = "sig_dfl"] +fn main() { loop { println!("hello world"); } } +``` + +```bash +% ./main | head -n 1 +hello world +``` + +## `#[unix_sigpipe = "sig_ign"]` + +Set the `SIGPIPE` handler to `SIG_IGN` before invoking `fn main()`. This will result in `ErrorKind::BrokenPipe` errors if you program tries to write to a closed pipe. This is normally what you want if you for example write socket servers, socket clients, or pipe peers. + +This is what libstd has done by default since 2014. (However, see the note on child processes below.) + +### Example + +```rust,no_run +#![feature(unix_sigpipe)] +#[unix_sigpipe = "sig_ign"] +fn main() { loop { println!("hello world"); } } +``` + +```bash +% ./main | head -n 1 +hello world +thread 'main' panicked at 'failed printing to stdout: Broken pipe (os error 32)', library/std/src/io/stdio.rs:1016:9 +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace +``` + +### Note on child processes + +When spawning child processes, the legacy Rust behavior if `#[unix_sigpipe]` is not specified is to +reset `SIGPIPE` to `SIG_DFL`. + +If `#[unix_sigpipe = "..."]` is specified, no matter what its value is, the signal disposition of +`SIGPIPE` is no longer reset. This means that the child inherits the parent's `SIGPIPE` behavior. "##, }, Lint { @@ -4585,17 +4243,78 @@ This feature is internal to the Rust compiler and is not intended for general us This feature is internal to the Rust compiler and is not intended for general use. ------------------------ +"##, + }, + Lint { + label: "yeet_expr", + description: r##"# `yeet_expr` + +The tracking issue for this feature is: [#96373] + +[#96373]: https://github.com/rust-lang/rust/issues/96373 + +------------------------ + +The `yeet_expr` feature adds support for `do yeet` expressions, +which can be used to early-exit from a function or `try` block. + +These are highly experimental, thus the placeholder syntax. + +```rust,edition2021 +#![feature(yeet_expr)] + +fn foo() -> Result { + do yeet 4; +} +assert_eq!(foo(), Err(4)); + +fn bar() -> Option { + do yeet; +} +assert_eq!(bar(), None); +``` "##, }, ]; pub const CLIPPY_LINTS: &[Lint] = &[ + Lint { + label: "clippy::absolute_paths", + description: r##"Checks for usage of items through absolute paths, like `std::env::current_dir`."##, + }, Lint { label: "clippy::absurd_extreme_comparisons", description: r##"Checks for comparisons where one side of the relation is either the minimum or maximum value for its type and warns if it involves a case that is always true or always false. Only integer and boolean types are checked."##, + }, + Lint { + label: "clippy::alloc_instead_of_core", + description: r##"Finds items imported through `alloc` when available through `core`."##, + }, + Lint { + label: "clippy::allow_attributes", + description: r##"Checks for usage of the `#[allow]` attribute and suggests replacing it with +the `#[expect]` (See [RFC 2383](https://rust-lang.github.io/rfcs/2383-lint-reasons.html)) + +The expect attribute is still unstable and requires the `lint_reasons` +on nightly. It can be enabled by adding `#![feature(lint_reasons)]` to +the crate root. + +This lint only warns outer attributes (`#[allow]`), as inner attributes +(`#![allow]`) are usually used to enable or disable lints on a global scale."##, + }, + Lint { + label: "clippy::allow_attributes_without_reason", + description: r##"Checks for attributes that allow lints without a reason. + +(This requires the `lint_reasons` feature)"##, + }, + Lint { + label: "clippy::almost_complete_range", + description: r##"Checks for ranges which almost include the entire range of letters from 'a' to 'z' +or digits from '0' to '9', but don't because they're a half open range."##, }, Lint { label: "clippy::almost_swapped", @@ -4609,6 +4328,22 @@ constants which are defined in or [`std::f64::consts`](https://doc.rust-lang.org/stable/std/f64/consts/#constants), respectively, suggesting to use the predefined constant."##, + }, + Lint { + label: "clippy::arc_with_non_send_sync", + description: r##". +This lint warns when you use `Arc` with a type that does not implement `Send` or `Sync`."##, + }, + Lint { + label: "clippy::arithmetic_side_effects", + description: r##"Checks any kind of arithmetic operation of any type. + +Operators like `+`, `-`, `*` or `<<` are usually capable of overflowing according to the [Rust +Reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html#overflow), +or can panic (`/`, `%`). + +Known safe built-in types like `Wrapping` or `Saturating`, floats, operations in constant +environments, allowed types and non-constant operations that won't overflow are ignored."##, }, Lint { label: "clippy::as_conversions", @@ -4617,15 +4352,27 @@ respectively, suggesting to use the predefined constant."##, Note that this lint is specialized in linting *every single* use of `as` regardless of whether good alternatives exist or not. If you want more precise lints for `as`, please consider using these separate lints: -`unnecessary_cast`, `cast_lossless/possible_truncation/possible_wrap/precision_loss/sign_loss`, +`unnecessary_cast`, `cast_lossless/cast_possible_truncation/cast_possible_wrap/cast_precision_loss/cast_sign_loss`, `fn_to_numeric_cast(_with_truncation)`, `char_lit_as_u8`, `ref_to_mut` and `ptr_as_ptr`. There is a good explanation the reason why this lint should work in this way and how it is useful [in this issue](https://github.com/rust-lang/rust-clippy/issues/5122)."##, }, + Lint { + label: "clippy::as_ptr_cast_mut", + description: r##"Checks for the result of a `&self`-taking `as_ptr` being cast to a mutable pointer"##, + }, + Lint { + label: "clippy::as_underscore", + description: r##"Checks for the usage of `as _` conversion using inferred type."##, + }, Lint { label: "clippy::assertions_on_constants", description: r##"Checks for `assert!(true)` and `assert!(false)` calls."##, }, + Lint { + label: "clippy::assertions_on_result_states", + description: r##"Checks for `assert!(r.is_ok())` or `assert!(r.is_err())` calls."##, + }, Lint { label: "clippy::assign_op_pattern", description: r##"Checks for `a = a op b` or `a = b commutative_op a` @@ -4639,16 +4386,19 @@ patterns."##, label: "clippy::async_yields_async", description: r##"Checks for async blocks that yield values of types that can themselves be awaited."##, + }, + Lint { + label: "clippy::await_holding_invalid_type", + description: r##"Allows users to configure types which should not be held across `await` +suspension points."##, }, Lint { label: "clippy::await_holding_lock", - description: r##"Checks for calls to await while holding a -non-async-aware MutexGuard."##, + description: r##"Checks for calls to await while holding a non-async-aware MutexGuard."##, }, Lint { label: "clippy::await_holding_refcell_ref", - description: r##"Checks for calls to await while holding a -`RefCell` `Ref` or `RefMut`."##, + description: r##"Checks for calls to await while holding a `RefCell` `Ref` or `RefMut`."##, }, Lint { label: "clippy::bad_bit_mask", @@ -4659,24 +4409,23 @@ The formula for detecting if an expression of the type `_ m {`!=`, `>=`, `>`, `!=`, `>=`, `>`}) can be determined from the following table: -|Comparison |Bit Op|Example |is always|Formula | -|------------|------|------------|---------|----------------------| -|`==` or `!=`| `&` |`x & 2 == 3`|`false` |`c & m != c` | -|`<` or `>=`| `&` |`x & 2 < 3` |`true` |`m < c` | -|`>` or `<=`| `&` |`x & 1 > 1` |`false` |`m <= c` | -|`==` or `!=`| `|` |`x | 1 == 0`|`false` |`c | m != c` | -|`<` or `>=`| `|` |`x | 1 < 1` |`false` |`m >= c` | -|`<=` or `>` | `|` |`x | 1 > 0` |`true` |`m > c` |"##, +|Comparison |Bit Op|Example |is always|Formula | +|------------|------|-------------|---------|----------------------| +|`==` or `!=`| `&` |`x & 2 == 3` |`false` |`c & m != c` | +|`<` or `>=`| `&` |`x & 2 < 3` |`true` |`m < c` | +|`>` or `<=`| `&` |`x & 1 > 1` |`false` |`m <= c` | +|`==` or `!=`| `\\|` |`x \\| 1 == 0`|`false` |`c \\| m != c` | +|`<` or `>=`| `\\|` |`x \\| 1 < 1` |`false` |`m >= c` | +|`<=` or `>` | `\\|` |`x \\| 1 > 0` |`true` |`m > c` |"##, + }, + Lint { + label: "clippy::big_endian_bytes", + description: r##"Checks for the usage of the `to_be_bytes` method and/or the function `from_be_bytes`."##, }, Lint { label: "clippy::bind_instead_of_map", description: r##"Checks for usage of `_.and_then(|x| Some(y))`, `_.and_then(|x| Ok(y))` or `_.or_else(|x| Err(y))`."##, - }, - Lint { - label: "clippy::blacklisted_name", - description: r##"Checks for usage of blacklisted names for variables, such -as `foo`."##, }, Lint { label: "clippy::blanket_clippy_restriction_lints", @@ -4697,6 +4446,18 @@ expression, statements or conditions that use closures with blocks."##, `x != true` and order comparisons such as `x < true` (or vice versa) and suggest using the variable directly."##, }, + Lint { + label: "clippy::bool_to_int_with_if", + description: r##"Instead of using an if statement to convert a bool to an int, +this lint suggests using a `from()` function or an `as` coercion."##, + }, + Lint { + label: "clippy::borrow_as_ptr", + description: r##"Checks for the usage of `&expr as *const T` or +`&mut expr as *mut T`, and suggest using `ptr::addr_of` or +`ptr::addr_of_mut` instead."##, + }, + Lint { label: "clippy::borrow_deref_ref", description: r##"Checks for `&*(&T)`."## }, Lint { label: "clippy::borrow_interior_mutable_const", description: r##"Checks if `const` items which is interior mutable (e.g., @@ -4704,13 +4465,18 @@ contains a `Cell`, `Mutex`, `AtomicXxxx`, etc.) has been borrowed directly."##, }, Lint { label: "clippy::borrowed_box", - description: r##"Checks for use of `&Box` anywhere in the code. + description: r##"Checks for usage of `&Box` anywhere in the code. Check the [Box documentation](https://doc.rust-lang.org/std/boxed/index.html) for more information."##, }, Lint { label: "clippy::box_collection", - description: r##"Checks for use of `Box` where T is a collection such as Vec anywhere in the code. + description: r##"Checks for usage of `Box` where T is a collection such as Vec anywhere in the code. Check the [Box documentation](https://doc.rust-lang.org/std/boxed/index.html) for more information."##, + }, + Lint { + label: "clippy::box_default", + description: r##"checks for `Box::new(T::default())`, which is better written as +`Box::::default()`."##, }, Lint { label: "clippy::boxed_local", @@ -4726,6 +4492,11 @@ moved out of the blocks."##, label: "clippy::builtin_type_shadow", description: r##"Warns if a generic shadows a built-in type."##, }, + Lint { + label: "clippy::bytes_count_to_len", + description: r##"It checks for `str::bytes().count()` and suggests replacing it with +`str::len()`."##, + }, Lint { label: "clippy::bytes_nth", description: r##"Checks for the use of `.bytes().nth()`."##, @@ -4739,24 +4510,43 @@ moved out of the blocks."##, label: "clippy::case_sensitive_file_extension_comparisons", description: r##"Checks for calls to `ends_with` with possible file extensions and suggests to use a case-insensitive approach instead."##, + }, + Lint { + label: "clippy::cast_abs_to_unsigned", + description: r##"Checks for usage of the `abs()` method that cast the result to unsigned."##, + }, + Lint { + label: "clippy::cast_enum_constructor", + description: r##"Checks for casts from an enum tuple constructor to an integer."##, + }, + Lint { + label: "clippy::cast_enum_truncation", + description: r##"Checks for casts from an enum type to an integral type which will definitely truncate the +value."##, }, Lint { label: "clippy::cast_lossless", description: r##"Checks for casts between numerical types that may be replaced by safe conversion functions."##, }, + Lint { + label: "clippy::cast_nan_to_int", + description: r##"Checks for a known NaN float being cast to an integer"##, + }, Lint { label: "clippy::cast_possible_truncation", description: r##"Checks for casts between numerical types that may truncate large values. This is expected behavior, so the cast is `Allow` by -default."##, +default. It suggests user either explicitly ignore the lint, +or use `try_from()` and handle the truncation, default, or panic explicitly."##, }, Lint { label: "clippy::cast_possible_wrap", description: r##"Checks for casts from an unsigned type to a signed type of -the same size. Performing such a cast is a 'no-op' for the compiler, -i.e., nothing is changed at the bit level, and the binary representation of -the value is reinterpreted. This can cause wrapping if the value is too big +the same size, or possibly smaller due to target dependent integers. +Performing such a cast is a 'no-op' for the compiler, i.e., nothing is +changed at the bit level, and the binary representation of the value is +reinterpreted. This can cause wrapping if the value is too big for the target signed type. However, the cast works as defined, so this lint is `Allow` by default."##, }, @@ -4775,10 +4565,6 @@ or any 64-bit integer to `f64`."##, description: r##"Checks for casts, using `as` or `pointer::cast`, from a less-strictly-aligned pointer to a more-strictly-aligned pointer"##, }, - Lint { - label: "clippy::cast_ref_to_mut", - description: r##"Checks for casts of `&T` to `&mut T` anywhere in the code."##, - }, Lint { label: "clippy::cast_sign_loss", description: r##"Checks for casts from a signed to an unsigned numerical @@ -4786,6 +4572,14 @@ type. In this case, negative values wrap around to large positive values, which can be quite surprising in practice. However, as the cast works as defined, this lint is `Allow` by default."##, }, + Lint { + label: "clippy::cast_slice_different_sizes", + description: r##"Checks for `as` casts between raw pointers to slices with differently sized elements."##, + }, + Lint { + label: "clippy::cast_slice_from_raw_parts", + description: r##"Checks for a raw slice being cast to a slice pointer"##, + }, Lint { label: "clippy::char_lit_as_u8", description: r##"Checks for expressions where a character literal is cast @@ -4806,8 +4600,8 @@ if it starts with a given char."##, description: r##"Checks for explicit bounds checking when casting."##, }, Lint { - label: "clippy::clone_double_ref", - description: r##"Checks for usage of `.clone()` on an `&&T`."##, + label: "clippy::clear_with_drain", + description: r##"Checks for usage of `.drain(..)` for the sole purpose of clearing a container."##, }, Lint { label: "clippy::clone_on_copy", @@ -4821,10 +4615,9 @@ function syntax instead (e.g., `Rc::clone(foo)`)."##, }, Lint { label: "clippy::cloned_instead_of_copied", - description: r##"Checks for usages of `cloned()` on an `Iterator` or `Option` where + description: r##"Checks for usage of `cloned()` on an `Iterator` or `Option` where `copied()` could be used instead."##, }, - Lint { label: "clippy::cmp_nan", description: r##"Checks for comparisons to NaN."## }, Lint { label: "clippy::cmp_null", description: r##"This lint checks for equality comparisons with `ptr::null`"##, @@ -4856,6 +4649,15 @@ without adding any branches. Note that this lint is not intended to find _all_ cases where nested match patterns can be merged, but only cases where merging would most likely make the code more readable."##, }, + Lint { + label: "clippy::collapsible_str_replace", + description: r##"Checks for consecutive calls to `str::replace` (2 or more) +that can be collapsed into a single call."##, + }, + Lint { + label: "clippy::collection_is_never_read", + description: r##"Checks for collections that are never queried."##, + }, Lint { label: "clippy::comparison_chain", description: r##"Checks comparison chains written with `if` that can be @@ -4871,6 +4673,10 @@ and suggests using `.is_empty()` where applicable."##, description: r##"Checks for types that implement `Copy` as well as `Iterator`."##, }, + Lint { + label: "clippy::crate_in_macro_def", + description: r##"Checks for usage of `crate` as opposed to `$crate` in a macro definition."##, + }, Lint { label: "clippy::create_dir", description: r##"Checks usage of `std::fs::create_dir` and suggest using `std::fs::create_dir_all` instead."##, @@ -4879,7 +4685,10 @@ and suggests using `.is_empty()` where applicable."##, label: "clippy::crosspointer_transmute", description: r##"Checks for transmutes between a type `T` and `*T`."##, }, - Lint { label: "clippy::dbg_macro", description: r##"Checks for usage of dbg!() macro."## }, + Lint { + label: "clippy::dbg_macro", + description: r##"Checks for usage of the [`dbg!`](https://doc.rust-lang.org/std/macro.dbg.html) macro."##, + }, Lint { label: "clippy::debug_assert_with_mut_call", description: r##"Checks for function/method calls with a mutable @@ -4893,6 +4702,15 @@ parameter in `debug_assert!`, `debug_assert_eq!` and `debug_assert_ne!` macros." label: "clippy::declare_interior_mutable_const", description: r##"Checks for declaration of `const` items which is interior mutable (e.g., contains a `Cell`, `Mutex`, `AtomicXxxx`, etc.)."##, + }, + Lint { + label: "clippy::default_constructed_unit_structs", + description: r##"Checks for construction on unit struct using `default`."##, + }, + Lint { + label: "clippy::default_instead_of_iter_empty", + description: r##"It checks for `std::iter::Empty::default()` and suggests replacing it with +`std::iter::empty()`."##, }, Lint { label: "clippy::default_numeric_fallback", @@ -4909,6 +4727,10 @@ See [RFC0212](https://github.com/rust-lang/rfcs/blob/master/text/0212-restore-in label: "clippy::default_trait_access", description: r##"Checks for literal calls to `Default::default()`."##, }, + Lint { + label: "clippy::default_union_representation", + description: r##"Displays a warning when a union is declared with the default representation (without a `#[repr(C)]` attribute)."##, + }, Lint { label: "clippy::deprecated_cfg_attr", description: r##"Checks for `#[cfg_attr(rustfmt, rustfmt_skip)]` and suggests to replace it @@ -4923,23 +4745,47 @@ field that is not a valid semantic version."##, label: "clippy::deref_addrof", description: r##"Checks for usage of `*&` and `*&mut` in expressions."##, }, + Lint { + label: "clippy::deref_by_slicing", + description: r##"Checks for slicing expressions which are equivalent to dereferencing the +value."##, + }, Lint { label: "clippy::derivable_impls", description: r##"Detects manual `std::default::Default` implementations that are identical to a derived implementation."##, }, Lint { - label: "clippy::derive_hash_xor_eq", - description: r##"Checks for deriving `Hash` but implementing `PartialEq` -explicitly or vice versa."##, + label: "clippy::derive_ord_xor_partial_ord", + description: r##"Lints against manual `PartialOrd` and `Ord` implementations for types with a derived `Ord` +or `PartialOrd` implementation."##, }, Lint { - label: "clippy::derive_ord_xor_partial_ord", - description: r##"Checks for deriving `Ord` but implementing `PartialOrd` -explicitly or vice versa."##, + label: "clippy::derive_partial_eq_without_eq", + description: r##"Checks for types that derive `PartialEq` and could implement `Eq`."##, + }, + Lint { + label: "clippy::derived_hash_with_manual_eq", + description: r##"Lints against manual `PartialEq` implementations for types with a derived `Hash` +implementation."##, + }, + Lint { + label: "clippy::disallowed_macros", + description: r##"Denies the configured macros in clippy.toml + +Note: Even though this lint is warn-by-default, it will only trigger if +macros are defined in the clippy.toml file."##, }, Lint { label: "clippy::disallowed_methods", - description: r##"Denies the configured methods and functions in clippy.toml"##, + description: r##"Denies the configured methods and functions in clippy.toml + +Note: Even though this lint is warn-by-default, it will only trigger if +methods are defined in the clippy.toml file."##, + }, + Lint { + label: "clippy::disallowed_names", + description: r##"Checks for usage of disallowed names for variables, such +as `foo`."##, }, Lint { label: "clippy::disallowed_script_idents", @@ -4958,12 +4804,20 @@ See also: [`non_ascii_idents`]. }, Lint { label: "clippy::disallowed_types", - description: r##"Denies the configured types in clippy.toml."##, + description: r##"Denies the configured types in clippy.toml. + +Note: Even though this lint is warn-by-default, it will only trigger if +types are defined in the clippy.toml file."##, }, Lint { label: "clippy::diverging_sub_expression", description: r##"Checks for diverging calls that are not match arms or statements."##, + }, + Lint { + label: "clippy::doc_link_with_quotes", + description: r##"Detects the syntax `['foo']` in documentation comments (notice quotes instead of backticks) +outside of code blocks"##, }, Lint { label: "clippy::doc_markdown", @@ -4989,14 +4843,19 @@ marked as `#[must_use]`."##, description: r##"Checks for unnecessary double parentheses."##, }, Lint { - label: "clippy::drop_copy", - description: r##"Checks for calls to `std::mem::drop` with a value -that derives the Copy trait"##, + label: "clippy::drain_collect", + description: r##"Checks for calls to `.drain()` that clear the collection, immediately followed by a call to `.collect()`. + +> Collection in this context refers to any type with a `drain` method: +> `Vec`, `VecDeque`, `BinaryHeap`, `HashSet`,`HashMap`, `String`"##, }, Lint { - label: "clippy::drop_ref", - description: r##"Checks for calls to `std::mem::drop` with a reference -instead of an owned value."##, + label: "clippy::drop_non_drop", + description: r##"Checks for calls to `std::mem::drop` with a value that does not implement `Drop`."##, + }, + Lint { + label: "clippy::duplicate_mod", + description: r##"Checks for files that are included as modules multiple times."##, }, Lint { label: "clippy::duplicate_underscore_argument", @@ -5013,6 +4872,10 @@ from other `Duration` methods."##, description: r##"Checks for usage of if expressions with an `else if` branch, but without a final `else` branch."##, }, + Lint { + label: "clippy::empty_drop", + description: r##"Checks for empty `Drop` implementations."##, + }, Lint { label: "clippy::empty_enum", description: r##"Checks for `enum`s with no variants. @@ -5021,11 +4884,19 @@ As of this writing, the `never_type` is still a nightly-only experimental API. Therefore, this lint is only triggered if the `never_type` is enabled."##, }, + Lint { + label: "clippy::empty_line_after_doc_comments", + description: r##"Checks for empty lines after documenation comments."##, + }, Lint { label: "clippy::empty_line_after_outer_attr", description: r##"Checks for empty lines after outer attributes"##, }, Lint { label: "clippy::empty_loop", description: r##"Checks for empty `loop` expressions."## }, + Lint { + label: "clippy::empty_structs_with_brackets", + description: r##"Finds structs without fields (a so-called empty struct) that are declared with brackets."##, + }, Lint { label: "clippy::enum_clike_unportable_variant", description: r##"Checks for C-like enumerations that are @@ -5052,10 +4923,18 @@ bitwise, difference and division binary operators (`==`, `>`, etc., `&&`, description: r##"Checks for erasing operations, e.g., `x * 0`."##, }, Lint { - label: "clippy::eval_order_dependence", - description: r##"Checks for a read and a write to the same variable where -whether the read occurs before or after the write depends on the evaluation -order of sub-expressions."##, + label: "clippy::err_expect", + description: r##"Checks for `.err().expect()` calls on the `Result` type."##, + }, + Lint { + label: "clippy::error_impl_error", + description: r##"Checks for types named `Error` that implement `Error`."##, + }, + Lint { + label: "clippy::excessive_nesting", + description: r##"Checks for blocks which are nested beyond a certain threshold. + +Note: Even though this lint is warn-by-default, it will only trigger if a maximum nesting level is defined in the clippy.toml file."##, }, Lint { label: "clippy::excessive_precision", @@ -5072,8 +4951,7 @@ than that supported by the underlying type."##, }, Lint { label: "clippy::exit", - description: r##"`exit()` terminates the program and doesn't provide a -stack trace."##, + description: r##"Detects calls to the `exit()` function which terminates the program."##, }, Lint { label: "clippy::expect_fun_call", @@ -5082,13 +4960,17 @@ etc., and suggests to use `unwrap_or_else` instead"##, }, Lint { label: "clippy::expect_used", - description: r##"Checks for `.expect()` calls on `Option`s and `Result`s."##, + description: r##"Checks for `.expect()` or `.expect_err()` calls on `Result`s and `.expect()` call on `Option`s."##, }, Lint { label: "clippy::expl_impl_clone_on_copy", description: r##"Checks for explicit `Clone` implementations for `Copy` types."##, }, + Lint { + label: "clippy::explicit_auto_deref", + description: r##"Checks for dereferencing expressions which would be covered by auto-deref."##, + }, Lint { label: "clippy::explicit_counter_loop", description: r##"Checks `for` loops over slices with an explicit counter @@ -5126,6 +5008,10 @@ replaced with `(e)print!()` / `(e)println!()`"##, description: r##"Checks for lifetimes in generics that are never used anywhere else."##, }, + Lint { + label: "clippy::extra_unused_type_parameters", + description: r##"Checks for type parameters in generics that are never used anywhere else."##, + }, Lint { label: "clippy::fallible_impl_from", description: r##"Checks for impls of `From<..>` that contain `panic!()` or `unwrap()`"##, @@ -5143,6 +5029,10 @@ with Default::default()."##, label: "clippy::filter_map", description: r##"Nothing. This lint has been deprecated."##, }, + Lint { + label: "clippy::filter_map_bool_then", + description: r##"Checks for usage of `bool::then` in `Iterator::filter_map`."##, + }, Lint { label: "clippy::filter_map_identity", description: r##"Checks for usage of `filter_map(|x| x)`."##, @@ -5162,7 +5052,7 @@ with Default::default()."##, }, Lint { label: "clippy::flat_map_option", - description: r##"Checks for usages of `Iterator::flat_map()` where `filter_map()` could be + description: r##"Checks for usage of `Iterator::flat_map()` where `filter_map()` could be used instead."##, }, Lint { label: "clippy::float_arithmetic", description: r##"Checks for float arithmetic."## }, @@ -5211,18 +5101,12 @@ store address."##, ignoring either the keys or values."##, }, Lint { - label: "clippy::for_loops_over_fallibles", - description: r##"Checks for `for` loops over `Option` or `Result` values."##, + label: "clippy::forget_non_drop", + description: r##"Checks for calls to `std::mem::forget` with a value that does not implement `Drop`."##, }, Lint { - label: "clippy::forget_copy", - description: r##"Checks for calls to `std::mem::forget` with a value that -derives the Copy trait"##, - }, - Lint { - label: "clippy::forget_ref", - description: r##"Checks for calls to `std::mem::forget` with a reference -instead of an owned value."##, + label: "clippy::format_collect", + description: r##"Checks for usage of `.map(|_| format!(..)).collect::()`."##, }, Lint { label: "clippy::format_in_format_args", @@ -5230,6 +5114,15 @@ instead of an owned value."##, formatting such as `format!` itself, `write!` or `println!`. Suggests inlining the `format!` call."##, }, + Lint { + label: "clippy::format_push_string", + description: r##"Detects cases where the result of a `format!` call is +appended to an existing `String`."##, + }, + Lint { + label: "clippy::four_forward_slashes", + description: r##"Checks for outer doc comments written with 4 forward slashes (`////`)."##, + }, Lint { label: "clippy::from_iter_instead_of_collect", description: r##"Checks for `from_iter()` function calls on types that implement the `FromIterator` @@ -5239,6 +5132,10 @@ trait."##, label: "clippy::from_over_into", description: r##"Searches for implementations of the `Into<..>` trait and suggests to implement `From<..>` instead."##, }, + Lint { + label: "clippy::from_raw_with_void_ptr", + description: r##"Checks if we're passing a `c_void` raw pointer to `{Box,Rc,Arc,Weak}::from_raw(_)`"##, + }, Lint { label: "clippy::from_str_radix_10", description: r##"Checks for function invocations of the form `primitive::from_str_radix(s, 10)`"##, @@ -5249,17 +5146,26 @@ trait."##, functions and methods to implement the `Send` marker trait. It is mostly used by library authors (public and internal) that target an audience where multithreaded executors are likely to be used for running these Futures."##, + }, + Lint { + label: "clippy::get_first", + description: r##"Checks for usage of `x.get(0)` instead of +`x.first()`."##, }, Lint { label: "clippy::get_last_with_len", - description: r##"Checks for using `x.get(x.len() - 1)` instead of + description: r##"Checks for usage of `x.get(x.len() - 1)` instead of `x.last()`."##, }, Lint { label: "clippy::get_unwrap", - description: r##"Checks for use of `.get().unwrap()` (or + description: r##"Checks for usage of `.get().unwrap()` (or `.get_mut().unwrap`) on a standard library type which implements `Index`"##, }, + Lint { + label: "clippy::host_endian_bytes", + description: r##"Checks for the usage of the `to_ne_bytes` method and/or the function `from_ne_bytes`."##, + }, Lint { label: "clippy::identity_op", description: r##"Checks for identity operations, e.g., `x + 0`."##, @@ -5285,12 +5191,20 @@ and the *else* part."##, }, Lint { label: "clippy::if_then_some_else_none", - description: r##"Checks for if-else that could be written to `bool::then`."##, + description: r##"Checks for if-else that could be written using either `bool::then` or `bool::then_some`."##, }, Lint { label: "clippy::ifs_same_cond", description: r##"Checks for consecutive `if`s with the same condition."##, }, + Lint { + label: "clippy::ignored_unit_patterns", + description: r##"Checks for usage of `_` in patterns of type `()`."##, + }, + Lint { + label: "clippy::impl_trait_in_params", + description: r##"Lints when `impl Trait` is being used in a function's parameters."##, + }, Lint { label: "clippy::implicit_clone", description: r##"Checks for the usage of `_.to_owned()`, `vec.to_vec()`, or similar when calling `_.clone()` would be clearer."##, @@ -5305,10 +5219,25 @@ algorithm (`SipHash`)."##, label: "clippy::implicit_return", description: r##"Checks for missing return statements at the end of a block."##, }, + Lint { + label: "clippy::implicit_saturating_add", + description: r##"Checks for implicit saturating addition."##, + }, Lint { label: "clippy::implicit_saturating_sub", description: r##"Checks for implicit saturating subtraction."##, }, + Lint { + label: "clippy::implied_bounds_in_impls", + description: r##"Looks for bounds in `impl Trait` in return position that are implied by other bounds. +This can happen when a trait is specified that another trait already has as a supertrait +(e.g. `fn() -> impl Deref + DerefMut` has an unnecessary `Deref` bound, +because `Deref` is a supertrait of `DerefMut`)"##, + }, + Lint { + label: "clippy::impossible_comparisons", + description: r##"Checks for double comparisons that can never succeed"##, + }, Lint { label: "clippy::imprecise_flops", description: r##"Looks for floating-point expressions that @@ -5343,10 +5272,10 @@ lint on constant `usize` indexing on arrays because that is handled by rustc's ` without changing the outcome. The basic structure can be seen in the following table: -|Comparison| Bit Op |Example |equals | -|----------|---------|-----------|-------| -|`>` / `<=`|`|` / `^`|`x | 2 > 3`|`x > 3`| -|`<` / `>=`|`|` / `^`|`x ^ 1 < 4`|`x < 4`|"##, +|Comparison| Bit Op |Example |equals | +|----------|----------|------------|-------| +|`>` / `<=`|`\\|` / `^`|`x \\| 2 > 3`|`x > 3`| +|`<` / `>=`|`\\|` / `^`|`x ^ 1 < 4` |`x < 4`|"##, }, Lint { label: "clippy::inefficient_to_string", @@ -5370,6 +5299,12 @@ or tuple struct where a `let` will suffice."##, label: "clippy::inherent_to_string_shadow_display", description: r##"Checks for the definition of inherent methods with a signature of `to_string(&self) -> String` and if the type implementing this method also implements the `Display` trait."##, }, + Lint { + label: "clippy::init_numbered_fields", + description: r##"Checks for tuple structs initialized with field syntax. +It will however not lint if a base initializer is present. +The lint will also ignore code in macros."##, + }, Lint { label: "clippy::inline_always", description: r##"Checks for items annotated with `#[inline(always)]`, @@ -5395,16 +5330,6 @@ unless the annotated function is empty or simply panics."##, label: "clippy::int_plus_one", description: r##"Checks for usage of `x >= y + 1` or `x - 1 >= y` (and `<=`) in a block"##, }, - Lint { - label: "clippy::integer_arithmetic", - description: r##"Checks for integer arithmetic operations which could overflow or panic. - -Specifically, checks for any operators (`+`, `-`, `*`, `<<`, etc) which are capable -of overflowing according to the [Rust -Reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html#overflow), -or which can panic (`/`, `%`). No bounds analysis or sophisticated reasoning is -attempted."##, - }, Lint { label: "clippy::integer_division", description: r##"Checks for division of integers"## }, Lint { label: "clippy::into_iter_on_ref", @@ -5431,10 +5356,20 @@ necessary. Only integer types are checked."##, label: "clippy::invisible_characters", description: r##"Checks for invisible Unicode characters in the code."##, }, + Lint { + label: "clippy::is_digit_ascii_radix", + description: r##"Finds usages of [`char::is_digit`](https://doc.rust-lang.org/stable/std/primitive.char.html#method.is_digit) that +can be replaced with [`is_ascii_digit`](https://doc.rust-lang.org/stable/std/primitive.char.html#method.is_ascii_digit) or +[`is_ascii_hexdigit`](https://doc.rust-lang.org/stable/std/primitive.char.html#method.is_ascii_hexdigit)."##, + }, Lint { label: "clippy::items_after_statements", description: r##"Checks for items declared after some statement in a block."##, }, + Lint { + label: "clippy::items_after_test_module", + description: r##"Triggers if an item is declared after the testing module marked with `#[cfg(test)]`."##, + }, Lint { label: "clippy::iter_cloned_collect", description: r##"Checks for the use of `.cloned().collect()` on slice to @@ -5444,6 +5379,11 @@ create a `Vec`."##, label: "clippy::iter_count", description: r##"Checks for the use of `.iter().count()`."##, }, + Lint { + label: "clippy::iter_kv_map", + description: r##"Checks for iterating a map (`HashMap` or `BTreeMap`) and +ignoring either the keys or values."##, + }, Lint { label: "clippy::iter_next_loop", description: r##"Checks for loops on `x.next()`."## }, Lint { label: "clippy::iter_next_slice", @@ -5455,16 +5395,41 @@ create a `Vec`."##, }, Lint { label: "clippy::iter_nth", - description: r##"Checks for use of `.iter().nth()` (and the related + description: r##"Checks for usage of `.iter().nth()` (and the related `.iter_mut().nth()`) on standard library types with *O*(1) element access."##, }, Lint { label: "clippy::iter_nth_zero", description: r##"Checks for the use of `iter.nth(0)`."##, }, + Lint { + label: "clippy::iter_on_empty_collections", + description: r##"Checks for calls to `iter`, `iter_mut` or `into_iter` on empty collections"##, + }, + Lint { + label: "clippy::iter_on_single_items", + description: r##"Checks for calls to `iter`, `iter_mut` or `into_iter` on collections containing a single item"##, + }, + Lint { + label: "clippy::iter_out_of_bounds", + description: r##"Looks for iterator combinator calls such as `.take(x)` or `.skip(x)` +where `x` is greater than the amount of items that an iterator will produce."##, + }, + Lint { + label: "clippy::iter_overeager_cloned", + description: r##"Checks for usage of `_.cloned().()` where call to `.cloned()` can be postponed."##, + }, Lint { label: "clippy::iter_skip_next", - description: r##"Checks for use of `.skip(x).next()` on iterators."##, + description: r##"Checks for usage of `.skip(x).next()` on iterators."##, + }, + Lint { + label: "clippy::iter_skip_zero", + description: r##"Checks for usage of `.skip(0)` on iterators."##, + }, + Lint { + label: "clippy::iter_with_drain", + description: r##"Checks for usage of `.drain(..)` on `Vec` and `VecDeque` for iteration."##, }, Lint { label: "clippy::iterator_step_by_zero", @@ -5490,11 +5455,30 @@ are too large."##, label: "clippy::large_enum_variant", description: r##"Checks for large size differences between variants on `enum`s."##, + }, + Lint { + label: "clippy::large_futures", + description: r##"It checks for the size of a `Future` created by `async fn` or `async {}`."##, + }, + Lint { + label: "clippy::large_include_file", + description: r##"Checks for the inclusion of large files via `include_bytes!()` +and `include_str!()`"##, }, Lint { label: "clippy::large_stack_arrays", description: r##"Checks for local arrays that may be too large."##, }, + Lint { + label: "clippy::large_stack_frames", + description: r##"Checks for functions that use a lot of stack space. + +This often happens when constructing a large type, such as an array with a lot of elements, +or constructing *many* smaller-but-still-large structs, or copying around a lot of large types. + +This lint is a more general version of [`large_stack_arrays`](https://rust-lang.github.io/rust-clippy/master/#large_stack_arrays) +that is intended to look at functions as a whole instead of only individual array expressions inside of a function."##, + }, Lint { label: "clippy::large_types_passed_by_value", description: r##"Checks for functions taking arguments by value, where @@ -5519,29 +5503,42 @@ just to compare to zero, and suggests using `.is_empty()` where applicable."##, returned."##, }, Lint { - label: "clippy::let_underscore_drop", - description: r##"Checks for `let _ = ` -where expr has a type that implements `Drop`"##, + label: "clippy::let_underscore_future", + description: r##"Checks for `let _ = ` where the resulting type of expr implements `Future`"##, }, Lint { label: "clippy::let_underscore_lock", - description: r##"Checks for `let _ = sync_lock`. -This supports `mutex` and `rwlock` in `std::sync` and `parking_lot`."##, + description: r##"Checks for `let _ = sync_lock`. This supports `mutex` and `rwlock` in +`parking_lot`. For `std` locks see the `rustc` lint +[`let_underscore_lock`](https://doc.rust-lang.org/nightly/rustc/lints/listing/deny-by-default.html#let-underscore-lock)"##, }, Lint { label: "clippy::let_underscore_must_use", description: r##"Checks for `let _ = ` where expr is `#[must_use]`"##, }, + Lint { + label: "clippy::let_underscore_untyped", + description: r##"Checks for `let _ = ` without a type annotation, and suggests to either provide one, +or remove the `let` keyword altogether."##, + }, Lint { label: "clippy::let_unit_value", description: r##"Checks for binding a unit value."## }, + Lint { + label: "clippy::let_with_type_underscore", + description: r##"Detects when a variable is declared with an explicit type of `_`."##, + }, + Lint { + label: "clippy::lines_filter_map_ok", + description: r##"Checks for usage of `lines.filter_map(Result::ok)` or `lines.flat_map(Result::ok)` +when `lines` has type `std::io::Lines`."##, + }, Lint { label: "clippy::linkedlist", description: r##"Checks for usage of any `LinkedList`, suggesting to use a `Vec` or a `VecDeque` (formerly called `RingBuf`)."##, }, Lint { - label: "clippy::logic_bug", - description: r##"Checks for boolean expressions that contain terminals that -can be eliminated."##, + label: "clippy::little_endian_bytes", + description: r##"Checks for the usage of the `to_le_bytes` method and/or the function `from_le_bytes`."##, }, Lint { label: "clippy::lossy_float_literal", @@ -5564,11 +5561,28 @@ cannot be represented as the underlying type without loss."##, label: "clippy::manual_async_fn", description: r##"It checks for manual implementations of `async` functions."##, }, + Lint { + label: "clippy::manual_bits", + description: r##"Checks for usage of `std::mem::size_of::() * 8` when +`T::BITS` is available."##, + }, + Lint { + label: "clippy::manual_clamp", + description: r##"Identifies good opportunities for a clamp function from std or core, and suggests using it."##, + }, + Lint { + label: "clippy::manual_filter", + description: r##"Checks for usage of `match` which could be implemented using `filter`"##, + }, Lint { label: "clippy::manual_filter_map", description: r##"Checks for usage of `_.filter(_).map(_)` that can be written more simply as `filter_map(_)`."##, }, + Lint { + label: "clippy::manual_find", + description: r##"Checks for manual implementations of Iterator::find"##, + }, Lint { label: "clippy::manual_find_map", description: r##"Checks for usage of `_.find(_).map(_)` that can be written more simply @@ -5576,18 +5590,56 @@ as `find_map(_)`."##, }, Lint { label: "clippy::manual_flatten", - description: r##"Check for unnecessary `if let` usage in a for loop + description: r##"Checks for unnecessary `if let` usage in a for loop where only the `Some` or `Ok` variant of the iterator element is used."##, + }, + Lint { + label: "clippy::manual_hash_one", + description: r##"Checks for cases where [`BuildHasher::hash_one`] can be used. + +[`BuildHasher::hash_one`]: https://doc.rust-lang.org/std/hash/trait.BuildHasher.html#method.hash_one"##, + }, + Lint { + label: "clippy::manual_instant_elapsed", + description: r##"Lints subtraction between `Instant::now()` and another `Instant`."##, + }, + Lint { + label: "clippy::manual_is_ascii_check", + description: r##"Suggests to use dedicated built-in methods, +`is_ascii_(lowercase|uppercase|digit)` for checking on corresponding ascii range"##, + }, + Lint { + label: "clippy::manual_is_finite", + description: r##"Checks for manual `is_finite` reimplementations +(i.e., `x != ::INFINITY && x != ::NEG_INFINITY`)."##, + }, + Lint { + label: "clippy::manual_is_infinite", + description: r##"Checks for manual `is_infinite` reimplementations +(i.e., `x == ::INFINITY || x == ::NEG_INFINITY`)."##, + }, + Lint { + label: "clippy::manual_let_else", + description: r##"Warn of cases where `let...else` could be used"##, + }, + Lint { + label: "clippy::manual_main_separator_str", + description: r##"Checks for references on `std::path::MAIN_SEPARATOR.to_string()` used +to build a `&str`."##, }, Lint { label: "clippy::manual_map", - description: r##"Checks for usages of `match` which could be implemented using `map`"##, + description: r##"Checks for usage of `match` which could be implemented using `map`"##, }, Lint { label: "clippy::manual_memcpy", description: r##"Checks for for-loops that manually copy items between slices that could be optimized by having a memcpy."##, }, + Lint { + label: "clippy::manual_next_back", + description: r##"Checks for `.rev().next()` on a `DoubleEndedIterator`"##, + }, Lint { label: "clippy::manual_non_exhaustive", description: r##"Checks for manual implementations of the non-exhaustive pattern."##, @@ -5601,28 +5653,66 @@ slices that could be optimized by having a memcpy."##, description: r##"Checks for expressions like `x >= 3 && x < 8` that could be more readably expressed as `(3..8).contains(x)`."##, }, + Lint { + label: "clippy::manual_range_patterns", + description: r##"Looks for combined OR patterns that are all contained in a specific range, +e.g. `6 | 4 | 5 | 9 | 7 | 8` can be rewritten as `4..=9`."##, + }, + Lint { + label: "clippy::manual_rem_euclid", + description: r##"Checks for an expression like `((x % 4) + 4) % 4` which is a common manual reimplementation +of `x.rem_euclid(4)`."##, + }, + Lint { + label: "clippy::manual_retain", + description: r##"Checks for code to be replaced by `.retain()`."##, + }, Lint { label: "clippy::manual_saturating_arithmetic", description: r##"Checks for `.checked_add/sub(x).unwrap_or(MAX/MIN)`."##, }, + Lint { + label: "clippy::manual_slice_size_calculation", + description: r##"When `a` is `&[T]`, detect `a.len() * size_of::()` and suggest `size_of_val(a)` +instead."##, + }, Lint { label: "clippy::manual_split_once", - description: r##"Checks for usages of `str::splitn(2, _)`"##, + description: r##"Checks for usage of `str::splitn(2, _)`"##, }, Lint { label: "clippy::manual_str_repeat", description: r##"Checks for manual implementations of `str::repeat`"##, }, + Lint { + label: "clippy::manual_string_new", + description: r##"Checks for usage of `` to create a `String`, such as `.to_string()`, `.to_owned()`, +`String::from()` and others."##, + }, Lint { label: "clippy::manual_strip", description: r##"Suggests using `strip_{prefix,suffix}` over `str::{starts,ends}_with` and slicing using the pattern's length."##, }, - Lint { label: "clippy::manual_swap", description: r##"Checks for manual swapping."## }, + Lint { + label: "clippy::manual_swap", + description: r##"Checks for manual swapping. + +Note that the lint will not be emitted in const blocks, as the suggestion would not be applicable."##, + }, + Lint { + label: "clippy::manual_try_fold", + description: r##"Checks for usage of `Iterator::fold` with a type that implements `Try`."##, + }, Lint { label: "clippy::manual_unwrap_or", description: r##"Finds patterns that reimplement `Option::unwrap_or` or `Result::unwrap_or`."##, }, + Lint { + label: "clippy::manual_while_let_some", + description: r##"Looks for loops that check for emptiness of a `Vec` in the condition and pop an element +in the body as a separate operation."##, + }, Lint { label: "clippy::many_single_char_names", description: r##"Checks for too many variables whose name consists of a @@ -5640,7 +5730,7 @@ and suggests `cloned()` or `copied()` instead"##, }, Lint { label: "clippy::map_entry", - description: r##"Checks for uses of `contains_key` + `insert` on `HashMap` + description: r##"Checks for usage of `contains_key` + `insert` on `HashMap` or `BTreeMap`."##, }, Lint { @@ -5695,7 +5785,10 @@ instead. It also checks for `if let &foo = bar` blocks."##, }, Lint { label: "clippy::match_same_arms", - description: r##"Checks for `match` with identical arm bodies."##, + description: r##"Checks for `match` with identical arm bodies. + +Note: Does not lint on wildcards if the `non_exhaustive_omitted_patterns_lint` feature is +enabled and disallowed."##, }, Lint { label: "clippy::match_single_binding", @@ -5718,10 +5811,15 @@ and take drastic actions like `panic!`."##, label: "clippy::maybe_infinite_iter", description: r##"Checks for iteration that may be infinite."##, }, + Lint { + label: "clippy::maybe_misused_cfg", + description: r##"Checks for `#[cfg(features = ...)]` and suggests to replace it with +`#[cfg(feature = ...)]`."##, + }, Lint { label: "clippy::mem_forget", description: r##"Checks for usage of `std::mem::forget(t)` where `t` is -`Drop`."##, +`Drop` or has a field that implements `Drop`."##, }, Lint { label: "clippy::mem_replace_option_with_none", @@ -5737,6 +5835,13 @@ and take drastic actions like `panic!`."##, label: "clippy::mem_replace_with_uninit", description: r##"Checks for `mem::replace(&mut _, mem::uninitialized())` and `mem::replace(&mut _, mem::zeroed())`."##, + }, + Lint { + label: "clippy::min_ident_chars", + description: r##"Checks for idents which comprise of a single letter. + +Note: This lint can be very noisy when enabled; it may be desirable to only enable it +temporarily."##, }, Lint { label: "clippy::min_max", @@ -5751,18 +5856,38 @@ used to clamp values, but switched so that the result is constant."##, label: "clippy::mismatched_target_os", description: r##"Checks for cfg attributes having operating systems used in target family position."##, }, + Lint { + label: "clippy::mismatching_type_param_order", + description: r##"Checks for type parameters which are positioned inconsistently between +a type definition and impl block. Specifically, a parameter in an impl +block which has the same name as a parameter in the type def, but is in +a different place."##, + }, + Lint { + label: "clippy::misnamed_getters", + description: r##"Checks for getter methods that return a field that doesn't correspond +to the name of the method, when there is a field's whose name matches that of the method."##, + }, Lint { label: "clippy::misrefactored_assign_op", description: r##"Checks for `a op= a op b` or `a op= b op a` patterns."##, }, + Lint { + label: "clippy::missing_assert_message", + description: r##"Checks assertions without a custom panic message."##, + }, + Lint { + label: "clippy::missing_asserts_for_indexing", + description: r##"Checks for repeated slice indexing without asserting beforehand that the length +is greater than the largest index used to index into the slice."##, + }, Lint { label: "clippy::missing_const_for_fn", description: r##"Suggests the use of `const` in functions and methods where possible."##, }, Lint { label: "clippy::missing_docs_in_private_items", - description: r##"Warns if there is missing doc for any documentable item -(public or private)."##, + description: r##"Warns if there is missing doc for any private documentable item"##, }, Lint { label: "clippy::missing_enforced_import_renames", @@ -5774,6 +5899,10 @@ in the `enforce-import-renames` config option."##, description: r##"Checks the doc comments of publicly visible functions that return a `Result` type and warns if there is no `# Errors` section."##, }, + Lint { + label: "clippy::missing_fields_in_debug", + description: r##"Checks for manual [`core::fmt::Debug`](https://doc.rust-lang.org/core/fmt/trait.Debug.html) implementations that do not use all fields."##, + }, Lint { label: "clippy::missing_inline_in_public_items", description: r##"It lints if an exported function, method, trait method with default impl, @@ -5788,6 +5917,17 @@ may panic and warns if there is no `# Panics` section."##, label: "clippy::missing_safety_doc", description: r##"Checks for the doc comments of publicly visible unsafe functions and warns if there is no `# Safety` section."##, + }, + Lint { label: "clippy::missing_spin_loop", description: r##"Checks for empty spin loops"## }, + Lint { + label: "clippy::missing_trait_methods", + description: r##"Checks if a provided method is used implicitly by a trait +implementation. A usage example would be a wrapper where every method +should perform some operation before delegating to the inner type's +implementation. + +This lint should typically be enabled on a specific trait `impl` item +rather than globally."##, }, Lint { label: "clippy::mistyped_literal_suffixes", @@ -5797,10 +5937,16 @@ unsafe functions and warns if there is no `# Safety` section."##, label: "clippy::mixed_case_hex_literals", description: r##"Warns on hexadecimal literals with mixed-case letter digits."##, + }, + Lint { + label: "clippy::mixed_read_write_in_expression", + description: r##"Checks for a read and a write to the same variable where +whether the read occurs before or after the write depends on the evaluation +order of sub-expressions."##, }, Lint { label: "clippy::mod_module_files", - description: r##"Checks that module layout uses only self named module files, bans mod.rs files."##, + description: r##"Checks that module layout uses only self named module files, bans `mod.rs` files."##, }, Lint { label: "clippy::module_inception", @@ -5818,6 +5964,7 @@ containing module's name."##, description: r##"Checks for getting the remainder of a division by one or minus one."##, }, + Lint { label: "clippy::multi_assignments", description: r##"Checks for nested assignments."## }, Lint { label: "clippy::multiple_crate_versions", description: r##"Checks to see if multiple versions of a crate are being @@ -5827,6 +5974,10 @@ used."##, label: "clippy::multiple_inherent_impl", description: r##"Checks for multiple inherent implementations of a struct"##, }, + Lint { + label: "clippy::multiple_unsafe_ops_per_block", + description: r##"Checks for `unsafe` blocks that contain more than one unsafe operation."##, + }, Lint { label: "clippy::must_use_candidate", description: r##"Checks for public functions that have no @@ -5840,8 +5991,12 @@ unit-returning functions and methods."##, }, Lint { label: "clippy::mut_from_ref", - description: r##"This lint checks for functions that take immutable -references and return mutable ones."##, + description: r##"This lint checks for functions that take immutable references and return +mutable ones. This will not trigger if no unsafe code exists as there +are multiple safe functions which will do this transformation + +To be on the conservative side, if there's at least one mutable +reference with the output lifetime, this lint will not trigger."##, }, Lint { label: "clippy::mut_mut", @@ -5861,11 +6016,11 @@ references and return mutable ones."##, }, Lint { label: "clippy::mutex_atomic", - description: r##"Checks for usages of `Mutex` where an atomic will do."##, + description: r##"Checks for usage of `Mutex` where an atomic will do."##, }, Lint { label: "clippy::mutex_integer", - description: r##"Checks for usages of `Mutex` where `X` is an integral + description: r##"Checks for usage of `Mutex` where `X` is an integral type."##, }, Lint { label: "clippy::naive_bytecount", description: r##"Checks for naive byte counts"## }, @@ -5876,13 +6031,19 @@ specify the `Self`-type explicitly"##, }, Lint { label: "clippy::needless_bitwise_bool", - description: r##"Checks for uses of bitwise and/or operators between booleans, where performance may be improved by using + description: r##"Checks for usage of bitwise and/or operators between booleans, where performance may be improved by using a lazy and."##, }, Lint { label: "clippy::needless_bool", description: r##"Checks for expressions of the form `if c { true } else { false }` (or vice versa) and suggests using the condition directly."##, + }, + Lint { + label: "clippy::needless_bool_assign", + description: r##"Checks for expressions of the form `if c { x = true } else { x = false }` +(or vice versa) and suggest assigning the variable directly from the +condition."##, }, Lint { label: "clippy::needless_borrow", @@ -5891,8 +6052,13 @@ be dereferenced immediately by the compiler."##, }, Lint { label: "clippy::needless_borrowed_reference", - description: r##"Checks for bindings that destructure a reference and borrow the inner + description: r##"Checks for bindings that needlessly destructure a reference and borrow the inner value with `&ref`."##, + }, + Lint { + label: "clippy::needless_borrows_for_generic_args", + description: r##"Checks for borrow operations (`&`) that used as a generic argument to a +function when the borrowed value could be used."##, }, Lint { label: "clippy::needless_collect", @@ -5910,11 +6076,16 @@ rearrangement of code can make the code easier to understand."##, label: "clippy::needless_doctest_main", description: r##"Checks for `fn main() { .. }` in doctests"##, }, + Lint { label: "clippy::needless_else", description: r##"Checks for empty `else` branches."## }, Lint { label: "clippy::needless_for_each", description: r##"Checks for usage of `for_each` that would be more simply written as a `for` loop."##, }, + Lint { + label: "clippy::needless_if", + description: r##"Checks for empty `if` branches with no else branch."##, + }, Lint { label: "clippy::needless_late_init", description: r##"Checks for late initializations that can be replaced by a `let` statement @@ -5924,11 +6095,32 @@ with an initializer."##, label: "clippy::needless_lifetimes", description: r##"Checks for lifetime annotations which can be removed by relying on lifetime elision."##, + }, + Lint { + label: "clippy::needless_match", + description: r##"Checks for unnecessary `match` or match-like `if let` returns for `Option` and `Result` +when function signatures are the same."##, }, Lint { label: "clippy::needless_option_as_deref", - description: r##"Checks for no-op uses of Option::{as_deref,as_deref_mut}, + description: r##"Checks for no-op uses of `Option::{as_deref, as_deref_mut}`, for example, `Option<&T>::as_deref()` returns the same type."##, + }, + Lint { + label: "clippy::needless_option_take", + description: r##"Checks for calling `take` function after `as_ref`."##, + }, + Lint { + label: "clippy::needless_parens_on_range_literals", + description: r##"The lint checks for parenthesis on literals in range statements that are +superfluous."##, + }, + Lint { + label: "clippy::needless_pass_by_ref_mut", + description: r##"Check if a `&mut` function argument is actually used mutably. + +Be careful if the function is publicly reexported as it would break compatibility with +users of this function."##, }, Lint { label: "clippy::needless_pass_by_value", @@ -5936,6 +6128,10 @@ for example, `Option<&T>::as_deref()` returns the same type."##, consuming them in its body."##, }, + Lint { + label: "clippy::needless_pub_self", + description: r##"Checks for usage of `pub(self)` and `pub(in self)`."##, + }, Lint { label: "clippy::needless_question_mark", description: r##"Suggests alternatives for useless applications of `?` in terminating expressions"##, @@ -5945,13 +6141,25 @@ body."##, description: r##"Checks for looping over the range of `0..len` of some collection just to get the values by index."##, }, + Lint { + label: "clippy::needless_raw_string_hashes", + description: r##"Checks for raw string literals with an unnecessary amount of hashes around them."##, + }, + Lint { + label: "clippy::needless_raw_strings", + description: r##"Checks for raw string literals where a string literal can be used instead."##, + }, Lint { label: "clippy::needless_return", description: r##"Checks for return statements at the end of a block."##, }, + Lint { + label: "clippy::needless_return_with_question_mark", + description: r##"Checks for return statements on `Err` paired with the `?` operator."##, + }, Lint { label: "clippy::needless_splitn", - description: r##"Checks for usages of `str::splitn` (or `str::rsplitn`) where using `str::split` would be the same."##, + description: r##"Checks for usage of `str::splitn` (or `str::rsplitn`) where using `str::split` would be the same."##, }, Lint { label: "clippy::needless_update", @@ -5985,7 +6193,7 @@ This lint is not applied to structs marked with }, Lint { label: "clippy::new_without_default", - description: r##"Checks for types with a `fn new() -> Self` method and no + description: r##"Checks for public types with a `pub fn new() -> Self` method and no implementation of [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html)."##, }, @@ -5993,14 +6201,34 @@ implementation of label: "clippy::no_effect", description: r##"Checks for statements which have no effect."##, }, + Lint { + label: "clippy::no_effect_replace", + description: r##"Checks for `replace` statements which have no effect."##, + }, Lint { label: "clippy::no_effect_underscore_binding", description: r##"Checks for binding to underscore prefixed variable without side-effects."##, }, + Lint { + label: "clippy::no_mangle_with_rust_abi", + description: r##"Checks for Rust ABI functions with the `#[no_mangle]` attribute."##, + }, Lint { label: "clippy::non_ascii_literal", description: r##"Checks for non-ASCII characters in string and char literals."##, }, + Lint { + label: "clippy::non_canonical_clone_impl", + description: r##"Checks for non-canonical implementations of `Clone` when `Copy` is already implemented."##, + }, + Lint { + label: "clippy::non_canonical_partial_ord_impl", + description: r##"Checks for non-canonical implementations of `PartialOrd` when `Ord` is already implemented."##, + }, + Lint { + label: "clippy::non_minimal_cfg", + description: r##"Checks for `any` and `all` combinators in `cfg` with only one condition."##, + }, Lint { label: "clippy::non_octal_unix_permissions", description: r##"Checks for non-octal values used to set Unix file permissions."##, @@ -6032,12 +6260,20 @@ that make no sense."##, description: r##"Checks for public functions that dereference raw pointer arguments but are not marked `unsafe`."##, }, + Lint { + label: "clippy::obfuscated_if_else", + description: r##"Checks for usage of `.then_some(..).unwrap_or(..)`"##, + }, Lint { label: "clippy::octal_escapes", description: r##"Checks for `\\0` escapes in string and byte literals that look like octal character escapes in C."##, }, Lint { label: "clippy::ok_expect", description: r##"Checks for usage of `ok().expect(..)`."## }, + Lint { + label: "clippy::only_used_in_recursion", + description: r##"Checks for arguments that are only used in recursion with no side-effects."##, + }, Lint { label: "clippy::op_ref", description: r##"Checks for arguments to `==` which have their address @@ -6046,7 +6282,7 @@ and suggests to dereference the other argument instead"##, }, Lint { label: "clippy::option_as_ref_deref", - description: r##"Checks for usage of `_.as_ref().map(Deref::deref)` or it's aliases (such as String::as_str)."##, + description: r##"Checks for usage of `_.as_ref().map(Deref::deref)` or its aliases (such as String::as_str)."##, }, Lint { label: "clippy::option_env_unwrap", @@ -6059,7 +6295,8 @@ suggests usage of the `env!` macro."##, }, Lint { label: "clippy::option_if_let_else", - description: r##"Lints usage of `if let Some(v) = ... { y } else { x }` which is more + description: r##"Lints usage of `if let Some(v) = ... { y } else { x }` and +`match .. { Some(v) => y, None/_ => x }` which are more idiomatically done with `Option::map_or` (if the else bit is a pure expression) or `Option::map_or_else` (if the else bit is an impure expression)."##, @@ -6075,14 +6312,19 @@ or closure that returns the unit type `()`."##, }, Lint { label: "clippy::option_option", - description: r##"Checks for use of `Option>` in function signatures and type + description: r##"Checks for usage of `Option>` in function signatures and type definitions"##, }, Lint { label: "clippy::or_fun_call", description: r##"Checks for calls to `.or(foo(..))`, `.unwrap_or(foo(..))`, -etc., and suggests to use `or_else`, `unwrap_or_else`, etc., or -`unwrap_or_default` instead."##, +`.or_insert(foo(..))` etc., and suggests to use `.or_else(|| foo(..))`, +`.unwrap_or_else(|| foo(..))`, `.unwrap_or_default()` or `.or_default()` +etc. instead."##, + }, + Lint { + label: "clippy::or_then_unwrap", + description: r##"Checks for `.or(…).unwrap()` calls to Options and Results."##, }, Lint { label: "clippy::out_of_bounds_indexing", @@ -6093,23 +6335,47 @@ index."##, label: "clippy::overflow_check_conditional", description: r##"Detects classic underflow/overflow checks."##, }, + Lint { + label: "clippy::overly_complex_bool_expr", + description: r##"Checks for boolean expressions that contain terminals that +can be eliminated."##, + }, Lint { label: "clippy::panic", description: r##"Checks for usage of `panic!`."## }, Lint { label: "clippy::panic_in_result_fn", - description: r##"Checks for usage of `panic!`, `unimplemented!`, `todo!`, `unreachable!` or assertions in a function of type result."##, + description: r##"Checks for usage of `panic!` or assertions in a function of type result."##, }, Lint { label: "clippy::panicking_unwrap", description: r##"Checks for calls of `unwrap[_err]()` that will always fail."##, }, + Lint { + label: "clippy::partial_pub_fields", + description: r##"Checks whether partial fields of a struct are public. + +Either make all fields of a type public, or make none of them public"##, + }, Lint { label: "clippy::partialeq_ne_impl", description: r##"Checks for manual re-implementations of `PartialEq::ne`."##, }, + Lint { + label: "clippy::partialeq_to_none", + description: r##"Checks for binary comparisons to a literal `Option::None`."##, + }, Lint { label: "clippy::path_buf_push_overwrite", description: r##"* Checks for [push](https://doc.rust-lang.org/std/path/struct.PathBuf.html#method.push) calls on `PathBuf` that can cause overwrites."##, + }, + Lint { + label: "clippy::path_ends_with_ext", + description: r##"Looks for calls to `Path::ends_with` calls where the argument looks like a file extension. + +By default, Clippy has a short list of known filenames that start with a dot +but aren't necessarily file extensions (e.g. the `.git` folder), which are allowed by default. +The `allowed-dotfiles` configuration can be used to allow additional +file extensions that Clippy should not lint."##, }, Lint { label: "clippy::pattern_type_mismatch", @@ -6132,6 +6398,10 @@ in a general way even outside of the various pattern matching mechanics. Of cour this lint can still be used to highlight areas of interest and ensure a good understanding of ownership semantics."##, }, + Lint { + label: "clippy::permissions_set_readonly_false", + description: r##"Checks for calls to `std::fs::Permissions.set_readonly` with argument `false`."##, + }, Lint { label: "clippy::possible_missing_comma", description: r##"Checks for possible missing comma in an array. It lints if @@ -6146,6 +6416,11 @@ parentheses * a negative numeric literal (which is really a unary `-` followed by a numeric literal) followed by a method call"##, + }, + Lint { + label: "clippy::print_in_format_impl", + description: r##"Checks for usage of `println`, `print`, `eprintln` or `eprint` in an +implementation of a formatting trait."##, }, Lint { label: "clippy::print_literal", @@ -6173,15 +6448,19 @@ print a newline."##, }, Lint { label: "clippy::ptr_arg", - description: r##"This lint checks for function arguments of type `&String` -or `&Vec` unless the references are mutable. It will also suggest you -replace `.clone()` calls with the appropriate `.to_owned()`/`to_string()` -calls."##, + description: r##"This lint checks for function arguments of type `&String`, `&Vec`, +`&PathBuf`, and `Cow<_>`. It will also suggest you replace `.clone()` calls +with the appropriate `.to_owned()`/`to_string()` calls."##, }, Lint { label: "clippy::ptr_as_ptr", description: r##"Checks for `as` casts between raw pointers without changing its mutability, namely `*const T` to `*const U` and `*mut T` to `*mut U`."##, + }, + Lint { + label: "clippy::ptr_cast_constness", + description: r##"Checks for `as` casts between raw pointers which change its constness, namely `*const T` to +`*mut T` and `*mut T` to `*const T`."##, }, Lint { label: "clippy::ptr_eq", description: r##"Use `std::ptr::eq` when applicable"## }, Lint { @@ -6193,10 +6472,26 @@ namely `*const T` to `*const U` and `*mut T` to `*mut U`."##, label: "clippy::pub_enum_variant_names", description: r##"Nothing. This lint has been deprecated."##, }, + Lint { label: "clippy::pub_use", description: r##"Restricts the usage of `pub use ...`"## }, + Lint { + label: "clippy::pub_with_shorthand", + description: r##"Checks for usage of `pub()` with `in`."##, + }, + Lint { + label: "clippy::pub_without_shorthand", + description: r##"Checks for usage of `pub()` without `in`. + +Note: As you cannot write a module's path in `pub()`, this will only trigger on +`pub(super)` and the like."##, + }, Lint { label: "clippy::question_mark", description: r##"Checks for expressions that could be replaced by the question mark operator."##, }, + Lint { + label: "clippy::question_mark_used", + description: r##"Checks for expressions that use the question mark operator and rejects them."##, + }, Lint { label: "clippy::range_minus_one", description: r##"Checks for inclusive ranges where 1 is subtracted from @@ -6220,10 +6515,49 @@ upper bound, e.g., `x..(y+1)`."##, label: "clippy::rc_buffer", description: r##"Checks for `Rc` and `Arc` when `T` is a mutable buffer type such as `String` or `Vec`."##, }, + Lint { + label: "clippy::rc_clone_in_vec_init", + description: r##"Checks for reference-counted pointers (`Arc`, `Rc`, `rc::Weak`, and `sync::Weak`) +in `vec![elem; len]`"##, + }, Lint { label: "clippy::rc_mutex", description: r##"Checks for `Rc>`."## }, + Lint { + label: "clippy::read_line_without_trim", + description: r##"Looks for calls to [`Stdin::read_line`] to read a line from the standard input +into a string, then later attempting to parse this string into a type without first trimming it, which will +always fail because the string has a trailing newline in it."##, + }, + Lint { + label: "clippy::read_zero_byte_vec", + description: r##"This lint catches reads into a zero-length `Vec`. +Especially in the case of a call to `with_capacity`, this lint warns that read +gets the number of bytes from the `Vec`'s length, not its capacity."##, + }, + Lint { + label: "clippy::readonly_write_lock", + description: r##"Looks for calls to `RwLock::write` where the lock is only used for reading."##, + }, + Lint { + label: "clippy::recursive_format_impl", + description: r##"Checks for format trait implementations (e.g. `Display`) with a recursive call to itself +which uses `self` as a parameter. +This is typically done indirectly with the `write!` macro or with `to_string()`."##, + }, Lint { label: "clippy::redundant_allocation", - description: r##"Checks for use of redundant allocations anywhere in the code."##, + description: r##"Checks for usage of redundant allocations anywhere in the code."##, + }, + Lint { + label: "clippy::redundant_as_str", + description: r##"Checks for usage of `as_str()` on a `String`` chained with a method available on the `String` itself."##, + }, + Lint { + label: "clippy::redundant_async_block", + description: r##"Checks for `async` block that only returns `await` on a future."##, + }, + Lint { + label: "clippy::redundant_at_rest_pattern", + description: r##"Checks for `[all @ ..]` patterns."##, }, Lint { label: "clippy::redundant_clone", @@ -6246,6 +6580,10 @@ are defined."##, description: r##"Checks for closures which only invoke a method on the closure argument and can be replaced by referencing the method directly."##, }, + Lint { + label: "clippy::redundant_comparisons", + description: r##"Checks for ineffective double comparisons against constants."##, + }, Lint { label: "clippy::redundant_else", description: r##"Checks for `else` blocks that can be removed without changing semantics."##, @@ -6259,6 +6597,14 @@ argument and can be replaced by referencing the method directly."##, description: r##"Checks for fields in struct literals where shorthands could be used."##, }, + Lint { + label: "clippy::redundant_guards", + description: r##"Checks for unnecessary guards in match expressions."##, + }, + Lint { + label: "clippy::redundant_locals", + description: r##"Checks for redundant redefinitions of local bindings."##, + }, Lint { label: "clippy::redundant_pattern", description: r##"Checks for patterns in the form `name @ _`."##, @@ -6282,19 +6628,22 @@ do not change the type."##, label: "clippy::redundant_static_lifetimes", description: r##"Checks for constants and statics with an explicit `'static` lifetime."##, }, + Lint { + label: "clippy::redundant_type_annotations", + description: r##"Warns about needless / redundant type annotations."##, + }, Lint { label: "clippy::ref_binding_to_reference", description: r##"Checks for `ref` bindings which create a reference to a reference."##, }, - Lint { - label: "clippy::ref_in_deref", - description: r##"Checks for references in expressions that use -auto dereference."##, - }, Lint { label: "clippy::ref_option_ref", description: r##"Checks for usage of `&Option<&T>`."##, }, + Lint { + label: "clippy::ref_patterns", + description: r##"Checks for usages of the `ref` keyword."##, + }, Lint { label: "clippy::regex_macro", description: r##"Nothing. This lint has been deprecated."##, @@ -6313,10 +6662,19 @@ they are equivalent to `1`. (Related discussion in [rust-clippy#7306](https://gi label: "clippy::replace_consts", description: r##"Nothing. This lint has been deprecated."##, }, + Lint { + label: "clippy::reserve_after_initialization", + description: r##"Informs the user about a more concise way to create a vector with a known capacity."##, + }, Lint { label: "clippy::rest_pat_in_fully_bound_structs", description: r##"Checks for unnecessary '..' pattern binding on struct when all fields are explicitly matched."##, }, + Lint { + label: "clippy::result_large_err", + description: r##"Checks for functions that return `Result` with an unusually large +`Err`-variant."##, + }, Lint { label: "clippy::result_map_or_into_option", description: r##"Checks for usage of `_.map_or(None, Some)`."##, @@ -6339,7 +6697,7 @@ implements `std::error::Error`."##, Lint { label: "clippy::reversed_empty_ranges", description: r##"Checks for range expressions `x..y` where both `x` and `y` -are constant and `x` is greater or equal to `y`."##, +are constant and `x` is greater to `y`. Also triggers if `x` is equal to `y` when they are conditions to a `for` loop."##, }, Lint { label: "clippy::same_functions_in_if_condition", @@ -6359,6 +6717,16 @@ one from a trait, another not from trait."##, label: "clippy::search_is_some", description: r##"Checks for an iterator or string search (such as `find()`, `position()`, or `rposition()`) followed by a call to `is_some()` or `is_none()`."##, + }, + Lint { + label: "clippy::seek_from_current", + description: r##"Checks an argument of `seek` method of `Seek` trait +and if it start seek from `SeekFrom::Current(0)`, suggests `stream_position` instead."##, + }, + Lint { + label: "clippy::seek_to_start_instead_of_rewind", + description: r##"Checks for jumps to the start of a stream that implements `Seek` +and uses the `seek` method providing `Start` as parameter."##, }, Lint { label: "clippy::self_assignment", @@ -6370,13 +6738,22 @@ one from a trait, another not from trait."##, }, Lint { label: "clippy::self_named_module_files", - description: r##"Checks that module layout uses only mod.rs files."##, + description: r##"Checks that module layout uses only `mod.rs` files."##, }, Lint { label: "clippy::semicolon_if_nothing_returned", description: r##"Looks for blocks of expressions and fires if the last expression returns `()` but is not followed by a semicolon."##, }, + Lint { + label: "clippy::semicolon_inside_block", + description: r##"Suggests moving the semicolon after a block to the inside of the block, after its last +expression."##, + }, + Lint { + label: "clippy::semicolon_outside_block", + description: r##"Suggests moving the semicolon from a block's final expression outside of the block."##, + }, Lint { label: "clippy::separated_literal_suffix", description: r##"Warns if literal suffixes are separated by an underscore. @@ -6419,15 +6796,43 @@ statement."##, implementation of a `std` trait (see [llogiq's blog post](http://llogiq.github.io/2015/07/30/traits.html) for further information) instead of an inherent implementation."##, + }, + Lint { + label: "clippy::should_panic_without_expect", + description: r##"Checks for `#[should_panic]` attributes without specifying the expected panic message."##, + }, + Lint { + label: "clippy::significant_drop_in_scrutinee", + description: r##"Checks for temporaries returned from function calls in a match scrutinee that have the +`clippy::has_significant_drop` attribute."##, + }, + Lint { + label: "clippy::significant_drop_tightening", + description: r##"Searches for elements marked with `#[clippy::has_significant_drop]` that could be early +dropped but are in fact dropped at the end of their scopes. In other words, enforces the +tightening of their possible lifetimes."##, }, Lint { label: "clippy::similar_names", - description: r##"Checks for names that are very similar and thus confusing."##, + description: r##"Checks for names that are very similar and thus confusing. + +Note: this lint looks for similar names throughout each +scope. To allow it, you need to allow it on the scope +level, not on the name that is reported."##, + }, + Lint { + label: "clippy::single_call_fn", + description: r##"Checks for functions that are only used once. Does not lint tests."##, }, Lint { label: "clippy::single_char_add_str", description: r##"Warns when using `push_str`/`insert_str` with a single-character string literal where `push`/`insert` with a `char` would work fine."##, + }, + Lint { + label: "clippy::single_char_lifetime_names", + description: r##"Checks for lifetimes with names which are one character +long."##, }, Lint { label: "clippy::single_char_pattern", @@ -6445,18 +6850,32 @@ where `push`/`insert` with a `char` would work fine."##, Lint { label: "clippy::single_match", description: r##"Checks for matches with a single arm where an `if let` -will usually suffice."##, +will usually suffice. + +This intentionally does not lint if there are comments +inside of the other arm, so as to allow the user to document +why having another explicit pattern with an empty body is necessary, +or because the comments need to be preserved for other reasons."##, }, Lint { label: "clippy::single_match_else", description: r##"Checks for matches with two arms where an `if let else` will usually suffice."##, }, + Lint { + label: "clippy::single_range_in_vec_init", + description: r##"Checks for `Vec` or array initializations that contain only one range."##, + }, Lint { label: "clippy::size_of_in_element_count", description: r##"Detects expressions where `size_of::` or `size_of_val::` is used as a count of elements of type `T`"##, + }, + Lint { + label: "clippy::size_of_ref", + description: r##"Checks for calls to `std::mem::size_of_val()` where the argument is +a reference to a reference."##, }, Lint { label: "clippy::skip_while_next", @@ -6469,9 +6888,17 @@ count of elements of type `T`"##, Lint { label: "clippy::stable_sort_primitive", description: r##"When sorting primitive values (integers, bools, chars, as well -as arrays, slices, and tuples of such items), it is better to +as arrays, slices, and tuples of such items), it is typically better to use an unstable sort than a stable sort."##, }, + Lint { + label: "clippy::std_instead_of_alloc", + description: r##"Finds items imported through `std` when available through `alloc`."##, + }, + Lint { + label: "clippy::std_instead_of_core", + description: r##"Finds items imported through `std` when available through `core`."##, + }, Lint { label: "clippy::str_to_string", description: r##"This lint checks for `.to_string()` method calls on values of type `&str`."##, @@ -6501,6 +6928,10 @@ match."##, description: r##"Checks for the `as_bytes` method called on string literals that contain only ASCII characters."##, }, + Lint { + label: "clippy::string_lit_chars_any", + description: r##"Checks for `.chars().any(|i| i == c)`."##, + }, Lint { label: "clippy::string_slice", description: r##"Checks for slice operations on strings"##, @@ -6532,9 +6963,18 @@ subtracting elements in an Add impl."##, }, Lint { label: "clippy::suspicious_assignment_formatting", - description: r##"Checks for use of the nonexistent `=*`, `=!` and `=-` + description: r##"Checks for usage of the non-existent `=*`, `=!` and `=-` operators."##, }, + Lint { + label: "clippy::suspicious_command_arg_space", + description: r##"Checks for `Command::arg()` invocations that look like they +should be multiple arguments instead, such as `arg(-t ext2)`."##, + }, + Lint { + label: "clippy::suspicious_doc_comments", + description: r##"Detects the use of outer doc comments (`///`, `/**`) followed by a bang (`!`): `///!`"##, + }, Lint { label: "clippy::suspicious_else_formatting", description: r##"Checks for formatting of `else`. It lints if the `else` @@ -6561,12 +7001,24 @@ of binary operators nearby."##, (https://doc.rust-lang.org/std/primitive.str.html#method.splitn) and related functions with either zero or one splits."##, }, + Lint { + label: "clippy::suspicious_to_owned", + description: r##"Checks for the usage of `_.to_owned()`, on a `Cow<'_, _>`."##, + }, Lint { label: "clippy::suspicious_unary_op_formatting", description: r##"Checks the formatting of a unary operator on the right hand side of a binary operator. It lints if there is no space between the binary and unary operators, but there is a space between the unary and its operand."##, }, + Lint { + label: "clippy::suspicious_xor_used_as_pow", + description: r##"Warns for a Bitwise XOR (`^`) operator being probably confused as a powering. It will not trigger if any of the numbers are not in decimal."##, + }, + Lint { + label: "clippy::swap_ptr_to_ref", + description: r##"Checks for calls to `core::mem::swap` where either parameter is derived from a pointer"##, + }, Lint { label: "clippy::tabs_in_doc_comments", description: r##"Checks doc comments for usage of tab characters."##, @@ -6577,12 +7029,13 @@ but there is a space between the unary and its operand."##, assign a value in it."##, }, Lint { - label: "clippy::to_digit_is_some", - description: r##"Checks for `.to_digit(..).is_some()` on `char`s."##, + label: "clippy::tests_outside_test_module", + description: r##"Triggers when a testing function (marked with the `#[test]` attribute) isn't inside a testing module +(marked with `#[cfg(test)]`)."##, }, Lint { - label: "clippy::to_string_in_display", - description: r##"Checks for uses of `to_string()` in `Display` traits."##, + label: "clippy::to_digit_is_some", + description: r##"Checks for `.to_digit(..).is_some()` on `char`s."##, }, Lint { label: "clippy::to_string_in_format_args", @@ -6610,7 +7063,7 @@ in a macro that does formatting."##, }, Lint { label: "clippy::trait_duplication_in_bounds", - description: r##"Checks for cases where generics are being used and multiple + description: r##"Checks for cases where generics or trait objects are being used and multiple syntax specifications for trait bounds are used simultaneously."##, }, Lint { @@ -6633,6 +7086,15 @@ syntax specifications for trait bounds are used simultaneously."##, label: "clippy::transmute_int_to_float", description: r##"Checks for transmutes from an integer to a float."##, }, + Lint { + label: "clippy::transmute_int_to_non_zero", + description: r##"Checks for transmutes from integers to `NonZero*` types, and suggests their `new_unchecked` +method instead."##, + }, + Lint { + label: "clippy::transmute_null_to_fn", + description: r##"Checks for null function pointer creation through transmute."##, + }, Lint { label: "clippy::transmute_num_to_bytes", description: r##"Checks for transmutes from a number to an array of `u8`"##, @@ -6646,6 +7108,11 @@ from a reference to a reference."##, label: "clippy::transmute_ptr_to_ref", description: r##"Checks for transmutes from a pointer to a reference."##, }, + Lint { + label: "clippy::transmute_undefined_repr", + description: r##"Checks for transmutes between types which do not have a representation defined relative to +each other."##, + }, Lint { label: "clippy::transmutes_expressible_as_ptr_casts", description: r##"Checks for transmutes that could be a pointer cast."##, @@ -6654,6 +7121,10 @@ from a reference to a reference."##, label: "clippy::transmuting_null", description: r##"Checks for transmute calls which would receive a null pointer."##, }, + Lint { + label: "clippy::trim_split_whitespace", + description: r##"Warns about calling `str::trim` (or variants) before `str::split_whitespace`."##, + }, Lint { label: "clippy::trivial_regex", description: r##"Checks for trivial [regex](https://crates.io/crates/regex) @@ -6665,25 +7136,51 @@ creation (with `Regex::new`, `RegexBuilder::new`, or `RegexSet::new`)."##, the argument type is `Copy` and small enough to be more efficient to always pass by value."##, }, - Lint { label: "clippy::try_err", description: r##"Checks for usages of `Err(x)?`."## }, + Lint { label: "clippy::try_err", description: r##"Checks for usage of `Err(x)?`."## }, + Lint { + label: "clippy::tuple_array_conversions", + description: r##"Checks for tuple<=>array conversions that are not done with `.into()`."##, + }, Lint { label: "clippy::type_complexity", description: r##"Checks for types used in structs, parameters and `let` declarations above a certain complexity threshold."##, }, + Lint { + label: "clippy::type_id_on_box", + description: r##"Looks for calls to ` as Any>::type_id`."##, + }, Lint { label: "clippy::type_repetition_in_bounds", description: r##"This lint warns about unnecessary type repetitions in trait bounds"##, }, Lint { - label: "clippy::undocumented_unsafe_blocks", - description: r##"Checks for `unsafe` blocks without a `// Safety: ` comment -explaining why the unsafe operations performed inside -the block are safe."##, + label: "clippy::unchecked_duration_subtraction", + description: r##"Lints subtraction between an [`Instant`] and a [`Duration`]."##, }, Lint { - label: "clippy::undropped_manually_drops", - description: r##"Prevents the safe `std::mem::drop` function from being called on `std::mem::ManuallyDrop`."##, + label: "clippy::undocumented_unsafe_blocks", + description: r##"Checks for `unsafe` blocks and impls without a `// SAFETY: ` comment +explaining why the unsafe operations performed inside +the block are safe. + +Note the comment must appear on the line(s) preceding the unsafe block +with nothing appearing in between. The following is ok: +```rust +foo( + // SAFETY: + // This is a valid safety comment + unsafe { *x } +) +``` +But neither of these are: +```rust +// SAFETY: +// This is not a valid safety comment +foo( + /* SAFETY: Neither is this */ unsafe { *x }, +); +```"##, }, Lint { label: "clippy::unicode_not_nfc", @@ -6704,6 +7201,11 @@ that is not equal to its description: r##"Checks for `set_len()` call that creates `Vec` with uninitialized elements. This is commonly caused by calling `set_len()` right after allocating or reserving a buffer with `new()`, `default()`, `with_capacity()`, or `reserve()`."##, + }, + Lint { + label: "clippy::uninlined_format_args", + description: r##"Detect when a variable is not inlined in a format string, +and suggests to inline it."##, }, Lint { label: "clippy::unit_arg", @@ -6721,24 +7223,41 @@ comparisons (like `==` and `<`) and asserts."##, description: r##"Checks for functions that expect closures of type Fn(...) -> Ord where the implemented closure returns the unit type. The lint also suggests to remove the semi-colon at the end of the statement if present."##, + }, + Lint { + label: "clippy::unnecessary_box_returns", + description: r##"Checks for a return type containing a `Box` where `T` implements `Sized` + +The lint ignores `Box` where `T` is larger than `unnecessary_box_size`, +as returning a large `T` directly may be detrimental to performance."##, }, Lint { label: "clippy::unnecessary_cast", - description: r##"Checks for casts to the same type, casts of int literals to integer types -and casts of float literals to float types."##, + description: r##"Checks for casts to the same type, casts of int literals to integer types, casts of float +literals to float types and casts between raw pointers without changing type or constness."##, }, Lint { label: "clippy::unnecessary_filter_map", - description: r##"Checks for `filter_map` calls which could be replaced by `filter` or `map`. + description: r##"Checks for `filter_map` calls that could be replaced by `filter` or `map`. More specifically it checks if the closure provided is only performing one of the filter or map operations and suggests the appropriate option."##, + }, + Lint { + label: "clippy::unnecessary_find_map", + description: r##"Checks for `find_map` calls that could be replaced by `find` or `map`. More +specifically it checks if the closure provided is only performing one of the +find or map operations and suggests the appropriate option."##, }, Lint { label: "clippy::unnecessary_fold", - description: r##"Checks for using `fold` when a more succinct alternative exists. + description: r##"Checks for usage of `fold` when a more succinct alternative exists. Specifically, this checks for `fold`s which could be replaced by `any`, `all`, `sum` or `product`."##, }, + Lint { + label: "clippy::unnecessary_join", + description: r##"Checks for usage of `.collect::>().join()` on iterators."##, + }, Lint { label: "clippy::unnecessary_lazy_evaluations", description: r##"As the counterpart to `or_fun_call`, this lint looks for unnecessary @@ -6750,7 +7269,16 @@ simpler code: - `and_then` to `and` - `or_else` to `or` - `get_or_insert_with` to `get_or_insert` - - `ok_or_else` to `ok_or`"##, + - `ok_or_else` to `ok_or` + - `then` to `then_some` (for msrv >= 1.62.0)"##, + }, + Lint { + label: "clippy::unnecessary_literal_unwrap", + description: r##"Checks for `.unwrap()` related calls on `Result`s and `Option`s that are constructed."##, + }, + Lint { + label: "clippy::unnecessary_map_on_constructor", + description: r##"Suggest removing the use of a may (or map_err) method when an Option or Result is being construted."##, }, Lint { label: "clippy::unnecessary_mut_passed", @@ -6761,6 +7289,19 @@ requires an immutable reference."##, label: "clippy::unnecessary_operation", description: r##"Checks for expression statements that can be reduced to a sub-expression."##, + }, + Lint { + label: "clippy::unnecessary_owned_empty_strings", + description: r##"Detects cases of owned empty strings being passed as an argument to a function expecting `&str`"##, + }, + Lint { + label: "clippy::unnecessary_safety_comment", + description: r##"Checks for `// SAFETY: ` comments on safe code."##, + }, + Lint { + label: "clippy::unnecessary_safety_doc", + description: r##"Checks for the doc comments of publicly visible +safe functions and traits and warns if there is a `# Safety` section."##, }, Lint { label: "clippy::unnecessary_self_imports", @@ -6768,8 +7309,13 @@ sub-expression."##, }, Lint { label: "clippy::unnecessary_sort_by", - description: r##"Detects uses of `Vec::sort_by` passing in a closure + description: r##"Checks for usage of `Vec::sort_by` passing in a closure which compares the two arguments, either directly or indirectly."##, + }, + Lint { + label: "clippy::unnecessary_struct_initialization", + description: r##"Checks for initialization of a `struct` by copying a base without setting +any field."##, }, Lint { label: "clippy::unnecessary_to_owned", @@ -6854,10 +7400,24 @@ types have different ABI, size or alignment."##, label: "clippy::unused_collect", description: r##"Nothing. This lint has been deprecated."##, }, + Lint { + label: "clippy::unused_format_specs", + description: r##"Detects [formatting parameters] that have no effect on the output of +`format!()`, `println!()` or similar macros."##, + }, Lint { label: "clippy::unused_io_amount", description: r##"Checks for unused written/read amount."##, }, + Lint { + label: "clippy::unused_peekable", + description: r##"Checks for the creation of a `peekable` iterator that is never `.peek()`ed"##, + }, + Lint { + label: "clippy::unused_rounding", + description: r##"Detects cases where a whole-number literal float is being rounded, using +the `floor`, `ceil`, or `round` methods."##, + }, Lint { label: "clippy::unused_self", description: r##"Checks methods that contain a `self` argument but don't use it"##, @@ -6876,13 +7436,17 @@ by nibble or byte."##, description: r##"Checks for functions of type `Result` that contain `expect()` or `unwrap()`"##, }, Lint { - label: "clippy::unwrap_or_else_default", - description: r##"Checks for usages of `_.unwrap_or_else(Default::default)` on `Option` and -`Result` values."##, + label: "clippy::unwrap_or_default", + description: r##"Checks for usages of the following functions with an argument that constructs a default value +(e.g., `Default::default` or `String::new`): +- `unwrap_or` +- `unwrap_or_else` +- `or_insert` +- `or_insert_with`"##, }, Lint { label: "clippy::unwrap_used", - description: r##"Checks for `.unwrap()` calls on `Option`s and on `Result`s."##, + description: r##"Checks for `.unwrap()` or `.unwrap_err()` calls on `Result`s and `.unwrap()` call on `Option`s."##, }, Lint { label: "clippy::upper_case_acronyms", @@ -6890,7 +7454,7 @@ by nibble or byte."##, }, Lint { label: "clippy::use_debug", - description: r##"Checks for use of `Debug` formatting. The purpose of this + description: r##"Checks for usage of `Debug` formatting. The purpose of this lint is to catch debugging remnants."##, }, Lint { @@ -6913,10 +7477,17 @@ types before and after the call are the same."##, description: r##"Checks for `extern crate` and `use` items annotated with lint attributes. -This lint permits `#[allow(unused_imports)]`, `#[allow(deprecated)]`, -`#[allow(unreachable_pub)]`, `#[allow(clippy::wildcard_imports)]` and -`#[allow(clippy::enum_glob_use)]` on `use` items and `#[allow(unused_imports)]` on -`extern crate` items with a `#[macro_use]` attribute."##, +This lint permits lint attributes for lints emitted on the items themself. +For `use` items these lints are: +* deprecated +* unreachable_pub +* unused_imports +* clippy::enum_glob_use +* clippy::macro_use_imports +* clippy::wildcard_imports + +For `extern crate` items these lints are: +* `unused_imports` on items with `#[macro_use]`"##, }, Lint { label: "clippy::useless_conversion", @@ -6940,17 +7511,24 @@ and transmutes that could be a cast."##, }, Lint { label: "clippy::useless_vec", - description: r##"Checks for usage of `&vec![..]` when using `&[..]` would + description: r##"Checks for usage of `vec![..]` when using `[..]` would be possible."##, }, Lint { label: "clippy::vec_box", - description: r##"Checks for use of `Vec>` where T: Sized anywhere in the code. + description: r##"Checks for usage of `Vec>` where T: Sized anywhere in the code. Check the [Box documentation](https://doc.rust-lang.org/std/boxed/index.html) for more information."##, }, Lint { label: "clippy::vec_init_then_push", - description: r##"Checks for calls to `push` immediately after creating a new `Vec`."##, + description: r##"Checks for calls to `push` immediately after creating a new `Vec`. + +If the `Vec` is created using `with_capacity` this will only lint if the capacity is a +constant and the number of pushes is greater than or equal to the initial capacity. + +If the `Vec` is extended after the initial sequence of pushes and it was default initialized +then this will only lint after there were at least four pushes. This number may change in +the future."##, }, Lint { label: "clippy::vec_resize_to_zero", @@ -6963,7 +7541,7 @@ to `trailing_zeros`"##, }, Lint { label: "clippy::verbose_file_reads", - description: r##"Checks for use of File::read_to_end and File::read_to_string."##, + description: r##"Checks for usage of File::read_to_end and File::read_to_string."##, }, Lint { label: "clippy::vtable_address_comparisons", @@ -7020,18 +7598,19 @@ print a newline."##, }, Lint { label: "clippy::wrong_self_convention", - description: r##"Checks for methods with certain name prefixes and which -doesn't match how self is taken. The actual rules are: + description: r##"Checks for methods with certain name prefixes or suffixes, and which +do not adhere to standard conventions regarding how `self` is taken. +The actual rules are: -|Prefix |Postfix |`self` taken | `self` type | -|-------|------------|-----------------------|--------------| -|`as_` | none |`&self` or `&mut self` | any | -|`from_`| none | none | any | -|`into_`| none |`self` | any | -|`is_` | none |`&self` or none | any | -|`to_` | `_mut` |`&mut self` | any | -|`to_` | not `_mut` |`self` | `Copy` | -|`to_` | not `_mut` |`&self` | not `Copy` | +|Prefix |Postfix |`self` taken | `self` type | +|-------|------------|-------------------------------|--------------| +|`as_` | none |`&self` or `&mut self` | any | +|`from_`| none | none | any | +|`into_`| none |`self` | any | +|`is_` | none |`&mut self` or `&self` or none | any | +|`to_` | `_mut` |`&mut self` | any | +|`to_` | not `_mut` |`self` | `Copy` | +|`to_` | not `_mut` |`&self` | not `Copy` | Note: Clippy doesn't trigger methods with `to_` prefix in: - Traits definition. @@ -7086,15 +7665,18 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ LintGroup { lint: Lint { label: "clippy::complexity", - description: r##"lint group for: clippy::bind_instead_of_map, clippy::bool_comparison, clippy::borrowed_box, clippy::char_lit_as_u8, clippy::clone_on_copy, clippy::crosspointer_transmute, clippy::deprecated_cfg_attr, clippy::deref_addrof, clippy::derivable_impls, clippy::diverging_sub_expression, clippy::double_comparisons, clippy::double_parens, clippy::duration_subsec, clippy::explicit_counter_loop, clippy::explicit_write, clippy::extra_unused_lifetimes, clippy::filter_map_identity, clippy::filter_next, clippy::flat_map_identity, clippy::get_last_with_len, clippy::identity_op, clippy::inspect_for_each, clippy::int_plus_one, clippy::iter_count, clippy::manual_filter_map, clippy::manual_find_map, clippy::manual_flatten, clippy::manual_split_once, clippy::manual_strip, clippy::manual_swap, clippy::manual_unwrap_or, clippy::map_flatten, clippy::map_identity, clippy::match_as_ref, clippy::match_single_binding, clippy::needless_arbitrary_self_type, clippy::needless_bool, clippy::needless_borrowed_reference, clippy::needless_lifetimes, clippy::needless_option_as_deref, clippy::needless_question_mark, clippy::needless_splitn, clippy::needless_update, clippy::neg_cmp_op_on_partial_ord, clippy::no_effect, clippy::nonminimal_bool, clippy::option_as_ref_deref, clippy::option_filter_map, clippy::option_map_unit_fn, clippy::overflow_check_conditional, clippy::partialeq_ne_impl, clippy::precedence, clippy::ptr_offset_with_cast, clippy::range_zip_with_len, clippy::redundant_closure_call, clippy::redundant_slicing, clippy::ref_in_deref, clippy::repeat_once, clippy::result_map_unit_fn, clippy::search_is_some, clippy::short_circuit_statement, clippy::single_element_loop, clippy::skip_while_next, clippy::string_from_utf8_as_bytes, clippy::strlen_on_c_strings, clippy::temporary_assignment, clippy::too_many_arguments, clippy::transmute_bytes_to_str, clippy::transmute_float_to_int, clippy::transmute_int_to_bool, clippy::transmute_int_to_char, clippy::transmute_int_to_float, clippy::transmute_num_to_bytes, clippy::transmute_ptr_to_ref, clippy::transmutes_expressible_as_ptr_casts, clippy::type_complexity, clippy::unit_arg, clippy::unnecessary_cast, clippy::unnecessary_filter_map, clippy::unnecessary_operation, clippy::unnecessary_sort_by, clippy::unnecessary_unwrap, clippy::unneeded_wildcard_pattern, clippy::useless_asref, clippy::useless_conversion, clippy::useless_format, clippy::vec_box, clippy::while_let_loop, clippy::wildcard_in_or_patterns, clippy::zero_divided_by_zero, clippy::zero_prefixed_literal"##, + description: r##"lint group for: clippy::bind_instead_of_map, clippy::bool_comparison, clippy::borrow_deref_ref, clippy::borrowed_box, clippy::bytes_count_to_len, clippy::char_lit_as_u8, clippy::clone_on_copy, clippy::crosspointer_transmute, clippy::default_constructed_unit_structs, clippy::deprecated_cfg_attr, clippy::deref_addrof, clippy::derivable_impls, clippy::diverging_sub_expression, clippy::double_comparisons, clippy::double_parens, clippy::duration_subsec, clippy::excessive_nesting, clippy::explicit_auto_deref, clippy::explicit_counter_loop, clippy::explicit_write, clippy::extra_unused_lifetimes, clippy::extra_unused_type_parameters, clippy::filter_map_identity, clippy::filter_next, clippy::flat_map_identity, clippy::get_last_with_len, clippy::identity_op, clippy::inspect_for_each, clippy::int_plus_one, clippy::iter_count, clippy::iter_kv_map, clippy::let_with_type_underscore, clippy::manual_filter, clippy::manual_filter_map, clippy::manual_find, clippy::manual_find_map, clippy::manual_flatten, clippy::manual_hash_one, clippy::manual_main_separator_str, clippy::manual_range_patterns, clippy::manual_rem_euclid, clippy::manual_slice_size_calculation, clippy::manual_split_once, clippy::manual_strip, clippy::manual_swap, clippy::manual_unwrap_or, clippy::map_flatten, clippy::map_identity, clippy::match_as_ref, clippy::match_single_binding, clippy::needless_arbitrary_self_type, clippy::needless_bool, clippy::needless_bool_assign, clippy::needless_borrowed_reference, clippy::needless_if, clippy::needless_lifetimes, clippy::needless_match, clippy::needless_option_as_deref, clippy::needless_option_take, clippy::needless_question_mark, clippy::needless_splitn, clippy::needless_update, clippy::neg_cmp_op_on_partial_ord, clippy::no_effect, clippy::nonminimal_bool, clippy::only_used_in_recursion, clippy::option_as_ref_deref, clippy::option_filter_map, clippy::option_map_unit_fn, clippy::or_then_unwrap, clippy::overflow_check_conditional, clippy::partialeq_ne_impl, clippy::precedence, clippy::ptr_offset_with_cast, clippy::range_zip_with_len, clippy::redundant_as_str, clippy::redundant_async_block, clippy::redundant_at_rest_pattern, clippy::redundant_closure_call, clippy::redundant_guards, clippy::redundant_slicing, clippy::repeat_once, clippy::reserve_after_initialization, clippy::result_map_unit_fn, clippy::search_is_some, clippy::seek_from_current, clippy::seek_to_start_instead_of_rewind, clippy::short_circuit_statement, clippy::single_element_loop, clippy::skip_while_next, clippy::string_from_utf8_as_bytes, clippy::strlen_on_c_strings, clippy::temporary_assignment, clippy::too_many_arguments, clippy::transmute_bytes_to_str, clippy::transmute_float_to_int, clippy::transmute_int_to_bool, clippy::transmute_int_to_char, clippy::transmute_int_to_float, clippy::transmute_int_to_non_zero, clippy::transmute_num_to_bytes, clippy::transmute_ptr_to_ref, clippy::transmutes_expressible_as_ptr_casts, clippy::type_complexity, clippy::unit_arg, clippy::unnecessary_cast, clippy::unnecessary_filter_map, clippy::unnecessary_find_map, clippy::unnecessary_literal_unwrap, clippy::unnecessary_map_on_constructor, clippy::unnecessary_operation, clippy::unnecessary_sort_by, clippy::unnecessary_unwrap, clippy::unneeded_wildcard_pattern, clippy::unused_format_specs, clippy::useless_asref, clippy::useless_conversion, clippy::useless_format, clippy::useless_transmute, clippy::vec_box, clippy::while_let_loop, clippy::wildcard_in_or_patterns, clippy::zero_divided_by_zero, clippy::zero_prefixed_literal"##, }, children: &[ "clippy::bind_instead_of_map", "clippy::bool_comparison", + "clippy::borrow_deref_ref", "clippy::borrowed_box", + "clippy::bytes_count_to_len", "clippy::char_lit_as_u8", "clippy::clone_on_copy", "clippy::crosspointer_transmute", + "clippy::default_constructed_unit_structs", "clippy::deprecated_cfg_attr", "clippy::deref_addrof", "clippy::derivable_impls", @@ -7102,9 +7684,12 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::double_comparisons", "clippy::double_parens", "clippy::duration_subsec", + "clippy::excessive_nesting", + "clippy::explicit_auto_deref", "clippy::explicit_counter_loop", "clippy::explicit_write", "clippy::extra_unused_lifetimes", + "clippy::extra_unused_type_parameters", "clippy::filter_map_identity", "clippy::filter_next", "clippy::flat_map_identity", @@ -7113,9 +7698,18 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::inspect_for_each", "clippy::int_plus_one", "clippy::iter_count", + "clippy::iter_kv_map", + "clippy::let_with_type_underscore", + "clippy::manual_filter", "clippy::manual_filter_map", + "clippy::manual_find", "clippy::manual_find_map", "clippy::manual_flatten", + "clippy::manual_hash_one", + "clippy::manual_main_separator_str", + "clippy::manual_range_patterns", + "clippy::manual_rem_euclid", + "clippy::manual_slice_size_calculation", "clippy::manual_split_once", "clippy::manual_strip", "clippy::manual_swap", @@ -7126,29 +7720,41 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::match_single_binding", "clippy::needless_arbitrary_self_type", "clippy::needless_bool", + "clippy::needless_bool_assign", "clippy::needless_borrowed_reference", + "clippy::needless_if", "clippy::needless_lifetimes", + "clippy::needless_match", "clippy::needless_option_as_deref", + "clippy::needless_option_take", "clippy::needless_question_mark", "clippy::needless_splitn", "clippy::needless_update", "clippy::neg_cmp_op_on_partial_ord", "clippy::no_effect", "clippy::nonminimal_bool", + "clippy::only_used_in_recursion", "clippy::option_as_ref_deref", "clippy::option_filter_map", "clippy::option_map_unit_fn", + "clippy::or_then_unwrap", "clippy::overflow_check_conditional", "clippy::partialeq_ne_impl", "clippy::precedence", "clippy::ptr_offset_with_cast", "clippy::range_zip_with_len", + "clippy::redundant_as_str", + "clippy::redundant_async_block", + "clippy::redundant_at_rest_pattern", "clippy::redundant_closure_call", + "clippy::redundant_guards", "clippy::redundant_slicing", - "clippy::ref_in_deref", "clippy::repeat_once", + "clippy::reserve_after_initialization", "clippy::result_map_unit_fn", "clippy::search_is_some", + "clippy::seek_from_current", + "clippy::seek_to_start_instead_of_rewind", "clippy::short_circuit_statement", "clippy::single_element_loop", "clippy::skip_while_next", @@ -7161,6 +7767,7 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::transmute_int_to_bool", "clippy::transmute_int_to_char", "clippy::transmute_int_to_float", + "clippy::transmute_int_to_non_zero", "clippy::transmute_num_to_bytes", "clippy::transmute_ptr_to_ref", "clippy::transmutes_expressible_as_ptr_casts", @@ -7168,13 +7775,18 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::unit_arg", "clippy::unnecessary_cast", "clippy::unnecessary_filter_map", + "clippy::unnecessary_find_map", + "clippy::unnecessary_literal_unwrap", + "clippy::unnecessary_map_on_constructor", "clippy::unnecessary_operation", "clippy::unnecessary_sort_by", "clippy::unnecessary_unwrap", "clippy::unneeded_wildcard_pattern", + "clippy::unused_format_specs", "clippy::useless_asref", "clippy::useless_conversion", "clippy::useless_format", + "clippy::useless_transmute", "clippy::vec_box", "clippy::while_let_loop", "clippy::wildcard_in_or_patterns", @@ -7185,7 +7797,7 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ LintGroup { lint: Lint { label: "clippy::correctness", - description: r##"lint group for: clippy::absurd_extreme_comparisons, clippy::almost_swapped, clippy::approx_constant, clippy::async_yields_async, clippy::bad_bit_mask, clippy::cast_ref_to_mut, clippy::clone_double_ref, clippy::cmp_nan, clippy::deprecated_semver, clippy::derive_hash_xor_eq, clippy::derive_ord_xor_partial_ord, clippy::drop_copy, clippy::drop_ref, clippy::enum_clike_unportable_variant, clippy::eq_op, clippy::erasing_op, clippy::fn_address_comparisons, clippy::forget_copy, clippy::forget_ref, clippy::if_let_mutex, clippy::if_same_then_else, clippy::ifs_same_cond, clippy::ineffective_bit_mask, clippy::infinite_iter, clippy::inherent_to_string_shadow_display, clippy::inline_fn_without_body, clippy::invalid_null_ptr_usage, clippy::invalid_regex, clippy::invisible_characters, clippy::iter_next_loop, clippy::iterator_step_by_zero, clippy::let_underscore_lock, clippy::logic_bug, clippy::match_str_case_mismatch, clippy::mem_replace_with_uninit, clippy::min_max, clippy::mismatched_target_os, clippy::mistyped_literal_suffixes, clippy::modulo_one, clippy::mut_from_ref, clippy::never_loop, clippy::non_octal_unix_permissions, clippy::nonsensical_open_options, clippy::not_unsafe_ptr_arg_deref, clippy::option_env_unwrap, clippy::out_of_bounds_indexing, clippy::panicking_unwrap, clippy::possible_missing_comma, clippy::reversed_empty_ranges, clippy::self_assignment, clippy::serde_api_misuse, clippy::size_of_in_element_count, clippy::suspicious_splitn, clippy::to_string_in_display, clippy::transmuting_null, clippy::undropped_manually_drops, clippy::uninit_assumed_init, clippy::uninit_vec, clippy::unit_cmp, clippy::unit_hash, clippy::unit_return_expecting_ord, clippy::unsound_collection_transmute, clippy::unused_io_amount, clippy::useless_attribute, clippy::vec_resize_to_zero, clippy::vtable_address_comparisons, clippy::while_immutable_condition, clippy::wrong_transmute, clippy::zst_offset"##, + description: r##"lint group for: clippy::absurd_extreme_comparisons, clippy::almost_swapped, clippy::approx_constant, clippy::async_yields_async, clippy::bad_bit_mask, clippy::cast_slice_different_sizes, clippy::deprecated_semver, clippy::derive_ord_xor_partial_ord, clippy::derived_hash_with_manual_eq, clippy::enum_clike_unportable_variant, clippy::eq_op, clippy::erasing_op, clippy::fn_address_comparisons, clippy::if_let_mutex, clippy::if_same_then_else, clippy::ifs_same_cond, clippy::impossible_comparisons, clippy::ineffective_bit_mask, clippy::infinite_iter, clippy::inherent_to_string_shadow_display, clippy::inline_fn_without_body, clippy::invalid_null_ptr_usage, clippy::invalid_regex, clippy::invisible_characters, clippy::iter_next_loop, clippy::iter_skip_zero, clippy::iterator_step_by_zero, clippy::let_underscore_lock, clippy::match_str_case_mismatch, clippy::mem_replace_with_uninit, clippy::min_max, clippy::mismatched_target_os, clippy::mistyped_literal_suffixes, clippy::modulo_one, clippy::mut_from_ref, clippy::never_loop, clippy::non_octal_unix_permissions, clippy::nonsensical_open_options, clippy::not_unsafe_ptr_arg_deref, clippy::option_env_unwrap, clippy::out_of_bounds_indexing, clippy::overly_complex_bool_expr, clippy::panicking_unwrap, clippy::possible_missing_comma, clippy::read_line_without_trim, clippy::read_zero_byte_vec, clippy::recursive_format_impl, clippy::redundant_comparisons, clippy::redundant_locals, clippy::reversed_empty_ranges, clippy::self_assignment, clippy::serde_api_misuse, clippy::size_of_in_element_count, clippy::suspicious_splitn, clippy::transmute_null_to_fn, clippy::transmuting_null, clippy::uninit_assumed_init, clippy::uninit_vec, clippy::unit_cmp, clippy::unit_hash, clippy::unit_return_expecting_ord, clippy::unsound_collection_transmute, clippy::unused_io_amount, clippy::useless_attribute, clippy::vec_resize_to_zero, clippy::vtable_address_comparisons, clippy::while_immutable_condition, clippy::wrong_transmute, clippy::zst_offset"##, }, children: &[ "clippy::absurd_extreme_comparisons", @@ -7193,23 +7805,18 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::approx_constant", "clippy::async_yields_async", "clippy::bad_bit_mask", - "clippy::cast_ref_to_mut", - "clippy::clone_double_ref", - "clippy::cmp_nan", + "clippy::cast_slice_different_sizes", "clippy::deprecated_semver", - "clippy::derive_hash_xor_eq", "clippy::derive_ord_xor_partial_ord", - "clippy::drop_copy", - "clippy::drop_ref", + "clippy::derived_hash_with_manual_eq", "clippy::enum_clike_unportable_variant", "clippy::eq_op", "clippy::erasing_op", "clippy::fn_address_comparisons", - "clippy::forget_copy", - "clippy::forget_ref", "clippy::if_let_mutex", "clippy::if_same_then_else", "clippy::ifs_same_cond", + "clippy::impossible_comparisons", "clippy::ineffective_bit_mask", "clippy::infinite_iter", "clippy::inherent_to_string_shadow_display", @@ -7218,9 +7825,9 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::invalid_regex", "clippy::invisible_characters", "clippy::iter_next_loop", + "clippy::iter_skip_zero", "clippy::iterator_step_by_zero", "clippy::let_underscore_lock", - "clippy::logic_bug", "clippy::match_str_case_mismatch", "clippy::mem_replace_with_uninit", "clippy::min_max", @@ -7234,16 +7841,21 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::not_unsafe_ptr_arg_deref", "clippy::option_env_unwrap", "clippy::out_of_bounds_indexing", + "clippy::overly_complex_bool_expr", "clippy::panicking_unwrap", "clippy::possible_missing_comma", + "clippy::read_line_without_trim", + "clippy::read_zero_byte_vec", + "clippy::recursive_format_impl", + "clippy::redundant_comparisons", + "clippy::redundant_locals", "clippy::reversed_empty_ranges", "clippy::self_assignment", "clippy::serde_api_misuse", "clippy::size_of_in_element_count", "clippy::suspicious_splitn", - "clippy::to_string_in_display", + "clippy::transmute_null_to_fn", "clippy::transmuting_null", - "clippy::undropped_manually_drops", "clippy::uninit_assumed_init", "clippy::uninit_vec", "clippy::unit_cmp", @@ -7286,45 +7898,65 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ LintGroup { lint: Lint { label: "clippy::nursery", - description: r##"lint group for: clippy::branches_sharing_code, clippy::cognitive_complexity, clippy::debug_assert_with_mut_call, clippy::disallowed_methods, clippy::disallowed_types, clippy::empty_line_after_outer_attr, clippy::equatable_if_let, clippy::fallible_impl_from, clippy::future_not_send, clippy::imprecise_flops, clippy::index_refutable_slice, clippy::missing_const_for_fn, clippy::mutex_integer, clippy::non_send_fields_in_send_ty, clippy::nonstandard_macro_braces, clippy::option_if_let_else, clippy::path_buf_push_overwrite, clippy::redundant_pub_crate, clippy::string_lit_as_bytes, clippy::suboptimal_flops, clippy::suspicious_operation_groupings, clippy::trailing_empty_array, clippy::trivial_regex, clippy::use_self, clippy::useless_let_if_seq, clippy::useless_transmute"##, + description: r##"lint group for: clippy::as_ptr_cast_mut, clippy::branches_sharing_code, clippy::clear_with_drain, clippy::cognitive_complexity, clippy::collection_is_never_read, clippy::debug_assert_with_mut_call, clippy::derive_partial_eq_without_eq, clippy::empty_line_after_doc_comments, clippy::empty_line_after_outer_attr, clippy::equatable_if_let, clippy::fallible_impl_from, clippy::future_not_send, clippy::implied_bounds_in_impls, clippy::imprecise_flops, clippy::iter_on_empty_collections, clippy::iter_on_single_items, clippy::iter_with_drain, clippy::large_stack_frames, clippy::manual_clamp, clippy::missing_const_for_fn, clippy::mutex_integer, clippy::needless_collect, clippy::non_send_fields_in_send_ty, clippy::nonstandard_macro_braces, clippy::option_if_let_else, clippy::or_fun_call, clippy::path_buf_push_overwrite, clippy::readonly_write_lock, clippy::redundant_clone, clippy::redundant_pub_crate, clippy::significant_drop_in_scrutinee, clippy::significant_drop_tightening, clippy::string_lit_as_bytes, clippy::suboptimal_flops, clippy::suspicious_operation_groupings, clippy::trailing_empty_array, clippy::trait_duplication_in_bounds, clippy::transmute_undefined_repr, clippy::trivial_regex, clippy::tuple_array_conversions, clippy::type_repetition_in_bounds, clippy::unnecessary_struct_initialization, clippy::unused_peekable, clippy::unused_rounding, clippy::use_self, clippy::useless_let_if_seq"##, }, children: &[ + "clippy::as_ptr_cast_mut", "clippy::branches_sharing_code", + "clippy::clear_with_drain", "clippy::cognitive_complexity", + "clippy::collection_is_never_read", "clippy::debug_assert_with_mut_call", - "clippy::disallowed_methods", - "clippy::disallowed_types", + "clippy::derive_partial_eq_without_eq", + "clippy::empty_line_after_doc_comments", "clippy::empty_line_after_outer_attr", "clippy::equatable_if_let", "clippy::fallible_impl_from", "clippy::future_not_send", + "clippy::implied_bounds_in_impls", "clippy::imprecise_flops", - "clippy::index_refutable_slice", + "clippy::iter_on_empty_collections", + "clippy::iter_on_single_items", + "clippy::iter_with_drain", + "clippy::large_stack_frames", + "clippy::manual_clamp", "clippy::missing_const_for_fn", "clippy::mutex_integer", + "clippy::needless_collect", "clippy::non_send_fields_in_send_ty", "clippy::nonstandard_macro_braces", "clippy::option_if_let_else", + "clippy::or_fun_call", "clippy::path_buf_push_overwrite", + "clippy::readonly_write_lock", + "clippy::redundant_clone", "clippy::redundant_pub_crate", + "clippy::significant_drop_in_scrutinee", + "clippy::significant_drop_tightening", "clippy::string_lit_as_bytes", "clippy::suboptimal_flops", "clippy::suspicious_operation_groupings", "clippy::trailing_empty_array", + "clippy::trait_duplication_in_bounds", + "clippy::transmute_undefined_repr", "clippy::trivial_regex", + "clippy::tuple_array_conversions", + "clippy::type_repetition_in_bounds", + "clippy::unnecessary_struct_initialization", + "clippy::unused_peekable", + "clippy::unused_rounding", "clippy::use_self", "clippy::useless_let_if_seq", - "clippy::useless_transmute", ], }, LintGroup { lint: Lint { label: "clippy::pedantic", - description: r##"lint group for: clippy::await_holding_lock, clippy::await_holding_refcell_ref, clippy::case_sensitive_file_extension_comparisons, clippy::cast_lossless, clippy::cast_possible_truncation, clippy::cast_possible_wrap, clippy::cast_precision_loss, clippy::cast_ptr_alignment, clippy::cast_sign_loss, clippy::checked_conversions, clippy::cloned_instead_of_copied, clippy::copy_iterator, clippy::default_trait_access, clippy::doc_markdown, clippy::empty_enum, clippy::enum_glob_use, clippy::expl_impl_clone_on_copy, clippy::explicit_deref_methods, clippy::explicit_into_iter_loop, clippy::explicit_iter_loop, clippy::filter_map_next, clippy::flat_map_option, clippy::float_cmp, clippy::fn_params_excessive_bools, clippy::from_iter_instead_of_collect, clippy::if_not_else, clippy::implicit_clone, clippy::implicit_hasher, clippy::implicit_saturating_sub, clippy::inconsistent_struct_constructor, clippy::inefficient_to_string, clippy::inline_always, clippy::invalid_upcast_comparisons, clippy::items_after_statements, clippy::iter_not_returning_iterator, clippy::large_digit_groups, clippy::large_stack_arrays, clippy::large_types_passed_by_value, clippy::let_underscore_drop, clippy::let_unit_value, clippy::linkedlist, clippy::macro_use_imports, clippy::manual_assert, clippy::manual_ok_or, clippy::many_single_char_names, clippy::map_unwrap_or, clippy::match_bool, clippy::match_on_vec_items, clippy::match_same_arms, clippy::match_wild_err_arm, clippy::match_wildcard_for_single_variants, clippy::maybe_infinite_iter, clippy::missing_errors_doc, clippy::missing_panics_doc, clippy::module_name_repetitions, clippy::must_use_candidate, clippy::mut_mut, clippy::naive_bytecount, clippy::needless_bitwise_bool, clippy::needless_continue, clippy::needless_for_each, clippy::needless_pass_by_value, clippy::no_effect_underscore_binding, clippy::option_option, clippy::ptr_as_ptr, clippy::range_minus_one, clippy::range_plus_one, clippy::redundant_closure_for_method_calls, clippy::redundant_else, clippy::ref_binding_to_reference, clippy::ref_option_ref, clippy::same_functions_in_if_condition, clippy::semicolon_if_nothing_returned, clippy::similar_names, clippy::single_match_else, clippy::string_add_assign, clippy::struct_excessive_bools, clippy::too_many_lines, clippy::trait_duplication_in_bounds, clippy::transmute_ptr_to_ptr, clippy::trivially_copy_pass_by_ref, clippy::type_repetition_in_bounds, clippy::unicode_not_nfc, clippy::unnecessary_wraps, clippy::unnested_or_patterns, clippy::unreadable_literal, clippy::unsafe_derive_deserialize, clippy::unused_async, clippy::unused_self, clippy::used_underscore_binding, clippy::verbose_bit_mask, clippy::wildcard_imports, clippy::zero_sized_map_values"##, + description: r##"lint group for: clippy::bool_to_int_with_if, clippy::borrow_as_ptr, clippy::case_sensitive_file_extension_comparisons, clippy::cast_lossless, clippy::cast_possible_truncation, clippy::cast_possible_wrap, clippy::cast_precision_loss, clippy::cast_ptr_alignment, clippy::cast_sign_loss, clippy::checked_conversions, clippy::cloned_instead_of_copied, clippy::copy_iterator, clippy::default_trait_access, clippy::doc_link_with_quotes, clippy::doc_markdown, clippy::empty_enum, clippy::enum_glob_use, clippy::expl_impl_clone_on_copy, clippy::explicit_deref_methods, clippy::explicit_into_iter_loop, clippy::explicit_iter_loop, clippy::filter_map_next, clippy::flat_map_option, clippy::float_cmp, clippy::fn_params_excessive_bools, clippy::from_iter_instead_of_collect, clippy::if_not_else, clippy::ignored_unit_patterns, clippy::implicit_clone, clippy::implicit_hasher, clippy::inconsistent_struct_constructor, clippy::index_refutable_slice, clippy::inefficient_to_string, clippy::inline_always, clippy::invalid_upcast_comparisons, clippy::items_after_statements, clippy::iter_not_returning_iterator, clippy::large_digit_groups, clippy::large_futures, clippy::large_stack_arrays, clippy::large_types_passed_by_value, clippy::linkedlist, clippy::macro_use_imports, clippy::manual_assert, clippy::manual_instant_elapsed, clippy::manual_let_else, clippy::manual_ok_or, clippy::manual_string_new, clippy::many_single_char_names, clippy::map_unwrap_or, clippy::match_bool, clippy::match_on_vec_items, clippy::match_same_arms, clippy::match_wild_err_arm, clippy::match_wildcard_for_single_variants, clippy::maybe_infinite_iter, clippy::mismatching_type_param_order, clippy::missing_errors_doc, clippy::missing_fields_in_debug, clippy::missing_panics_doc, clippy::module_name_repetitions, clippy::must_use_candidate, clippy::mut_mut, clippy::naive_bytecount, clippy::needless_bitwise_bool, clippy::needless_continue, clippy::needless_for_each, clippy::needless_pass_by_value, clippy::needless_raw_string_hashes, clippy::no_effect_underscore_binding, clippy::no_mangle_with_rust_abi, clippy::option_option, clippy::ptr_as_ptr, clippy::ptr_cast_constness, clippy::range_minus_one, clippy::range_plus_one, clippy::redundant_closure_for_method_calls, clippy::redundant_else, clippy::ref_binding_to_reference, clippy::ref_option_ref, clippy::return_self_not_must_use, clippy::same_functions_in_if_condition, clippy::semicolon_if_nothing_returned, clippy::should_panic_without_expect, clippy::similar_names, clippy::single_match_else, clippy::stable_sort_primitive, clippy::string_add_assign, clippy::struct_excessive_bools, clippy::too_many_lines, clippy::transmute_ptr_to_ptr, clippy::trivially_copy_pass_by_ref, clippy::unchecked_duration_subtraction, clippy::unicode_not_nfc, clippy::uninlined_format_args, clippy::unnecessary_box_returns, clippy::unnecessary_join, clippy::unnecessary_wraps, clippy::unnested_or_patterns, clippy::unreadable_literal, clippy::unsafe_derive_deserialize, clippy::unused_async, clippy::unused_self, clippy::used_underscore_binding, clippy::verbose_bit_mask, clippy::wildcard_imports, clippy::zero_sized_map_values"##, }, children: &[ - "clippy::await_holding_lock", - "clippy::await_holding_refcell_ref", + "clippy::bool_to_int_with_if", + "clippy::borrow_as_ptr", "clippy::case_sensitive_file_extension_comparisons", "clippy::cast_lossless", "clippy::cast_possible_truncation", @@ -7336,6 +7968,7 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::cloned_instead_of_copied", "clippy::copy_iterator", "clippy::default_trait_access", + "clippy::doc_link_with_quotes", "clippy::doc_markdown", "clippy::empty_enum", "clippy::enum_glob_use", @@ -7349,24 +7982,27 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::fn_params_excessive_bools", "clippy::from_iter_instead_of_collect", "clippy::if_not_else", + "clippy::ignored_unit_patterns", "clippy::implicit_clone", "clippy::implicit_hasher", - "clippy::implicit_saturating_sub", "clippy::inconsistent_struct_constructor", + "clippy::index_refutable_slice", "clippy::inefficient_to_string", "clippy::inline_always", "clippy::invalid_upcast_comparisons", "clippy::items_after_statements", "clippy::iter_not_returning_iterator", "clippy::large_digit_groups", + "clippy::large_futures", "clippy::large_stack_arrays", "clippy::large_types_passed_by_value", - "clippy::let_underscore_drop", - "clippy::let_unit_value", "clippy::linkedlist", "clippy::macro_use_imports", "clippy::manual_assert", + "clippy::manual_instant_elapsed", + "clippy::manual_let_else", "clippy::manual_ok_or", + "clippy::manual_string_new", "clippy::many_single_char_names", "clippy::map_unwrap_or", "clippy::match_bool", @@ -7375,7 +8011,9 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::match_wild_err_arm", "clippy::match_wildcard_for_single_variants", "clippy::maybe_infinite_iter", + "clippy::mismatching_type_param_order", "clippy::missing_errors_doc", + "clippy::missing_fields_in_debug", "clippy::missing_panics_doc", "clippy::module_name_repetitions", "clippy::must_use_candidate", @@ -7385,27 +8023,35 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::needless_continue", "clippy::needless_for_each", "clippy::needless_pass_by_value", + "clippy::needless_raw_string_hashes", "clippy::no_effect_underscore_binding", + "clippy::no_mangle_with_rust_abi", "clippy::option_option", "clippy::ptr_as_ptr", + "clippy::ptr_cast_constness", "clippy::range_minus_one", "clippy::range_plus_one", "clippy::redundant_closure_for_method_calls", "clippy::redundant_else", "clippy::ref_binding_to_reference", "clippy::ref_option_ref", + "clippy::return_self_not_must_use", "clippy::same_functions_in_if_condition", "clippy::semicolon_if_nothing_returned", + "clippy::should_panic_without_expect", "clippy::similar_names", "clippy::single_match_else", + "clippy::stable_sort_primitive", "clippy::string_add_assign", "clippy::struct_excessive_bools", "clippy::too_many_lines", - "clippy::trait_duplication_in_bounds", "clippy::transmute_ptr_to_ptr", "clippy::trivially_copy_pass_by_ref", - "clippy::type_repetition_in_bounds", + "clippy::unchecked_duration_subtraction", "clippy::unicode_not_nfc", + "clippy::uninlined_format_args", + "clippy::unnecessary_box_returns", + "clippy::unnecessary_join", "clippy::unnecessary_wraps", "clippy::unnested_or_patterns", "clippy::unreadable_literal", @@ -7421,29 +8067,33 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ LintGroup { lint: Lint { label: "clippy::perf", - description: r##"lint group for: clippy::box_collection, clippy::boxed_local, clippy::cmp_owned, clippy::expect_fun_call, clippy::extend_with_drain, clippy::format_in_format_args, clippy::iter_nth, clippy::large_const_arrays, clippy::large_enum_variant, clippy::manual_memcpy, clippy::manual_str_repeat, clippy::map_entry, clippy::mutex_atomic, clippy::needless_collect, clippy::or_fun_call, clippy::redundant_allocation, clippy::redundant_clone, clippy::single_char_pattern, clippy::slow_vector_initialization, clippy::stable_sort_primitive, clippy::to_string_in_format_args, clippy::unnecessary_to_owned, clippy::useless_vec, clippy::vec_init_then_push"##, + description: r##"lint group for: clippy::box_collection, clippy::box_default, clippy::boxed_local, clippy::cmp_owned, clippy::collapsible_str_replace, clippy::drain_collect, clippy::expect_fun_call, clippy::extend_with_drain, clippy::format_collect, clippy::format_in_format_args, clippy::iter_nth, clippy::iter_overeager_cloned, clippy::large_const_arrays, clippy::large_enum_variant, clippy::manual_memcpy, clippy::manual_retain, clippy::manual_str_repeat, clippy::manual_try_fold, clippy::map_entry, clippy::missing_spin_loop, clippy::redundant_allocation, clippy::result_large_err, clippy::single_char_pattern, clippy::slow_vector_initialization, clippy::to_string_in_format_args, clippy::unnecessary_to_owned, clippy::useless_vec, clippy::vec_init_then_push"##, }, children: &[ "clippy::box_collection", + "clippy::box_default", "clippy::boxed_local", "clippy::cmp_owned", + "clippy::collapsible_str_replace", + "clippy::drain_collect", "clippy::expect_fun_call", "clippy::extend_with_drain", + "clippy::format_collect", "clippy::format_in_format_args", "clippy::iter_nth", + "clippy::iter_overeager_cloned", "clippy::large_const_arrays", "clippy::large_enum_variant", "clippy::manual_memcpy", + "clippy::manual_retain", "clippy::manual_str_repeat", + "clippy::manual_try_fold", "clippy::map_entry", - "clippy::mutex_atomic", - "clippy::needless_collect", - "clippy::or_fun_call", + "clippy::missing_spin_loop", "clippy::redundant_allocation", - "clippy::redundant_clone", + "clippy::result_large_err", "clippy::single_char_pattern", "clippy::slow_vector_initialization", - "clippy::stable_sort_primitive", "clippy::to_string_in_format_args", "clippy::unnecessary_to_owned", "clippy::useless_vec", @@ -7453,17 +8103,30 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ LintGroup { lint: Lint { label: "clippy::restriction", - description: r##"lint group for: clippy::as_conversions, clippy::clone_on_ref_ptr, clippy::create_dir, clippy::dbg_macro, clippy::decimal_literal_representation, clippy::default_numeric_fallback, clippy::disallowed_script_idents, clippy::else_if_without_else, clippy::exhaustive_enums, clippy::exhaustive_structs, clippy::exit, clippy::expect_used, clippy::filetype_is_file, clippy::float_arithmetic, clippy::float_cmp_const, clippy::fn_to_numeric_cast_any, clippy::get_unwrap, clippy::if_then_some_else_none, clippy::implicit_return, clippy::indexing_slicing, clippy::inline_asm_x86_att_syntax, clippy::inline_asm_x86_intel_syntax, clippy::integer_arithmetic, clippy::integer_division, clippy::let_underscore_must_use, clippy::lossy_float_literal, clippy::map_err_ignore, clippy::mem_forget, clippy::missing_docs_in_private_items, clippy::missing_enforced_import_renames, clippy::missing_inline_in_public_items, clippy::mod_module_files, clippy::modulo_arithmetic, clippy::multiple_inherent_impl, clippy::non_ascii_literal, clippy::panic, clippy::panic_in_result_fn, clippy::pattern_type_mismatch, clippy::print_stderr, clippy::print_stdout, clippy::rc_buffer, clippy::rc_mutex, clippy::rest_pat_in_fully_bound_structs, clippy::same_name_method, clippy::self_named_module_files, clippy::separated_literal_suffix, clippy::shadow_reuse, clippy::shadow_same, clippy::shadow_unrelated, clippy::str_to_string, clippy::string_add, clippy::string_slice, clippy::string_to_string, clippy::todo, clippy::undocumented_unsafe_blocks, clippy::unimplemented, clippy::unnecessary_self_imports, clippy::unneeded_field_pattern, clippy::unreachable, clippy::unseparated_literal_suffix, clippy::unwrap_in_result, clippy::unwrap_used, clippy::use_debug, clippy::verbose_file_reads, clippy::wildcard_enum_match_arm"##, + description: r##"lint group for: clippy::absolute_paths, clippy::alloc_instead_of_core, clippy::allow_attributes, clippy::allow_attributes_without_reason, clippy::arithmetic_side_effects, clippy::as_conversions, clippy::as_underscore, clippy::assertions_on_result_states, clippy::big_endian_bytes, clippy::clone_on_ref_ptr, clippy::create_dir, clippy::dbg_macro, clippy::decimal_literal_representation, clippy::default_numeric_fallback, clippy::default_union_representation, clippy::deref_by_slicing, clippy::disallowed_script_idents, clippy::else_if_without_else, clippy::empty_drop, clippy::empty_structs_with_brackets, clippy::error_impl_error, clippy::exhaustive_enums, clippy::exhaustive_structs, clippy::exit, clippy::expect_used, clippy::filetype_is_file, clippy::float_arithmetic, clippy::float_cmp_const, clippy::fn_to_numeric_cast_any, clippy::format_push_string, clippy::get_unwrap, clippy::host_endian_bytes, clippy::if_then_some_else_none, clippy::impl_trait_in_params, clippy::implicit_return, clippy::indexing_slicing, clippy::inline_asm_x86_att_syntax, clippy::inline_asm_x86_intel_syntax, clippy::integer_division, clippy::large_include_file, clippy::let_underscore_must_use, clippy::let_underscore_untyped, clippy::little_endian_bytes, clippy::lossy_float_literal, clippy::map_err_ignore, clippy::mem_forget, clippy::min_ident_chars, clippy::missing_assert_message, clippy::missing_asserts_for_indexing, clippy::missing_docs_in_private_items, clippy::missing_enforced_import_renames, clippy::missing_inline_in_public_items, clippy::missing_trait_methods, clippy::mixed_read_write_in_expression, clippy::mod_module_files, clippy::modulo_arithmetic, clippy::multiple_inherent_impl, clippy::multiple_unsafe_ops_per_block, clippy::mutex_atomic, clippy::needless_raw_strings, clippy::non_ascii_literal, clippy::panic, clippy::panic_in_result_fn, clippy::partial_pub_fields, clippy::pattern_type_mismatch, clippy::print_stderr, clippy::print_stdout, clippy::pub_use, clippy::pub_with_shorthand, clippy::pub_without_shorthand, clippy::question_mark_used, clippy::rc_buffer, clippy::rc_mutex, clippy::redundant_type_annotations, clippy::ref_patterns, clippy::rest_pat_in_fully_bound_structs, clippy::same_name_method, clippy::self_named_module_files, clippy::semicolon_inside_block, clippy::semicolon_outside_block, clippy::separated_literal_suffix, clippy::shadow_reuse, clippy::shadow_same, clippy::shadow_unrelated, clippy::single_call_fn, clippy::single_char_lifetime_names, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::str_to_string, clippy::string_add, clippy::string_lit_chars_any, clippy::string_slice, clippy::string_to_string, clippy::suspicious_xor_used_as_pow, clippy::tests_outside_test_module, clippy::todo, clippy::try_err, clippy::undocumented_unsafe_blocks, clippy::unimplemented, clippy::unnecessary_safety_comment, clippy::unnecessary_safety_doc, clippy::unnecessary_self_imports, clippy::unneeded_field_pattern, clippy::unreachable, clippy::unseparated_literal_suffix, clippy::unwrap_in_result, clippy::unwrap_used, clippy::use_debug, clippy::verbose_file_reads, clippy::wildcard_enum_match_arm"##, }, children: &[ + "clippy::absolute_paths", + "clippy::alloc_instead_of_core", + "clippy::allow_attributes", + "clippy::allow_attributes_without_reason", + "clippy::arithmetic_side_effects", "clippy::as_conversions", + "clippy::as_underscore", + "clippy::assertions_on_result_states", + "clippy::big_endian_bytes", "clippy::clone_on_ref_ptr", "clippy::create_dir", "clippy::dbg_macro", "clippy::decimal_literal_representation", "clippy::default_numeric_fallback", + "clippy::default_union_representation", + "clippy::deref_by_slicing", "clippy::disallowed_script_idents", "clippy::else_if_without_else", + "clippy::empty_drop", + "clippy::empty_structs_with_brackets", + "clippy::error_impl_error", "clippy::exhaustive_enums", "clippy::exhaustive_structs", "clippy::exit", @@ -7472,46 +8135,78 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::float_arithmetic", "clippy::float_cmp_const", "clippy::fn_to_numeric_cast_any", + "clippy::format_push_string", "clippy::get_unwrap", + "clippy::host_endian_bytes", "clippy::if_then_some_else_none", + "clippy::impl_trait_in_params", "clippy::implicit_return", "clippy::indexing_slicing", "clippy::inline_asm_x86_att_syntax", "clippy::inline_asm_x86_intel_syntax", - "clippy::integer_arithmetic", "clippy::integer_division", + "clippy::large_include_file", "clippy::let_underscore_must_use", + "clippy::let_underscore_untyped", + "clippy::little_endian_bytes", "clippy::lossy_float_literal", "clippy::map_err_ignore", "clippy::mem_forget", + "clippy::min_ident_chars", + "clippy::missing_assert_message", + "clippy::missing_asserts_for_indexing", "clippy::missing_docs_in_private_items", "clippy::missing_enforced_import_renames", "clippy::missing_inline_in_public_items", + "clippy::missing_trait_methods", + "clippy::mixed_read_write_in_expression", "clippy::mod_module_files", "clippy::modulo_arithmetic", "clippy::multiple_inherent_impl", + "clippy::multiple_unsafe_ops_per_block", + "clippy::mutex_atomic", + "clippy::needless_raw_strings", "clippy::non_ascii_literal", "clippy::panic", "clippy::panic_in_result_fn", + "clippy::partial_pub_fields", "clippy::pattern_type_mismatch", "clippy::print_stderr", "clippy::print_stdout", + "clippy::pub_use", + "clippy::pub_with_shorthand", + "clippy::pub_without_shorthand", + "clippy::question_mark_used", "clippy::rc_buffer", "clippy::rc_mutex", + "clippy::redundant_type_annotations", + "clippy::ref_patterns", "clippy::rest_pat_in_fully_bound_structs", "clippy::same_name_method", "clippy::self_named_module_files", + "clippy::semicolon_inside_block", + "clippy::semicolon_outside_block", "clippy::separated_literal_suffix", "clippy::shadow_reuse", "clippy::shadow_same", "clippy::shadow_unrelated", + "clippy::single_call_fn", + "clippy::single_char_lifetime_names", + "clippy::std_instead_of_alloc", + "clippy::std_instead_of_core", "clippy::str_to_string", "clippy::string_add", + "clippy::string_lit_chars_any", "clippy::string_slice", "clippy::string_to_string", + "clippy::suspicious_xor_used_as_pow", + "clippy::tests_outside_test_module", "clippy::todo", + "clippy::try_err", "clippy::undocumented_unsafe_blocks", "clippy::unimplemented", + "clippy::unnecessary_safety_comment", + "clippy::unnecessary_safety_doc", "clippy::unnecessary_self_imports", "clippy::unneeded_field_pattern", "clippy::unreachable", @@ -7526,12 +8221,11 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ LintGroup { lint: Lint { label: "clippy::style", - description: r##"lint group for: clippy::assertions_on_constants, clippy::assign_op_pattern, clippy::blacklisted_name, clippy::blocks_in_if_conditions, clippy::bool_assert_comparison, clippy::borrow_interior_mutable_const, clippy::builtin_type_shadow, clippy::bytes_nth, clippy::chars_last_cmp, clippy::chars_next_cmp, clippy::cmp_null, clippy::collapsible_else_if, clippy::collapsible_if, clippy::collapsible_match, clippy::comparison_chain, clippy::comparison_to_empty, clippy::declare_interior_mutable_const, clippy::double_must_use, clippy::double_neg, clippy::duplicate_underscore_argument, clippy::enum_variant_names, clippy::excessive_precision, clippy::field_reassign_with_default, clippy::fn_to_numeric_cast, clippy::fn_to_numeric_cast_with_truncation, clippy::for_kv_map, clippy::from_over_into, clippy::from_str_radix_10, clippy::inconsistent_digit_grouping, clippy::infallible_destructuring_match, clippy::inherent_to_string, clippy::into_iter_on_ref, clippy::iter_cloned_collect, clippy::iter_next_slice, clippy::iter_nth_zero, clippy::iter_skip_next, clippy::just_underscores_and_digits, clippy::len_without_is_empty, clippy::len_zero, clippy::let_and_return, clippy::main_recursion, clippy::manual_async_fn, clippy::manual_map, clippy::manual_non_exhaustive, clippy::manual_range_contains, clippy::manual_saturating_arithmetic, clippy::map_clone, clippy::map_collect_result_unit, clippy::match_like_matches_macro, clippy::match_overlapping_arm, clippy::match_ref_pats, clippy::match_result_ok, clippy::mem_replace_option_with_none, clippy::mem_replace_with_default, clippy::missing_safety_doc, clippy::mixed_case_hex_literals, clippy::module_inception, clippy::must_use_unit, clippy::mut_mutex_lock, clippy::needless_borrow, clippy::needless_doctest_main, clippy::needless_late_init, clippy::needless_range_loop, clippy::needless_return, clippy::neg_multiply, clippy::new_ret_no_self, clippy::new_without_default, clippy::ok_expect, clippy::op_ref, clippy::option_map_or_none, clippy::print_literal, clippy::print_with_newline, clippy::println_empty_string, clippy::ptr_arg, clippy::ptr_eq, clippy::question_mark, clippy::redundant_closure, clippy::redundant_field_names, clippy::redundant_pattern, clippy::redundant_pattern_matching, clippy::redundant_static_lifetimes, clippy::result_map_or_into_option, clippy::result_unit_err, clippy::same_item_push, clippy::self_named_constructors, clippy::should_implement_trait, clippy::single_char_add_str, clippy::single_component_path_imports, clippy::single_match, clippy::string_extend_chars, clippy::tabs_in_doc_comments, clippy::to_digit_is_some, clippy::toplevel_ref_arg, clippy::try_err, clippy::unnecessary_fold, clippy::unnecessary_lazy_evaluations, clippy::unnecessary_mut_passed, clippy::unsafe_removed_from_name, clippy::unused_unit, clippy::unusual_byte_groupings, clippy::unwrap_or_else_default, clippy::upper_case_acronyms, clippy::while_let_on_iterator, clippy::write_literal, clippy::write_with_newline, clippy::writeln_empty_string, clippy::wrong_self_convention, clippy::zero_ptr"##, + description: r##"lint group for: clippy::assertions_on_constants, clippy::assign_op_pattern, clippy::blocks_in_if_conditions, clippy::bool_assert_comparison, clippy::borrow_interior_mutable_const, clippy::builtin_type_shadow, clippy::bytes_nth, clippy::chars_last_cmp, clippy::chars_next_cmp, clippy::cmp_null, clippy::collapsible_else_if, clippy::collapsible_if, clippy::collapsible_match, clippy::comparison_chain, clippy::comparison_to_empty, clippy::declare_interior_mutable_const, clippy::default_instead_of_iter_empty, clippy::disallowed_macros, clippy::disallowed_methods, clippy::disallowed_names, clippy::disallowed_types, clippy::double_must_use, clippy::double_neg, clippy::duplicate_underscore_argument, clippy::enum_variant_names, clippy::err_expect, clippy::excessive_precision, clippy::field_reassign_with_default, clippy::filter_map_bool_then, clippy::fn_to_numeric_cast, clippy::fn_to_numeric_cast_with_truncation, clippy::for_kv_map, clippy::from_over_into, clippy::from_str_radix_10, clippy::get_first, clippy::implicit_saturating_add, clippy::implicit_saturating_sub, clippy::inconsistent_digit_grouping, clippy::infallible_destructuring_match, clippy::inherent_to_string, clippy::init_numbered_fields, clippy::into_iter_on_ref, clippy::is_digit_ascii_radix, clippy::items_after_test_module, clippy::iter_cloned_collect, clippy::iter_next_slice, clippy::iter_nth_zero, clippy::iter_skip_next, clippy::just_underscores_and_digits, clippy::len_without_is_empty, clippy::len_zero, clippy::let_and_return, clippy::let_unit_value, clippy::main_recursion, clippy::manual_async_fn, clippy::manual_bits, clippy::manual_is_ascii_check, clippy::manual_is_finite, clippy::manual_is_infinite, clippy::manual_map, clippy::manual_next_back, clippy::manual_non_exhaustive, clippy::manual_range_contains, clippy::manual_saturating_arithmetic, clippy::manual_while_let_some, clippy::map_clone, clippy::map_collect_result_unit, clippy::match_like_matches_macro, clippy::match_overlapping_arm, clippy::match_ref_pats, clippy::match_result_ok, clippy::mem_replace_option_with_none, clippy::mem_replace_with_default, clippy::missing_safety_doc, clippy::mixed_case_hex_literals, clippy::module_inception, clippy::must_use_unit, clippy::mut_mutex_lock, clippy::needless_borrow, clippy::needless_borrows_for_generic_args, clippy::needless_doctest_main, clippy::needless_else, clippy::needless_late_init, clippy::needless_parens_on_range_literals, clippy::needless_pub_self, clippy::needless_range_loop, clippy::needless_return, clippy::needless_return_with_question_mark, clippy::neg_multiply, clippy::new_ret_no_self, clippy::new_without_default, clippy::non_minimal_cfg, clippy::obfuscated_if_else, clippy::ok_expect, clippy::op_ref, clippy::option_map_or_none, clippy::partialeq_to_none, clippy::print_literal, clippy::print_with_newline, clippy::println_empty_string, clippy::ptr_arg, clippy::ptr_eq, clippy::question_mark, clippy::redundant_closure, clippy::redundant_field_names, clippy::redundant_pattern, clippy::redundant_pattern_matching, clippy::redundant_static_lifetimes, clippy::result_map_or_into_option, clippy::result_unit_err, clippy::same_item_push, clippy::self_named_constructors, clippy::should_implement_trait, clippy::single_char_add_str, clippy::single_component_path_imports, clippy::single_match, clippy::string_extend_chars, clippy::tabs_in_doc_comments, clippy::to_digit_is_some, clippy::toplevel_ref_arg, clippy::trim_split_whitespace, clippy::unnecessary_fold, clippy::unnecessary_lazy_evaluations, clippy::unnecessary_mut_passed, clippy::unnecessary_owned_empty_strings, clippy::unsafe_removed_from_name, clippy::unused_unit, clippy::unusual_byte_groupings, clippy::unwrap_or_default, clippy::upper_case_acronyms, clippy::while_let_on_iterator, clippy::write_literal, clippy::write_with_newline, clippy::writeln_empty_string, clippy::wrong_self_convention, clippy::zero_ptr"##, }, children: &[ "clippy::assertions_on_constants", "clippy::assign_op_pattern", - "clippy::blacklisted_name", "clippy::blocks_in_if_conditions", "clippy::bool_assert_comparison", "clippy::borrow_interior_mutable_const", @@ -7546,21 +8240,34 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::comparison_chain", "clippy::comparison_to_empty", "clippy::declare_interior_mutable_const", + "clippy::default_instead_of_iter_empty", + "clippy::disallowed_macros", + "clippy::disallowed_methods", + "clippy::disallowed_names", + "clippy::disallowed_types", "clippy::double_must_use", "clippy::double_neg", "clippy::duplicate_underscore_argument", "clippy::enum_variant_names", + "clippy::err_expect", "clippy::excessive_precision", "clippy::field_reassign_with_default", + "clippy::filter_map_bool_then", "clippy::fn_to_numeric_cast", "clippy::fn_to_numeric_cast_with_truncation", "clippy::for_kv_map", "clippy::from_over_into", "clippy::from_str_radix_10", + "clippy::get_first", + "clippy::implicit_saturating_add", + "clippy::implicit_saturating_sub", "clippy::inconsistent_digit_grouping", "clippy::infallible_destructuring_match", "clippy::inherent_to_string", + "clippy::init_numbered_fields", "clippy::into_iter_on_ref", + "clippy::is_digit_ascii_radix", + "clippy::items_after_test_module", "clippy::iter_cloned_collect", "clippy::iter_next_slice", "clippy::iter_nth_zero", @@ -7569,12 +8276,19 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::len_without_is_empty", "clippy::len_zero", "clippy::let_and_return", + "clippy::let_unit_value", "clippy::main_recursion", "clippy::manual_async_fn", + "clippy::manual_bits", + "clippy::manual_is_ascii_check", + "clippy::manual_is_finite", + "clippy::manual_is_infinite", "clippy::manual_map", + "clippy::manual_next_back", "clippy::manual_non_exhaustive", "clippy::manual_range_contains", "clippy::manual_saturating_arithmetic", + "clippy::manual_while_let_some", "clippy::map_clone", "clippy::map_collect_result_unit", "clippy::match_like_matches_macro", @@ -7589,16 +8303,24 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::must_use_unit", "clippy::mut_mutex_lock", "clippy::needless_borrow", + "clippy::needless_borrows_for_generic_args", "clippy::needless_doctest_main", + "clippy::needless_else", "clippy::needless_late_init", + "clippy::needless_parens_on_range_literals", + "clippy::needless_pub_self", "clippy::needless_range_loop", "clippy::needless_return", + "clippy::needless_return_with_question_mark", "clippy::neg_multiply", "clippy::new_ret_no_self", "clippy::new_without_default", + "clippy::non_minimal_cfg", + "clippy::obfuscated_if_else", "clippy::ok_expect", "clippy::op_ref", "clippy::option_map_or_none", + "clippy::partialeq_to_none", "clippy::print_literal", "clippy::print_with_newline", "clippy::println_empty_string", @@ -7622,14 +8344,15 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::tabs_in_doc_comments", "clippy::to_digit_is_some", "clippy::toplevel_ref_arg", - "clippy::try_err", + "clippy::trim_split_whitespace", "clippy::unnecessary_fold", "clippy::unnecessary_lazy_evaluations", "clippy::unnecessary_mut_passed", + "clippy::unnecessary_owned_empty_strings", "clippy::unsafe_removed_from_name", "clippy::unused_unit", "clippy::unusual_byte_groupings", - "clippy::unwrap_or_else_default", + "clippy::unwrap_or_default", "clippy::upper_case_acronyms", "clippy::while_let_on_iterator", "clippy::write_literal", @@ -7642,25 +8365,59 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ LintGroup { lint: Lint { label: "clippy::suspicious", - description: r##"lint group for: clippy::blanket_clippy_restriction_lints, clippy::empty_loop, clippy::eval_order_dependence, clippy::float_equality_without_abs, clippy::for_loops_over_fallibles, clippy::misrefactored_assign_op, clippy::mut_range_bound, clippy::mutable_key_type, clippy::octal_escapes, clippy::return_self_not_must_use, clippy::suspicious_arithmetic_impl, clippy::suspicious_assignment_formatting, clippy::suspicious_else_formatting, clippy::suspicious_map, clippy::suspicious_op_assign_impl, clippy::suspicious_unary_op_formatting"##, + description: r##"lint group for: clippy::almost_complete_range, clippy::arc_with_non_send_sync, clippy::await_holding_invalid_type, clippy::await_holding_lock, clippy::await_holding_refcell_ref, clippy::blanket_clippy_restriction_lints, clippy::cast_abs_to_unsigned, clippy::cast_enum_constructor, clippy::cast_enum_truncation, clippy::cast_nan_to_int, clippy::cast_slice_from_raw_parts, clippy::crate_in_macro_def, clippy::drop_non_drop, clippy::duplicate_mod, clippy::empty_loop, clippy::float_equality_without_abs, clippy::forget_non_drop, clippy::four_forward_slashes, clippy::from_raw_with_void_ptr, clippy::iter_out_of_bounds, clippy::let_underscore_future, clippy::lines_filter_map_ok, clippy::maybe_misused_cfg, clippy::misnamed_getters, clippy::misrefactored_assign_op, clippy::multi_assignments, clippy::mut_range_bound, clippy::mutable_key_type, clippy::needless_pass_by_ref_mut, clippy::no_effect_replace, clippy::non_canonical_clone_impl, clippy::non_canonical_partial_ord_impl, clippy::octal_escapes, clippy::path_ends_with_ext, clippy::permissions_set_readonly_false, clippy::print_in_format_impl, clippy::rc_clone_in_vec_init, clippy::single_range_in_vec_init, clippy::size_of_ref, clippy::suspicious_arithmetic_impl, clippy::suspicious_assignment_formatting, clippy::suspicious_command_arg_space, clippy::suspicious_doc_comments, clippy::suspicious_else_formatting, clippy::suspicious_map, clippy::suspicious_op_assign_impl, clippy::suspicious_to_owned, clippy::suspicious_unary_op_formatting, clippy::swap_ptr_to_ref, clippy::type_id_on_box"##, }, children: &[ + "clippy::almost_complete_range", + "clippy::arc_with_non_send_sync", + "clippy::await_holding_invalid_type", + "clippy::await_holding_lock", + "clippy::await_holding_refcell_ref", "clippy::blanket_clippy_restriction_lints", + "clippy::cast_abs_to_unsigned", + "clippy::cast_enum_constructor", + "clippy::cast_enum_truncation", + "clippy::cast_nan_to_int", + "clippy::cast_slice_from_raw_parts", + "clippy::crate_in_macro_def", + "clippy::drop_non_drop", + "clippy::duplicate_mod", "clippy::empty_loop", - "clippy::eval_order_dependence", "clippy::float_equality_without_abs", - "clippy::for_loops_over_fallibles", + "clippy::forget_non_drop", + "clippy::four_forward_slashes", + "clippy::from_raw_with_void_ptr", + "clippy::iter_out_of_bounds", + "clippy::let_underscore_future", + "clippy::lines_filter_map_ok", + "clippy::maybe_misused_cfg", + "clippy::misnamed_getters", "clippy::misrefactored_assign_op", + "clippy::multi_assignments", "clippy::mut_range_bound", "clippy::mutable_key_type", + "clippy::needless_pass_by_ref_mut", + "clippy::no_effect_replace", + "clippy::non_canonical_clone_impl", + "clippy::non_canonical_partial_ord_impl", "clippy::octal_escapes", - "clippy::return_self_not_must_use", + "clippy::path_ends_with_ext", + "clippy::permissions_set_readonly_false", + "clippy::print_in_format_impl", + "clippy::rc_clone_in_vec_init", + "clippy::single_range_in_vec_init", + "clippy::size_of_ref", "clippy::suspicious_arithmetic_impl", "clippy::suspicious_assignment_formatting", + "clippy::suspicious_command_arg_space", + "clippy::suspicious_doc_comments", "clippy::suspicious_else_formatting", "clippy::suspicious_map", "clippy::suspicious_op_assign_impl", + "clippy::suspicious_to_owned", "clippy::suspicious_unary_op_formatting", + "clippy::swap_ptr_to_ref", + "clippy::type_id_on_box", ], }, ]; diff --git a/crates/ide-db/src/tests/sourcegen_lints.rs b/crates/ide-db/src/tests/sourcegen_lints.rs index c7d5f3613d4b..457f94d3f9f3 100644 --- a/crates/ide-db/src/tests/sourcegen_lints.rs +++ b/crates/ide-db/src/tests/sourcegen_lints.rs @@ -51,7 +51,7 @@ pub struct LintGroup { let contents = sourcegen::add_preamble("sourcegen_lints", sourcegen::reformat(contents)); - let destination = project_root().join("crates/ide_db/src/generated/lints.rs"); + let destination = project_root().join("crates/ide-db/src/generated/lints.rs"); sourcegen::ensure_file_contents(destination.as_path(), &contents); } @@ -196,7 +196,7 @@ fn generate_descriptor_clippy(buf: &mut String, path: &Path) { let mut clippy_lints: Vec = Vec::new(); let mut clippy_groups: std::collections::BTreeMap> = Default::default(); - for line in file_content.lines().map(|line| line.trim()) { + for line in file_content.lines().map(str::trim) { if let Some(line) = line.strip_prefix(r#""id": ""#) { let clippy_lint = ClippyLint { id: line.strip_suffix(r#"","#).expect("should be suffixed by comma").into(), @@ -211,12 +211,19 @@ fn generate_descriptor_clippy(buf: &mut String, path: &Path) { .push(clippy_lints.last().unwrap().id.clone()); } } else if let Some(line) = line.strip_prefix(r#""docs": ""#) { - let prefix_to_strip = r#" ### What it does"#; - let line = match line.strip_prefix(prefix_to_strip) { - Some(line) => line, + let header = "### What it does"; + let line = match line.find(header) { + Some(idx) => &line[idx + header.len()..], None => { - eprintln!("unexpected clippy prefix for {}", clippy_lints.last().unwrap().id); - continue; + let id = &clippy_lints.last().unwrap().id; + // these just don't have the common header + let allowed = ["allow_attributes", "read_line_without_trim"]; + if allowed.contains(&id.as_str()) { + line + } else { + eprintln!("\nunexpected clippy prefix for {id}, line={line:?}\n",); + continue; + } } }; // Only take the description, any more than this is a lot of additional data we would embed into the exe diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs index 81d6db564ff5..e54bc48d555b 100644 --- a/crates/ide/src/hover/tests.rs +++ b/crates/ide/src/hover/tests.rs @@ -5266,38 +5266,46 @@ pub fn foo() {} #[test] fn hover_feature() { check( - r#"#![feature(box_syntax$0)]"#, - expect![[r##" - *box_syntax* - ``` - box_syntax - ``` - ___ + r#"#![feature(intrinsics$0)]"#, + expect![[r#" + *intrinsics* + ``` + intrinsics + ``` + ___ - # `box_syntax` + # `intrinsics` - The tracking issue for this feature is: [#49733] + The tracking issue for this feature is: None. - [#49733]: https://github.com/rust-lang/rust/issues/49733 + Intrinsics are never intended to be stable directly, but intrinsics are often + exported in some sort of stable manner. Prefer using the stable interfaces to + the intrinsic directly when you can. - See also [`box_patterns`](box-patterns.md) + ------------------------ - ------------------------ - Currently the only stable way to create a `Box` is via the `Box::new` method. - Also it is not possible in stable Rust to destructure a `Box` in a match - pattern. The unstable `box` keyword can be used to create a `Box`. An example - usage would be: + These are imported as if they were FFI functions, with the special + `rust-intrinsic` ABI. For example, if one was in a freestanding + context, but wished to be able to `transmute` between types, and + perform efficient pointer arithmetic, one would import those functions + via a declaration like - ```rust - #![feature(box_syntax)] + ```rust + #![feature(intrinsics)] + #![allow(internal_features)] + # fn main() {} - fn main() { - let b = box 5; - } - ``` + extern "rust-intrinsic" { + fn transmute(x: T) -> U; - "##]], + fn arith_offset(dst: *const T, offset: isize) -> *const T; + } + ``` + + As with any other FFI functions, these are always `unsafe` to call. + + "#]], ) } diff --git a/crates/rust-analyzer/tests/slow-tests/tidy.rs b/crates/rust-analyzer/tests/slow-tests/tidy.rs index 8b5c92c66023..e9b250bebf21 100644 --- a/crates/rust-analyzer/tests/slow-tests/tidy.rs +++ b/crates/rust-analyzer/tests/slow-tests/tidy.rs @@ -300,6 +300,8 @@ fn check_test_attrs(path: &Path, text: &str) { // This file. "slow-tests/tidy.rs", "test-utils/src/fixture.rs", + // Generated code from lints contains doc tests in string literals. + "ide-db/src/generated/lints.rs", ]; if text.contains("#[should_panic") && !need_panic.iter().any(|p| path.ends_with(p)) { panic!( From a943b19e0865a7a1bf1ad0562c2e3426ba9bd22d Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 29 Sep 2023 15:30:47 +0200 Subject: [PATCH 084/435] Make rustc_layout_scalar_valid_range attributes work for non-decimal literals --- crates/hir-ty/src/layout/adt.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/crates/hir-ty/src/layout/adt.rs b/crates/hir-ty/src/layout/adt.rs index 85ef649b8959..457b227427ed 100644 --- a/crates/hir-ty/src/layout/adt.rs +++ b/crates/hir-ty/src/layout/adt.rs @@ -119,7 +119,15 @@ fn layout_scalar_valid_range(db: &dyn HirDatabase, def: AdtId) -> (Bound, let attr = attrs.by_key(name).tt_values(); for tree in attr { if let Some(it) = tree.token_trees.first() { - if let Ok(it) = it.to_string().parse() { + let text = it.to_string().replace('_', ""); + let base = match text.as_bytes() { + [b'0', b'x', ..] => 16, + [b'0', b'o', ..] => 8, + [b'0', b'b', ..] => 2, + _ => 10, + }; + + if let Ok(it) = u128::from_str_radix(&text, base) { return Bound::Included(it); } } From dd8ea977b700d9ef6089dea6e5f1353f567c06d1 Mon Sep 17 00:00:00 2001 From: Martin Nordholts Date: Fri, 29 Sep 2023 17:39:26 +0200 Subject: [PATCH 085/435] vscode: Fix line and col regexp for problem matcher When building the Rust compiler with `./x check` from within VS Code, the current `rustc` problem matcher thinks that the output from that command that looks like this: Build completed successfully in 0:00:26 is about a problem in a file named `0` on line 00, col 26. This wouldn't be so bad if it wasn't for that VS Code tends to get stuck on this problem because of problems with opening the file '0'. The rust compiler will never output problems with a line or a column that starts with 0, so change the regexp to require lines and cols to begin with [1-9] to fix this problem. --- editors/code/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/editors/code/package.json b/editors/code/package.json index 639588566344..3ceec9edf4b6 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -1621,7 +1621,7 @@ "message": 3 }, { - "regexp": "^[\\s->=]*(.*?):(\\d*):(\\d*)\\s*$", + "regexp": "^[\\s->=]*(.*?):([1-9]\\d*):([1-9]\\d*)\\s*$", "file": 1, "line": 2, "column": 3 From ae5d74dffbec2946f198d5dcf0a288a9c06f37de Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 29 Sep 2023 21:06:47 +0200 Subject: [PATCH 086/435] typing underscore should not trigger completions in types or patterns --- crates/ide-completion/src/lib.rs | 22 +++++ crates/ide-completion/src/tests/special.rs | 109 +++++++++++++++++++++ 2 files changed, 131 insertions(+) diff --git a/crates/ide-completion/src/lib.rs b/crates/ide-completion/src/lib.rs index 2eaa42040a01..2fad293d16d7 100644 --- a/crates/ide-completion/src/lib.rs +++ b/crates/ide-completion/src/lib.rs @@ -169,6 +169,28 @@ pub fn completions( return Some(completions.into()); } + // when the user types a bare `_` (that is it does not belong to an identifier) + // the user might just wanted to type a `_` for type inference or pattern discarding + // so try to suppress completions in those cases + if trigger_character == Some('_') && ctx.original_token.kind() == syntax::SyntaxKind::UNDERSCORE + { + if let CompletionAnalysis::NameRef(NameRefContext { + kind: + NameRefKind::Path( + path_ctx @ PathCompletionCtx { + kind: PathKind::Type { .. } | PathKind::Pat { .. }, + .. + }, + ), + .. + }) = analysis + { + if path_ctx.is_trivial_path() { + return None; + } + } + } + { let acc = &mut completions; diff --git a/crates/ide-completion/src/tests/special.rs b/crates/ide-completion/src/tests/special.rs index 83888e08f1c7..d3dbd7cc2277 100644 --- a/crates/ide-completion/src/tests/special.rs +++ b/crates/ide-completion/src/tests/special.rs @@ -1372,3 +1372,112 @@ fn main() { expect!("pub const fn baz<'foo>(&'foo mut self, x: &'foo Foo) -> !"), ); } + +#[test] +fn skips_underscore() { + check_with_trigger_character( + r#" +fn foo(_$0) { } +"#, + Some('_'), + expect![[r#""#]], + ); + check_with_trigger_character( + r#" +fn foo(_: _$0) { } +"#, + Some('_'), + expect![[r#""#]], + ); + check_with_trigger_character( + r#" +fn foo() { + foo::<_$0>(); +} +"#, + Some('_'), + expect![[r#""#]], + ); + // underscore expressions are fine, they are invalid so the user definitely meant to type an + // underscored name here + check_with_trigger_character( + r#" +fn foo() { + _$0 +} +"#, + Some('_'), + expect![[r#" + fn foo() fn() + bt u32 + kw const + kw crate:: + kw enum + kw extern + kw false + kw fn + kw for + kw if + kw if let + kw impl + kw let + kw loop + kw match + kw mod + kw return + kw self:: + kw static + kw struct + kw trait + kw true + kw type + kw union + kw unsafe + kw use + kw while + kw while let + sn macro_rules + sn pd + sn ppd + "#]], + ); +} + +#[test] +fn no_skip_underscore_ident() { + check_with_trigger_character( + r#" +fn foo(a_$0) { } +"#, + Some('_'), + expect![[r#" + kw mut + kw ref + "#]], + ); + check_with_trigger_character( + r#" +fn foo(_: a_$0) { } +"#, + Some('_'), + expect![[r#" + bt u32 + kw crate:: + kw self:: + "#]], + ); + check_with_trigger_character( + r#" +fn foo() { + foo::(); +} +"#, + Some('_'), + expect![[r#" + tp T + bt u32 + kw crate:: + kw self:: + "#]], + ); +} From af28458643abfc074e479b6e77654f55891e0f39 Mon Sep 17 00:00:00 2001 From: hkalbasi Date: Sat, 30 Sep 2023 08:37:15 +0330 Subject: [PATCH 087/435] Downgrade `unused_variables` to experimental --- crates/ide-diagnostics/src/handlers/unused_variables.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/ide-diagnostics/src/handlers/unused_variables.rs b/crates/ide-diagnostics/src/handlers/unused_variables.rs index 2658f12f8ad3..28ccf474b40b 100644 --- a/crates/ide-diagnostics/src/handlers/unused_variables.rs +++ b/crates/ide-diagnostics/src/handlers/unused_variables.rs @@ -14,6 +14,7 @@ pub(crate) fn unused_variables( "unused variable", ast, ) + .experimental() } #[cfg(test)] From 40f80e29a5f33a5e5209f3075aa771789a3b6002 Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Sat, 30 Sep 2023 08:04:04 -0700 Subject: [PATCH 088/435] move `to_camel_case` and `char_has_case` from case_conv to stdx --- .../src/diagnostics/decl_check/case_conv.rs | 54 ++----------------- crates/stdx/src/lib.rs | 51 ++++++++++++++++++ 2 files changed, 55 insertions(+), 50 deletions(-) diff --git a/crates/hir-ty/src/diagnostics/decl_check/case_conv.rs b/crates/hir-ty/src/diagnostics/decl_check/case_conv.rs index 2c1368962092..cbe1af157037 100644 --- a/crates/hir-ty/src/diagnostics/decl_check/case_conv.rs +++ b/crates/hir-ty/src/diagnostics/decl_check/case_conv.rs @@ -11,50 +11,7 @@ pub(crate) fn to_camel_case(ident: &str) -> Option { return None; } - // Taken from rustc. - let ret = ident - .trim_matches('_') - .split('_') - .filter(|component| !component.is_empty()) - .map(|component| { - let mut camel_cased_component = String::with_capacity(component.len()); - - let mut new_word = true; - let mut prev_is_lower_case = true; - - for c in component.chars() { - // Preserve the case if an uppercase letter follows a lowercase letter, so that - // `camelCase` is converted to `CamelCase`. - if prev_is_lower_case && c.is_uppercase() { - new_word = true; - } - - if new_word { - camel_cased_component.extend(c.to_uppercase()); - } else { - camel_cased_component.extend(c.to_lowercase()); - } - - prev_is_lower_case = c.is_lowercase(); - new_word = false; - } - - camel_cased_component - }) - .fold((String::new(), None), |(acc, prev): (_, Option), next| { - // separate two components with an underscore if their boundary cannot - // be distinguished using an uppercase/lowercase case distinction - let join = prev - .and_then(|prev| { - let f = next.chars().next()?; - let l = prev.chars().last()?; - Some(!char_has_case(l) && !char_has_case(f)) - }) - .unwrap_or(false); - (acc + if join { "_" } else { "" } + &next, Some(next)) - }) - .0; - Some(ret) + Some(stdx::to_camel_case(ident)) } /// Converts an identifier to a lower_snake_case form. @@ -97,7 +54,9 @@ fn is_camel_case(name: &str) -> bool { && !name.chars().any(|snd| { let ret = match fst { None => false, - Some(fst) => char_has_case(fst) && snd == '_' || char_has_case(snd) && fst == '_', + Some(fst) => { + stdx::char_has_case(fst) && snd == '_' || stdx::char_has_case(snd) && fst == '_' + } }; fst = Some(snd); @@ -135,11 +94,6 @@ fn is_snake_case bool>(ident: &str, wrong_case: F) -> bool { }) } -// Taken from rustc. -fn char_has_case(c: char) -> bool { - c.is_lowercase() || c.is_uppercase() -} - #[cfg(test)] mod tests { use super::*; diff --git a/crates/stdx/src/lib.rs b/crates/stdx/src/lib.rs index 24990d6a0e71..89c54eee55f1 100644 --- a/crates/stdx/src/lib.rs +++ b/crates/stdx/src/lib.rs @@ -89,6 +89,57 @@ where words.join("_") } +// Taken from rustc. +pub fn to_camel_case(ident: &str) -> String { + ident + .trim_matches('_') + .split('_') + .filter(|component| !component.is_empty()) + .map(|component| { + let mut camel_cased_component = String::with_capacity(component.len()); + + let mut new_word = true; + let mut prev_is_lower_case = true; + + for c in component.chars() { + // Preserve the case if an uppercase letter follows a lowercase letter, so that + // `camelCase` is converted to `CamelCase`. + if prev_is_lower_case && c.is_uppercase() { + new_word = true; + } + + if new_word { + camel_cased_component.extend(c.to_uppercase()); + } else { + camel_cased_component.extend(c.to_lowercase()); + } + + prev_is_lower_case = c.is_lowercase(); + new_word = false; + } + + camel_cased_component + }) + .fold((String::new(), None), |(acc, prev): (_, Option), next| { + // separate two components with an underscore if their boundary cannot + // be distinguished using an uppercase/lowercase case distinction + let join = prev + .and_then(|prev| { + let f = next.chars().next()?; + let l = prev.chars().last()?; + Some(!char_has_case(l) && !char_has_case(f)) + }) + .unwrap_or(false); + (acc + if join { "_" } else { "" } + &next, Some(next)) + }) + .0 +} + +// Taken from rustc. +pub fn char_has_case(c: char) -> bool { + c.is_lowercase() || c.is_uppercase() +} + pub fn replace(buf: &mut String, from: char, to: &str) { if !buf.contains(from) { return; From 2611fbf62380547555e1ce520a83d6ce24bd72b2 Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Sat, 30 Sep 2023 17:06:00 -0700 Subject: [PATCH 089/435] implement basic version of convert_tuple_return_type_to_struct assist --- .../convert_tuple_return_type_to_struct.rs | 891 ++++++++++++++++++ crates/ide-assists/src/lib.rs | 2 + crates/ide-assists/src/tests/generated.rs | 27 + 3 files changed, 920 insertions(+) create mode 100644 crates/ide-assists/src/handlers/convert_tuple_return_type_to_struct.rs diff --git a/crates/ide-assists/src/handlers/convert_tuple_return_type_to_struct.rs b/crates/ide-assists/src/handlers/convert_tuple_return_type_to_struct.rs new file mode 100644 index 000000000000..c71a2de7c0f9 --- /dev/null +++ b/crates/ide-assists/src/handlers/convert_tuple_return_type_to_struct.rs @@ -0,0 +1,891 @@ +use either::Either; +use hir::ModuleDef; +use ide_db::{ + assists::{AssistId, AssistKind}, + defs::Definition, + helpers::mod_path_to_ast, + imports::insert_use::{insert_use, ImportScope}, + search::{FileReference, UsageSearchResult}, + source_change::SourceChangeBuilder, + syntax_helpers::node_ext::{for_each_tail_expr, walk_expr}, + FxHashSet, +}; +use syntax::{ + ast::{self, edit::IndentLevel, edit_in_place::Indent, make, HasName}, + match_ast, ted, AstNode, SyntaxNode, +}; + +use crate::assist_context::{AssistContext, Assists}; + +// Assist: convert_tuple_return_type_to_struct +// +// This converts the return type of a function from a tuple type +// into a tuple struct and updates the body accordingly. +// +// ``` +// fn bar() { +// let (a, b, c) = foo(); +// } +// +// fn foo() -> ($0u32, u32, u32) { +// (1, 2, 3) +// } +// ``` +// -> +// ``` +// fn bar() { +// let FooResult(a, b, c) = foo(); +// } +// +// struct FooResult(u32, u32, u32); +// +// fn foo() -> FooResult { +// FooResult(1, 2, 3) +// } +// ``` +pub(crate) fn convert_tuple_return_type_to_struct( + acc: &mut Assists, + ctx: &AssistContext<'_>, +) -> Option<()> { + let ret_type = ctx.find_node_at_offset::()?; + let type_ref = ret_type.ty()?; + + let ast::Type::TupleType(tuple_ty) = &type_ref else { return None }; + if tuple_ty.fields().any(|field| matches!(field, ast::Type::ImplTraitType(_))) { + return None; + } + + let fn_ = ret_type.syntax().parent().and_then(ast::Fn::cast)?; + let fn_def = ctx.sema.to_def(&fn_)?; + let fn_name = fn_.name()?; + let target_module = ctx.sema.scope(fn_.syntax())?.module().nearest_non_block_module(ctx.db()); + + let target = type_ref.syntax().text_range(); + acc.add( + AssistId("convert_tuple_return_type_to_struct", AssistKind::RefactorRewrite), + "Convert tuple return type to tuple struct", + target, + move |edit| { + let ret_type = edit.make_mut(ret_type); + let fn_ = edit.make_mut(fn_); + + let usages = Definition::Function(fn_def).usages(&ctx.sema).all(); + let struct_name = format!("{}Result", stdx::to_camel_case(&fn_name.to_string())); + let parent = fn_.syntax().ancestors().find_map(>::cast); + add_tuple_struct_def( + edit, + ctx, + &usages, + parent.as_ref().map(|it| it.syntax()).unwrap_or(fn_.syntax()), + tuple_ty, + &struct_name, + &target_module, + ); + + ted::replace( + ret_type.syntax(), + make::ret_type(make::ty(&struct_name)).syntax().clone_for_update(), + ); + + if let Some(fn_body) = fn_.body() { + replace_body_return_values(ast::Expr::BlockExpr(fn_body), &struct_name); + } + + replace_usages(edit, ctx, &usages, &struct_name, &target_module); + }, + ) +} + +/// Replaces tuple usages with the corresponding tuple struct pattern. +fn replace_usages( + edit: &mut SourceChangeBuilder, + ctx: &AssistContext<'_>, + usages: &UsageSearchResult, + struct_name: &str, + target_module: &hir::Module, +) { + for (file_id, references) in usages.iter() { + edit.edit_file(*file_id); + + let refs_with_imports = + augment_references_with_imports(edit, ctx, references, struct_name, target_module); + + refs_with_imports.into_iter().rev().for_each(|(name, import_data)| { + if let Some(fn_) = name.syntax().parent().and_then(ast::Fn::cast) { + cov_mark::hit!(replace_trait_impl_fns); + + if let Some(ret_type) = fn_.ret_type() { + ted::replace( + ret_type.syntax(), + make::ret_type(make::ty(struct_name)).syntax().clone_for_update(), + ); + } + + if let Some(fn_body) = fn_.body() { + replace_body_return_values(ast::Expr::BlockExpr(fn_body), struct_name); + } + } else { + // replace tuple patterns + let pats = name + .syntax() + .ancestors() + .nth(5) + .and_then(node_to_pats) + .or_else(|| { + cov_mark::hit!(replace_method_usage); + + name.syntax() + .parent() + .filter(|node| ast::MethodCallExpr::can_cast(node.kind())) + .and_then(|node| node.parent().and_then(node_to_pats)) + }) + .unwrap_or(Vec::new()); + + let tuple_pats = pats.iter().filter_map(|pat| match pat { + ast::Pat::TuplePat(tuple_pat) => Some(tuple_pat), + _ => None, + }); + for tuple_pat in tuple_pats { + ted::replace( + tuple_pat.syntax(), + make::tuple_struct_pat( + make::path_from_text(struct_name), + tuple_pat.fields(), + ) + .clone_for_update() + .syntax(), + ); + } + } + // add imports across modules where needed + if let Some((import_scope, path)) = import_data { + insert_use(&import_scope, path, &ctx.config.insert_use); + } + }) + } +} + +fn node_to_pats(node: SyntaxNode) -> Option> { + match_ast! { + match node { + ast::LetStmt(it) => it.pat().map(|pat| vec![pat]), + ast::LetExpr(it) => it.pat().map(|pat| vec![pat]), + ast::MatchExpr(it) => it.match_arm_list().map(|arm_list| { + arm_list.arms().filter_map(|arm| arm.pat()).collect() + }), + _ => None, + } + } +} + +fn augment_references_with_imports( + edit: &mut SourceChangeBuilder, + ctx: &AssistContext<'_>, + references: &[FileReference], + struct_name: &str, + target_module: &hir::Module, +) -> Vec<(ast::NameLike, Option<(ImportScope, ast::Path)>)> { + let mut visited_modules = FxHashSet::default(); + + references + .iter() + .filter_map(|FileReference { name, .. }| { + ctx.sema.scope(name.syntax()).map(|scope| (name, scope.module())) + }) + .map(|(name, ref_module)| { + let new_name = edit.make_mut(name.clone()); + + // if the referenced module is not the same as the target one and has not been seen before, add an import + let import_data = if ref_module.nearest_non_block_module(ctx.db()) != *target_module + && !visited_modules.contains(&ref_module) + { + visited_modules.insert(ref_module); + + let import_scope = + ImportScope::find_insert_use_container(new_name.syntax(), &ctx.sema); + let path = ref_module + .find_use_path_prefixed( + ctx.sema.db, + ModuleDef::Module(*target_module), + ctx.config.insert_use.prefix_kind, + ctx.config.prefer_no_std, + ) + .map(|mod_path| { + make::path_concat( + mod_path_to_ast(&mod_path), + make::path_from_text(struct_name), + ) + }); + + import_scope.zip(path) + } else { + None + }; + + (new_name, import_data) + }) + .collect() +} + +// Adds the definition of the tuple struct before the parent function. +fn add_tuple_struct_def( + edit: &mut SourceChangeBuilder, + ctx: &AssistContext<'_>, + usages: &UsageSearchResult, + parent: &SyntaxNode, + tuple_ty: &ast::TupleType, + struct_name: &str, + target_module: &hir::Module, +) { + let make_struct_pub = usages + .iter() + .flat_map(|(_, refs)| refs) + .filter_map(|FileReference { name, .. }| { + ctx.sema.scope(name.syntax()).map(|scope| scope.module()) + }) + .any(|module| module.nearest_non_block_module(ctx.db()) != *target_module); + let visibility = if make_struct_pub { Some(make::visibility_pub()) } else { None }; + + let field_list = ast::FieldList::TupleFieldList(make::tuple_field_list( + tuple_ty.fields().map(|ty| make::tuple_field(visibility.clone(), ty)), + )); + let struct_name = make::name(struct_name); + let struct_def = make::struct_(visibility, struct_name, None, field_list).clone_for_update(); + + let indent = IndentLevel::from_node(parent); + struct_def.reindent_to(indent); + + edit.insert(parent.text_range().start(), format!("{struct_def}\n\n{indent}")); +} + +/// Replaces each returned tuple in `body` with the constructor of the tuple struct named `struct_name`. +fn replace_body_return_values(body: ast::Expr, struct_name: &str) { + let mut exprs_to_wrap = Vec::new(); + + let tail_cb = &mut |e: &_| tail_cb_impl(&mut exprs_to_wrap, e); + walk_expr(&body, &mut |expr| { + if let ast::Expr::ReturnExpr(ret_expr) = expr { + if let Some(ret_expr_arg) = &ret_expr.expr() { + for_each_tail_expr(ret_expr_arg, tail_cb); + } + } + }); + for_each_tail_expr(&body, tail_cb); + + for ret_expr in exprs_to_wrap { + if let ast::Expr::TupleExpr(tuple_expr) = &ret_expr { + let struct_constructor = make::expr_call( + make::expr_path(make::ext::ident_path(struct_name)), + make::arg_list(tuple_expr.fields()), + ) + .clone_for_update(); + ted::replace(ret_expr.syntax(), struct_constructor.syntax()); + } + } +} + +fn tail_cb_impl(acc: &mut Vec, e: &ast::Expr) { + match e { + ast::Expr::BreakExpr(break_expr) => { + if let Some(break_expr_arg) = break_expr.expr() { + for_each_tail_expr(&break_expr_arg, &mut |e| tail_cb_impl(acc, e)) + } + } + ast::Expr::ReturnExpr(_) => { + // all return expressions have already been handled by the walk loop + } + e => acc.push(e.clone()), + } +} + +#[cfg(test)] +mod tests { + use super::*; + + use crate::tests::{check_assist, check_assist_not_applicable}; + + #[test] + fn function_basic() { + check_assist( + convert_tuple_return_type_to_struct, + r#" +fn bar() -> $0(&'static str, bool) { + ("bar", true) +} +"#, + r#" +struct BarResult(&'static str, bool); + +fn bar() -> BarResult { + BarResult("bar", true) +} +"#, + ) + } + + #[test] + fn struct_and_usages_indented() { + check_assist( + convert_tuple_return_type_to_struct, + r#" +mod foo { + pub(crate) fn foo() { + let (bar, baz) = bar(); + println!("{bar} {baz}"); + } + + pub(crate) fn bar() -> $0(usize, bool) { + (42, true) + } +} +"#, + r#" +mod foo { + pub(crate) fn foo() { + let BarResult(bar, baz) = bar(); + println!("{bar} {baz}"); + } + + struct BarResult(usize, bool); + + pub(crate) fn bar() -> BarResult { + BarResult(42, true) + } +} +"#, + ) + } + + #[test] + fn field_usage() { + check_assist( + convert_tuple_return_type_to_struct, + r#" +fn bar() -> $0(usize, bool) { + (42, true) +} + +fn main() { + let bar_result = bar(); + println!("{} {}", bar_result.1, bar().0); +} +"#, + r#" +struct BarResult(usize, bool); + +fn bar() -> BarResult { + BarResult(42, true) +} + +fn main() { + let bar_result = bar(); + println!("{} {}", bar_result.1, bar().0); +} +"#, + ) + } + + #[test] + fn method_usage() { + cov_mark::check!(replace_method_usage); + check_assist( + convert_tuple_return_type_to_struct, + r#" +struct Foo; + +impl Foo { + fn foo(&self, x: usize) -> $0(usize, usize) { + (x, x) + } +} + +fn main() { + let foo = Foo {}; + let (x, y) = foo.foo(2); +} +"#, + r#" +struct Foo; + +struct FooResult(usize, usize); + +impl Foo { + fn foo(&self, x: usize) -> FooResult { + FooResult(x, x) + } +} + +fn main() { + let foo = Foo {}; + let FooResult(x, y) = foo.foo(2); +} +"#, + ) + } + + #[test] + fn method_usage_within_same_impl() { + check_assist( + convert_tuple_return_type_to_struct, + r#" +struct Foo; + +impl Foo { + fn new() -> $0(usize, usize) { + (0, 0) + } + + fn foo() { + let (mut foo1, mut foo2) = Self::new(); + } +} +"#, + r#" +struct Foo; + +struct NewResult(usize, usize); + +impl Foo { + fn new() -> NewResult { + NewResult(0, 0) + } + + fn foo() { + let NewResult(mut foo1, mut foo2) = Self::new(); + } +} +"#, + ) + } + + #[test] + fn multiple_usages() { + check_assist( + convert_tuple_return_type_to_struct, + r#" +fn bar() -> $0(usize, usize) { + (42, 24) +} + +fn main() { + let bar_result = bar(); + let (foo, b) = bar(); + let (b, baz) = bar(); + + if foo == b && b == baz { + println!("{} {}", bar_result.1, bar().0); + } +} +"#, + r#" +struct BarResult(usize, usize); + +fn bar() -> BarResult { + BarResult(42, 24) +} + +fn main() { + let bar_result = bar(); + let BarResult(foo, b) = bar(); + let BarResult(b, baz) = bar(); + + if foo == b && b == baz { + println!("{} {}", bar_result.1, bar().0); + } +} +"#, + ) + } + + #[test] + fn usage_match_tuple_pat() { + check_assist( + convert_tuple_return_type_to_struct, + r#" +fn bar() -> $0(usize, bool) { + (42, true) +} + +fn main() { + match bar() { + x if x.0 == 0 => println!("0"), + (x, false) => println!("{x}"), + (42, true) => println!("bar"), + _ => println!("foo"), + } +} +"#, + r#" +struct BarResult(usize, bool); + +fn bar() -> BarResult { + BarResult(42, true) +} + +fn main() { + match bar() { + x if x.0 == 0 => println!("0"), + BarResult(x, false) => println!("{x}"), + BarResult(42, true) => println!("bar"), + _ => println!("foo"), + } +} +"#, + ) + } + + #[test] + fn usage_if_let_tuple_pat() { + check_assist( + convert_tuple_return_type_to_struct, + r#" +fn bar() -> $0(usize, bool) { + (42, true) +} + +fn main() { + if let (42, true) = bar() { + println!("bar") + } +} +"#, + r#" +struct BarResult(usize, bool); + +fn bar() -> BarResult { + BarResult(42, true) +} + +fn main() { + if let BarResult(42, true) = bar() { + println!("bar") + } +} +"#, + ) + } + + #[test] + fn function_nested_outer() { + check_assist( + convert_tuple_return_type_to_struct, + r#" +fn bar() -> $0(usize, bool) { + fn foo() -> (usize, bool) { + (42, true) + } + + foo() +} +"#, + r#" +struct BarResult(usize, bool); + +fn bar() -> BarResult { + fn foo() -> (usize, bool) { + (42, true) + } + + foo() +} +"#, + ) + } + + #[test] + fn function_nested_inner() { + check_assist( + convert_tuple_return_type_to_struct, + r#" +fn bar() -> (usize, bool) { + fn foo() -> $0(usize, bool) { + (42, true) + } + + foo() +} +"#, + r#" +fn bar() -> (usize, bool) { + struct FooResult(usize, bool); + + fn foo() -> FooResult { + FooResult(42, true) + } + + foo() +} +"#, + ) + } + + #[test] + fn trait_impl_and_usage() { + cov_mark::check!(replace_trait_impl_fns); + check_assist( + convert_tuple_return_type_to_struct, + r#" +struct Struct; + +trait Foo { + fn foo(&self) -> $0(usize, bool); +} + +impl Foo for Struct { + fn foo(&self) -> (usize, bool) { + (0, true) + } +} + +fn main() { + let s = Struct {}; + let (foo, bar) = s.foo(); + let (foo, bar) = Struct::foo(&s); + println!("{foo} {bar}"); +} +"#, + r#" +struct Struct; + +struct FooResult(usize, bool); + +trait Foo { + fn foo(&self) -> FooResult; +} + +impl Foo for Struct { + fn foo(&self) -> FooResult { + FooResult(0, true) + } +} + +fn main() { + let s = Struct {}; + let FooResult(foo, bar) = s.foo(); + let FooResult(foo, bar) = Struct::foo(&s); + println!("{foo} {bar}"); +} +"#, + ) + } + + #[test] + fn body_wraps_nested() { + check_assist( + convert_tuple_return_type_to_struct, + r#" +fn foo() -> $0(u8, usize, u32) { + if true { + match 3 { + 0 => (1, 2, 3), + _ => return (4, 5, 6), + } + } else { + (2, 1, 3) + } +} +"#, + r#" +struct FooResult(u8, usize, u32); + +fn foo() -> FooResult { + if true { + match 3 { + 0 => FooResult(1, 2, 3), + _ => return FooResult(4, 5, 6), + } + } else { + FooResult(2, 1, 3) + } +} +"#, + ) + } + + #[test] + fn body_wraps_break_and_return() { + check_assist( + convert_tuple_return_type_to_struct, + r#" +fn foo(mut i: isize) -> (usize, $0u32, u8) { + if i < 0 { + return (0, 0, 0); + } + + loop { + if i == 2 { + println!("foo"); + break (1, 2, 3); + } + i += 1; + } +} +"#, + r#" +struct FooResult(usize, u32, u8); + +fn foo(mut i: isize) -> FooResult { + if i < 0 { + return FooResult(0, 0, 0); + } + + loop { + if i == 2 { + println!("foo"); + break FooResult(1, 2, 3); + } + i += 1; + } +} +"#, + ) + } + + #[test] + fn body_doesnt_wrap_identifier() { + check_assist( + convert_tuple_return_type_to_struct, + r#" +fn foo() -> $0(u8, usize, u32) { + let tuple = (1, 2, 3); + tuple +} +"#, + r#" +struct FooResult(u8, usize, u32); + +fn foo() -> FooResult { + let tuple = (1, 2, 3); + tuple +} +"#, + ) + } + + #[test] + fn body_doesnt_wrap_other_exprs() { + check_assist( + convert_tuple_return_type_to_struct, + r#" +fn bar(num: usize) -> (u8, usize, u32) { + (1, num, 3) +} + +fn foo() -> $0(u8, usize, u32) { + bar(2) +} +"#, + r#" +fn bar(num: usize) -> (u8, usize, u32) { + (1, num, 3) +} + +struct FooResult(u8, usize, u32); + +fn foo() -> FooResult { + bar(2) +} +"#, + ) + } + + #[test] + fn cross_file_and_module() { + check_assist( + convert_tuple_return_type_to_struct, + r#" +//- /main.rs +mod foo; + +fn main() { + use foo::bar; + + let (bar, baz) = bar::bar(); + println!("{}", bar == baz); +} + +//- /foo.rs +pub mod bar { + pub fn bar() -> $0(usize, usize) { + (1, 3) + } +} +"#, + r#" +//- /main.rs +use crate::foo::bar::BarResult; + +mod foo; + +fn main() { + use foo::bar; + + let BarResult(bar, baz) = bar::bar(); + println!("{}", bar == baz); +} + +//- /foo.rs +pub mod bar { + pub struct BarResult(pub usize, pub usize); + + pub fn bar() -> BarResult { + BarResult(1, 3) + } +} +"#, + ) + } + + #[test] + fn does_not_replace_nested_usage() { + check_assist( + convert_tuple_return_type_to_struct, + r#" +fn bar() -> $0(usize, bool) { + (42, true) +} + +fn main() { + let ((bar1, bar2), foo) = (bar(), 3); + println!("{bar1} {bar2} {foo}"); +} +"#, + r#" +struct BarResult(usize, bool); + +fn bar() -> BarResult { + BarResult(42, true) +} + +fn main() { + let ((bar1, bar2), foo) = (bar(), 3); + println!("{bar1} {bar2} {foo}"); +} +"#, + ) + } + + #[test] + fn function_with_non_tuple_return_type() { + check_assist_not_applicable( + convert_tuple_return_type_to_struct, + r#" +fn bar() -> $0usize { + 0 +} +"#, + ) + } + + #[test] + fn function_with_impl_type() { + check_assist_not_applicable( + convert_tuple_return_type_to_struct, + r#" +fn bar() -> $0(impl Clone, usize) { + ("bar", 0) +} +"#, + ) + } +} diff --git a/crates/ide-assists/src/lib.rs b/crates/ide-assists/src/lib.rs index a17ce93e928c..3dd1be869df5 100644 --- a/crates/ide-assists/src/lib.rs +++ b/crates/ide-assists/src/lib.rs @@ -125,6 +125,7 @@ mod handlers { mod convert_let_else_to_match; mod convert_match_to_let_else; mod convert_nested_function_to_closure; + mod convert_tuple_return_type_to_struct; mod convert_tuple_struct_to_named_struct; mod convert_named_struct_to_tuple_struct; mod convert_to_guarded_return; @@ -239,6 +240,7 @@ mod handlers { convert_iter_for_each_to_for::convert_for_loop_with_for_each, convert_let_else_to_match::convert_let_else_to_match, convert_match_to_let_else::convert_match_to_let_else, + convert_tuple_return_type_to_struct::convert_tuple_return_type_to_struct, convert_named_struct_to_tuple_struct::convert_named_struct_to_tuple_struct, convert_nested_function_to_closure::convert_nested_function_to_closure, convert_to_guarded_return::convert_to_guarded_return, diff --git a/crates/ide-assists/src/tests/generated.rs b/crates/ide-assists/src/tests/generated.rs index 63a08a0e5697..cc87ee7b8558 100644 --- a/crates/ide-assists/src/tests/generated.rs +++ b/crates/ide-assists/src/tests/generated.rs @@ -586,6 +586,33 @@ fn main() { ) } +#[test] +fn doctest_convert_tuple_return_type_to_struct() { + check_doc_test( + "convert_tuple_return_type_to_struct", + r#####" +fn bar() { + let (a, b, c) = foo(); +} + +fn foo() -> ($0u32, u32, u32) { + (1, 2, 3) +} +"#####, + r#####" +fn bar() { + let FooResult(a, b, c) = foo(); +} + +struct FooResult(u32, u32, u32); + +fn foo() -> FooResult { + FooResult(1, 2, 3) +} +"#####, + ) +} + #[test] fn doctest_convert_tuple_struct_to_named_struct() { check_doc_test( From 146a7cc490b6e45e8b4192e38cab3bae00216712 Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Sun, 1 Oct 2023 11:32:37 -0700 Subject: [PATCH 090/435] fix: allow more kinds of if let patterns in guarded return assist --- .../src/handlers/convert_to_guarded_return.rs | 76 ++++++++++++++----- 1 file changed, 57 insertions(+), 19 deletions(-) diff --git a/crates/ide-assists/src/handlers/convert_to_guarded_return.rs b/crates/ide-assists/src/handlers/convert_to_guarded_return.rs index 7d0e424769ec..73ba3f5c4cdc 100644 --- a/crates/ide-assists/src/handlers/convert_to_guarded_return.rs +++ b/crates/ide-assists/src/handlers/convert_to_guarded_return.rs @@ -51,22 +51,7 @@ pub(crate) fn convert_to_guarded_return(acc: &mut Assists, ctx: &AssistContext<' // Check if there is an IfLet that we can handle. let (if_let_pat, cond_expr) = if is_pattern_cond(cond.clone()) { let let_ = single_let(cond)?; - match let_.pat() { - Some(ast::Pat::TupleStructPat(pat)) if pat.fields().count() == 1 => { - let path = pat.path()?; - if path.qualifier().is_some() { - return None; - } - - let bound_ident = pat.fields().next()?; - if !ast::IdentPat::can_cast(bound_ident.syntax().kind()) { - return None; - } - - (Some((path, bound_ident)), let_.expr()?) - } - _ => return None, // Unsupported IfLet. - } + (Some(let_.pat()?), let_.expr()?) } else { (None, cond) }; @@ -136,11 +121,10 @@ pub(crate) fn convert_to_guarded_return(acc: &mut Assists, ctx: &AssistContext<' }; new_expr.syntax().clone_for_update() } - Some((path, bound_ident)) => { + Some(pat) => { // If-let. - let pat = make::tuple_struct_pat(path, once(bound_ident)); let let_else_stmt = make::let_else_stmt( - pat.into(), + pat, None, cond_expr, ast::make::tail_only_block_expr(early_expression), @@ -442,6 +426,60 @@ fn main() { ); } + #[test] + fn convert_arbitrary_if_let_patterns() { + check_assist( + convert_to_guarded_return, + r#" +fn main() { + $0if let None = Some(92) { + foo(); + } +} +"#, + r#" +fn main() { + let None = Some(92) else { return }; + foo(); +} +"#, + ); + + check_assist( + convert_to_guarded_return, + r#" +fn main() { + $0if let [1, x] = [1, 92] { + foo(x); + } +} +"#, + r#" +fn main() { + let [1, x] = [1, 92] else { return }; + foo(x); +} +"#, + ); + + check_assist( + convert_to_guarded_return, + r#" +fn main() { + $0if let (Some(x), None) = (Some(92), None) { + foo(x); + } +} +"#, + r#" +fn main() { + let (Some(x), None) = (Some(92), None) else { return }; + foo(x); +} +"#, + ); + } + #[test] fn ignore_already_converted_if() { check_assist_not_applicable( From 34d3490198fe6e7f56eb60c9665d25ef9cfd6f4e Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Sun, 1 Oct 2023 21:27:06 -0700 Subject: [PATCH 091/435] feat: add assist for applying De Morgan's law to iterators --- .../src/handlers/apply_demorgan.rs | 329 +++++++++++++++++- crates/ide-assists/src/lib.rs | 1 + crates/ide-assists/src/tests/generated.rs | 24 ++ 3 files changed, 352 insertions(+), 2 deletions(-) diff --git a/crates/ide-assists/src/handlers/apply_demorgan.rs b/crates/ide-assists/src/handlers/apply_demorgan.rs index 66bc2f6dadc3..74db300465ae 100644 --- a/crates/ide-assists/src/handlers/apply_demorgan.rs +++ b/crates/ide-assists/src/handlers/apply_demorgan.rs @@ -1,7 +1,13 @@ use std::collections::VecDeque; +use ide_db::{ + assists::GroupLabel, + famous_defs::FamousDefs, + source_change::SourceChangeBuilder, + syntax_helpers::node_ext::{for_each_tail_expr, walk_expr}, +}; use syntax::{ - ast::{self, AstNode, Expr::BinExpr}, + ast::{self, make, AstNode, Expr::BinExpr, HasArgList}, ted::{self, Position}, SyntaxKind, }; @@ -89,7 +95,8 @@ pub(crate) fn apply_demorgan(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti let dm_lhs = demorganed.lhs()?; - acc.add( + acc.add_group( + &GroupLabel("Apply De Morgan's law".to_string()), AssistId("apply_demorgan", AssistKind::RefactorRewrite), "Apply De Morgan's law", op_range, @@ -143,6 +150,122 @@ pub(crate) fn apply_demorgan(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti ) } +// Assist: apply_demorgan_iterator +// +// Apply https://en.wikipedia.org/wiki/De_Morgan%27s_laws[De Morgan's law] to +// `Iterator::all` and `Iterator::any`. +// +// This transforms expressions of the form `!iter.any(|x| predicate(x))` into +// `iter.all(|x| !predicate(x))` and vice versa. This also works the other way for +// `Iterator::all` into `Iterator::any`. +// +// ``` +// # //- minicore: iterator +// fn main() { +// let arr = [1, 2, 3]; +// if !arr.into_iter().$0any(|num| num == 4) { +// println!("foo"); +// } +// } +// ``` +// -> +// ``` +// fn main() { +// let arr = [1, 2, 3]; +// if arr.into_iter().all(|num| num != 4) { +// println!("foo"); +// } +// } +// ``` +pub(crate) fn apply_demorgan_iterator(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { + let method_call: ast::MethodCallExpr = ctx.find_node_at_offset()?; + let (name, arg_expr) = validate_method_call_expr(ctx, &method_call)?; + + let ast::Expr::ClosureExpr(closure_expr) = arg_expr else { return None }; + let closure_body = closure_expr.body()?; + + let op_range = method_call.syntax().text_range(); + let label = format!("Apply De Morgan's law to `Iterator::{}`", name.text().as_str()); + acc.add_group( + &GroupLabel("Apply De Morgan's law".to_string()), + AssistId("apply_demorgan_iterator", AssistKind::RefactorRewrite), + label, + op_range, + |edit| { + // replace the method name + let new_name = match name.text().as_str() { + "all" => make::name_ref("any"), + "any" => make::name_ref("all"), + _ => unreachable!(), + } + .clone_for_update(); + edit.replace_ast(name, new_name); + + // negate all tail expressions in the closure body + let tail_cb = &mut |e: &_| tail_cb_impl(edit, e); + walk_expr(&closure_body, &mut |expr| { + if let ast::Expr::ReturnExpr(ret_expr) = expr { + if let Some(ret_expr_arg) = &ret_expr.expr() { + for_each_tail_expr(ret_expr_arg, tail_cb); + } + } + }); + for_each_tail_expr(&closure_body, tail_cb); + + // negate the whole method call + if let Some(prefix_expr) = method_call + .syntax() + .parent() + .and_then(ast::PrefixExpr::cast) + .filter(|prefix_expr| matches!(prefix_expr.op_kind(), Some(ast::UnaryOp::Not))) + { + edit.delete(prefix_expr.op_token().unwrap().text_range()); + } else { + edit.insert(method_call.syntax().text_range().start(), "!"); + } + }, + ) +} + +/// Ensures that the method call is to `Iterator::all` or `Iterator::any`. +fn validate_method_call_expr( + ctx: &AssistContext<'_>, + method_call: &ast::MethodCallExpr, +) -> Option<(ast::NameRef, ast::Expr)> { + let name_ref = method_call.name_ref()?; + if name_ref.text() != "all" && name_ref.text() != "any" { + return None; + } + let arg_expr = method_call.arg_list()?.args().next()?; + + let sema = &ctx.sema; + + let receiver = method_call.receiver()?; + let it_type = sema.type_of_expr(&receiver)?.adjusted(); + let module = sema.scope(receiver.syntax())?.module(); + let krate = module.krate(); + + let iter_trait = FamousDefs(sema, krate).core_iter_Iterator()?; + it_type.impls_trait(sema.db, iter_trait, &[]).then_some((name_ref, arg_expr)) +} + +fn tail_cb_impl(edit: &mut SourceChangeBuilder, e: &ast::Expr) { + match e { + ast::Expr::BreakExpr(break_expr) => { + if let Some(break_expr_arg) = break_expr.expr() { + for_each_tail_expr(&break_expr_arg, &mut |e| tail_cb_impl(edit, e)) + } + } + ast::Expr::ReturnExpr(_) => { + // all return expressions have already been handled by the walk loop + } + e => { + let inverted_body = invert_boolean_expression(e.clone()); + edit.replace(e.syntax().text_range(), inverted_body.syntax().text()); + } + } +} + #[cfg(test)] mod tests { use super::*; @@ -255,4 +378,206 @@ fn f() { !(S <= S || S < S) } "fn() { let x = a && b && c; }", ) } + + #[test] + fn demorgan_iterator_any_all_reverse() { + check_assist( + apply_demorgan_iterator, + r#" +//- minicore: iterator +fn main() { + let arr = [1, 2, 3]; + if arr.into_iter().all(|num| num $0!= 4) { + println!("foo"); + } +} +"#, + r#" +fn main() { + let arr = [1, 2, 3]; + if !arr.into_iter().any(|num| num == 4) { + println!("foo"); + } +} +"#, + ); + } + + #[test] + fn demorgan_iterator_all_any() { + check_assist( + apply_demorgan_iterator, + r#" +//- minicore: iterator +fn main() { + let arr = [1, 2, 3]; + if !arr.into_iter().$0all(|num| num > 3) { + println!("foo"); + } +} +"#, + r#" +fn main() { + let arr = [1, 2, 3]; + if arr.into_iter().any(|num| num <= 3) { + println!("foo"); + } +} +"#, + ); + } + + #[test] + fn demorgan_iterator_multiple_terms() { + check_assist( + apply_demorgan_iterator, + r#" +//- minicore: iterator +fn main() { + let arr = [1, 2, 3]; + if !arr.into_iter().$0any(|num| num > 3 && num == 23 && num <= 30) { + println!("foo"); + } +} +"#, + r#" +fn main() { + let arr = [1, 2, 3]; + if arr.into_iter().all(|num| !(num > 3 && num == 23 && num <= 30)) { + println!("foo"); + } +} +"#, + ); + } + + #[test] + fn demorgan_iterator_double_negation() { + check_assist( + apply_demorgan_iterator, + r#" +//- minicore: iterator +fn main() { + let arr = [1, 2, 3]; + if !arr.into_iter().$0all(|num| !(num > 3)) { + println!("foo"); + } +} +"#, + r#" +fn main() { + let arr = [1, 2, 3]; + if arr.into_iter().any(|num| num > 3) { + println!("foo"); + } +} +"#, + ); + } + + #[test] + fn demorgan_iterator_double_parens() { + check_assist( + apply_demorgan_iterator, + r#" +//- minicore: iterator +fn main() { + let arr = [1, 2, 3]; + if !arr.into_iter().$0any(|num| (num > 3 && (num == 1 || num == 2))) { + println!("foo"); + } +} +"#, + r#" +fn main() { + let arr = [1, 2, 3]; + if arr.into_iter().all(|num| !(num > 3 && (num == 1 || num == 2))) { + println!("foo"); + } +} +"#, + ); + } + + #[test] + fn demorgan_iterator_multiline() { + check_assist( + apply_demorgan_iterator, + r#" +//- minicore: iterator +fn main() { + let arr = [1, 2, 3]; + if arr + .into_iter() + .all$0(|num| !num.is_negative()) + { + println!("foo"); + } +} +"#, + r#" +fn main() { + let arr = [1, 2, 3]; + if !arr + .into_iter() + .any(|num| num.is_negative()) + { + println!("foo"); + } +} +"#, + ); + } + + #[test] + fn demorgan_iterator_block_closure() { + check_assist( + apply_demorgan_iterator, + r#" +//- minicore: iterator +fn main() { + let arr = [-1, 1, 2, 3]; + if arr.into_iter().all(|num: i32| { + $0if num.is_positive() { + num <= 3 + } else { + num >= -1 + } + }) { + println!("foo"); + } +} +"#, + r#" +fn main() { + let arr = [-1, 1, 2, 3]; + if !arr.into_iter().any(|num: i32| { + if num.is_positive() { + num > 3 + } else { + num < -1 + } + }) { + println!("foo"); + } +} +"#, + ); + } + + #[test] + fn demorgan_iterator_wrong_method() { + check_assist_not_applicable( + apply_demorgan_iterator, + r#" +//- minicore: iterator +fn main() { + let arr = [1, 2, 3]; + if !arr.into_iter().$0map(|num| num > 3) { + println!("foo"); + } +} +"#, + ); + } } diff --git a/crates/ide-assists/src/lib.rs b/crates/ide-assists/src/lib.rs index a17ce93e928c..50476ccf3638 100644 --- a/crates/ide-assists/src/lib.rs +++ b/crates/ide-assists/src/lib.rs @@ -226,6 +226,7 @@ mod handlers { add_return_type::add_return_type, add_turbo_fish::add_turbo_fish, apply_demorgan::apply_demorgan, + apply_demorgan::apply_demorgan_iterator, auto_import::auto_import, bind_unused_param::bind_unused_param, bool_to_enum::bool_to_enum, diff --git a/crates/ide-assists/src/tests/generated.rs b/crates/ide-assists/src/tests/generated.rs index 5a815d5c6a18..65bd74c018bb 100644 --- a/crates/ide-assists/src/tests/generated.rs +++ b/crates/ide-assists/src/tests/generated.rs @@ -244,6 +244,30 @@ fn main() { ) } +#[test] +fn doctest_apply_demorgan_iterator() { + check_doc_test( + "apply_demorgan_iterator", + r#####" +//- minicore: iterator +fn main() { + let arr = [1, 2, 3]; + if !arr.into_iter().$0any(|num| num == 4) { + println!("foo"); + } +} +"#####, + r#####" +fn main() { + let arr = [1, 2, 3]; + if arr.into_iter().all(|num| num != 4) { + println!("foo"); + } +} +"#####, + ) +} + #[test] fn doctest_auto_import() { check_doc_test( From 084ee934b8fe9bcec5a05c724805e48875e09d2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Mon, 2 Oct 2023 10:47:18 +0300 Subject: [PATCH 092/435] Strip base prefix in layout_scalar_valid_range --- crates/hir-ty/src/layout/adt.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/hir-ty/src/layout/adt.rs b/crates/hir-ty/src/layout/adt.rs index 457b227427ed..c2778b9a8ea0 100644 --- a/crates/hir-ty/src/layout/adt.rs +++ b/crates/hir-ty/src/layout/adt.rs @@ -120,14 +120,14 @@ fn layout_scalar_valid_range(db: &dyn HirDatabase, def: AdtId) -> (Bound, for tree in attr { if let Some(it) = tree.token_trees.first() { let text = it.to_string().replace('_', ""); - let base = match text.as_bytes() { - [b'0', b'x', ..] => 16, - [b'0', b'o', ..] => 8, - [b'0', b'b', ..] => 2, - _ => 10, + let (text, base) = match text.as_bytes() { + [b'0', b'x', ..] => (&text[2..], 16), + [b'0', b'o', ..] => (&text[2..], 8), + [b'0', b'b', ..] => (&text[2..], 2), + _ => (&*text, 10), }; - if let Ok(it) = u128::from_str_radix(&text, base) { + if let Ok(it) = u128::from_str_radix(text, base) { return Bound::Included(it); } } From 7c113ee77ce1a81d0f177b01ed24c88eae9e17ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Tue, 3 Oct 2023 17:32:57 +0300 Subject: [PATCH 093/435] Add mock description to rustc-dependencies --- crates/rustc-dependencies/Cargo.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/rustc-dependencies/Cargo.toml b/crates/rustc-dependencies/Cargo.toml index 901706d3d95f..5c5a3cd8bf32 100644 --- a/crates/rustc-dependencies/Cargo.toml +++ b/crates/rustc-dependencies/Cargo.toml @@ -1,6 +1,8 @@ [package] name = "rustc-dependencies" version = "0.0.0" +description = "TBD" + rust-version.workspace = true edition.workspace = true license.workspace = true From a8ec77dc7e30af115f542e137395e204b0fb5b28 Mon Sep 17 00:00:00 2001 From: David Barsky Date: Tue, 3 Oct 2023 16:44:09 -0400 Subject: [PATCH 094/435] address PR feedback. --- crates/rust-analyzer/src/handlers/request.rs | 40 +++----------------- 1 file changed, 6 insertions(+), 34 deletions(-) diff --git a/crates/rust-analyzer/src/handlers/request.rs b/crates/rust-analyzer/src/handlers/request.rs index ad6319586cfe..8dc0c97bc58f 100644 --- a/crates/rust-analyzer/src/handlers/request.rs +++ b/crates/rust-analyzer/src/handlers/request.rs @@ -1997,41 +1997,13 @@ fn run_rustfmt( } RustfmtConfig::CustomCommand { command, args } => { let cmd = PathBuf::from(&command); - let mut components = cmd.components(); - - // to support rustc's suggested, default configuration - let mut cmd = match components.next() { - Some(std::path::Component::CurDir) => { - let rest = components.as_path(); - - let roots = snap - .workspaces - .iter() - .flat_map(|ws| ws.workspace_definition_path()) - .collect::>(); - - let abs: Option = roots.into_iter().find_map(|base| { - let abs = base.join(rest); - std::fs::metadata(&abs).ok().map(|_| abs) - }); - - let command = match abs { - Some(cmd) => cmd, - None => { - tracing::error!( - rustfmt = ?command, - "Unable to make the format command an absolute path" - ); - anyhow::bail!( - "Unable to make the format command an absolute path: {}", - command - ); - } - }; - - process::Command::new(&command.as_os_str()) + let workspace = CargoTargetSpec::for_file(&snap, file_id)?; + let mut cmd = match workspace { + Some(spec) => { + let cmd = spec.workspace_root.join(cmd); + process::Command::new(cmd.as_os_str()) } - _ => process::Command::new(command), + None => process::Command::new(cmd), }; cmd.envs(snap.config.extra_env()); From 61361bb2129208c67134432f0bb1264749ed7180 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Tue, 3 Oct 2023 21:12:23 +0000 Subject: [PATCH 095/435] Use `transmute_unchecked` and make the types explicit in query type erasure This doesn't really change anything, but makes the code a bit more explicit/readable. --- compiler/rustc_middle/src/query/erase.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index 8ba3764bcc31..88af3eac6ae9 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -2,7 +2,8 @@ use crate::mir; use crate::query::CyclePlaceholder; use crate::traits; use crate::ty::{self, Ty}; -use std::mem::{size_of, transmute_copy, MaybeUninit}; +use std::mem::{size_of, MaybeUninit}; +use std::intrinsics::transmute_unchecked; #[derive(Copy, Clone)] pub struct Erased { @@ -30,7 +31,7 @@ pub fn erase(src: T) -> Erase { Erased::<::Result> { // SAFETY: It is safe to transmute to MaybeUninit for types with the same sizes. - data: unsafe { transmute_copy(&src) }, + data: unsafe { transmute_unchecked::>(src) }, } } @@ -41,7 +42,7 @@ pub fn restore(value: Erase) -> T { // SAFETY: Due to the use of impl Trait in `Erase` the only way to safely create an instance // of `Erase` is to call `erase`, so we know that `value.data` is a valid instance of `T` of // the right size. - unsafe { transmute_copy(&value.data) } + unsafe { transmute_unchecked::, T>(value.data) } } impl EraseType for &'_ T { From b3d50255d9100a5034a7ef350aec29595c020faf Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Tue, 3 Oct 2023 21:13:19 +0000 Subject: [PATCH 096/435] Use consisntent style of `size_of` in query type erasure All other impls replace type generics with `()` (or a type implementing the necessery traits) and lifetimes with `'static`, do the same for those impls. --- compiler/rustc_middle/src/query/erase.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index 88af3eac6ae9..deefd438c4ad 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -2,8 +2,8 @@ use crate::mir; use crate::query::CyclePlaceholder; use crate::traits; use crate::ty::{self, Ty}; -use std::mem::{size_of, MaybeUninit}; use std::intrinsics::transmute_unchecked; +use std::mem::{size_of, MaybeUninit}; #[derive(Copy, Clone)] pub struct Erased { @@ -46,15 +46,15 @@ pub fn restore(value: Erase) -> T { } impl EraseType for &'_ T { - type Result = [u8; size_of::<*const ()>()]; + type Result = [u8; size_of::<&'static ()>()]; } impl EraseType for &'_ [T] { - type Result = [u8; size_of::<*const [()]>()]; + type Result = [u8; size_of::<&'static [()]>()]; } impl EraseType for &'_ ty::List { - type Result = [u8; size_of::<*const ()>()]; + type Result = [u8; size_of::<&'static ty::List<()>>()]; } impl EraseType for &'_ rustc_index::IndexSlice { From fe398163b63c11ccc3e4879c77a1157cd65af164 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 4 Oct 2023 12:04:37 +0200 Subject: [PATCH 097/435] Recognize custom main function as binary entrypoint for runnables --- crates/hir-def/src/attr.rs | 4 ++ crates/hir/src/lib.rs | 11 +++++ crates/ide/src/runnables.rs | 80 ++++++++++++++++++++++++++----------- 3 files changed, 72 insertions(+), 23 deletions(-) diff --git a/crates/hir-def/src/attr.rs b/crates/hir-def/src/attr.rs index c6454eb9ea02..fa3025e0303d 100644 --- a/crates/hir-def/src/attr.rs +++ b/crates/hir-def/src/attr.rs @@ -215,6 +215,10 @@ impl Attrs { self.doc_exprs().flat_map(|doc_expr| doc_expr.aliases().to_vec()) } + pub fn export_name(&self) -> Option<&SmolStr> { + self.by_key("export_name").string_value() + } + pub fn is_proc_macro(&self) -> bool { self.by_key("proc_macro").exists() } diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index a6c6c0dbb8bf..8e48afd6af81 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -1971,6 +1971,17 @@ impl Function { db.function_data(self.id).attrs.is_test() } + /// is this a `fn main` or a function with an `export_name` of `main`? + pub fn is_main(self, db: &dyn HirDatabase) -> bool { + if !self.module(db).is_crate_root() { + return false; + } + let data = db.function_data(self.id); + + data.name.to_smol_str() == "main" + || data.attrs.export_name().map(core::ops::Deref::deref) == Some("main") + } + /// Does this function have the ignore attribute? pub fn is_ignore(self, db: &dyn HirDatabase) -> bool { db.function_data(self.id).attrs.is_ignore() diff --git a/crates/ide/src/runnables.rs b/crates/ide/src/runnables.rs index 2d528c642558..07cdddd15f82 100644 --- a/crates/ide/src/runnables.rs +++ b/crates/ide/src/runnables.rs @@ -308,11 +308,7 @@ pub(crate) fn runnable_fn( sema: &Semantics<'_, RootDatabase>, def: hir::Function, ) -> Option { - let name = def.name(sema.db).to_smol_str(); - - let root = def.module(sema.db).krate().root_module(); - - let kind = if name == "main" && def.module(sema.db) == root { + let kind = if def.is_main(sema.db) { RunnableKind::Bin } else { let test_id = || { @@ -320,7 +316,9 @@ pub(crate) fn runnable_fn( let def: hir::ModuleDef = def.into(); def.canonical_path(sema.db) }; - canonical_path.map(TestId::Path).unwrap_or(TestId::Name(name)) + canonical_path + .map(TestId::Path) + .unwrap_or(TestId::Name(def.name(sema.db).to_smol_str())) }; if def.is_test(sema.db) { @@ -587,6 +585,9 @@ mod tests { $0 fn main() {} +#[export_name = "main"] +fn __cortex_m_rt_main_trampoline() {} + #[test] fn test_foo() {} @@ -604,7 +605,7 @@ mod not_a_root { fn main() {} } "#, - &[TestMod, Bin, Test, Test, Test, Bench], + &[TestMod, Bin, Bin, Test, Test, Test, Bench], expect![[r#" [ Runnable { @@ -613,7 +614,7 @@ mod not_a_root { file_id: FileId( 0, ), - full_range: 0..190, + full_range: 0..253, name: "", kind: Module, }, @@ -642,8 +643,22 @@ mod not_a_root { file_id: FileId( 0, ), - full_range: 15..39, - focus_range: 26..34, + full_range: 15..76, + focus_range: 42..71, + name: "__cortex_m_rt_main_trampoline", + kind: Function, + }, + kind: Bin, + cfg: None, + }, + Runnable { + use_name_in_title: false, + nav: NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 78..102, + focus_range: 89..97, name: "test_foo", kind: Function, }, @@ -663,8 +678,8 @@ mod not_a_root { file_id: FileId( 0, ), - full_range: 41..92, - focus_range: 73..87, + full_range: 104..155, + focus_range: 136..150, name: "test_full_path", kind: Function, }, @@ -684,8 +699,8 @@ mod not_a_root { file_id: FileId( 0, ), - full_range: 94..128, - focus_range: 115..123, + full_range: 157..191, + focus_range: 178..186, name: "test_foo", kind: Function, }, @@ -705,8 +720,8 @@ mod not_a_root { file_id: FileId( 0, ), - full_range: 130..152, - focus_range: 142..147, + full_range: 193..215, + focus_range: 205..210, name: "bench", kind: Function, }, @@ -1655,12 +1670,18 @@ macro_rules! gen2 { } } } +macro_rules! gen_main { + () => { + fn main() {} + } +} mod tests { gen!(); } gen2!(); +gen_main!(); "#, - &[TestMod, TestMod, Test, Test, TestMod], + &[TestMod, TestMod, Test, Test, TestMod, Bin], expect![[r#" [ Runnable { @@ -1669,7 +1690,7 @@ gen2!(); file_id: FileId( 0, ), - full_range: 0..237, + full_range: 0..315, name: "", kind: Module, }, @@ -1684,8 +1705,8 @@ gen2!(); file_id: FileId( 0, ), - full_range: 202..227, - focus_range: 206..211, + full_range: 267..292, + focus_range: 271..276, name: "tests", kind: Module, description: "mod tests", @@ -1701,7 +1722,7 @@ gen2!(); file_id: FileId( 0, ), - full_range: 218..225, + full_range: 283..290, name: "foo_test", kind: Function, }, @@ -1721,7 +1742,7 @@ gen2!(); file_id: FileId( 0, ), - full_range: 228..236, + full_range: 293..301, name: "foo_test2", kind: Function, }, @@ -1741,7 +1762,7 @@ gen2!(); file_id: FileId( 0, ), - full_range: 228..236, + full_range: 293..301, name: "tests2", kind: Module, description: "mod tests2", @@ -1751,6 +1772,19 @@ gen2!(); }, cfg: None, }, + Runnable { + use_name_in_title: false, + nav: NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 302..314, + name: "main", + kind: Function, + }, + kind: Bin, + cfg: None, + }, ] "#]], ); From c266387e130de11c60be2c2d7d0a1d5c3bc3eb62 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 4 Oct 2023 13:06:23 +0200 Subject: [PATCH 098/435] Replace unwrap with expect --- crates/ide-assists/src/handlers/apply_demorgan.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/crates/ide-assists/src/handlers/apply_demorgan.rs b/crates/ide-assists/src/handlers/apply_demorgan.rs index 74db300465ae..2d41243c20eb 100644 --- a/crates/ide-assists/src/handlers/apply_demorgan.rs +++ b/crates/ide-assists/src/handlers/apply_demorgan.rs @@ -219,7 +219,12 @@ pub(crate) fn apply_demorgan_iterator(acc: &mut Assists, ctx: &AssistContext<'_> .and_then(ast::PrefixExpr::cast) .filter(|prefix_expr| matches!(prefix_expr.op_kind(), Some(ast::UnaryOp::Not))) { - edit.delete(prefix_expr.op_token().unwrap().text_range()); + edit.delete( + prefix_expr + .op_token() + .expect("prefix expression always has an operator") + .text_range(), + ); } else { edit.insert(method_call.syntax().text_range().start(), "!"); } From 9ba8dbc902321301c084d7512b14589ebe1b024e Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Wed, 4 Oct 2023 08:04:59 -0700 Subject: [PATCH 099/435] style: clean up magic number for finding pattern usages --- .../convert_tuple_return_type_to_struct.rs | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/crates/ide-assists/src/handlers/convert_tuple_return_type_to_struct.rs b/crates/ide-assists/src/handlers/convert_tuple_return_type_to_struct.rs index c71a2de7c0f9..32db5ee8dabf 100644 --- a/crates/ide-assists/src/handlers/convert_tuple_return_type_to_struct.rs +++ b/crates/ide-assists/src/handlers/convert_tuple_return_type_to_struct.rs @@ -129,16 +129,12 @@ fn replace_usages( let pats = name .syntax() .ancestors() - .nth(5) - .and_then(node_to_pats) - .or_else(|| { - cov_mark::hit!(replace_method_usage); - - name.syntax() - .parent() - .filter(|node| ast::MethodCallExpr::can_cast(node.kind())) - .and_then(|node| node.parent().and_then(node_to_pats)) + .find(|node| { + ast::CallExpr::can_cast(node.kind()) + || ast::MethodCallExpr::can_cast(node.kind()) }) + .and_then(|node| node.parent()) + .and_then(node_to_pats) .unwrap_or(Vec::new()); let tuple_pats = pats.iter().filter_map(|pat| match pat { @@ -387,7 +383,6 @@ fn main() { #[test] fn method_usage() { - cov_mark::check!(replace_method_usage); check_assist( convert_tuple_return_type_to_struct, r#" From ab091b73d0117d9788549289d3cd1ac709b462dd Mon Sep 17 00:00:00 2001 From: dfireBird Date: Wed, 4 Oct 2023 10:14:03 +0530 Subject: [PATCH 100/435] Add config for the default click action of extension status bar --- editors/code/package.json | 13 +++++++++++++ editors/code/src/config.ts | 4 ++++ editors/code/src/ctx.ts | 6 +++++- 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/editors/code/package.json b/editors/code/package.json index 639588566344..349f49465e31 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -371,6 +371,19 @@ ], "markdownDescription": "Problem matchers to use for `rust-analyzer.run` command, eg `[\"$rustc\", \"$rust-panic\"]`." }, + "rust-analyzer.statusBar.clickAction": { + "type": "string", + "enum": [ + "stopServer", + "openLogs" + ], + "enumDescriptions": [ + "Stop Server", + "Open Logs" + ], + "default": "openLogs", + "markdownDescription": "Action to run when clicking the extension status bar item." + }, "rust-analyzer.server.path": { "type": [ "null", diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts index 9821aee6f92b..987d936943a1 100644 --- a/editors/code/src/config.ts +++ b/editors/code/src/config.ts @@ -329,6 +329,10 @@ export class Config { get showDependenciesExplorer() { return this.get("showDependenciesExplorer"); } + + get statusBarClickAction() { + return this.get("statusBar.clickAction"); + } } // the optional `cb?` parameter is meant to be used to add additional diff --git a/editors/code/src/ctx.ts b/editors/code/src/ctx.ts index 904efa4d5eb0..84d1ad98bd98 100644 --- a/editors/code/src/ctx.ts +++ b/editors/code/src/ctx.ts @@ -400,7 +400,11 @@ export class Ctx { statusBar.tooltip.appendText(status.message ?? "Ready"); statusBar.color = undefined; statusBar.backgroundColor = undefined; - statusBar.command = "rust-analyzer.openLogs"; + if (this.config.statusBarClickAction === "stopServer") { + statusBar.command = "rust-analyzer.stopServer"; + } else { + statusBar.command = "rust-analyzer.openLogs"; + } this.dependencies?.refresh(); break; case "warning": From 4af730eb26fc8fc41e0fd8952e8b04759910b580 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 5 Oct 2023 13:21:12 +0200 Subject: [PATCH 101/435] Do flyimport completions by prefix search for short paths --- crates/hir-def/src/import_map.rs | 13 +++- .../src/completions/flyimport.rs | 12 +-- crates/ide-completion/src/tests/flyimport.rs | 76 ++++++++++++++++--- crates/ide-db/src/imports/import_assets.rs | 47 +++++++++--- crates/ide-db/src/items_locator.rs | 30 +++++--- crates/ide-db/src/symbol_index.rs | 43 ++++++++--- 6 files changed, 174 insertions(+), 47 deletions(-) diff --git a/crates/hir-def/src/import_map.rs b/crates/hir-def/src/import_map.rs index 90763d4c3dfe..6461439bb713 100644 --- a/crates/hir-def/src/import_map.rs +++ b/crates/hir-def/src/import_map.rs @@ -283,6 +283,8 @@ enum SearchMode { /// Import map entry should contain all letters from the query string, /// in the same order, but not necessary adjacent. Fuzzy, + /// Import map entry should match the query string by prefix. + Prefix, } /// Three possible ways to search for the name in associated and/or other items. @@ -324,6 +326,14 @@ impl Query { Self { search_mode: SearchMode::Fuzzy, ..self } } + pub fn prefix(self) -> Self { + Self { search_mode: SearchMode::Prefix, ..self } + } + + pub fn exact(self) -> Self { + Self { search_mode: SearchMode::Exact, ..self } + } + /// Specifies whether we want to include associated items in the result. pub fn assoc_search_mode(self, assoc_mode: AssocSearchMode) -> Self { Self { assoc_mode, ..self } @@ -361,7 +371,8 @@ impl Query { let query_string = if case_insensitive { &self.lowercased } else { &self.query }; match self.search_mode { - SearchMode::Exact => &input == query_string, + SearchMode::Exact => input == *query_string, + SearchMode::Prefix => input.starts_with(query_string), SearchMode::Fuzzy => { let mut input_chars = input.chars(); for query_char in query_string.chars() { diff --git a/crates/ide-completion/src/completions/flyimport.rs b/crates/ide-completion/src/completions/flyimport.rs index 39c1b7f7b3fb..0961021e48e0 100644 --- a/crates/ide-completion/src/completions/flyimport.rs +++ b/crates/ide-completion/src/completions/flyimport.rs @@ -13,10 +13,9 @@ use crate::{ TypeLocation, }, render::{render_resolution_with_import, render_resolution_with_import_pat, RenderContext}, + Completions, }; -use super::Completions; - // Feature: Completion With Autoimport // // When completing names in the current scope, proposes additional imports from other modules or crates, @@ -377,9 +376,12 @@ fn import_assets_for_path( &ctx.sema, ctx.token.parent()?, )?; - if fuzzy_name_length < 3 { - cov_mark::hit!(flyimport_exact_on_short_path); - assets_for_path.path_fuzzy_name_to_exact(false); + if fuzzy_name_length == 0 { + // nothing matches the empty string exactly, but we still compute assoc items in this case + assets_for_path.path_fuzzy_name_to_exact(); + } else if fuzzy_name_length < 3 { + cov_mark::hit!(flyimport_prefix_on_short_path); + assets_for_path.path_fuzzy_name_to_prefix(); } Some(assets_for_path) } diff --git a/crates/ide-completion/src/tests/flyimport.rs b/crates/ide-completion/src/tests/flyimport.rs index 4cdfd546f6ad..21f693d79f1d 100644 --- a/crates/ide-completion/src/tests/flyimport.rs +++ b/crates/ide-completion/src/tests/flyimport.rs @@ -116,19 +116,47 @@ fn main() { } #[test] -fn short_paths_are_ignored() { - cov_mark::check!(flyimport_exact_on_short_path); +fn short_paths_are_prefix_matched() { + cov_mark::check!(flyimport_prefix_on_short_path); check( r#" //- /lib.rs crate:dep -pub struct Bar; +pub struct Barc; pub struct Rcar; pub struct Rc; +pub const RC: () = (); pub mod some_module { pub struct Bar; pub struct Rcar; pub struct Rc; + pub const RC: () = (); +} + +//- /main.rs crate:main deps:dep +fn main() { + Rc$0 +} +"#, + expect![[r#" + st Rc (use dep::Rc) + st Rcar (use dep::Rcar) + st Rc (use dep::some_module::Rc) + st Rcar (use dep::some_module::Rcar) + "#]], + ); + check( + r#" +//- /lib.rs crate:dep +pub struct Barc; +pub struct Rcar; +pub struct Rc; +pub const RC: () = (); +pub mod some_module { + pub struct Bar; + pub struct Rcar; + pub struct Rc; + pub const RC: () = (); } //- /main.rs crate:main deps:dep @@ -137,8 +165,36 @@ fn main() { } "#, expect![[r#" + ct RC (use dep::RC) st Rc (use dep::Rc) + st Rcar (use dep::Rcar) + ct RC (use dep::some_module::RC) st Rc (use dep::some_module::Rc) + st Rcar (use dep::some_module::Rcar) + "#]], + ); + check( + r#" +//- /lib.rs crate:dep +pub struct Barc; +pub struct Rcar; +pub struct Rc; +pub const RC: () = (); +pub mod some_module { + pub struct Bar; + pub struct Rcar; + pub struct Rc; + pub const RC: () = (); +} + +//- /main.rs crate:main deps:dep +fn main() { + RC$0 +} +"#, + expect![[r#" + ct RC (use dep::RC) + ct RC (use dep::some_module::RC) "#]], ); } @@ -841,8 +897,8 @@ fn main() { TES$0 }"#, expect![[r#" - ct TEST_CONST (use foo::TEST_CONST) - "#]], + ct TEST_CONST (use foo::TEST_CONST) + "#]], ); check( @@ -858,9 +914,9 @@ fn main() { tes$0 }"#, expect![[r#" - ct TEST_CONST (use foo::TEST_CONST) - fn test_function() (use foo::test_function) fn() -> i32 - "#]], + ct TEST_CONST (use foo::TEST_CONST) + fn test_function() (use foo::test_function) fn() -> i32 + "#]], ); check( @@ -873,9 +929,9 @@ mod foo { } fn main() { - Te$0 + Tes$0 }"#, - expect![[]], + expect![""], ); } diff --git a/crates/ide-db/src/imports/import_assets.rs b/crates/ide-db/src/imports/import_assets.rs index e475c5cd66b6..da5a951f0b7b 100644 --- a/crates/ide-db/src/imports/import_assets.rs +++ b/crates/ide-db/src/imports/import_assets.rs @@ -68,22 +68,29 @@ pub struct FirstSegmentUnresolved { pub enum NameToImport { /// Requires items with names that exactly match the given string, bool indicates case-sensitivity. Exact(String, bool), - /// Requires items with names that case-insensitively contain all letters from the string, + /// Requires items with names that match the given string by prefix, bool indicates case-sensitivity. + Prefix(String, bool), + /// Requires items with names contain all letters from the string, /// in the same order, but not necessary adjacent. - Fuzzy(String), + Fuzzy(String, bool), } impl NameToImport { pub fn exact_case_sensitive(s: String) -> NameToImport { NameToImport::Exact(s, true) } -} -impl NameToImport { + pub fn fuzzy(s: String) -> NameToImport { + // unless all chars are lowercase, we do a case sensitive search + let case_sensitive = s.chars().any(|c| c.is_uppercase()); + NameToImport::Fuzzy(s, case_sensitive) + } + pub fn text(&self) -> &str { match self { - NameToImport::Exact(text, _) => text.as_str(), - NameToImport::Fuzzy(text) => text.as_str(), + NameToImport::Prefix(text, _) + | NameToImport::Exact(text, _) + | NameToImport::Fuzzy(text, _) => text.as_str(), } } } @@ -165,7 +172,7 @@ impl ImportAssets { Some(Self { import_candidate: ImportCandidate::TraitMethod(TraitImportCandidate { receiver_ty, - assoc_item_name: NameToImport::Fuzzy(fuzzy_method_name), + assoc_item_name: NameToImport::fuzzy(fuzzy_method_name), }), module_with_candidate: module_with_method_call, candidate_node, @@ -228,12 +235,30 @@ impl ImportAssets { self.search_for(sema, None, prefer_no_std) } - pub fn path_fuzzy_name_to_exact(&mut self, case_sensitive: bool) { + /// Requires imports to by prefix instead of fuzzily. + pub fn path_fuzzy_name_to_prefix(&mut self) { if let ImportCandidate::Path(PathImportCandidate { name: to_import, .. }) = &mut self.import_candidate { - let name = match to_import { - NameToImport::Fuzzy(name) => std::mem::take(name), + let (name, case_sensitive) = match to_import { + NameToImport::Fuzzy(name, case_sensitive) => { + (std::mem::take(name), *case_sensitive) + } + _ => return, + }; + *to_import = NameToImport::Prefix(name, case_sensitive); + } + } + + /// Requires imports to match exactly instead of fuzzily. + pub fn path_fuzzy_name_to_exact(&mut self) { + if let ImportCandidate::Path(PathImportCandidate { name: to_import, .. }) = + &mut self.import_candidate + { + let (name, case_sensitive) = match to_import { + NameToImport::Fuzzy(name, case_sensitive) => { + (std::mem::take(name), *case_sensitive) + } _ => return, }; *to_import = NameToImport::Exact(name, case_sensitive); @@ -623,7 +648,7 @@ impl ImportCandidate { fuzzy_name: String, sema: &Semantics<'_, RootDatabase>, ) -> Option { - path_import_candidate(sema, qualifier, NameToImport::Fuzzy(fuzzy_name)) + path_import_candidate(sema, qualifier, NameToImport::fuzzy(fuzzy_name)) } } diff --git a/crates/ide-db/src/items_locator.rs b/crates/ide-db/src/items_locator.rs index 3f7a3ec2d0fd..67ed44f08b7f 100644 --- a/crates/ide-db/src/items_locator.rs +++ b/crates/ide-db/src/items_locator.rs @@ -31,26 +31,34 @@ pub fn items_with_name<'a>( ) }); + let prefix = matches!(name, NameToImport::Prefix(..)); let (mut local_query, mut external_query) = match name { - NameToImport::Exact(exact_name, case_sensitive) => { + NameToImport::Prefix(exact_name, case_sensitive) + | NameToImport::Exact(exact_name, case_sensitive) => { let mut local_query = symbol_index::Query::new(exact_name.clone()); - local_query.exact(); - - let external_query = import_map::Query::new(exact_name); - - ( - local_query, - if case_sensitive { external_query.case_sensitive() } else { external_query }, - ) + let mut external_query = import_map::Query::new(exact_name); + if prefix { + local_query.prefix(); + external_query = external_query.prefix(); + } else { + local_query.exact(); + external_query = external_query.exact(); + } + if case_sensitive { + local_query.case_sensitive(); + external_query = external_query.case_sensitive(); + } + (local_query, external_query) } - NameToImport::Fuzzy(fuzzy_search_string) => { + NameToImport::Fuzzy(fuzzy_search_string, case_sensitive) => { let mut local_query = symbol_index::Query::new(fuzzy_search_string.clone()); + local_query.fuzzy(); let mut external_query = import_map::Query::new(fuzzy_search_string.clone()) .fuzzy() .assoc_search_mode(assoc_item_search); - if fuzzy_search_string.to_lowercase() != fuzzy_search_string { + if case_sensitive { local_query.case_sensitive(); external_query = external_query.case_sensitive(); } diff --git a/crates/ide-db/src/symbol_index.rs b/crates/ide-db/src/symbol_index.rs index f699f999baf7..3e89159c2c6e 100644 --- a/crates/ide-db/src/symbol_index.rs +++ b/crates/ide-db/src/symbol_index.rs @@ -43,13 +43,20 @@ use triomphe::Arc; use crate::RootDatabase; +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +enum SearchMode { + Fuzzy, + Exact, + Prefix, +} + #[derive(Debug)] pub struct Query { query: String, lowercased: String, only_types: bool, libs: bool, - exact: bool, + mode: SearchMode, case_sensitive: bool, limit: usize, } @@ -62,7 +69,7 @@ impl Query { lowercased, only_types: false, libs: false, - exact: false, + mode: SearchMode::Fuzzy, case_sensitive: false, limit: usize::max_value(), } @@ -76,8 +83,16 @@ impl Query { self.libs = true; } + pub fn fuzzy(&mut self) { + self.mode = SearchMode::Fuzzy; + } + pub fn exact(&mut self) { - self.exact = true; + self.mode = SearchMode::Exact; + } + + pub fn prefix(&mut self) { + self.mode = SearchMode::Prefix; } pub fn case_sensitive(&mut self) { @@ -329,13 +344,23 @@ impl Query { { continue; } - if self.exact { - if symbol.name != self.query { - continue; + let skip = match self.mode { + SearchMode::Fuzzy => { + self.case_sensitive + && self.query.chars().any(|c| !symbol.name.contains(c)) } - } else if self.case_sensitive - && self.query.chars().any(|c| !symbol.name.contains(c)) - { + SearchMode::Exact => symbol.name != self.query, + SearchMode::Prefix if self.case_sensitive => { + !symbol.name.starts_with(&self.query) + } + SearchMode::Prefix => symbol + .name + .chars() + .zip(self.lowercased.chars()) + .all(|(n, q)| n.to_lowercase().next() == Some(q)), + }; + + if skip { continue; } From 58239f2990ac8f148d943960a23c625465f7a80e Mon Sep 17 00:00:00 2001 From: cui fliter Date: Thu, 5 Oct 2023 17:41:50 +0800 Subject: [PATCH 102/435] Remove repetitive words Signed-off-by: cui fliter --- crates/ide/src/syntax_highlighting.rs | 2 +- crates/mbe/src/expander.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/ide/src/syntax_highlighting.rs b/crates/ide/src/syntax_highlighting.rs index bb01c81d66fb..dd72484b3807 100644 --- a/crates/ide/src/syntax_highlighting.rs +++ b/crates/ide/src/syntax_highlighting.rs @@ -245,7 +245,7 @@ fn traverse( let mut macro_highlighter = MacroHighlighter::default(); // FIXME: these are not perfectly accurate, we determine them by the real file's syntax tree - // an an attribute nested in a macro call will not emit `inside_attribute` + // an attribute nested in a macro call will not emit `inside_attribute` let mut inside_attribute = false; let mut inside_macro_call = false; diff --git a/crates/mbe/src/expander.rs b/crates/mbe/src/expander.rs index f2d89d3efe5a..908048c99042 100644 --- a/crates/mbe/src/expander.rs +++ b/crates/mbe/src/expander.rs @@ -119,7 +119,7 @@ enum Fragment { /// precedence. Note that this impl is different from the one currently in /// `rustc` -- `rustc` doesn't translate fragments into token trees at all. /// - /// At one point in time, we tried to to use "fake" delimiters here a-la + /// At one point in time, we tried to use "fake" delimiters here à la /// proc-macro delimiter=none. As we later discovered, "none" delimiters are /// tricky to handle in the parser, and rustc doesn't handle those either. Expr(tt::TokenTree), From e7295ff40cc507627e763425e78003dc7ac977e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Thu, 5 Oct 2023 15:03:44 +0300 Subject: [PATCH 103/435] Prepare for rust-bors --- .github/workflows/ci.yaml | 1 + rust-bors.toml | 1 + 2 files changed, 2 insertions(+) create mode 100644 rust-bors.toml diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 6dc339eddf34..1f2a7796d114 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -8,6 +8,7 @@ on: branches: - auto - try + - automation/bors/try env: CARGO_INCREMENTAL: 0 diff --git a/rust-bors.toml b/rust-bors.toml new file mode 100644 index 000000000000..c31ba66c50f4 --- /dev/null +++ b/rust-bors.toml @@ -0,0 +1 @@ +timeout = 3600 From 114f8a07e99346083e302eed8ea0ab475923b61a Mon Sep 17 00:00:00 2001 From: Tobias Berger Date: Fri, 6 Oct 2023 09:24:28 +0200 Subject: [PATCH 104/435] Fix typos exec_intrinsic --- crates/hir-ty/src/mir/eval/shim.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/hir-ty/src/mir/eval/shim.rs b/crates/hir-ty/src/mir/eval/shim.rs index 803ef631f1e0..2de99e41659c 100644 --- a/crates/hir-ty/src/mir/eval/shim.rs +++ b/crates/hir-ty/src/mir/eval/shim.rs @@ -1045,7 +1045,7 @@ impl Evaluator<'_> { } "transmute" => { let [arg] = args else { - return Err(MirEvalError::TypeError("trasmute arg is not provided")); + return Err(MirEvalError::TypeError("transmute arg is not provided")); }; destination.write_from_interval(self, arg.interval) } @@ -1065,7 +1065,7 @@ impl Evaluator<'_> { } "ctlz" | "ctlz_nonzero" => { let [arg] = args else { - return Err(MirEvalError::TypeError("cttz arg is not provided")); + return Err(MirEvalError::TypeError("ctlz arg is not provided")); }; let result = u128::from_le_bytes(pad16(arg.get(self)?, false)).leading_zeros() as usize; From 88a00bf49d1d183c65489e6d02b6e4678c824322 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 6 Oct 2023 12:32:37 +0200 Subject: [PATCH 105/435] Shrink PatPtr by swapping its AstPtr and Either wrap order --- crates/hir-def/src/body.rs | 6 +- crates/hir-def/src/body/lower.rs | 26 +++-- crates/hir-def/src/body/scope.rs | 5 +- crates/hir-ty/src/diagnostics/decl_check.rs | 72 +++++++------- crates/hir-ty/src/mir/eval.rs | 5 +- crates/hir-ty/src/tests.rs | 14 +-- crates/hir/src/diagnostics.rs | 11 +-- crates/hir/src/lib.rs | 99 ++++++++++--------- .../src/handlers/mismatched_arg_count.rs | 7 +- .../src/handlers/missing_fields.rs | 16 ++- .../src/handlers/no_such_field.rs | 18 ++-- .../src/handlers/private_assoc_item.rs | 10 +- .../src/handlers/type_mismatch.rs | 36 ++++--- .../rust-analyzer/src/cli/analysis_stats.rs | 11 +-- crates/syntax/src/ptr.rs | 18 ++++ 15 files changed, 164 insertions(+), 190 deletions(-) diff --git a/crates/hir-def/src/body.rs b/crates/hir-def/src/body.rs index c0baf6011f79..1942c60c075d 100644 --- a/crates/hir-def/src/body.rs +++ b/crates/hir-def/src/body.rs @@ -57,7 +57,7 @@ pub struct Body { pub type ExprPtr = AstPtr; pub type ExprSource = InFile; -pub type PatPtr = Either, AstPtr>; +pub type PatPtr = AstPtr>; pub type PatSource = InFile; pub type LabelPtr = AstPtr; @@ -356,12 +356,12 @@ impl BodySourceMap { } pub fn node_pat(&self, node: InFile<&ast::Pat>) -> Option { - let src = node.map(|it| Either::Left(AstPtr::new(it))); + let src = node.map(|it| AstPtr::new(it).wrap_left()); self.pat_map.get(&src).cloned() } pub fn node_self_param(&self, node: InFile<&ast::SelfParam>) -> Option { - let src = node.map(|it| Either::Right(AstPtr::new(it))); + let src = node.map(|it| AstPtr::new(it).wrap_right()); self.pat_map.get(&src).cloned() } diff --git a/crates/hir-def/src/body/lower.rs b/crates/hir-def/src/body/lower.rs index cc02df80a8ff..e4158d7564bd 100644 --- a/crates/hir-def/src/body/lower.rs +++ b/crates/hir-def/src/body/lower.rs @@ -196,16 +196,12 @@ impl ExprCollector<'_> { if let Some(self_param) = param_list.self_param().filter(|_| attr_enabled.next().unwrap_or(false)) { - let ptr = AstPtr::new(&self_param); - let binding_id: la_arena::Idx = self.alloc_binding( - name![self], - BindingAnnotation::new( - self_param.mut_token().is_some() && self_param.amp_token().is_none(), - false, - ), - ); - let param_pat = - self.alloc_pat(Pat::Bind { id: binding_id, subpat: None }, Either::Right(ptr)); + let is_mutable = + self_param.mut_token().is_some() && self_param.amp_token().is_none(); + let ptr = AstPtr::new(&Either::Right(self_param)); + let binding_id: la_arena::Idx = + self.alloc_binding(name![self], BindingAnnotation::new(is_mutable, false)); + let param_pat = self.alloc_pat(Pat::Bind { id: binding_id, subpat: None }, ptr); self.add_definition_to_binding(binding_id, param_pat); self.body.params.push(param_pat); } @@ -1260,8 +1256,8 @@ impl ExprCollector<'_> { (Some(id), Pat::Bind { id, subpat }) }; - let ptr = AstPtr::new(&pat); - let pat = self.alloc_pat(pattern, Either::Left(ptr)); + let ptr = AstPtr::new(&Either::Left(pat)); + let pat = self.alloc_pat(pattern, ptr); if let Some(binding_id) = binding { self.add_definition_to_binding(binding_id, pat); } @@ -1395,7 +1391,7 @@ impl ExprCollector<'_> { ast::Pat::MacroPat(mac) => match mac.macro_call() { Some(call) => { let macro_ptr = AstPtr::new(&call); - let src = self.expander.to_source(Either::Left(AstPtr::new(&pat))); + let src = self.expander.to_source(AstPtr::new(&Either::Left(pat))); let pat = self.collect_macro_call(call, macro_ptr, true, |this, expanded_pat| { this.collect_pat_opt(expanded_pat, binding_list) @@ -1430,8 +1426,8 @@ impl ExprCollector<'_> { Pat::Range { start, end } } }; - let ptr = AstPtr::new(&pat); - self.alloc_pat(pattern, Either::Left(ptr)) + let ptr = AstPtr::new(&Either::Left(pat)); + self.alloc_pat(pattern, ptr) } fn collect_pat_opt(&mut self, pat: Option, binding_list: &mut BindingList) -> PatId { diff --git a/crates/hir-def/src/body/scope.rs b/crates/hir-def/src/body/scope.rs index f69466631355..baca293e2904 100644 --- a/crates/hir-def/src/body/scope.rs +++ b/crates/hir-def/src/body/scope.rs @@ -475,10 +475,7 @@ fn foo() { .pat_syntax(*body.bindings[resolved.binding()].definitions.first().unwrap()) .unwrap(); - let local_name = pat_src.value.either( - |it| it.syntax_node_ptr().to_node(file.syntax()), - |it| it.syntax_node_ptr().to_node(file.syntax()), - ); + let local_name = pat_src.value.syntax_node_ptr().to_node(file.syntax()); assert_eq!(local_name.text_range(), expected_name.syntax().text_range()); } diff --git a/crates/hir-ty/src/diagnostics/decl_check.rs b/crates/hir-ty/src/diagnostics/decl_check.rs index 36d69edf9d5d..60563e02b701 100644 --- a/crates/hir-ty/src/diagnostics/decl_check.rs +++ b/crates/hir-ty/src/diagnostics/decl_check.rs @@ -336,48 +336,44 @@ impl<'a> DeclValidator<'a> { for (id, replacement) in pats_replacements { if let Ok(source_ptr) = source_map.pat_syntax(id) { - if let Some(expr) = source_ptr.value.as_ref().left() { + if let Some(ptr) = source_ptr.value.clone().cast::() { let root = source_ptr.file_syntax(self.db.upcast()); - if let ast::Pat::IdentPat(ident_pat) = expr.to_node(&root) { - let parent = match ident_pat.syntax().parent() { - Some(parent) => parent, - None => continue, - }; - let name_ast = match ident_pat.name() { - Some(name_ast) => name_ast, - None => continue, - }; + let ident_pat = ptr.to_node(&root); + let parent = match ident_pat.syntax().parent() { + Some(parent) => parent, + None => continue, + }; + let name_ast = match ident_pat.name() { + Some(name_ast) => name_ast, + None => continue, + }; - let is_param = ast::Param::can_cast(parent.kind()); + let is_param = ast::Param::can_cast(parent.kind()); - // We have to check that it's either `let var = ...` or `var @ Variant(_)` statement, - // because e.g. match arms are patterns as well. - // In other words, we check that it's a named variable binding. - let is_binding = ast::LetStmt::can_cast(parent.kind()) - || (ast::MatchArm::can_cast(parent.kind()) - && ident_pat.at_token().is_some()); - if !(is_param || is_binding) { - // This pattern is not an actual variable declaration, e.g. `Some(val) => {..}` match arm. - continue; - } - - let ident_type = - if is_param { IdentType::Parameter } else { IdentType::Variable }; - - let diagnostic = IncorrectCase { - file: source_ptr.file_id, - ident_type, - ident: AstPtr::new(&name_ast), - expected_case: replacement.expected_case, - ident_text: replacement - .current_name - .display(self.db.upcast()) - .to_string(), - suggested_text: replacement.suggested_text, - }; - - self.sink.push(diagnostic); + // We have to check that it's either `let var = ...` or `var @ Variant(_)` statement, + // because e.g. match arms are patterns as well. + // In other words, we check that it's a named variable binding. + let is_binding = ast::LetStmt::can_cast(parent.kind()) + || (ast::MatchArm::can_cast(parent.kind()) + && ident_pat.at_token().is_some()); + if !(is_param || is_binding) { + // This pattern is not an actual variable declaration, e.g. `Some(val) => {..}` match arm. + continue; } + + let ident_type = + if is_param { IdentType::Parameter } else { IdentType::Variable }; + + let diagnostic = IncorrectCase { + file: source_ptr.file_id, + ident_type, + ident: AstPtr::new(&name_ast), + expected_case: replacement.expected_case, + ident_text: replacement.current_name.display(self.db.upcast()).to_string(), + suggested_text: replacement.suggested_text, + }; + + self.sink.push(diagnostic); } } } diff --git a/crates/hir-ty/src/mir/eval.rs b/crates/hir-ty/src/mir/eval.rs index 98c78f7f3051..7823c3203413 100644 --- a/crates/hir-ty/src/mir/eval.rs +++ b/crates/hir-ty/src/mir/eval.rs @@ -375,10 +375,7 @@ impl MirEvalError { Err(_) => continue, }, MirSpan::PatId(p) => match source_map.pat_syntax(*p) { - Ok(s) => s.map(|it| match it { - Either::Left(e) => e.into(), - Either::Right(e) => e.into(), - }), + Ok(s) => s.map(|it| it.syntax_node_ptr()), Err(_) => continue, }, MirSpan::Unknown => continue, diff --git a/crates/hir-ty/src/tests.rs b/crates/hir-ty/src/tests.rs index d22d0d85c8e1..1446e83fa887 100644 --- a/crates/hir-ty/src/tests.rs +++ b/crates/hir-ty/src/tests.rs @@ -269,12 +269,7 @@ fn pat_node( Some(match body_source_map.pat_syntax(pat) { Ok(sp) => { let root = db.parse_or_expand(sp.file_id); - sp.map(|ptr| { - ptr.either( - |it| it.to_node(&root).syntax().clone(), - |it| it.to_node(&root).syntax().clone(), - ) - }) + sp.map(|ptr| ptr.to_node(&root).syntax().clone()) } Err(SyntheticSyntax) => return None, }) @@ -303,12 +298,7 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String { let syntax_ptr = match body_source_map.pat_syntax(pat) { Ok(sp) => { let root = db.parse_or_expand(sp.file_id); - sp.map(|ptr| { - ptr.either( - |it| it.to_node(&root).syntax().clone(), - |it| it.to_node(&root).syntax().clone(), - ) - }) + sp.map(|ptr| ptr.to_node(&root).syntax().clone()) } Err(SyntheticSyntax) => continue, }; diff --git a/crates/hir/src/diagnostics.rs b/crates/hir/src/diagnostics.rs index 66ad95c5597c..67d3169243c6 100644 --- a/crates/hir/src/diagnostics.rs +++ b/crates/hir/src/diagnostics.rs @@ -174,20 +174,19 @@ pub struct MalformedDerive { #[derive(Debug)] pub struct NoSuchField { - pub field: InFile, AstPtr>>, + pub field: InFile>>, pub private: bool, } #[derive(Debug)] pub struct PrivateAssocItem { - pub expr_or_pat: - InFile, Either, AstPtr>>>, + pub expr_or_pat: InFile>>>, pub item: AssocItem, } #[derive(Debug)] pub struct MismatchedTupleStructPatArgCount { - pub expr_or_pat: InFile, AstPtr>>, + pub expr_or_pat: InFile>>, pub expected: usize, pub found: usize, } @@ -228,7 +227,7 @@ pub struct MissingUnsafe { #[derive(Debug)] pub struct MissingFields { pub file: HirFileId, - pub field_list_parent: Either, AstPtr>, + pub field_list_parent: AstPtr>, pub field_list_parent_path: Option>, pub missed_fields: Vec, } @@ -255,7 +254,7 @@ pub struct MissingMatchArms { #[derive(Debug)] pub struct TypeMismatch { - pub expr_or_pat: Either>, InFile>>, + pub expr_or_pat: InFile>>, pub expected: Type, pub actual: Type, } diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 8e48afd6af81..8246297705ca 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -1509,10 +1509,10 @@ impl DefWithBody { &hir_ty::InferenceDiagnostic::NoSuchField { field: expr, private } => { let expr_or_pat = match expr { ExprOrPatId::ExprId(expr) => { - source_map.field_syntax(expr).map(Either::Left) + source_map.field_syntax(expr).map(AstPtr::wrap_left) } ExprOrPatId::PatId(pat) => { - source_map.pat_field_syntax(pat).map(Either::Right) + source_map.pat_field_syntax(pat).map(AstPtr::wrap_right) } }; acc.push(NoSuchField { field: expr_or_pat, private }.into()) @@ -1530,8 +1530,8 @@ impl DefWithBody { } &hir_ty::InferenceDiagnostic::PrivateAssocItem { id, item } => { let expr_or_pat = match id { - ExprOrPatId::ExprId(expr) => expr_syntax(expr).map(Either::Left), - ExprOrPatId::PatId(pat) => pat_syntax(pat).map(Either::Right), + ExprOrPatId::ExprId(expr) => expr_syntax(expr).map(AstPtr::wrap_left), + ExprOrPatId::PatId(pat) => pat_syntax(pat).map(AstPtr::wrap_right), }; let item = item.into(); acc.push(PrivateAssocItem { expr_or_pat, item }.into()) @@ -1609,12 +1609,17 @@ impl DefWithBody { found, } => { let expr_or_pat = match pat { - ExprOrPatId::ExprId(expr) => expr_syntax(expr).map(Either::Left), - ExprOrPatId::PatId(pat) => source_map - .pat_syntax(pat) - .expect("unexpected synthetic") - .map(|it| it.unwrap_left()) - .map(Either::Right), + ExprOrPatId::ExprId(expr) => expr_syntax(expr).map(AstPtr::wrap_left), + ExprOrPatId::PatId(pat) => { + let InFile { file_id, value } = + source_map.pat_syntax(pat).expect("unexpected synthetic"); + + // cast from Either -> Either<_, Pat> + let Some(ptr) = AstPtr::try_from_raw(value.syntax_node_ptr()) else { + continue; + }; + InFile { file_id, value: ptr } + } }; acc.push( MismatchedTupleStructPatArgCount { expr_or_pat, expected, found }.into(), @@ -1628,11 +1633,15 @@ impl DefWithBody { ExprOrPatId::PatId(pat) => source_map.pat_syntax(pat).map(Either::Right), }; let expr_or_pat = match expr_or_pat { - Ok(Either::Left(expr)) => Either::Left(expr), - Ok(Either::Right(InFile { file_id, value: Either::Left(pat) })) => { - Either::Right(InFile { file_id, value: pat }) + Ok(Either::Left(expr)) => expr.map(AstPtr::wrap_left), + Ok(Either::Right(InFile { file_id, value: pat })) => { + // cast from Either -> Either<_, Pat> + let Some(ptr) = AstPtr::try_from_raw(pat.syntax_node_ptr()) else { + continue; + }; + InFile { file_id, value: ptr } } - Ok(Either::Right(_)) | Err(SyntheticSyntax) => continue, + Err(SyntheticSyntax) => continue, }; acc.push( @@ -1667,10 +1676,7 @@ impl DefWithBody { Err(_) => continue, }, mir::MirSpan::PatId(p) => match source_map.pat_syntax(p) { - Ok(s) => s.map(|it| match it { - Either::Left(e) => e.into(), - Either::Right(e) => e.into(), - }), + Ok(s) => s.map(|it| it.into()), Err(_) => continue, }, mir::MirSpan::Unknown => continue, @@ -1721,10 +1727,7 @@ impl DefWithBody { Err(_) => continue, }, mir::MirSpan::PatId(p) => match source_map.pat_syntax(*p) { - Ok(s) => s.map(|it| match it { - Either::Left(e) => e.into(), - Either::Right(e) => e.into(), - }), + Ok(s) => s.map(|it| it.into()), Err(_) => continue, }, mir::MirSpan::Unknown => continue, @@ -1763,18 +1766,18 @@ impl DefWithBody { Ok(source_ptr) => { let root = source_ptr.file_syntax(db.upcast()); if let ast::Expr::RecordExpr(record_expr) = - &source_ptr.value.to_node(&root) + source_ptr.value.to_node(&root) { if record_expr.record_expr_field_list().is_some() { + let field_list_parent_path = + record_expr.path().map(|path| AstPtr::new(&path)); acc.push( MissingFields { file: source_ptr.file_id, - field_list_parent: Either::Left(AstPtr::new( + field_list_parent: AstPtr::new(&Either::Left( record_expr, )), - field_list_parent_path: record_expr - .path() - .map(|path| AstPtr::new(&path)), + field_list_parent_path, missed_fields, } .into(), @@ -1786,24 +1789,24 @@ impl DefWithBody { }, Either::Right(record_pat) => match source_map.pat_syntax(record_pat) { Ok(source_ptr) => { - if let Some(expr) = source_ptr.value.as_ref().left() { + if let Some(ptr) = source_ptr.value.clone().cast::() + { let root = source_ptr.file_syntax(db.upcast()); - if let ast::Pat::RecordPat(record_pat) = expr.to_node(&root) { - if record_pat.record_pat_field_list().is_some() { - acc.push( - MissingFields { - file: source_ptr.file_id, - field_list_parent: Either::Right(AstPtr::new( - &record_pat, - )), - field_list_parent_path: record_pat - .path() - .map(|path| AstPtr::new(&path)), - missed_fields, - } - .into(), - ) - } + let record_pat = ptr.to_node(&root); + if record_pat.record_pat_field_list().is_some() { + let field_list_parent_path = + record_pat.path().map(|path| AstPtr::new(&path)); + acc.push( + MissingFields { + file: source_ptr.file_id, + field_list_parent: AstPtr::new(&Either::Right( + record_pat, + )), + field_list_parent_path, + missed_fields, + } + .into(), + ) } } } @@ -2948,10 +2951,10 @@ impl Local { .map(|&definition| { let src = source_map.pat_syntax(definition).unwrap(); // Hmm... let root = src.file_syntax(db.upcast()); - src.map(|ast| match ast { - // Suspicious unwrap - Either::Left(it) => Either::Left(it.cast().unwrap().to_node(&root)), - Either::Right(it) => Either::Right(it.to_node(&root)), + src.map(|ast| match ast.to_node(&root) { + Either::Left(ast::Pat::IdentPat(it)) => Either::Left(it), + Either::Left(_) => unreachable!("local with non ident-pattern"), + Either::Right(it) => Either::Right(it), }) }) .map(move |source| LocalSource { local: self, source }) diff --git a/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs b/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs index ede9858c7265..06ba13bcc55c 100644 --- a/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs +++ b/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs @@ -23,12 +23,7 @@ pub(crate) fn mismatched_tuple_struct_pat_arg_count( Diagnostic::new( DiagnosticCode::RustcHardError("E0023"), message, - invalid_args_range( - ctx, - d.expr_or_pat.clone().map(|it| it.either(Into::into, Into::into)), - d.expected, - d.found, - ), + invalid_args_range(ctx, d.expr_or_pat.clone().map(Into::into), d.expected, d.found), ) } diff --git a/crates/ide-diagnostics/src/handlers/missing_fields.rs b/crates/ide-diagnostics/src/handlers/missing_fields.rs index 3178c7fa2bc7..c09be3fee7e1 100644 --- a/crates/ide-diagnostics/src/handlers/missing_fields.rs +++ b/crates/ide-diagnostics/src/handlers/missing_fields.rs @@ -39,7 +39,7 @@ pub(crate) fn missing_fields(ctx: &DiagnosticsContext<'_>, d: &hir::MissingField d.field_list_parent_path .clone() .map(SyntaxNodePtr::from) - .unwrap_or_else(|| d.field_list_parent.clone().either(|it| it.into(), |it| it.into())), + .unwrap_or_else(|| d.field_list_parent.clone().into()), ); Diagnostic::new_with_syntax_node_ptr(ctx, DiagnosticCode::RustcHardError("E0063"), message, ptr) @@ -58,10 +58,8 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Option ctx.sema.scope(ptr.to_node(&root).syntax()).map(|it| it.module()), - Either::Right(ptr) => ctx.sema.scope(ptr.to_node(&root).syntax()).map(|it| it.module()), - }; + let current_module = + ctx.sema.scope(d.field_list_parent.to_node(&root).syntax()).map(|it| it.module()); let build_text_edit = |parent_syntax, new_syntax: &SyntaxNode, old_syntax| { let edit = { @@ -87,9 +85,8 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Option { - let field_list_parent = record_expr.to_node(&root); + match &d.field_list_parent.to_node(&root) { + Either::Left(field_list_parent) => { let missing_fields = ctx.sema.record_literal_missing_fields(&field_list_parent); let mut locals = FxHashMap::default(); @@ -152,8 +149,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Option { - let field_list_parent = record_pat.to_node(&root); + Either::Right(field_list_parent) => { let missing_fields = ctx.sema.record_pattern_missing_fields(&field_list_parent); let old_field_list = field_list_parent.record_pat_field_list()?; diff --git a/crates/ide-diagnostics/src/handlers/no_such_field.rs b/crates/ide-diagnostics/src/handlers/no_such_field.rs index 290c16c9d247..ee8a9c95793c 100644 --- a/crates/ide-diagnostics/src/handlers/no_such_field.rs +++ b/crates/ide-diagnostics/src/handlers/no_such_field.rs @@ -13,7 +13,7 @@ use crate::{fix, Assist, Diagnostic, DiagnosticCode, DiagnosticsContext}; // // This diagnostic is triggered if created structure does not have field provided in record. pub(crate) fn no_such_field(ctx: &DiagnosticsContext<'_>, d: &hir::NoSuchField) -> Diagnostic { - let node = d.field.clone().map(|it| it.either(Into::into, Into::into)); + let node = d.field.clone().map(Into::into); if d.private { // FIXME: quickfix to add required visibility Diagnostic::new_with_syntax_node_ptr( @@ -35,15 +35,13 @@ pub(crate) fn no_such_field(ctx: &DiagnosticsContext<'_>, d: &hir::NoSuchField) fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::NoSuchField) -> Option> { // FIXME: quickfix for pattern - match &d.field.value { - Either::Left(ptr) => { - let root = ctx.sema.db.parse_or_expand(d.field.file_id); - missing_record_expr_field_fixes( - &ctx.sema, - d.field.file_id.original_file(ctx.sema.db), - &ptr.to_node(&root), - ) - } + let root = ctx.sema.db.parse_or_expand(d.field.file_id); + match &d.field.value.to_node(&root) { + Either::Left(node) => missing_record_expr_field_fixes( + &ctx.sema, + d.field.file_id.original_file(ctx.sema.db), + node, + ), _ => None, } } diff --git a/crates/ide-diagnostics/src/handlers/private_assoc_item.rs b/crates/ide-diagnostics/src/handlers/private_assoc_item.rs index c44d28e77f6d..a828b8b4fd29 100644 --- a/crates/ide-diagnostics/src/handlers/private_assoc_item.rs +++ b/crates/ide-diagnostics/src/handlers/private_assoc_item.rs @@ -1,5 +1,3 @@ -use either::Either; - use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext}; // Diagnostic: private-assoc-item @@ -28,13 +26,7 @@ pub(crate) fn private_assoc_item( }, name, ), - d.expr_or_pat.clone().map(|it| match it { - Either::Left(it) => it.into(), - Either::Right(it) => match it { - Either::Left(it) => it.into(), - Either::Right(it) => it.into(), - }, - }), + d.expr_or_pat.clone().map(Into::into), ) } diff --git a/crates/ide-diagnostics/src/handlers/type_mismatch.rs b/crates/ide-diagnostics/src/handlers/type_mismatch.rs index 1f400bb42dde..14454fe8dc40 100644 --- a/crates/ide-diagnostics/src/handlers/type_mismatch.rs +++ b/crates/ide-diagnostics/src/handlers/type_mismatch.rs @@ -1,4 +1,3 @@ -use either::Either; use hir::{db::ExpandDatabase, ClosureStyle, HirDisplay, InFile, Type}; use ide_db::{famous_defs::FamousDefs, source_change::SourceChange}; use syntax::{ @@ -14,9 +13,11 @@ use crate::{adjusted_display_range, fix, Assist, Diagnostic, DiagnosticCode, Dia // This diagnostic is triggered when the type of an expression or pattern does not match // the expected type. pub(crate) fn type_mismatch(ctx: &DiagnosticsContext<'_>, d: &hir::TypeMismatch) -> Diagnostic { - let display_range = match &d.expr_or_pat { - Either::Left(expr) => { - adjusted_display_range::(ctx, expr.clone().map(|it| it.into()), &|expr| { + let display_range = match &d.expr_or_pat.value { + expr if ast::Expr::can_cast(expr.kind()) => adjusted_display_range::( + ctx, + InFile { file_id: d.expr_or_pat.file_id, value: expr.syntax_node_ptr() }, + &|expr| { let salient_token_range = match expr { ast::Expr::IfExpr(it) => it.if_token()?.text_range(), ast::Expr::LoopExpr(it) => it.loop_token()?.text_range(), @@ -32,10 +33,15 @@ pub(crate) fn type_mismatch(ctx: &DiagnosticsContext<'_>, d: &hir::TypeMismatch) cov_mark::hit!(type_mismatch_range_adjustment); Some(salient_token_range) - }) - } - Either::Right(pat) => { - ctx.sema.diagnostics_display_range(pat.clone().map(|it| it.into())).range + }, + ), + pat => { + ctx.sema + .diagnostics_display_range(InFile { + file_id: d.expr_or_pat.file_id, + value: pat.syntax_node_ptr(), + }) + .range } }; let mut diag = Diagnostic::new( @@ -57,14 +63,12 @@ pub(crate) fn type_mismatch(ctx: &DiagnosticsContext<'_>, d: &hir::TypeMismatch) fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::TypeMismatch) -> Option> { let mut fixes = Vec::new(); - match &d.expr_or_pat { - Either::Left(expr_ptr) => { - add_reference(ctx, d, expr_ptr, &mut fixes); - add_missing_ok_or_some(ctx, d, expr_ptr, &mut fixes); - remove_semicolon(ctx, d, expr_ptr, &mut fixes); - str_ref_to_owned(ctx, d, expr_ptr, &mut fixes); - } - Either::Right(_pat_ptr) => {} + if let Some(expr_ptr) = d.expr_or_pat.value.clone().cast::() { + let expr_ptr = &InFile { file_id: d.expr_or_pat.file_id, value: expr_ptr.clone() }; + add_reference(ctx, d, expr_ptr, &mut fixes); + add_missing_ok_or_some(ctx, d, expr_ptr, &mut fixes); + remove_semicolon(ctx, d, expr_ptr, &mut fixes); + str_ref_to_owned(ctx, d, expr_ptr, &mut fixes); } if fixes.is_empty() { diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs index dcb3ca6581cb..230ff5f9b86a 100644 --- a/crates/rust-analyzer/src/cli/analysis_stats.rs +++ b/crates/rust-analyzer/src/cli/analysis_stats.rs @@ -846,9 +846,7 @@ fn location_csv_pat(db: &RootDatabase, vfs: &Vfs, sm: &BodySourceMap, pat_id: Pa Err(SyntheticSyntax) => return "synthetic,,".to_string(), }; let root = db.parse_or_expand(src.file_id); - let node = src.map(|e| { - e.either(|it| it.to_node(&root).syntax().clone(), |it| it.to_node(&root).syntax().clone()) - }); + let node = src.map(|e| e.to_node(&root).syntax().clone()); let original_range = node.as_ref().original_file_range(db); let path = vfs.file_path(original_range.file_id); let line_index = db.line_index(original_range.file_id); @@ -888,12 +886,7 @@ fn pat_syntax_range( let src = sm.pat_syntax(pat_id); if let Ok(src) = src { let root = db.parse_or_expand(src.file_id); - let node = src.map(|e| { - e.either( - |it| it.to_node(&root).syntax().clone(), - |it| it.to_node(&root).syntax().clone(), - ) - }); + let node = src.map(|e| e.to_node(&root).syntax().clone()); let original_range = node.as_ref().original_file_range(db); let path = vfs.file_path(original_range.file_id); let line_index = db.line_index(original_range.file_id); diff --git a/crates/syntax/src/ptr.rs b/crates/syntax/src/ptr.rs index 1d4a89201ae4..71762996cd7d 100644 --- a/crates/syntax/src/ptr.rs +++ b/crates/syntax/src/ptr.rs @@ -73,6 +73,10 @@ impl AstPtr { Some(AstPtr { raw: self.raw, _ty: PhantomData }) } + pub fn kind(&self) -> parser::SyntaxKind { + self.raw.kind() + } + pub fn upcast(self) -> AstPtr where N: Into, @@ -84,6 +88,20 @@ impl AstPtr { pub fn try_from_raw(raw: SyntaxNodePtr) -> Option> { N::can_cast(raw.kind()).then_some(AstPtr { raw, _ty: PhantomData }) } + + pub fn wrap_left(self) -> AstPtr> + where + either::Either: AstNode, + { + AstPtr { raw: self.raw, _ty: PhantomData } + } + + pub fn wrap_right(self) -> AstPtr> + where + either::Either: AstNode, + { + AstPtr { raw: self.raw, _ty: PhantomData } + } } impl From> for SyntaxNodePtr { From b3ebc9ab6a0793612d75d3587f9de3522f6a71bb Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 6 Oct 2023 13:26:36 +0200 Subject: [PATCH 106/435] Check for both path separators on windows --- crates/rust-analyzer/src/handlers/request.rs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/crates/rust-analyzer/src/handlers/request.rs b/crates/rust-analyzer/src/handlers/request.rs index 8dc0c97bc58f..6c2f1ec3fede 100644 --- a/crates/rust-analyzer/src/handlers/request.rs +++ b/crates/rust-analyzer/src/handlers/request.rs @@ -2000,8 +2000,18 @@ fn run_rustfmt( let workspace = CargoTargetSpec::for_file(&snap, file_id)?; let mut cmd = match workspace { Some(spec) => { - let cmd = spec.workspace_root.join(cmd); - process::Command::new(cmd.as_os_str()) + // approach: if the command name contains a path seperator, join it with the workspace root. + // however, if the path is absolute, joining will result in the absolute path being preserved. + // as a fallback, rely on $PATH-based discovery. + let cmd_path = + if cfg!(windows) && command.contains(&[std::path::MAIN_SEPARATOR, '/']) { + spec.workspace_root.join(cmd).into() + } else if command.contains(std::path::MAIN_SEPARATOR) { + spec.workspace_root.join(cmd).into() + } else { + cmd + }; + process::Command::new(cmd_path) } None => process::Command::new(cmd), }; From c5d9bfaa52d04cdebc691ec3eb7433e5f27ccddd Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Sat, 7 Oct 2023 23:24:55 +0200 Subject: [PATCH 107/435] internal: fix automatic rustc/rustdoc lint generation --- crates/ide-db/src/generated/lints.rs | 95 ++++++++-------- crates/ide-db/src/tests/sourcegen_lints.rs | 122 +++++++++++++-------- 2 files changed, 125 insertions(+), 92 deletions(-) diff --git a/crates/ide-db/src/generated/lints.rs b/crates/ide-db/src/generated/lints.rs index 52321d5bf1d7..9ddcae60563e 100644 --- a/crates/ide-db/src/generated/lints.rs +++ b/crates/ide-db/src/generated/lints.rs @@ -30,6 +30,10 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "asm_sub_register", description: r##"using only a subset of a register for inline asm inputs"##, }, + Lint { + label: "async_fn_in_trait", + description: r##"use of `async fn` in definition of a publicly-reachable trait"##, + }, Lint { label: "bad_asm_style", description: r##"incorrect use of inline assembly"## }, Lint { label: "bare_trait_objects", @@ -80,6 +84,10 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "const_item_mutation", description: r##"detects attempts to mutate a `const` item"##, }, + Lint { + label: "const_patterns_without_partial_eq", + description: r##"constant in pattern does not implement `PartialEq`"##, + }, Lint { label: "dead_code", description: r##"detect unused, unexported items"## }, Lint { label: "deprecated", description: r##"detects use of deprecated items"## }, Lint { @@ -166,7 +174,7 @@ pub const DEFAULT_LINTS: &[Lint] = &[ }, Lint { label: "future_incompatible", - description: r##"lint group for: deref-into-dyn-supertrait, ambiguous-associated-items, ambiguous-glob-imports, byte-slice-in-packed-struct-with-derive, cenum-impl-drop-cast, coherence-leak-check, coinductive-overlap-in-coherence, conflicting-repr-hints, const-evaluatable-unchecked, deprecated-cfg-attr-crate-type-name, elided-lifetimes-in-associated-constant, forbidden-lint-groups, ill-formed-attribute-input, illegal-floating-point-literal-pattern, implied-bounds-entailment, indirect-structural-match, invalid-alignment, invalid-doc-attributes, invalid-type-param-default, late-bound-lifetime-arguments, legacy-derive-helpers, macro-expanded-macro-exports-accessed-by-absolute-paths, missing-fragment-specifier, nontrivial-structural-match, order-dependent-trait-objects, patterns-in-fns-without-body, pointer-structural-match, proc-macro-back-compat, proc-macro-derive-resolution-fallback, pub-use-of-private-extern-crate, repr-transparent-external-private-fields, semicolon-in-expressions-from-macros, soft-unstable, suspicious-auto-trait-impls, uninhabited-static, unstable-name-collisions, unstable-syntax-pre-expansion, unsupported-calling-conventions, where-clauses-object-safety"##, + description: r##"lint group for: deref-into-dyn-supertrait, ambiguous-associated-items, ambiguous-glob-imports, byte-slice-in-packed-struct-with-derive, cenum-impl-drop-cast, coherence-leak-check, coinductive-overlap-in-coherence, conflicting-repr-hints, const-evaluatable-unchecked, const-patterns-without-partial-eq, deprecated-cfg-attr-crate-type-name, elided-lifetimes-in-associated-constant, forbidden-lint-groups, ill-formed-attribute-input, illegal-floating-point-literal-pattern, implied-bounds-entailment, indirect-structural-match, invalid-alignment, invalid-doc-attributes, invalid-type-param-default, late-bound-lifetime-arguments, legacy-derive-helpers, macro-expanded-macro-exports-accessed-by-absolute-paths, missing-fragment-specifier, nontrivial-structural-match, order-dependent-trait-objects, patterns-in-fns-without-body, pointer-structural-match, proc-macro-back-compat, proc-macro-derive-resolution-fallback, pub-use-of-private-extern-crate, repr-transparent-external-private-fields, semicolon-in-expressions-from-macros, soft-unstable, suspicious-auto-trait-impls, uninhabited-static, unstable-name-collisions, unstable-syntax-pre-expansion, unsupported-calling-conventions, where-clauses-object-safety"##, }, Lint { label: "fuzzy_provenance_casts", @@ -731,11 +739,12 @@ pub const DEFAULT_LINTS: &[Lint] = &[ description: r##"suggest using `loop { }` instead of `while true { }`"##, }, ]; + pub const DEFAULT_LINT_GROUPS: &[LintGroup] = &[ LintGroup { lint: Lint { label: "future_incompatible", - description: r##"lint group for: deref-into-dyn-supertrait, ambiguous-associated-items, ambiguous-glob-imports, byte-slice-in-packed-struct-with-derive, cenum-impl-drop-cast, coherence-leak-check, coinductive-overlap-in-coherence, conflicting-repr-hints, const-evaluatable-unchecked, deprecated-cfg-attr-crate-type-name, elided-lifetimes-in-associated-constant, forbidden-lint-groups, ill-formed-attribute-input, illegal-floating-point-literal-pattern, implied-bounds-entailment, indirect-structural-match, invalid-alignment, invalid-doc-attributes, invalid-type-param-default, late-bound-lifetime-arguments, legacy-derive-helpers, macro-expanded-macro-exports-accessed-by-absolute-paths, missing-fragment-specifier, nontrivial-structural-match, order-dependent-trait-objects, patterns-in-fns-without-body, pointer-structural-match, proc-macro-back-compat, proc-macro-derive-resolution-fallback, pub-use-of-private-extern-crate, repr-transparent-external-private-fields, semicolon-in-expressions-from-macros, soft-unstable, suspicious-auto-trait-impls, uninhabited-static, unstable-name-collisions, unstable-syntax-pre-expansion, unsupported-calling-conventions, where-clauses-object-safety"##, + description: r##"lint group for: deref-into-dyn-supertrait, ambiguous-associated-items, ambiguous-glob-imports, byte-slice-in-packed-struct-with-derive, cenum-impl-drop-cast, coherence-leak-check, coinductive-overlap-in-coherence, conflicting-repr-hints, const-evaluatable-unchecked, const-patterns-without-partial-eq, deprecated-cfg-attr-crate-type-name, elided-lifetimes-in-associated-constant, forbidden-lint-groups, ill-formed-attribute-input, illegal-floating-point-literal-pattern, implied-bounds-entailment, indirect-structural-match, invalid-alignment, invalid-doc-attributes, invalid-type-param-default, late-bound-lifetime-arguments, legacy-derive-helpers, macro-expanded-macro-exports-accessed-by-absolute-paths, missing-fragment-specifier, nontrivial-structural-match, order-dependent-trait-objects, patterns-in-fns-without-body, pointer-structural-match, proc-macro-back-compat, proc-macro-derive-resolution-fallback, pub-use-of-private-extern-crate, repr-transparent-external-private-fields, semicolon-in-expressions-from-macros, soft-unstable, suspicious-auto-trait-impls, uninhabited-static, unstable-name-collisions, unstable-syntax-pre-expansion, unsupported-calling-conventions, where-clauses-object-safety"##, }, children: &[ "deref_into_dyn_supertrait", @@ -747,6 +756,7 @@ pub const DEFAULT_LINT_GROUPS: &[LintGroup] = &[ "coinductive_overlap_in_coherence", "conflicting_repr_hints", "const_evaluatable_unchecked", + "const_patterns_without_partial_eq", "deprecated_cfg_attr_crate_type_name", "elided_lifetimes_in_associated_constant", "forbidden_lint_groups", @@ -874,10 +884,6 @@ pub const DEFAULT_LINT_GROUPS: &[LintGroup] = &[ ]; pub const RUSTDOC_LINTS: &[Lint] = &[ - Lint { label: "____", description: r##"-------"## }, - Lint { label: "____", description: r##"lint group for: ---------"## }, - Lint { label: "name", description: r##"meaning"## }, - Lint { label: "name", description: r##"lint group for: sub-lints"## }, Lint { label: "rustdoc::all", description: r##"lint group for: rustdoc::broken-intra-doc-links, rustdoc::private-intra-doc-links, rustdoc::private-doc-tests, rustdoc::invalid-codeblock-attributes, rustdoc::invalid-rust-codeblocks, rustdoc::invalid-html-tags, rustdoc::bare-urls, rustdoc::missing-crate-level-docs, rustdoc::unescaped-backticks, rustdoc::redundant-explicit-links"##, @@ -924,34 +930,25 @@ pub const RUSTDOC_LINTS: &[Lint] = &[ description: r##"detects unescaped backticks in doc comments"##, }, ]; -pub const RUSTDOC_LINT_GROUPS: &[LintGroup] = &[ - LintGroup { - lint: Lint { label: "____", description: r##"lint group for: ---------"## }, - children: &["_________"], + +pub const RUSTDOC_LINT_GROUPS: &[LintGroup] = &[LintGroup { + lint: Lint { + label: "rustdoc::all", + description: r##"lint group for: rustdoc::broken-intra-doc-links, rustdoc::private-intra-doc-links, rustdoc::private-doc-tests, rustdoc::invalid-codeblock-attributes, rustdoc::invalid-rust-codeblocks, rustdoc::invalid-html-tags, rustdoc::bare-urls, rustdoc::missing-crate-level-docs, rustdoc::unescaped-backticks, rustdoc::redundant-explicit-links"##, }, - LintGroup { - lint: Lint { label: "name", description: r##"lint group for: sub-lints"## }, - children: &["sub_lints"], - }, - LintGroup { - lint: Lint { - label: "rustdoc::all", - description: r##"lint group for: rustdoc::broken-intra-doc-links, rustdoc::private-intra-doc-links, rustdoc::private-doc-tests, rustdoc::invalid-codeblock-attributes, rustdoc::invalid-rust-codeblocks, rustdoc::invalid-html-tags, rustdoc::bare-urls, rustdoc::missing-crate-level-docs, rustdoc::unescaped-backticks, rustdoc::redundant-explicit-links"##, - }, - children: &[ - "rustdoc::broken_intra_doc_links", - "rustdoc::private_intra_doc_links", - "rustdoc::private_doc_tests", - "rustdoc::invalid_codeblock_attributes", - "rustdoc::invalid_rust_codeblocks", - "rustdoc::invalid_html_tags", - "rustdoc::bare_urls", - "rustdoc::missing_crate_level_docs", - "rustdoc::unescaped_backticks", - "rustdoc::redundant_explicit_links", - ], - }, -]; + children: &[ + "rustdoc::broken_intra_doc_links", + "rustdoc::private_intra_doc_links", + "rustdoc::private_doc_tests", + "rustdoc::invalid_codeblock_attributes", + "rustdoc::invalid_rust_codeblocks", + "rustdoc::invalid_html_tags", + "rustdoc::bare_urls", + "rustdoc::missing_crate_level_docs", + "rustdoc::unescaped_backticks", + "rustdoc::redundant_explicit_links", + ], +}]; pub const FEATURES: &[Lint] = &[ Lint { @@ -3149,7 +3146,7 @@ of a library. Plugins can extend [Rust's lint infrastructure](../../reference/attributes/diagnostics.md#lint-check-attributes) with additional checks for code style, safety, etc. Now let's write a plugin -[`lint-plugin-test.rs`](https://github.com/rust-lang/rust/blob/master/tests/ui-fulldeps/auxiliary/lint-plugin-test.rs) +[`lint-plugin-test.rs`](https://github.com/rust-lang/rust/blob/master/tests/ui-fulldeps/plugin/auxiliary/lint-plugin-test.rs) that warns about any item named `lintme`. ```rust,ignore (requires-stage-2) @@ -3159,14 +3156,14 @@ extern crate rustc_ast; // Load rustc as a plugin to get macros extern crate rustc_driver; -#[macro_use] extern crate rustc_lint; #[macro_use] extern crate rustc_session; -use rustc_driver::plugin::Registry; -use rustc_lint::{EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass}; use rustc_ast::ast; +use rustc_driver::plugin::Registry; +use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; + declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'"); declare_lint_pass!(Pass => [TEST_LINT]); @@ -3174,9 +3171,7 @@ declare_lint_pass!(Pass => [TEST_LINT]); impl EarlyLintPass for Pass { fn check_item(&mut self, cx: &EarlyContext, it: &ast::Item) { if it.ident.name.as_str() == "lintme" { - cx.lint(TEST_LINT, |lint| { - lint.build("item is named 'lintme'").set_span(it.span).emit() - }); + cx.lint(TEST_LINT, "item is named 'lintme'", |lint| lint.set_span(it.span)); } } } @@ -5335,6 +5330,12 @@ unless the annotated function is empty or simply panics."##, label: "clippy::into_iter_on_ref", description: r##"Checks for `into_iter` calls on references which should be replaced by `iter` or `iter_mut`."##, + }, + Lint { + label: "clippy::into_iter_without_iter", + description: r##"This is the opposite of the `iter_without_into_iter` lint. +It looks for `IntoIterator for (&|&mut) Type` implementations without an inherent `iter` or `iter_mut` method +on the type or on any of the types in its `Deref` chain."##, }, Lint { label: "clippy::invalid_null_ptr_usage", @@ -5431,6 +5432,10 @@ where `x` is greater than the amount of items that an iterator will produce."##, label: "clippy::iter_with_drain", description: r##"Checks for usage of `.drain(..)` on `Vec` and `VecDeque` for iteration."##, }, + Lint { + label: "clippy::iter_without_into_iter", + description: r##"Looks for `iter` and `iter_mut` methods without an associated `IntoIterator for (&|&mut) Type` implementation."##, + }, Lint { label: "clippy::iterator_step_by_zero", description: r##"Checks for calling `.step_by(0)` on iterators which panics."##, @@ -7898,7 +7903,7 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ LintGroup { lint: Lint { label: "clippy::nursery", - description: r##"lint group for: clippy::as_ptr_cast_mut, clippy::branches_sharing_code, clippy::clear_with_drain, clippy::cognitive_complexity, clippy::collection_is_never_read, clippy::debug_assert_with_mut_call, clippy::derive_partial_eq_without_eq, clippy::empty_line_after_doc_comments, clippy::empty_line_after_outer_attr, clippy::equatable_if_let, clippy::fallible_impl_from, clippy::future_not_send, clippy::implied_bounds_in_impls, clippy::imprecise_flops, clippy::iter_on_empty_collections, clippy::iter_on_single_items, clippy::iter_with_drain, clippy::large_stack_frames, clippy::manual_clamp, clippy::missing_const_for_fn, clippy::mutex_integer, clippy::needless_collect, clippy::non_send_fields_in_send_ty, clippy::nonstandard_macro_braces, clippy::option_if_let_else, clippy::or_fun_call, clippy::path_buf_push_overwrite, clippy::readonly_write_lock, clippy::redundant_clone, clippy::redundant_pub_crate, clippy::significant_drop_in_scrutinee, clippy::significant_drop_tightening, clippy::string_lit_as_bytes, clippy::suboptimal_flops, clippy::suspicious_operation_groupings, clippy::trailing_empty_array, clippy::trait_duplication_in_bounds, clippy::transmute_undefined_repr, clippy::trivial_regex, clippy::tuple_array_conversions, clippy::type_repetition_in_bounds, clippy::unnecessary_struct_initialization, clippy::unused_peekable, clippy::unused_rounding, clippy::use_self, clippy::useless_let_if_seq"##, + description: r##"lint group for: clippy::as_ptr_cast_mut, clippy::branches_sharing_code, clippy::clear_with_drain, clippy::cognitive_complexity, clippy::collection_is_never_read, clippy::debug_assert_with_mut_call, clippy::derive_partial_eq_without_eq, clippy::empty_line_after_doc_comments, clippy::empty_line_after_outer_attr, clippy::equatable_if_let, clippy::fallible_impl_from, clippy::future_not_send, clippy::implied_bounds_in_impls, clippy::imprecise_flops, clippy::iter_on_empty_collections, clippy::iter_on_single_items, clippy::iter_with_drain, clippy::large_stack_frames, clippy::manual_clamp, clippy::missing_const_for_fn, clippy::mutex_integer, clippy::needless_collect, clippy::needless_pass_by_ref_mut, clippy::non_send_fields_in_send_ty, clippy::nonstandard_macro_braces, clippy::option_if_let_else, clippy::or_fun_call, clippy::path_buf_push_overwrite, clippy::readonly_write_lock, clippy::redundant_clone, clippy::redundant_pub_crate, clippy::significant_drop_in_scrutinee, clippy::significant_drop_tightening, clippy::string_lit_as_bytes, clippy::suboptimal_flops, clippy::suspicious_operation_groupings, clippy::trailing_empty_array, clippy::trait_duplication_in_bounds, clippy::transmute_undefined_repr, clippy::trivial_regex, clippy::tuple_array_conversions, clippy::type_repetition_in_bounds, clippy::unnecessary_struct_initialization, clippy::unused_peekable, clippy::unused_rounding, clippy::use_self, clippy::useless_let_if_seq"##, }, children: &[ "clippy::as_ptr_cast_mut", @@ -7923,6 +7928,7 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::missing_const_for_fn", "clippy::mutex_integer", "clippy::needless_collect", + "clippy::needless_pass_by_ref_mut", "clippy::non_send_fields_in_send_ty", "clippy::nonstandard_macro_braces", "clippy::option_if_let_else", @@ -7952,7 +7958,7 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ LintGroup { lint: Lint { label: "clippy::pedantic", - description: r##"lint group for: clippy::bool_to_int_with_if, clippy::borrow_as_ptr, clippy::case_sensitive_file_extension_comparisons, clippy::cast_lossless, clippy::cast_possible_truncation, clippy::cast_possible_wrap, clippy::cast_precision_loss, clippy::cast_ptr_alignment, clippy::cast_sign_loss, clippy::checked_conversions, clippy::cloned_instead_of_copied, clippy::copy_iterator, clippy::default_trait_access, clippy::doc_link_with_quotes, clippy::doc_markdown, clippy::empty_enum, clippy::enum_glob_use, clippy::expl_impl_clone_on_copy, clippy::explicit_deref_methods, clippy::explicit_into_iter_loop, clippy::explicit_iter_loop, clippy::filter_map_next, clippy::flat_map_option, clippy::float_cmp, clippy::fn_params_excessive_bools, clippy::from_iter_instead_of_collect, clippy::if_not_else, clippy::ignored_unit_patterns, clippy::implicit_clone, clippy::implicit_hasher, clippy::inconsistent_struct_constructor, clippy::index_refutable_slice, clippy::inefficient_to_string, clippy::inline_always, clippy::invalid_upcast_comparisons, clippy::items_after_statements, clippy::iter_not_returning_iterator, clippy::large_digit_groups, clippy::large_futures, clippy::large_stack_arrays, clippy::large_types_passed_by_value, clippy::linkedlist, clippy::macro_use_imports, clippy::manual_assert, clippy::manual_instant_elapsed, clippy::manual_let_else, clippy::manual_ok_or, clippy::manual_string_new, clippy::many_single_char_names, clippy::map_unwrap_or, clippy::match_bool, clippy::match_on_vec_items, clippy::match_same_arms, clippy::match_wild_err_arm, clippy::match_wildcard_for_single_variants, clippy::maybe_infinite_iter, clippy::mismatching_type_param_order, clippy::missing_errors_doc, clippy::missing_fields_in_debug, clippy::missing_panics_doc, clippy::module_name_repetitions, clippy::must_use_candidate, clippy::mut_mut, clippy::naive_bytecount, clippy::needless_bitwise_bool, clippy::needless_continue, clippy::needless_for_each, clippy::needless_pass_by_value, clippy::needless_raw_string_hashes, clippy::no_effect_underscore_binding, clippy::no_mangle_with_rust_abi, clippy::option_option, clippy::ptr_as_ptr, clippy::ptr_cast_constness, clippy::range_minus_one, clippy::range_plus_one, clippy::redundant_closure_for_method_calls, clippy::redundant_else, clippy::ref_binding_to_reference, clippy::ref_option_ref, clippy::return_self_not_must_use, clippy::same_functions_in_if_condition, clippy::semicolon_if_nothing_returned, clippy::should_panic_without_expect, clippy::similar_names, clippy::single_match_else, clippy::stable_sort_primitive, clippy::string_add_assign, clippy::struct_excessive_bools, clippy::too_many_lines, clippy::transmute_ptr_to_ptr, clippy::trivially_copy_pass_by_ref, clippy::unchecked_duration_subtraction, clippy::unicode_not_nfc, clippy::uninlined_format_args, clippy::unnecessary_box_returns, clippy::unnecessary_join, clippy::unnecessary_wraps, clippy::unnested_or_patterns, clippy::unreadable_literal, clippy::unsafe_derive_deserialize, clippy::unused_async, clippy::unused_self, clippy::used_underscore_binding, clippy::verbose_bit_mask, clippy::wildcard_imports, clippy::zero_sized_map_values"##, + description: r##"lint group for: clippy::bool_to_int_with_if, clippy::borrow_as_ptr, clippy::case_sensitive_file_extension_comparisons, clippy::cast_lossless, clippy::cast_possible_truncation, clippy::cast_possible_wrap, clippy::cast_precision_loss, clippy::cast_ptr_alignment, clippy::cast_sign_loss, clippy::checked_conversions, clippy::cloned_instead_of_copied, clippy::copy_iterator, clippy::default_trait_access, clippy::doc_link_with_quotes, clippy::doc_markdown, clippy::empty_enum, clippy::enum_glob_use, clippy::expl_impl_clone_on_copy, clippy::explicit_deref_methods, clippy::explicit_into_iter_loop, clippy::explicit_iter_loop, clippy::filter_map_next, clippy::flat_map_option, clippy::float_cmp, clippy::fn_params_excessive_bools, clippy::from_iter_instead_of_collect, clippy::if_not_else, clippy::ignored_unit_patterns, clippy::implicit_clone, clippy::implicit_hasher, clippy::inconsistent_struct_constructor, clippy::index_refutable_slice, clippy::inefficient_to_string, clippy::inline_always, clippy::into_iter_without_iter, clippy::invalid_upcast_comparisons, clippy::items_after_statements, clippy::iter_not_returning_iterator, clippy::iter_without_into_iter, clippy::large_digit_groups, clippy::large_futures, clippy::large_stack_arrays, clippy::large_types_passed_by_value, clippy::linkedlist, clippy::macro_use_imports, clippy::manual_assert, clippy::manual_instant_elapsed, clippy::manual_let_else, clippy::manual_ok_or, clippy::manual_string_new, clippy::many_single_char_names, clippy::map_unwrap_or, clippy::match_bool, clippy::match_on_vec_items, clippy::match_same_arms, clippy::match_wild_err_arm, clippy::match_wildcard_for_single_variants, clippy::maybe_infinite_iter, clippy::mismatching_type_param_order, clippy::missing_errors_doc, clippy::missing_fields_in_debug, clippy::missing_panics_doc, clippy::module_name_repetitions, clippy::must_use_candidate, clippy::mut_mut, clippy::naive_bytecount, clippy::needless_bitwise_bool, clippy::needless_continue, clippy::needless_for_each, clippy::needless_pass_by_value, clippy::needless_raw_string_hashes, clippy::no_effect_underscore_binding, clippy::no_mangle_with_rust_abi, clippy::option_option, clippy::ptr_as_ptr, clippy::ptr_cast_constness, clippy::range_minus_one, clippy::range_plus_one, clippy::redundant_closure_for_method_calls, clippy::redundant_else, clippy::ref_binding_to_reference, clippy::ref_option_ref, clippy::return_self_not_must_use, clippy::same_functions_in_if_condition, clippy::semicolon_if_nothing_returned, clippy::should_panic_without_expect, clippy::similar_names, clippy::single_match_else, clippy::stable_sort_primitive, clippy::string_add_assign, clippy::struct_excessive_bools, clippy::too_many_lines, clippy::transmute_ptr_to_ptr, clippy::trivially_copy_pass_by_ref, clippy::unchecked_duration_subtraction, clippy::unicode_not_nfc, clippy::uninlined_format_args, clippy::unnecessary_box_returns, clippy::unnecessary_join, clippy::unnecessary_wraps, clippy::unnested_or_patterns, clippy::unreadable_literal, clippy::unsafe_derive_deserialize, clippy::unused_async, clippy::unused_self, clippy::used_underscore_binding, clippy::verbose_bit_mask, clippy::wildcard_imports, clippy::zero_sized_map_values"##, }, children: &[ "clippy::bool_to_int_with_if", @@ -7989,9 +7995,11 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::index_refutable_slice", "clippy::inefficient_to_string", "clippy::inline_always", + "clippy::into_iter_without_iter", "clippy::invalid_upcast_comparisons", "clippy::items_after_statements", "clippy::iter_not_returning_iterator", + "clippy::iter_without_into_iter", "clippy::large_digit_groups", "clippy::large_futures", "clippy::large_stack_arrays", @@ -8365,7 +8373,7 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ LintGroup { lint: Lint { label: "clippy::suspicious", - description: r##"lint group for: clippy::almost_complete_range, clippy::arc_with_non_send_sync, clippy::await_holding_invalid_type, clippy::await_holding_lock, clippy::await_holding_refcell_ref, clippy::blanket_clippy_restriction_lints, clippy::cast_abs_to_unsigned, clippy::cast_enum_constructor, clippy::cast_enum_truncation, clippy::cast_nan_to_int, clippy::cast_slice_from_raw_parts, clippy::crate_in_macro_def, clippy::drop_non_drop, clippy::duplicate_mod, clippy::empty_loop, clippy::float_equality_without_abs, clippy::forget_non_drop, clippy::four_forward_slashes, clippy::from_raw_with_void_ptr, clippy::iter_out_of_bounds, clippy::let_underscore_future, clippy::lines_filter_map_ok, clippy::maybe_misused_cfg, clippy::misnamed_getters, clippy::misrefactored_assign_op, clippy::multi_assignments, clippy::mut_range_bound, clippy::mutable_key_type, clippy::needless_pass_by_ref_mut, clippy::no_effect_replace, clippy::non_canonical_clone_impl, clippy::non_canonical_partial_ord_impl, clippy::octal_escapes, clippy::path_ends_with_ext, clippy::permissions_set_readonly_false, clippy::print_in_format_impl, clippy::rc_clone_in_vec_init, clippy::single_range_in_vec_init, clippy::size_of_ref, clippy::suspicious_arithmetic_impl, clippy::suspicious_assignment_formatting, clippy::suspicious_command_arg_space, clippy::suspicious_doc_comments, clippy::suspicious_else_formatting, clippy::suspicious_map, clippy::suspicious_op_assign_impl, clippy::suspicious_to_owned, clippy::suspicious_unary_op_formatting, clippy::swap_ptr_to_ref, clippy::type_id_on_box"##, + description: r##"lint group for: clippy::almost_complete_range, clippy::arc_with_non_send_sync, clippy::await_holding_invalid_type, clippy::await_holding_lock, clippy::await_holding_refcell_ref, clippy::blanket_clippy_restriction_lints, clippy::cast_abs_to_unsigned, clippy::cast_enum_constructor, clippy::cast_enum_truncation, clippy::cast_nan_to_int, clippy::cast_slice_from_raw_parts, clippy::crate_in_macro_def, clippy::drop_non_drop, clippy::duplicate_mod, clippy::empty_loop, clippy::float_equality_without_abs, clippy::forget_non_drop, clippy::four_forward_slashes, clippy::from_raw_with_void_ptr, clippy::iter_out_of_bounds, clippy::let_underscore_future, clippy::lines_filter_map_ok, clippy::maybe_misused_cfg, clippy::misnamed_getters, clippy::misrefactored_assign_op, clippy::multi_assignments, clippy::mut_range_bound, clippy::mutable_key_type, clippy::no_effect_replace, clippy::non_canonical_clone_impl, clippy::non_canonical_partial_ord_impl, clippy::octal_escapes, clippy::path_ends_with_ext, clippy::permissions_set_readonly_false, clippy::print_in_format_impl, clippy::rc_clone_in_vec_init, clippy::single_range_in_vec_init, clippy::size_of_ref, clippy::suspicious_arithmetic_impl, clippy::suspicious_assignment_formatting, clippy::suspicious_command_arg_space, clippy::suspicious_doc_comments, clippy::suspicious_else_formatting, clippy::suspicious_map, clippy::suspicious_op_assign_impl, clippy::suspicious_to_owned, clippy::suspicious_unary_op_formatting, clippy::swap_ptr_to_ref, clippy::type_id_on_box"##, }, children: &[ "clippy::almost_complete_range", @@ -8396,7 +8404,6 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::multi_assignments", "clippy::mut_range_bound", "clippy::mutable_key_type", - "clippy::needless_pass_by_ref_mut", "clippy::no_effect_replace", "clippy::non_canonical_clone_impl", "clippy::non_canonical_partial_ord_impl", diff --git a/crates/ide-db/src/tests/sourcegen_lints.rs b/crates/ide-db/src/tests/sourcegen_lints.rs index 457f94d3f9f3..8d7117b0c902 100644 --- a/crates/ide-db/src/tests/sourcegen_lints.rs +++ b/crates/ide-db/src/tests/sourcegen_lints.rs @@ -55,37 +55,56 @@ pub struct LintGroup { sourcegen::ensure_file_contents(destination.as_path(), &contents); } +/// Parses the output of `rustdoc -Whelp` and prints `Lint` and `LintGroup` constants into `buf`. +/// +/// As of writing, the output of `rustc -Whelp` (not rustdoc) has the following format: +/// +/// ```text +/// Lint checks provided by rustc: +/// +/// name default meaning +/// ---- ------- ------- +/// +/// ... +/// +/// Lint groups provided by rustc: +/// +/// name sub-lints +/// ---- --------- +/// +/// ... +/// ``` +/// +/// `rustdoc -Whelp` (and any other custom `rustc` driver) adds another two +/// tables after the `rustc` ones, with a different title but the same format. fn generate_lint_descriptor(sh: &Shell, buf: &mut String) { - // FIXME: rustdoc currently requires an input file for -Whelp cc https://github.com/rust-lang/rust/pull/88831 - let file = project_root().join(file!()); - let stdout = cmd!(sh, "rustdoc -W help {file}").read().unwrap(); - let start_lints = stdout.find("---- ------- -------").unwrap(); - let start_lint_groups = stdout.find("---- ---------").unwrap(); - let start_lints_rustdoc = - stdout.find("Lint checks provided by plugins loaded by this crate:").unwrap(); - let start_lint_groups_rustdoc = - stdout.find("Lint groups provided by plugins loaded by this crate:").unwrap(); + let stdout = cmd!(sh, "rustdoc -Whelp").read().unwrap(); + let lints_pat = "---- ------- -------\n"; + let lint_groups_pat = "---- ---------\n"; + let lints = find_and_slice(&stdout, lints_pat); + let lint_groups = find_and_slice(lints, lint_groups_pat); + let lints_rustdoc = find_and_slice(lint_groups, lints_pat); + let lint_groups_rustdoc = find_and_slice(lints_rustdoc, lint_groups_pat); buf.push_str(r#"pub const DEFAULT_LINTS: &[Lint] = &["#); buf.push('\n'); - let lints = stdout[start_lints..].lines().skip(1).take_while(|l| !l.is_empty()).map(|line| { + let lints = lints.lines().take_while(|l| !l.is_empty()).map(|line| { let (name, rest) = line.trim().split_once(char::is_whitespace).unwrap(); let (_default_level, description) = rest.trim().split_once(char::is_whitespace).unwrap(); (name.trim(), Cow::Borrowed(description.trim()), vec![]) }); - let lint_groups = - stdout[start_lint_groups..].lines().skip(1).take_while(|l| !l.is_empty()).map(|line| { - let (name, lints) = line.trim().split_once(char::is_whitespace).unwrap(); - ( - name.trim(), - format!("lint group for: {}", lints.trim()).into(), - lints - .split_ascii_whitespace() - .map(|s| s.trim().trim_matches(',').replace('-', "_")) - .collect(), - ) - }); + let lint_groups = lint_groups.lines().take_while(|l| !l.is_empty()).map(|line| { + let (name, lints) = line.trim().split_once(char::is_whitespace).unwrap(); + ( + name.trim(), + format!("lint group for: {}", lints.trim()).into(), + lints + .split_ascii_whitespace() + .map(|s| s.trim().trim_matches(',').replace('-', "_")) + .collect(), + ) + }); let lints = lints .chain(lint_groups) @@ -94,7 +113,8 @@ fn generate_lint_descriptor(sh: &Shell, buf: &mut String) { for (name, description, ..) in &lints { push_lint_completion(buf, &name.replace('-', "_"), description); } - buf.push_str("];\n"); + buf.push_str("];\n\n"); + buf.push_str(r#"pub const DEFAULT_LINT_GROUPS: &[LintGroup] = &["#); for (name, description, children) in &lints { if !children.is_empty() { @@ -115,27 +135,23 @@ fn generate_lint_descriptor(sh: &Shell, buf: &mut String) { buf.push_str(r#"pub const RUSTDOC_LINTS: &[Lint] = &["#); buf.push('\n'); - let lints_rustdoc = - stdout[start_lints_rustdoc..].lines().skip(2).take_while(|l| !l.is_empty()).map(|line| { - let (name, rest) = line.trim().split_once(char::is_whitespace).unwrap(); - let (_default_level, description) = - rest.trim().split_once(char::is_whitespace).unwrap(); - (name.trim(), Cow::Borrowed(description.trim()), vec![]) - }); + let lints_rustdoc = lints_rustdoc.lines().take_while(|l| !l.is_empty()).map(|line| { + let (name, rest) = line.trim().split_once(char::is_whitespace).unwrap(); + let (_default_level, description) = rest.trim().split_once(char::is_whitespace).unwrap(); + (name.trim(), Cow::Borrowed(description.trim()), vec![]) + }); let lint_groups_rustdoc = - stdout[start_lint_groups_rustdoc..].lines().skip(2).take_while(|l| !l.is_empty()).map( - |line| { - let (name, lints) = line.trim().split_once(char::is_whitespace).unwrap(); - ( - name.trim(), - format!("lint group for: {}", lints.trim()).into(), - lints - .split_ascii_whitespace() - .map(|s| s.trim().trim_matches(',').replace('-', "_")) - .collect(), - ) - }, - ); + lint_groups_rustdoc.lines().take_while(|l| !l.is_empty()).map(|line| { + let (name, lints) = line.trim().split_once(char::is_whitespace).unwrap(); + ( + name.trim(), + format!("lint group for: {}", lints.trim()).into(), + lints + .split_ascii_whitespace() + .map(|s| s.trim().trim_matches(',').replace('-', "_")) + .collect(), + ) + }); let lints_rustdoc = lints_rustdoc .chain(lint_groups_rustdoc) @@ -145,7 +161,7 @@ fn generate_lint_descriptor(sh: &Shell, buf: &mut String) { for (name, description, ..) in &lints_rustdoc { push_lint_completion(buf, &name.replace('-', "_"), description) } - buf.push_str("];\n"); + buf.push_str("];\n\n"); buf.push_str(r#"pub const RUSTDOC_LINT_GROUPS: &[LintGroup] = &["#); for (name, description, children) in &lints_rustdoc { @@ -157,14 +173,24 @@ fn generate_lint_descriptor(sh: &Shell, buf: &mut String) { buf.push_str("];\n"); } +#[track_caller] +fn find_and_slice<'a>(i: &'a str, p: &str) -> &'a str { + let idx = i.find(p).unwrap(); + &i[idx + p.len()..] +} + +/// Parses the unstable book root directory at `src_dir` and prints a constant +/// with the list of unstable features into `buf`. +/// +/// It does this by looking for all `.md` files in the `language-features` and +/// `library-features` directories, and using the file name as the feature +/// name, and the file contents as the feature description. fn generate_feature_descriptor(buf: &mut String, src_dir: &Path) { let mut features = ["language-features", "library-features"] .into_iter() .flat_map(|it| sourcegen::list_files(&src_dir.join(it))) - .filter(|path| { - // Get all `.md ` files - path.extension().unwrap_or_default().to_str().unwrap_or_default() == "md" - }) + // Get all `.md` files + .filter(|path| path.extension() == Some("md".as_ref())) .map(|path| { let feature_ident = path.file_stem().unwrap().to_str().unwrap().replace('-', "_"); let doc = fs::read_to_string(path).unwrap(); From 3dfc1bfc67c9779ec3c936c1987349ac77cd8af4 Mon Sep 17 00:00:00 2001 From: Elias Holzmann <9659253+EliasHolzmann@users.noreply.github.com> Date: Sun, 8 Oct 2023 03:31:23 +0200 Subject: [PATCH 108/435] Use vscode.env.openExternal instead of the vscode.open command for docs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to the VS Code documentation, the vscode.open command opens the URL _in the editor_ (https://code.visualstudio.com/api/references/commands). However, in reality, it seems to do so only for file:// URLs, falling back to other applications for other URL schemes (at least for HTTP/HTTPS). Until now, the URL to the documentation was always HTTP based, so using the vscode.open command was perfectly fine. However, displaying local documentation will be supported from now on (see next commit). Local documentation is not HTTP-based, but instead addressed via a file:// URL. The file URL would therefore be opened in VS Code instead of in the browser — this is definitely not what the user wants. Therefore, the vscode.env.openExternal function is used instead, this function never opens the URL in VS Code. --- editors/code/src/commands.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/editors/code/src/commands.ts b/editors/code/src/commands.ts index 245557b1e88a..5e602510601a 100644 --- a/editors/code/src/commands.ts +++ b/editors/code/src/commands.ts @@ -950,7 +950,7 @@ export function openDocs(ctx: CtxInit): Cmd { const doclink = await client.sendRequest(ra.openDocs, { position, textDocument }); if (doclink != null) { - await vscode.commands.executeCommand("vscode.open", vscode.Uri.parse(doclink)); + await vscode.env.openExternal(vscode.Uri.parse(doclink)); } }; } From aeef7b644b135c80c2fc7a28954d97194df7fabc Mon Sep 17 00:00:00 2001 From: Victor Song Date: Fri, 29 Sep 2023 03:49:37 -0500 Subject: [PATCH 109/435] Add config option to use `rust-analyzer` specific target dir Adds a Rust Analyzer configuration option to set a custom target directory for builds. This is a workaround for Rust Analyzer blocking debug builds while running `cargo check`. This change should close #6007 --- crates/rust-analyzer/src/config.rs | 200 ++++++++++++++++++++++++----- docs/user/generated_config.adoc | 9 ++ editors/code/package.json | 15 +++ 3 files changed, 190 insertions(+), 34 deletions(-) diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 8e780baa36dd..3cd6fa49b204 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -480,6 +480,13 @@ config_data! { /// tests or binaries. For example, it may be `--release`. runnables_extraArgs: Vec = "[]", + /// Optional path to a rust-analyzer specific target directory. + /// This is useful to prevent rust-analyzer's `cargo check` from blocking builds. + /// + /// Set to `true` to use a subdirectory of the existing target directory or + /// set to a path to use that path. + rust_analyzerTargetDir: Option = "null", + /// Path to the Cargo.toml of the rust compiler workspace, for usage in rustc_private /// projects, or "discover" to try to automatically find it if the `rustc-dev` component /// is installed. @@ -1192,6 +1199,7 @@ impl Config { } pub fn cargo(&self) -> CargoConfig { + let target_directory = self.target_dir_from_config(); let rustc_source = self.data.rustc_source.as_ref().map(|rustc_src| { if rustc_src == "discover" { RustLibSource::Discover @@ -1209,6 +1217,10 @@ impl Config { let sysroot_src = self.data.cargo_sysrootSrc.as_ref().map(|sysroot| self.root_path.join(sysroot)); + let mut extra_args = self.data.cargo_extraArgs.clone(); + + add_target_dir_to_args(&mut extra_args, target_directory); + CargoConfig { features: match &self.data.cargo_features { CargoFeaturesDef::All => CargoFeatures::All, @@ -1261,7 +1273,7 @@ impl Config { InvocationLocation::Workspace => project_model::InvocationLocation::Workspace, }, run_build_script_command: self.data.cargo_buildScripts_overrideCommand.clone(), - extra_args: self.data.cargo_extraArgs.clone(), + extra_args, extra_env: self.data.cargo_extraEnv.clone(), } } @@ -1281,10 +1293,14 @@ impl Config { } pub fn flycheck(&self) -> FlycheckConfig { + let target_directory = self.target_dir_from_config(); + match &self.data.check_overrideCommand { Some(args) if !args.is_empty() => { let mut args = args.clone(); let command = args.remove(0); + add_target_dir_to_args(&mut args, target_directory); + FlycheckConfig::CustomCommand { command, args, @@ -1303,42 +1319,61 @@ impl Config { }, } } - Some(_) | None => FlycheckConfig::CargoCommand { - command: self.data.check_command.clone(), - target_triples: self - .data - .check_targets - .clone() - .and_then(|targets| match &targets.0[..] { - [] => None, - targets => Some(targets.into()), - }) - .unwrap_or_else(|| self.data.cargo_target.clone().into_iter().collect()), - all_targets: self.data.check_allTargets, - no_default_features: self - .data - .check_noDefaultFeatures - .unwrap_or(self.data.cargo_noDefaultFeatures), - all_features: matches!( - self.data.check_features.as_ref().unwrap_or(&self.data.cargo_features), - CargoFeaturesDef::All - ), - features: match self - .data - .check_features - .clone() - .unwrap_or_else(|| self.data.cargo_features.clone()) - { - CargoFeaturesDef::All => vec![], - CargoFeaturesDef::Selected(it) => it, - }, - extra_args: self.check_extra_args(), - extra_env: self.check_extra_env(), - ansi_color_output: self.color_diagnostic_output(), - }, + Some(_) | None => { + let mut extra_args = self.check_extra_args(); + add_target_dir_to_args(&mut extra_args, target_directory); + + FlycheckConfig::CargoCommand { + command: self.data.check_command.clone(), + target_triples: self + .data + .check_targets + .clone() + .and_then(|targets| match &targets.0[..] { + [] => None, + targets => Some(targets.into()), + }) + .unwrap_or_else(|| self.data.cargo_target.clone().into_iter().collect()), + all_targets: self.data.check_allTargets, + no_default_features: self + .data + .check_noDefaultFeatures + .unwrap_or(self.data.cargo_noDefaultFeatures), + all_features: matches!( + self.data.check_features.as_ref().unwrap_or(&self.data.cargo_features), + CargoFeaturesDef::All + ), + features: match self + .data + .check_features + .clone() + .unwrap_or_else(|| self.data.cargo_features.clone()) + { + CargoFeaturesDef::All => vec![], + CargoFeaturesDef::Selected(it) => it, + }, + extra_args, + extra_env: self.check_extra_env(), + ansi_color_output: self.color_diagnostic_output(), + } + } } } + fn target_dir_from_config(&self) -> Option { + self.data + .rust_analyzerTargetDir + .as_ref() + .map(|target_dir| match target_dir { + TargetDirectory::UseSubdirectory(yes) if *yes => { + Some(String::from("target/rust-analyzer")) + } + TargetDirectory::UseSubdirectory(_) => None, + TargetDirectory::Directory(dir) => Some(dir.clone()), + }) + .flatten() + } + pub fn check_on_save(&self) -> bool { self.data.checkOnSave } @@ -1690,6 +1725,13 @@ impl Config { self.is_visual_studio_code } } + +fn add_target_dir_to_args(args: &mut Vec, target_dir: Option) { + if let Some(target_dir) = target_dir { + args.push(format!("--target-dir={}", target_dir)); + } +} + // Deserialization definitions macro_rules! create_bool_or_string_de { @@ -2037,6 +2079,14 @@ pub enum MemoryLayoutHoverRenderKindDef { Both, } +#[derive(Deserialize, Debug, Clone, PartialEq)] +#[serde(rename_all = "snake_case")] +#[serde(untagged)] +pub enum TargetDirectory { + UseSubdirectory(bool), + Directory(String), +} + macro_rules! _config_data { (struct $name:ident { $( @@ -2465,6 +2515,19 @@ fn field_props(field: &str, ty: &str, doc: &[&str], default: &str) -> serde_json }, ], }, + "Option" => set! { + "anyOf": [ + { + "type": "null" + }, + { + "type": "boolean" + }, + { + "type": "string" + }, + ], + }, _ => panic!("missing entry for {ty}: {default}"), } @@ -2625,4 +2688,73 @@ mod tests { Some(AbsPathBuf::try_from(project_root().join("./server")).unwrap()) ); } + + #[test] + fn cargo_target_dir_unset() { + let mut config = Config::new( + AbsPathBuf::try_from(project_root()).unwrap(), + Default::default(), + vec![], + false, + ); + config + .update(serde_json::json!({ + "rust": { "analyzerTargetDir": null } + })) + .unwrap(); + assert_eq!(config.data.rust_analyzerTargetDir, None); + assert_eq!(config.cargo().extra_args.len(), 0); + assert!( + matches!(config.flycheck(), FlycheckConfig::CargoCommand { extra_args, .. } if extra_args.is_empty()) + ); + } + + #[test] + fn cargo_target_dir_subdir() { + let mut config = Config::new( + AbsPathBuf::try_from(project_root()).unwrap(), + Default::default(), + vec![], + false, + ); + config + .update(serde_json::json!({ + "rust": { "analyzerTargetDir": true } + })) + .unwrap(); + assert_eq!( + config.data.rust_analyzerTargetDir, + Some(TargetDirectory::UseSubdirectory(true)) + ); + assert_eq!( + config.cargo().extra_args, + vec!["--target-dir=target/rust-analyzer".to_string()] + ); + assert!( + matches!(config.flycheck(), FlycheckConfig::CargoCommand { extra_args, .. } if extra_args == vec!["--target-dir=target/rust-analyzer".to_string()]) + ); + } + + #[test] + fn cargo_target_dir_relative_dir() { + let mut config = Config::new( + AbsPathBuf::try_from(project_root()).unwrap(), + Default::default(), + vec![], + false, + ); + config + .update(serde_json::json!({ + "rust": { "analyzerTargetDir": "other_folder" } + })) + .unwrap(); + assert_eq!( + config.data.rust_analyzerTargetDir, + Some(TargetDirectory::Directory("other_folder".to_string())) + ); + assert_eq!(config.cargo().extra_args, vec!["--target-dir=other_folder".to_string()]); + assert!( + matches!(config.flycheck(), FlycheckConfig::CargoCommand { extra_args, .. } if extra_args == vec!["--target-dir=other_folder".to_string()]) + ); + } } diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc index dec7a5075748..f7ae6afe3860 100644 --- a/docs/user/generated_config.adoc +++ b/docs/user/generated_config.adoc @@ -757,6 +757,15 @@ Command to be executed instead of 'cargo' for runnables. Additional arguments to be passed to cargo for runnables such as tests or binaries. For example, it may be `--release`. -- +[[rust-analyzer.rust.analyzerTargetDir]]rust-analyzer.rust.analyzerTargetDir (default: `null`):: ++ +-- +Optional path to a rust-analyzer specific target directory. +This is useful to prevent rust-analyzer's `cargo check` from blocking builds. + +Set to `true` to use a subdirectory of the existing target directory or +set to a path to use that path. +-- [[rust-analyzer.rustc.source]]rust-analyzer.rustc.source (default: `null`):: + -- diff --git a/editors/code/package.json b/editors/code/package.json index 554b05c46c70..e1402cb0f5c4 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -1488,6 +1488,21 @@ "type": "string" } }, + "rust-analyzer.rust.analyzerTargetDir": { + "markdownDescription": "Optional path to a rust-analyzer specific target directory.\nThis is useful to prevent rust-analyzer's `cargo check` from blocking builds.\n\nSet to `true` to use a subdirectory of the existing target directory or\nset to a path to use that path.", + "default": null, + "anyOf": [ + { + "type": "null" + }, + { + "type": "boolean" + }, + { + "type": "string" + } + ] + }, "rust-analyzer.rustc.source": { "markdownDescription": "Path to the Cargo.toml of the rust compiler workspace, for usage in rustc_private\nprojects, or \"discover\" to try to automatically find it if the `rustc-dev` component\nis installed.\n\nAny project which uses rust-analyzer with the rustcPrivate\ncrates must set `[package.metadata.rust-analyzer] rustc_private=true` to use it.\n\nThis option does not take effect until rust-analyzer is restarted.", "default": null, From 53b670059456ba15e4374e5ab7ba4e2468066d0c Mon Sep 17 00:00:00 2001 From: Victor Song Date: Sat, 30 Sep 2023 21:02:12 -0500 Subject: [PATCH 110/435] Add dedicated `target_dir` field to `CargoConfig` and `FlycheckConfig` Add dedicated field for `target_dir` in the configurations for Cargo and Flycheck. Also change the directory to be a `PathBuf` as opposed to a `String` to be more appropriate to the operating system. --- crates/flycheck/src/lib.rs | 5 + crates/project-model/src/build_scripts.rs | 4 + crates/project-model/src/cargo_workspace.rs | 2 + crates/rust-analyzer/src/config.rs | 111 ++++++++------------ 4 files changed, 54 insertions(+), 68 deletions(-) diff --git a/crates/flycheck/src/lib.rs b/crates/flycheck/src/lib.rs index 2de719af92ce..0749d91eb32a 100644 --- a/crates/flycheck/src/lib.rs +++ b/crates/flycheck/src/lib.rs @@ -50,6 +50,7 @@ pub enum FlycheckConfig { extra_args: Vec, extra_env: FxHashMap, ansi_color_output: bool, + target_dir: Option, }, CustomCommand { command: String, @@ -308,6 +309,7 @@ impl FlycheckActor { features, extra_env, ansi_color_output, + target_dir, } => { let mut cmd = Command::new(toolchain::cargo()); cmd.arg(command); @@ -340,6 +342,9 @@ impl FlycheckActor { cmd.arg(features.join(" ")); } } + if let Some(target_dir) = target_dir { + cmd.arg("--target-dir").arg(target_dir); + } cmd.envs(extra_env); (cmd, extra_args) } diff --git a/crates/project-model/src/build_scripts.rs b/crates/project-model/src/build_scripts.rs index fb0f3ab7d174..68cd40c040b3 100644 --- a/crates/project-model/src/build_scripts.rs +++ b/crates/project-model/src/build_scripts.rs @@ -73,6 +73,10 @@ impl WorkspaceBuildScripts { cmd.args(["check", "--quiet", "--workspace", "--message-format=json"]); cmd.args(&config.extra_args); + if let Some(target_dir) = &config.target_dir { + cmd.arg("--target-dir").arg(target_dir); + } + // --all-targets includes tests, benches and examples in addition to the // default lib and bins. This is an independent concept from the --target // flag below. diff --git a/crates/project-model/src/cargo_workspace.rs b/crates/project-model/src/cargo_workspace.rs index e47808a2cc9f..ca3d6e0596ca 100644 --- a/crates/project-model/src/cargo_workspace.rs +++ b/crates/project-model/src/cargo_workspace.rs @@ -96,6 +96,8 @@ pub struct CargoConfig { pub extra_env: FxHashMap, pub invocation_strategy: InvocationStrategy, pub invocation_location: InvocationLocation, + /// Optional path to use instead of `target` when building + pub target_dir: Option, } pub type Package = Idx; diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 3cd6fa49b204..8f1543de0045 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -1199,7 +1199,6 @@ impl Config { } pub fn cargo(&self) -> CargoConfig { - let target_directory = self.target_dir_from_config(); let rustc_source = self.data.rustc_source.as_ref().map(|rustc_src| { if rustc_src == "discover" { RustLibSource::Discover @@ -1217,10 +1216,6 @@ impl Config { let sysroot_src = self.data.cargo_sysrootSrc.as_ref().map(|sysroot| self.root_path.join(sysroot)); - let mut extra_args = self.data.cargo_extraArgs.clone(); - - add_target_dir_to_args(&mut extra_args, target_directory); - CargoConfig { features: match &self.data.cargo_features { CargoFeaturesDef::All => CargoFeatures::All, @@ -1273,8 +1268,9 @@ impl Config { InvocationLocation::Workspace => project_model::InvocationLocation::Workspace, }, run_build_script_command: self.data.cargo_buildScripts_overrideCommand.clone(), - extra_args, + extra_args: self.data.cargo_extraArgs.clone(), extra_env: self.data.cargo_extraEnv.clone(), + target_dir: self.target_dir_from_config(), } } @@ -1293,14 +1289,10 @@ impl Config { } pub fn flycheck(&self) -> FlycheckConfig { - let target_directory = self.target_dir_from_config(); - match &self.data.check_overrideCommand { Some(args) if !args.is_empty() => { let mut args = args.clone(); let command = args.remove(0); - add_target_dir_to_args(&mut args, target_directory); - FlycheckConfig::CustomCommand { command, args, @@ -1319,54 +1311,50 @@ impl Config { }, } } - Some(_) | None => { - let mut extra_args = self.check_extra_args(); - add_target_dir_to_args(&mut extra_args, target_directory); - - FlycheckConfig::CargoCommand { - command: self.data.check_command.clone(), - target_triples: self - .data - .check_targets - .clone() - .and_then(|targets| match &targets.0[..] { - [] => None, - targets => Some(targets.into()), - }) - .unwrap_or_else(|| self.data.cargo_target.clone().into_iter().collect()), - all_targets: self.data.check_allTargets, - no_default_features: self - .data - .check_noDefaultFeatures - .unwrap_or(self.data.cargo_noDefaultFeatures), - all_features: matches!( - self.data.check_features.as_ref().unwrap_or(&self.data.cargo_features), - CargoFeaturesDef::All - ), - features: match self - .data - .check_features - .clone() - .unwrap_or_else(|| self.data.cargo_features.clone()) - { - CargoFeaturesDef::All => vec![], - CargoFeaturesDef::Selected(it) => it, - }, - extra_args, - extra_env: self.check_extra_env(), - ansi_color_output: self.color_diagnostic_output(), - } - } + Some(_) | None => FlycheckConfig::CargoCommand { + command: self.data.check_command.clone(), + target_triples: self + .data + .check_targets + .clone() + .and_then(|targets| match &targets.0[..] { + [] => None, + targets => Some(targets.into()), + }) + .unwrap_or_else(|| self.data.cargo_target.clone().into_iter().collect()), + all_targets: self.data.check_allTargets, + no_default_features: self + .data + .check_noDefaultFeatures + .unwrap_or(self.data.cargo_noDefaultFeatures), + all_features: matches!( + self.data.check_features.as_ref().unwrap_or(&self.data.cargo_features), + CargoFeaturesDef::All + ), + features: match self + .data + .check_features + .clone() + .unwrap_or_else(|| self.data.cargo_features.clone()) + { + CargoFeaturesDef::All => vec![], + CargoFeaturesDef::Selected(it) => it, + }, + extra_args: self.check_extra_args(), + extra_env: self.check_extra_env(), + ansi_color_output: self.color_diagnostic_output(), + target_dir: self.target_dir_from_config(), + }, } } - fn target_dir_from_config(&self) -> Option { + fn target_dir_from_config(&self) -> Option { self.data .rust_analyzerTargetDir .as_ref() .map(|target_dir| match target_dir { TargetDirectory::UseSubdirectory(yes) if *yes => { - Some(String::from("target/rust-analyzer")) + Some(PathBuf::from("target/rust-analyzer")) } TargetDirectory::UseSubdirectory(_) => None, TargetDirectory::Directory(dir) => Some(dir.clone()), @@ -1725,13 +1713,6 @@ impl Config { self.is_visual_studio_code } } - -fn add_target_dir_to_args(args: &mut Vec, target_dir: Option) { - if let Some(target_dir) = target_dir { - args.push(format!("--target-dir={}", target_dir)); - } -} - // Deserialization definitions macro_rules! create_bool_or_string_de { @@ -2084,7 +2065,7 @@ pub enum MemoryLayoutHoverRenderKindDef { #[serde(untagged)] pub enum TargetDirectory { UseSubdirectory(bool), - Directory(String), + Directory(PathBuf), } macro_rules! _config_data { @@ -2703,9 +2684,8 @@ mod tests { })) .unwrap(); assert_eq!(config.data.rust_analyzerTargetDir, None); - assert_eq!(config.cargo().extra_args.len(), 0); assert!( - matches!(config.flycheck(), FlycheckConfig::CargoCommand { extra_args, .. } if extra_args.is_empty()) + matches!(config.flycheck(), FlycheckConfig::CargoCommand { target_dir, .. } if target_dir == None) ); } @@ -2726,12 +2706,8 @@ mod tests { config.data.rust_analyzerTargetDir, Some(TargetDirectory::UseSubdirectory(true)) ); - assert_eq!( - config.cargo().extra_args, - vec!["--target-dir=target/rust-analyzer".to_string()] - ); assert!( - matches!(config.flycheck(), FlycheckConfig::CargoCommand { extra_args, .. } if extra_args == vec!["--target-dir=target/rust-analyzer".to_string()]) + matches!(config.flycheck(), FlycheckConfig::CargoCommand { target_dir, .. } if target_dir == Some(PathBuf::from("target/rust-analyzer"))) ); } @@ -2750,11 +2726,10 @@ mod tests { .unwrap(); assert_eq!( config.data.rust_analyzerTargetDir, - Some(TargetDirectory::Directory("other_folder".to_string())) + Some(TargetDirectory::Directory(PathBuf::from("other_folder"))) ); - assert_eq!(config.cargo().extra_args, vec!["--target-dir=other_folder".to_string()]); assert!( - matches!(config.flycheck(), FlycheckConfig::CargoCommand { extra_args, .. } if extra_args == vec!["--target-dir=other_folder".to_string()]) + matches!(config.flycheck(), FlycheckConfig::CargoCommand { target_dir, .. } if target_dir == Some(PathBuf::from("other_folder"))) ); } } From ef0b3bbef1a1b4cd88619f9a5f43d526f96af184 Mon Sep 17 00:00:00 2001 From: Victor Song Date: Sat, 30 Sep 2023 21:21:00 -0500 Subject: [PATCH 111/435] Clarify documentation on new parameter --- crates/rust-analyzer/src/config.rs | 2 +- docs/user/generated_config.adoc | 2 +- editors/code/package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 8f1543de0045..39a98bcd29a8 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -484,7 +484,7 @@ config_data! { /// This is useful to prevent rust-analyzer's `cargo check` from blocking builds. /// /// Set to `true` to use a subdirectory of the existing target directory or - /// set to a path to use that path. + /// set to a path relative to the workspace to use that path. rust_analyzerTargetDir: Option = "null", /// Path to the Cargo.toml of the rust compiler workspace, for usage in rustc_private diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc index f7ae6afe3860..4440caaed89c 100644 --- a/docs/user/generated_config.adoc +++ b/docs/user/generated_config.adoc @@ -764,7 +764,7 @@ Optional path to a rust-analyzer specific target directory. This is useful to prevent rust-analyzer's `cargo check` from blocking builds. Set to `true` to use a subdirectory of the existing target directory or -set to a path to use that path. +set to a path relative to the workspace to use that path. -- [[rust-analyzer.rustc.source]]rust-analyzer.rustc.source (default: `null`):: + diff --git a/editors/code/package.json b/editors/code/package.json index e1402cb0f5c4..a18acb98301d 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -1489,7 +1489,7 @@ } }, "rust-analyzer.rust.analyzerTargetDir": { - "markdownDescription": "Optional path to a rust-analyzer specific target directory.\nThis is useful to prevent rust-analyzer's `cargo check` from blocking builds.\n\nSet to `true` to use a subdirectory of the existing target directory or\nset to a path to use that path.", + "markdownDescription": "Optional path to a rust-analyzer specific target directory.\nThis is useful to prevent rust-analyzer's `cargo check` from blocking builds.\n\nSet to `true` to use a subdirectory of the existing target directory or\nset to a path relative to the workspace to use that path.", "default": null, "anyOf": [ { From 3682c3791bff7a98179d256c1b972ee75e91b5d4 Mon Sep 17 00:00:00 2001 From: Victor Song Date: Sat, 30 Sep 2023 21:23:16 -0500 Subject: [PATCH 112/435] Set `CARGO_TARGET_DIR` when using Flycheck custom command --- crates/flycheck/src/lib.rs | 6 ++++++ crates/rust-analyzer/src/config.rs | 4 +++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/crates/flycheck/src/lib.rs b/crates/flycheck/src/lib.rs index 0749d91eb32a..f0d2f79f6332 100644 --- a/crates/flycheck/src/lib.rs +++ b/crates/flycheck/src/lib.rs @@ -58,6 +58,7 @@ pub enum FlycheckConfig { extra_env: FxHashMap, invocation_strategy: InvocationStrategy, invocation_location: InvocationLocation, + target_dir: Option, }, } @@ -354,10 +355,15 @@ impl FlycheckActor { extra_env, invocation_strategy, invocation_location, + target_dir, } => { let mut cmd = Command::new(command); cmd.envs(extra_env); + if let Some(target_dir) = target_dir { + cmd.env("CARGO_TARGET_DIR", target_dir); + } + match invocation_location { InvocationLocation::Workspace => { match invocation_strategy { diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 39a98bcd29a8..23cf71cff4fa 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -1289,6 +1289,7 @@ impl Config { } pub fn flycheck(&self) -> FlycheckConfig { + let target_dir = self.target_dir_from_config(); match &self.data.check_overrideCommand { Some(args) if !args.is_empty() => { let mut args = args.clone(); @@ -1309,6 +1310,7 @@ impl Config { } InvocationLocation::Workspace => flycheck::InvocationLocation::Workspace, }, + target_dir, } } Some(_) | None => FlycheckConfig::CargoCommand { @@ -1343,7 +1345,7 @@ impl Config { extra_args: self.check_extra_args(), extra_env: self.check_extra_env(), ansi_color_output: self.color_diagnostic_output(), - target_dir: self.target_dir_from_config(), + target_dir, }, } } From 2290cc3cf393079d30c026249af27838cc2d4595 Mon Sep 17 00:00:00 2001 From: Victor Song Date: Wed, 4 Oct 2023 08:13:01 -0500 Subject: [PATCH 113/435] Pass target directory as flag instead of env variable --- crates/flycheck/src/lib.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/flycheck/src/lib.rs b/crates/flycheck/src/lib.rs index f0d2f79f6332..c2ad2661eb46 100644 --- a/crates/flycheck/src/lib.rs +++ b/crates/flycheck/src/lib.rs @@ -360,10 +360,6 @@ impl FlycheckActor { let mut cmd = Command::new(command); cmd.envs(extra_env); - if let Some(target_dir) = target_dir { - cmd.env("CARGO_TARGET_DIR", target_dir); - } - match invocation_location { InvocationLocation::Workspace => { match invocation_strategy { @@ -381,6 +377,10 @@ impl FlycheckActor { } } + if let Some(target_dir) = target_dir { + cmd.arg("--target-dir").arg(target_dir); + } + (cmd, args) } }; From 9771e1e18fafef7571ad46374c5e55d4acd8aa09 Mon Sep 17 00:00:00 2001 From: Victor Song Date: Mon, 9 Oct 2023 02:03:45 -0500 Subject: [PATCH 114/435] Don't pass any target directory options to custom flycheck --- crates/flycheck/src/lib.rs | 6 ------ crates/rust-analyzer/src/config.rs | 4 +--- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/crates/flycheck/src/lib.rs b/crates/flycheck/src/lib.rs index c2ad2661eb46..0749d91eb32a 100644 --- a/crates/flycheck/src/lib.rs +++ b/crates/flycheck/src/lib.rs @@ -58,7 +58,6 @@ pub enum FlycheckConfig { extra_env: FxHashMap, invocation_strategy: InvocationStrategy, invocation_location: InvocationLocation, - target_dir: Option, }, } @@ -355,7 +354,6 @@ impl FlycheckActor { extra_env, invocation_strategy, invocation_location, - target_dir, } => { let mut cmd = Command::new(command); cmd.envs(extra_env); @@ -377,10 +375,6 @@ impl FlycheckActor { } } - if let Some(target_dir) = target_dir { - cmd.arg("--target-dir").arg(target_dir); - } - (cmd, args) } }; diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 23cf71cff4fa..39a98bcd29a8 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -1289,7 +1289,6 @@ impl Config { } pub fn flycheck(&self) -> FlycheckConfig { - let target_dir = self.target_dir_from_config(); match &self.data.check_overrideCommand { Some(args) if !args.is_empty() => { let mut args = args.clone(); @@ -1310,7 +1309,6 @@ impl Config { } InvocationLocation::Workspace => flycheck::InvocationLocation::Workspace, }, - target_dir, } } Some(_) | None => FlycheckConfig::CargoCommand { @@ -1345,7 +1343,7 @@ impl Config { extra_args: self.check_extra_args(), extra_env: self.check_extra_env(), ansi_color_output: self.color_diagnostic_output(), - target_dir, + target_dir: self.target_dir_from_config(), }, } } From a39d2076db1f39e49a7c7c5365eac8a11abcdc9e Mon Sep 17 00:00:00 2001 From: Victor Song Date: Mon, 9 Oct 2023 02:14:46 -0500 Subject: [PATCH 115/435] Addressed PR style comments --- crates/rust-analyzer/src/config.rs | 21 +++++++++------------ docs/user/generated_config.adoc | 3 ++- editors/code/package.json | 2 +- 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 39a98bcd29a8..c8df4255d96b 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -481,7 +481,8 @@ config_data! { runnables_extraArgs: Vec = "[]", /// Optional path to a rust-analyzer specific target directory. - /// This is useful to prevent rust-analyzer's `cargo check` from blocking builds. + /// This prevents rust-analyzer's `cargo check` from locking the `Cargo.lock` + /// at the expense of duplicating build artifacts. /// /// Set to `true` to use a subdirectory of the existing target directory or /// set to a path relative to the workspace to use that path. @@ -1349,17 +1350,13 @@ impl Config { } fn target_dir_from_config(&self) -> Option { - self.data - .rust_analyzerTargetDir - .as_ref() - .map(|target_dir| match target_dir { - TargetDirectory::UseSubdirectory(yes) if *yes => { - Some(PathBuf::from("target/rust-analyzer")) - } - TargetDirectory::UseSubdirectory(_) => None, - TargetDirectory::Directory(dir) => Some(dir.clone()), - }) - .flatten() + self.data.rust_analyzerTargetDir.as_ref().and_then(|target_dir| match target_dir { + TargetDirectory::UseSubdirectory(yes) if *yes => { + Some(PathBuf::from("target/rust-analyzer")) + } + TargetDirectory::UseSubdirectory(_) => None, + TargetDirectory::Directory(dir) => Some(dir.clone()), + }) } pub fn check_on_save(&self) -> bool { diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc index 4440caaed89c..7c76ae81bea0 100644 --- a/docs/user/generated_config.adoc +++ b/docs/user/generated_config.adoc @@ -761,7 +761,8 @@ tests or binaries. For example, it may be `--release`. + -- Optional path to a rust-analyzer specific target directory. -This is useful to prevent rust-analyzer's `cargo check` from blocking builds. +This prevents rust-analyzer's `cargo check` from locking the `Cargo.lock` +at the expense of duplicating build artifacts. Set to `true` to use a subdirectory of the existing target directory or set to a path relative to the workspace to use that path. diff --git a/editors/code/package.json b/editors/code/package.json index a18acb98301d..fc6597a0d402 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -1489,7 +1489,7 @@ } }, "rust-analyzer.rust.analyzerTargetDir": { - "markdownDescription": "Optional path to a rust-analyzer specific target directory.\nThis is useful to prevent rust-analyzer's `cargo check` from blocking builds.\n\nSet to `true` to use a subdirectory of the existing target directory or\nset to a path relative to the workspace to use that path.", + "markdownDescription": "Optional path to a rust-analyzer specific target directory.\nThis prevents rust-analyzer's `cargo check` from locking the `Cargo.lock`\nat the expense of duplicating build artifacts.\n\nSet to `true` to use a subdirectory of the existing target directory or\nset to a path relative to the workspace to use that path.", "default": null, "anyOf": [ { From 0c4be03456846af044c97c691824e50fe55c227a Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Sun, 8 Oct 2023 01:04:14 +0200 Subject: [PATCH 116/435] feat: generate descriptors for all unstable features --- crates/ide-db/src/generated/lints.rs | 5581 ++++++++++++++++++++ crates/ide-db/src/tests/sourcegen_lints.rs | 36 +- 2 files changed, 5611 insertions(+), 6 deletions(-) diff --git a/crates/ide-db/src/generated/lints.rs b/crates/ide-db/src/generated/lints.rs index 9ddcae60563e..1cb6ff8627a2 100644 --- a/crates/ide-db/src/generated/lints.rs +++ b/crates/ide-db/src/generated/lints.rs @@ -9,6 +9,7 @@ pub struct LintGroup { pub lint: Lint, pub children: &'static [&'static str], } + pub const DEFAULT_LINTS: &[Lint] = &[ Lint { label: "absolute_paths_not_starting_with_crate", @@ -951,6 +952,39 @@ pub const RUSTDOC_LINT_GROUPS: &[LintGroup] = &[LintGroup { }]; pub const FEATURES: &[Lint] = &[ + Lint { + label: "aarch64_ver_target_feature", + description: r##"# `aarch64_ver_target_feature` + +The tracking issue for this feature is: [#44839] + +[#44839]: https://github.com/rust-lang/rust/issues/44839 + +------------------------ +"##, + }, + Lint { + label: "abi_amdgpu_kernel", + description: r##"# `abi_amdgpu_kernel` + +The tracking issue for this feature is: [#51575] + +[#51575]: https://github.com/rust-lang/rust/issues/51575 + +------------------------ +"##, + }, + Lint { + label: "abi_avr_interrupt", + description: r##"# `abi_avr_interrupt` + +The tracking issue for this feature is: [#69664] + +[#69664]: https://github.com/rust-lang/rust/issues/69664 + +------------------------ +"##, + }, Lint { label: "abi_c_cmse_nonsecure_call", description: r##"# `abi_c_cmse_nonsecure_call` @@ -1151,6 +1185,121 @@ $ cat $(find -name '*.s') ret; } ``` +"##, + }, + Lint { + label: "abi_riscv_interrupt", + description: r##"# `abi_riscv_interrupt` + +The tracking issue for this feature is: [#111889] + +[#111889]: https://github.com/rust-lang/rust/issues/111889 + +------------------------ +"##, + }, + Lint { + label: "abi_unadjusted", + description: r##"# `abi_unadjusted` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "abi_vectorcall", + description: r##"# `abi_vectorcall` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "abi_x86_interrupt", + description: r##"# `abi_x86_interrupt` + +The tracking issue for this feature is: [#40180] + +[#40180]: https://github.com/rust-lang/rust/issues/40180 + +------------------------ +"##, + }, + Lint { + label: "absolute_path", + description: r##"# `absolute_path` + +The tracking issue for this feature is: [#92750] + +[#92750]: https://github.com/rust-lang/rust/issues/92750 + +------------------------ +"##, + }, + Lint { + label: "addr_parse_ascii", + description: r##"# `addr_parse_ascii` + +The tracking issue for this feature is: [#101035] + +[#101035]: https://github.com/rust-lang/rust/issues/101035 + +------------------------ +"##, + }, + Lint { + label: "adt_const_params", + description: r##"# `adt_const_params` + +The tracking issue for this feature is: [#95174] + +[#95174]: https://github.com/rust-lang/rust/issues/95174 + +------------------------ +"##, + }, + Lint { + label: "alloc_error_handler", + description: r##"# `alloc_error_handler` + +The tracking issue for this feature is: [#51540] + +[#51540]: https://github.com/rust-lang/rust/issues/51540 + +------------------------ +"##, + }, + Lint { + label: "alloc_error_hook", + description: r##"# `alloc_error_hook` + +The tracking issue for this feature is: [#51245] + +[#51245]: https://github.com/rust-lang/rust/issues/51245 + +------------------------ +"##, + }, + Lint { + label: "alloc_internals", + description: r##"# `alloc_internals` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "alloc_layout_extra", + description: r##"# `alloc_layout_extra` + +The tracking issue for this feature is: [#55724] + +[#55724]: https://github.com/rust-lang/rust/issues/55724 + +------------------------ "##, }, Lint { @@ -1180,6 +1329,165 @@ This feature does not have a tracking issue, it is an unstable implementation detail of the `global_allocator` feature not intended for use outside the compiler. +------------------------ +"##, + }, + Lint { + label: "allow_internal_unsafe", + description: r##"# `allow_internal_unsafe` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "allow_internal_unstable", + description: r##"# `allow_internal_unstable` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "anonymous_lifetime_in_impl_trait", + description: r##"# `anonymous_lifetime_in_impl_trait` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "arbitrary_self_types", + description: r##"# `arbitrary_self_types` + +The tracking issue for this feature is: [#44874] + +[#44874]: https://github.com/rust-lang/rust/issues/44874 + +------------------------ +"##, + }, + Lint { + label: "arc_unwrap_or_clone", + description: r##"# `arc_unwrap_or_clone` + +The tracking issue for this feature is: [#93610] + +[#93610]: https://github.com/rust-lang/rust/issues/93610 + +------------------------ +"##, + }, + Lint { + label: "arm_target_feature", + description: r##"# `arm_target_feature` + +The tracking issue for this feature is: [#44839] + +[#44839]: https://github.com/rust-lang/rust/issues/44839 + +------------------------ +"##, + }, + Lint { + label: "array_chunks", + description: r##"# `array_chunks` + +The tracking issue for this feature is: [#74985] + +[#74985]: https://github.com/rust-lang/rust/issues/74985 + +------------------------ +"##, + }, + Lint { + label: "array_into_iter_constructors", + description: r##"# `array_into_iter_constructors` + +The tracking issue for this feature is: [#91583] + +[#91583]: https://github.com/rust-lang/rust/issues/91583 + +------------------------ +"##, + }, + Lint { + label: "array_methods", + description: r##"# `array_methods` + +The tracking issue for this feature is: [#76118] + +[#76118]: https://github.com/rust-lang/rust/issues/76118 + +------------------------ +"##, + }, + Lint { + label: "array_try_from_fn", + description: r##"# `array_try_from_fn` + +The tracking issue for this feature is: [#89379] + +[#89379]: https://github.com/rust-lang/rust/issues/89379 + +------------------------ +"##, + }, + Lint { + label: "array_try_map", + description: r##"# `array_try_map` + +The tracking issue for this feature is: [#79711] + +[#79711]: https://github.com/rust-lang/rust/issues/79711 + +------------------------ +"##, + }, + Lint { + label: "array_windows", + description: r##"# `array_windows` + +The tracking issue for this feature is: [#75027] + +[#75027]: https://github.com/rust-lang/rust/issues/75027 + +------------------------ +"##, + }, + Lint { + label: "as_array_of_cells", + description: r##"# `as_array_of_cells` + +The tracking issue for this feature is: [#88248] + +[#88248]: https://github.com/rust-lang/rust/issues/88248 + +------------------------ +"##, + }, + Lint { + label: "ascii_char", + description: r##"# `ascii_char` + +The tracking issue for this feature is: [#110998] + +[#110998]: https://github.com/rust-lang/rust/issues/110998 + +------------------------ +"##, + }, + Lint { + label: "ascii_char_variants", + description: r##"# `ascii_char_variants` + +The tracking issue for this feature is: [#110998] + +[#110998]: https://github.com/rust-lang/rust/issues/110998 + ------------------------ "##, }, @@ -1391,6 +1699,138 @@ The tracking issue for this feature is: [#93334] ------------------------ This feature adds a `may_unwind` option to `asm!` which allows an `asm` block to unwind stack and be part of the stack unwinding process. This option is only supported by the LLVM backend right now. +"##, + }, + Lint { + label: "assert_matches", + description: r##"# `assert_matches` + +The tracking issue for this feature is: [#82775] + +[#82775]: https://github.com/rust-lang/rust/issues/82775 + +------------------------ +"##, + }, + Lint { + label: "associated_const_equality", + description: r##"# `associated_const_equality` + +The tracking issue for this feature is: [#92827] + +[#92827]: https://github.com/rust-lang/rust/issues/92827 + +------------------------ +"##, + }, + Lint { + label: "associated_type_bounds", + description: r##"# `associated_type_bounds` + +The tracking issue for this feature is: [#52662] + +[#52662]: https://github.com/rust-lang/rust/issues/52662 + +------------------------ +"##, + }, + Lint { + label: "associated_type_defaults", + description: r##"# `associated_type_defaults` + +The tracking issue for this feature is: [#29661] + +[#29661]: https://github.com/rust-lang/rust/issues/29661 + +------------------------ +"##, + }, + Lint { + label: "async_closure", + description: r##"# `async_closure` + +The tracking issue for this feature is: [#62290] + +[#62290]: https://github.com/rust-lang/rust/issues/62290 + +------------------------ +"##, + }, + Lint { + label: "async_fn_in_trait", + description: r##"# `async_fn_in_trait` + +The tracking issue for this feature is: [#91611] + +[#91611]: https://github.com/rust-lang/rust/issues/91611 + +------------------------ +"##, + }, + Lint { + label: "async_fn_track_caller", + description: r##"# `async_fn_track_caller` + +The tracking issue for this feature is: [#110011] + +[#110011]: https://github.com/rust-lang/rust/issues/110011 + +------------------------ +"##, + }, + Lint { + label: "async_iter_from_iter", + description: r##"# `async_iter_from_iter` + +The tracking issue for this feature is: [#81798] + +[#81798]: https://github.com/rust-lang/rust/issues/81798 + +------------------------ +"##, + }, + Lint { + label: "async_iterator", + description: r##"# `async_iterator` + +The tracking issue for this feature is: [#79024] + +[#79024]: https://github.com/rust-lang/rust/issues/79024 + +------------------------ +"##, + }, + Lint { + label: "atomic_bool_fetch_not", + description: r##"# `atomic_bool_fetch_not` + +The tracking issue for this feature is: [#98485] + +[#98485]: https://github.com/rust-lang/rust/issues/98485 + +------------------------ +"##, + }, + Lint { + label: "atomic_from_mut", + description: r##"# `atomic_from_mut` + +The tracking issue for this feature is: [#76314] + +[#76314]: https://github.com/rust-lang/rust/issues/76314 + +------------------------ +"##, + }, + Lint { + label: "atomic_from_ptr", + description: r##"# `atomic_from_ptr` + +The tracking issue for this feature is: [#108652] + +[#108652]: https://github.com/rust-lang/rust/issues/108652 + +------------------------ "##, }, Lint { @@ -1501,6 +1941,116 @@ Auto traits cannot have any trait items, such as methods or associated types. Th ## Supertraits Auto traits cannot have supertraits. This is for soundness reasons, as the interaction of coinduction with implied bounds is difficult to reconcile. +"##, + }, + Lint { + label: "avx512_target_feature", + description: r##"# `avx512_target_feature` + +The tracking issue for this feature is: [#44839] + +[#44839]: https://github.com/rust-lang/rust/issues/44839 + +------------------------ +"##, + }, + Lint { + label: "backtrace_frames", + description: r##"# `backtrace_frames` + +The tracking issue for this feature is: [#79676] + +[#79676]: https://github.com/rust-lang/rust/issues/79676 + +------------------------ +"##, + }, + Lint { + label: "bigint_helper_methods", + description: r##"# `bigint_helper_methods` + +The tracking issue for this feature is: [#85532] + +[#85532]: https://github.com/rust-lang/rust/issues/85532 + +------------------------ +"##, + }, + Lint { + label: "binary_heap_as_slice", + description: r##"# `binary_heap_as_slice` + +The tracking issue for this feature is: [#83659] + +[#83659]: https://github.com/rust-lang/rust/issues/83659 + +------------------------ +"##, + }, + Lint { + label: "binary_heap_drain_sorted", + description: r##"# `binary_heap_drain_sorted` + +The tracking issue for this feature is: [#59278] + +[#59278]: https://github.com/rust-lang/rust/issues/59278 + +------------------------ +"##, + }, + Lint { + label: "binary_heap_into_iter_sorted", + description: r##"# `binary_heap_into_iter_sorted` + +The tracking issue for this feature is: [#59278] + +[#59278]: https://github.com/rust-lang/rust/issues/59278 + +------------------------ +"##, + }, + Lint { + label: "bound_as_ref", + description: r##"# `bound_as_ref` + +The tracking issue for this feature is: [#80996] + +[#80996]: https://github.com/rust-lang/rust/issues/80996 + +------------------------ +"##, + }, + Lint { + label: "bound_map", + description: r##"# `bound_map` + +The tracking issue for this feature is: [#86026] + +[#86026]: https://github.com/rust-lang/rust/issues/86026 + +------------------------ +"##, + }, + Lint { + label: "box_into_boxed_slice", + description: r##"# `box_into_boxed_slice` + +The tracking issue for this feature is: [#71582] + +[#71582]: https://github.com/rust-lang/rust/issues/71582 + +------------------------ +"##, + }, + Lint { + label: "box_into_inner", + description: r##"# `box_into_inner` + +The tracking issue for this feature is: [#80437] + +[#80437]: https://github.com/rust-lang/rust/issues/80437 + +------------------------ "##, }, Lint { @@ -1535,6 +2085,105 @@ fn main() { } } ``` +"##, + }, + Lint { + label: "bpf_target_feature", + description: r##"# `bpf_target_feature` + +The tracking issue for this feature is: [#44839] + +[#44839]: https://github.com/rust-lang/rust/issues/44839 + +------------------------ +"##, + }, + Lint { + label: "btree_cursors", + description: r##"# `btree_cursors` + +The tracking issue for this feature is: [#107540] + +[#107540]: https://github.com/rust-lang/rust/issues/107540 + +------------------------ +"##, + }, + Lint { + label: "btree_extract_if", + description: r##"# `btree_extract_if` + +The tracking issue for this feature is: [#70530] + +[#70530]: https://github.com/rust-lang/rust/issues/70530 + +------------------------ +"##, + }, + Lint { + label: "btreemap_alloc", + description: r##"# `btreemap_alloc` + +The tracking issue for this feature is: [#32838] + +[#32838]: https://github.com/rust-lang/rust/issues/32838 + +------------------------ +"##, + }, + Lint { + label: "buf_read_has_data_left", + description: r##"# `buf_read_has_data_left` + +The tracking issue for this feature is: [#86423] + +[#86423]: https://github.com/rust-lang/rust/issues/86423 + +------------------------ +"##, + }, + Lint { + label: "builtin_syntax", + description: r##"# `builtin_syntax` + +The tracking issue for this feature is: [#110680] + +[#110680]: https://github.com/rust-lang/rust/issues/110680 + +------------------------ +"##, + }, + Lint { + label: "byte_slice_trim_ascii", + description: r##"# `byte_slice_trim_ascii` + +The tracking issue for this feature is: [#94035] + +[#94035]: https://github.com/rust-lang/rust/issues/94035 + +------------------------ +"##, + }, + Lint { + label: "c_size_t", + description: r##"# `c_size_t` + +The tracking issue for this feature is: [#88345] + +[#88345]: https://github.com/rust-lang/rust/issues/88345 + +------------------------ +"##, + }, + Lint { + label: "c_str_literals", + description: r##"# `c_str_literals` + +The tracking issue for this feature is: [#105723] + +[#105723]: https://github.com/rust-lang/rust/issues/105723 + +------------------------ "##, }, Lint { @@ -1631,6 +2280,94 @@ pub unsafe extern "C" fn vadd(n: usize, mut args: VaList) -> usize { This feature is internal to the Rust compiler and is not intended for general use. +------------------------ +"##, + }, + Lint { + label: "can_vector", + description: r##"# `can_vector` + +The tracking issue for this feature is: [#69941] + +[#69941]: https://github.com/rust-lang/rust/issues/69941 + +------------------------ +"##, + }, + Lint { + label: "cell_leak", + description: r##"# `cell_leak` + +The tracking issue for this feature is: [#69099] + +[#69099]: https://github.com/rust-lang/rust/issues/69099 + +------------------------ +"##, + }, + Lint { + label: "cell_update", + description: r##"# `cell_update` + +The tracking issue for this feature is: [#50186] + +[#50186]: https://github.com/rust-lang/rust/issues/50186 + +------------------------ +"##, + }, + Lint { + label: "cfg_accessible", + description: r##"# `cfg_accessible` + +The tracking issue for this feature is: [#64797] + +[#64797]: https://github.com/rust-lang/rust/issues/64797 + +------------------------ +"##, + }, + Lint { + label: "cfg_eval", + description: r##"# `cfg_eval` + +The tracking issue for this feature is: [#82679] + +[#82679]: https://github.com/rust-lang/rust/issues/82679 + +------------------------ +"##, + }, + Lint { + label: "cfg_match", + description: r##"# `cfg_match` + +The tracking issue for this feature is: [#115585] + +[#115585]: https://github.com/rust-lang/rust/issues/115585 + +------------------------ +"##, + }, + Lint { + label: "cfg_overflow_checks", + description: r##"# `cfg_overflow_checks` + +The tracking issue for this feature is: [#111466] + +[#111466]: https://github.com/rust-lang/rust/issues/111466 + +------------------------ +"##, + }, + Lint { + label: "cfg_relocation_model", + description: r##"# `cfg_relocation_model` + +The tracking issue for this feature is: [#114929] + +[#114929]: https://github.com/rust-lang/rust/issues/114929 + ------------------------ "##, }, @@ -1670,6 +2407,61 @@ fn b() { } } ``` +"##, + }, + Lint { + label: "cfg_target_abi", + description: r##"# `cfg_target_abi` + +The tracking issue for this feature is: [#80970] + +[#80970]: https://github.com/rust-lang/rust/issues/80970 + +------------------------ +"##, + }, + Lint { + label: "cfg_target_compact", + description: r##"# `cfg_target_compact` + +The tracking issue for this feature is: [#96901] + +[#96901]: https://github.com/rust-lang/rust/issues/96901 + +------------------------ +"##, + }, + Lint { + label: "cfg_target_has_atomic", + description: r##"# `cfg_target_has_atomic` + +The tracking issue for this feature is: [#94039] + +[#94039]: https://github.com/rust-lang/rust/issues/94039 + +------------------------ +"##, + }, + Lint { + label: "cfg_target_has_atomic_equal_alignment", + description: r##"# `cfg_target_has_atomic_equal_alignment` + +The tracking issue for this feature is: [#93822] + +[#93822]: https://github.com/rust-lang/rust/issues/93822 + +------------------------ +"##, + }, + Lint { + label: "cfg_target_thread_local", + description: r##"# `cfg_target_thread_local` + +The tracking issue for this feature is: [#29594] + +[#29594]: https://github.com/rust-lang/rust/issues/29594 + +------------------------ "##, }, Lint { @@ -1738,6 +2530,48 @@ extern { type Type2; } ``` +"##, + }, + Lint { + label: "char_indices_offset", + description: r##"# `char_indices_offset` + +The tracking issue for this feature is: [#83871] + +[#83871]: https://github.com/rust-lang/rust/issues/83871 + +------------------------ +"##, + }, + Lint { + label: "char_internals", + description: r##"# `char_internals` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "char_min", + description: r##"# `char_min` + +The tracking issue for this feature is: [#114298] + +[#114298]: https://github.com/rust-lang/rust/issues/114298 + +------------------------ +"##, + }, + Lint { + label: "closure_lifetime_binder", + description: r##"# `closure_lifetime_binder` + +The tracking issue for this feature is: [#97362] + +[#97362]: https://github.com/rust-lang/rust/issues/97362 + +------------------------ "##, }, Lint { @@ -1754,6 +2588,17 @@ Allows using the `#[track_caller]` attribute on closures and generators. Calls made to the closure or generator will have caller information available through `std::panic::Location::caller()`, just like using `#[track_caller]` on a function. +"##, + }, + Lint { + label: "cmp_minmax", + description: r##"# `cmp_minmax` + +The tracking issue for this feature is: [#115939] + +[#115939]: https://github.com/rust-lang/rust/issues/115939 + +------------------------ "##, }, Lint { @@ -1839,6 +2684,28 @@ $ arm-none-eabi-objdump -D function.o 3c: f7ff fffe bl 0 <_ZN4core9panicking5panic17h5c028258ca2fb3f5E> 40: defe udf #254 ; 0xfe ``` +"##, + }, + Lint { + label: "coerce_unsized", + description: r##"# `coerce_unsized` + +The tracking issue for this feature is: [#18598] + +[#18598]: https://github.com/rust-lang/rust/issues/18598 + +------------------------ +"##, + }, + Lint { + label: "collapse_debuginfo", + description: r##"# `collapse_debuginfo` + +The tracking issue for this feature is: [#100758] + +[#100758]: https://github.com/rust-lang/rust/issues/100758 + +------------------------ "##, }, Lint { @@ -1847,6 +2714,17 @@ $ arm-none-eabi-objdump -D function.o This feature is internal to the Rust compiler and is not intended for general use. +------------------------ +"##, + }, + Lint { + label: "concat_bytes", + description: r##"# `concat_bytes` + +The tracking issue for this feature is: [#87555] + +[#87555]: https://github.com/rust-lang/rust/issues/87555 + ------------------------ "##, }, @@ -1874,6 +2752,1030 @@ fn main() { assert_eq!(f(), 23); } ``` +"##, + }, + Lint { + label: "const_align_of_val", + description: r##"# `const_align_of_val` + +The tracking issue for this feature is: [#46571] + +[#46571]: https://github.com/rust-lang/rust/issues/46571 + +------------------------ +"##, + }, + Lint { + label: "const_align_of_val_raw", + description: r##"# `const_align_of_val_raw` + +The tracking issue for this feature is: [#46571] + +[#46571]: https://github.com/rust-lang/rust/issues/46571 + +------------------------ +"##, + }, + Lint { + label: "const_align_offset", + description: r##"# `const_align_offset` + +The tracking issue for this feature is: [#90962] + +[#90962]: https://github.com/rust-lang/rust/issues/90962 + +------------------------ +"##, + }, + Lint { + label: "const_alloc_error", + description: r##"# `const_alloc_error` + +The tracking issue for this feature is: [#92523] + +[#92523]: https://github.com/rust-lang/rust/issues/92523 + +------------------------ +"##, + }, + Lint { + label: "const_alloc_layout", + description: r##"# `const_alloc_layout` + +The tracking issue for this feature is: [#67521] + +[#67521]: https://github.com/rust-lang/rust/issues/67521 + +------------------------ +"##, + }, + Lint { + label: "const_arguments_as_str", + description: r##"# `const_arguments_as_str` + +The tracking issue for this feature is: [#103900] + +[#103900]: https://github.com/rust-lang/rust/issues/103900 + +------------------------ +"##, + }, + Lint { + label: "const_array_from_ref", + description: r##"# `const_array_from_ref` + +The tracking issue for this feature is: [#90206] + +[#90206]: https://github.com/rust-lang/rust/issues/90206 + +------------------------ +"##, + }, + Lint { + label: "const_array_into_iter_constructors", + description: r##"# `const_array_into_iter_constructors` + +The tracking issue for this feature is: [#91583] + +[#91583]: https://github.com/rust-lang/rust/issues/91583 + +------------------------ +"##, + }, + Lint { + label: "const_assert_type2", + description: r##"# `const_assert_type2` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "const_assume", + description: r##"# `const_assume` + +The tracking issue for this feature is: [#76972] + +[#76972]: https://github.com/rust-lang/rust/issues/76972 + +------------------------ +"##, + }, + Lint { + label: "const_async_blocks", + description: r##"# `const_async_blocks` + +The tracking issue for this feature is: [#85368] + +[#85368]: https://github.com/rust-lang/rust/issues/85368 + +------------------------ +"##, + }, + Lint { + label: "const_bigint_helper_methods", + description: r##"# `const_bigint_helper_methods` + +The tracking issue for this feature is: [#85532] + +[#85532]: https://github.com/rust-lang/rust/issues/85532 + +------------------------ +"##, + }, + Lint { + label: "const_black_box", + description: r##"# `const_black_box` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "const_box", + description: r##"# `const_box` + +The tracking issue for this feature is: [#92521] + +[#92521]: https://github.com/rust-lang/rust/issues/92521 + +------------------------ +"##, + }, + Lint { + label: "const_btree_len", + description: r##"# `const_btree_len` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "const_caller_location", + description: r##"# `const_caller_location` + +The tracking issue for this feature is: [#76156] + +[#76156]: https://github.com/rust-lang/rust/issues/76156 + +------------------------ +"##, + }, + Lint { + label: "const_cell_into_inner", + description: r##"# `const_cell_into_inner` + +The tracking issue for this feature is: [#78729] + +[#78729]: https://github.com/rust-lang/rust/issues/78729 + +------------------------ +"##, + }, + Lint { + label: "const_char_from_u32_unchecked", + description: r##"# `const_char_from_u32_unchecked` + +The tracking issue for this feature is: [#89259] + +[#89259]: https://github.com/rust-lang/rust/issues/89259 + +------------------------ +"##, + }, + Lint { + label: "const_closures", + description: r##"# `const_closures` + +The tracking issue for this feature is: [#106003] + +[#106003]: https://github.com/rust-lang/rust/issues/106003 + +------------------------ +"##, + }, + Lint { + label: "const_collections_with_hasher", + description: r##"# `const_collections_with_hasher` + +The tracking issue for this feature is: [#102575] + +[#102575]: https://github.com/rust-lang/rust/issues/102575 + +------------------------ +"##, + }, + Lint { + label: "const_cow_is_borrowed", + description: r##"# `const_cow_is_borrowed` + +The tracking issue for this feature is: [#65143] + +[#65143]: https://github.com/rust-lang/rust/issues/65143 + +------------------------ +"##, + }, + Lint { + label: "const_cstr_from_ptr", + description: r##"# `const_cstr_from_ptr` + +The tracking issue for this feature is: [#113219] + +[#113219]: https://github.com/rust-lang/rust/issues/113219 + +------------------------ +"##, + }, + Lint { + label: "const_discriminant", + description: r##"# `const_discriminant` + +The tracking issue for this feature is: [#69821] + +[#69821]: https://github.com/rust-lang/rust/issues/69821 + +------------------------ +"##, + }, + Lint { + label: "const_eval_select", + description: r##"# `const_eval_select` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "const_exact_div", + description: r##"# `const_exact_div` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "const_extern_fn", + description: r##"# `const_extern_fn` + +The tracking issue for this feature is: [#64926] + +[#64926]: https://github.com/rust-lang/rust/issues/64926 + +------------------------ +"##, + }, + Lint { + label: "const_float_bits_conv", + description: r##"# `const_float_bits_conv` + +The tracking issue for this feature is: [#72447] + +[#72447]: https://github.com/rust-lang/rust/issues/72447 + +------------------------ +"##, + }, + Lint { + label: "const_float_classify", + description: r##"# `const_float_classify` + +The tracking issue for this feature is: [#72505] + +[#72505]: https://github.com/rust-lang/rust/issues/72505 + +------------------------ +"##, + }, + Lint { + label: "const_fmt_arguments_new", + description: r##"# `const_fmt_arguments_new` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "const_fn_floating_point_arithmetic", + description: r##"# `const_fn_floating_point_arithmetic` + +The tracking issue for this feature is: [#57241] + +[#57241]: https://github.com/rust-lang/rust/issues/57241 + +------------------------ +"##, + }, + Lint { + label: "const_for", + description: r##"# `const_for` + +The tracking issue for this feature is: [#87575] + +[#87575]: https://github.com/rust-lang/rust/issues/87575 + +------------------------ +"##, + }, + Lint { + label: "const_format_args", + description: r##"# `const_format_args` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "const_hash", + description: r##"# `const_hash` + +The tracking issue for this feature is: [#104061] + +[#104061]: https://github.com/rust-lang/rust/issues/104061 + +------------------------ +"##, + }, + Lint { + label: "const_heap", + description: r##"# `const_heap` + +The tracking issue for this feature is: [#79597] + +[#79597]: https://github.com/rust-lang/rust/issues/79597 + +------------------------ +"##, + }, + Lint { + label: "const_index_range_slice_index", + description: r##"# `const_index_range_slice_index` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "const_inherent_unchecked_arith", + description: r##"# `const_inherent_unchecked_arith` + +The tracking issue for this feature is: [#85122] + +[#85122]: https://github.com/rust-lang/rust/issues/85122 + +------------------------ +"##, + }, + Lint { + label: "const_int_unchecked_arith", + description: r##"# `const_int_unchecked_arith` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "const_intoiterator_identity", + description: r##"# `const_intoiterator_identity` + +The tracking issue for this feature is: [#90603] + +[#90603]: https://github.com/rust-lang/rust/issues/90603 + +------------------------ +"##, + }, + Lint { + label: "const_intrinsic_compare_bytes", + description: r##"# `const_intrinsic_compare_bytes` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "const_intrinsic_forget", + description: r##"# `const_intrinsic_forget` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "const_intrinsic_raw_eq", + description: r##"# `const_intrinsic_raw_eq` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "const_io_structs", + description: r##"# `const_io_structs` + +The tracking issue for this feature is: [#78812] + +[#78812]: https://github.com/rust-lang/rust/issues/78812 + +------------------------ +"##, + }, + Lint { + label: "const_ip", + description: r##"# `const_ip` + +The tracking issue for this feature is: [#76205] + +[#76205]: https://github.com/rust-lang/rust/issues/76205 + +------------------------ +"##, + }, + Lint { + label: "const_ipv4", + description: r##"# `const_ipv4` + +The tracking issue for this feature is: [#76205] + +[#76205]: https://github.com/rust-lang/rust/issues/76205 + +------------------------ +"##, + }, + Lint { + label: "const_ipv6", + description: r##"# `const_ipv6` + +The tracking issue for this feature is: [#76205] + +[#76205]: https://github.com/rust-lang/rust/issues/76205 + +------------------------ +"##, + }, + Lint { + label: "const_likely", + description: r##"# `const_likely` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "const_location_fields", + description: r##"# `const_location_fields` + +The tracking issue for this feature is: [#102911] + +[#102911]: https://github.com/rust-lang/rust/issues/102911 + +------------------------ +"##, + }, + Lint { + label: "const_maybe_uninit_array_assume_init", + description: r##"# `const_maybe_uninit_array_assume_init` + +The tracking issue for this feature is: [#96097] + +[#96097]: https://github.com/rust-lang/rust/issues/96097 + +------------------------ +"##, + }, + Lint { + label: "const_maybe_uninit_as_mut_ptr", + description: r##"# `const_maybe_uninit_as_mut_ptr` + +The tracking issue for this feature is: [#75251] + +[#75251]: https://github.com/rust-lang/rust/issues/75251 + +------------------------ +"##, + }, + Lint { + label: "const_maybe_uninit_assume_init", + description: r##"# `const_maybe_uninit_assume_init` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "const_maybe_uninit_assume_init_read", + description: r##"# `const_maybe_uninit_assume_init_read` + +The tracking issue for this feature is: [#63567] + +[#63567]: https://github.com/rust-lang/rust/issues/63567 + +------------------------ +"##, + }, + Lint { + label: "const_maybe_uninit_uninit_array", + description: r##"# `const_maybe_uninit_uninit_array` + +The tracking issue for this feature is: [#96097] + +[#96097]: https://github.com/rust-lang/rust/issues/96097 + +------------------------ +"##, + }, + Lint { + label: "const_maybe_uninit_write", + description: r##"# `const_maybe_uninit_write` + +The tracking issue for this feature is: [#63567] + +[#63567]: https://github.com/rust-lang/rust/issues/63567 + +------------------------ +"##, + }, + Lint { + label: "const_maybe_uninit_zeroed", + description: r##"# `const_maybe_uninit_zeroed` + +The tracking issue for this feature is: [#91850] + +[#91850]: https://github.com/rust-lang/rust/issues/91850 + +------------------------ +"##, + }, + Lint { + label: "const_mut_refs", + description: r##"# `const_mut_refs` + +The tracking issue for this feature is: [#57349] + +[#57349]: https://github.com/rust-lang/rust/issues/57349 + +------------------------ +"##, + }, + Lint { + label: "const_nonnull_new", + description: r##"# `const_nonnull_new` + +The tracking issue for this feature is: [#93235] + +[#93235]: https://github.com/rust-lang/rust/issues/93235 + +------------------------ +"##, + }, + Lint { + label: "const_num_midpoint", + description: r##"# `const_num_midpoint` + +The tracking issue for this feature is: [#110840] + +[#110840]: https://github.com/rust-lang/rust/issues/110840 + +------------------------ +"##, + }, + Lint { + label: "const_option", + description: r##"# `const_option` + +The tracking issue for this feature is: [#67441] + +[#67441]: https://github.com/rust-lang/rust/issues/67441 + +------------------------ +"##, + }, + Lint { + label: "const_option_ext", + description: r##"# `const_option_ext` + +The tracking issue for this feature is: [#91930] + +[#91930]: https://github.com/rust-lang/rust/issues/91930 + +------------------------ +"##, + }, + Lint { + label: "const_pin", + description: r##"# `const_pin` + +The tracking issue for this feature is: [#76654] + +[#76654]: https://github.com/rust-lang/rust/issues/76654 + +------------------------ +"##, + }, + Lint { + label: "const_pointer_byte_offsets", + description: r##"# `const_pointer_byte_offsets` + +The tracking issue for this feature is: [#96283] + +[#96283]: https://github.com/rust-lang/rust/issues/96283 + +------------------------ +"##, + }, + Lint { + label: "const_pointer_is_aligned", + description: r##"# `const_pointer_is_aligned` + +The tracking issue for this feature is: [#104203] + +[#104203]: https://github.com/rust-lang/rust/issues/104203 + +------------------------ +"##, + }, + Lint { + label: "const_precise_live_drops", + description: r##"# `const_precise_live_drops` + +The tracking issue for this feature is: [#73255] + +[#73255]: https://github.com/rust-lang/rust/issues/73255 + +------------------------ +"##, + }, + Lint { + label: "const_pref_align_of", + description: r##"# `const_pref_align_of` + +The tracking issue for this feature is: [#91971] + +[#91971]: https://github.com/rust-lang/rust/issues/91971 + +------------------------ +"##, + }, + Lint { + label: "const_ptr_as_ref", + description: r##"# `const_ptr_as_ref` + +The tracking issue for this feature is: [#91822] + +[#91822]: https://github.com/rust-lang/rust/issues/91822 + +------------------------ +"##, + }, + Lint { + label: "const_ptr_is_null", + description: r##"# `const_ptr_is_null` + +The tracking issue for this feature is: [#74939] + +[#74939]: https://github.com/rust-lang/rust/issues/74939 + +------------------------ +"##, + }, + Lint { + label: "const_ptr_sub_ptr", + description: r##"# `const_ptr_sub_ptr` + +The tracking issue for this feature is: [#95892] + +[#95892]: https://github.com/rust-lang/rust/issues/95892 + +------------------------ +"##, + }, + Lint { + label: "const_ptr_write", + description: r##"# `const_ptr_write` + +The tracking issue for this feature is: [#86302] + +[#86302]: https://github.com/rust-lang/rust/issues/86302 + +------------------------ +"##, + }, + Lint { + label: "const_range_bounds", + description: r##"# `const_range_bounds` + +The tracking issue for this feature is: [#108082] + +[#108082]: https://github.com/rust-lang/rust/issues/108082 + +------------------------ +"##, + }, + Lint { + label: "const_raw_ptr_comparison", + description: r##"# `const_raw_ptr_comparison` + +The tracking issue for this feature is: [#53020] + +[#53020]: https://github.com/rust-lang/rust/issues/53020 + +------------------------ +"##, + }, + Lint { + label: "const_refs_to_cell", + description: r##"# `const_refs_to_cell` + +The tracking issue for this feature is: [#80384] + +[#80384]: https://github.com/rust-lang/rust/issues/80384 + +------------------------ +"##, + }, + Lint { + label: "const_replace", + description: r##"# `const_replace` + +The tracking issue for this feature is: [#83164] + +[#83164]: https://github.com/rust-lang/rust/issues/83164 + +------------------------ +"##, + }, + Lint { + label: "const_result", + description: r##"# `const_result` + +The tracking issue for this feature is: [#82814] + +[#82814]: https://github.com/rust-lang/rust/issues/82814 + +------------------------ +"##, + }, + Lint { + label: "const_size_of_val", + description: r##"# `const_size_of_val` + +The tracking issue for this feature is: [#46571] + +[#46571]: https://github.com/rust-lang/rust/issues/46571 + +------------------------ +"##, + }, + Lint { + label: "const_size_of_val_raw", + description: r##"# `const_size_of_val_raw` + +The tracking issue for this feature is: [#46571] + +[#46571]: https://github.com/rust-lang/rust/issues/46571 + +------------------------ +"##, + }, + Lint { + label: "const_slice_first_last", + description: r##"# `const_slice_first_last` + +The tracking issue for this feature is: [#83570] + +[#83570]: https://github.com/rust-lang/rust/issues/83570 + +------------------------ +"##, + }, + Lint { + label: "const_slice_from_mut_ptr_range", + description: r##"# `const_slice_from_mut_ptr_range` + +The tracking issue for this feature is: [#89792] + +[#89792]: https://github.com/rust-lang/rust/issues/89792 + +------------------------ +"##, + }, + Lint { + label: "const_slice_from_ptr_range", + description: r##"# `const_slice_from_ptr_range` + +The tracking issue for this feature is: [#89792] + +[#89792]: https://github.com/rust-lang/rust/issues/89792 + +------------------------ +"##, + }, + Lint { + label: "const_slice_from_raw_parts_mut", + description: r##"# `const_slice_from_raw_parts_mut` + +The tracking issue for this feature is: [#67456] + +[#67456]: https://github.com/rust-lang/rust/issues/67456 + +------------------------ +"##, + }, + Lint { + label: "const_slice_from_ref", + description: r##"# `const_slice_from_ref` + +The tracking issue for this feature is: [#90206] + +[#90206]: https://github.com/rust-lang/rust/issues/90206 + +------------------------ +"##, + }, + Lint { + label: "const_slice_index", + description: r##"# `const_slice_index` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "const_slice_ptr_len", + description: r##"# `const_slice_ptr_len` + +The tracking issue for this feature is: [#71146] + +[#71146]: https://github.com/rust-lang/rust/issues/71146 + +------------------------ +"##, + }, + Lint { + label: "const_slice_split_at_mut", + description: r##"# `const_slice_split_at_mut` + +The tracking issue for this feature is: [#101804] + +[#101804]: https://github.com/rust-lang/rust/issues/101804 + +------------------------ +"##, + }, + Lint { + label: "const_str_from_utf8", + description: r##"# `const_str_from_utf8` + +The tracking issue for this feature is: [#91006] + +[#91006]: https://github.com/rust-lang/rust/issues/91006 + +------------------------ +"##, + }, + Lint { + label: "const_str_from_utf8_unchecked_mut", + description: r##"# `const_str_from_utf8_unchecked_mut` + +The tracking issue for this feature is: [#91005] + +[#91005]: https://github.com/rust-lang/rust/issues/91005 + +------------------------ +"##, + }, + Lint { + label: "const_swap", + description: r##"# `const_swap` + +The tracking issue for this feature is: [#83163] + +[#83163]: https://github.com/rust-lang/rust/issues/83163 + +------------------------ +"##, + }, + Lint { + label: "const_trait_impl", + description: r##"# `const_trait_impl` + +The tracking issue for this feature is: [#67792] + +[#67792]: https://github.com/rust-lang/rust/issues/67792 + +------------------------ +"##, + }, + Lint { + label: "const_try", + description: r##"# `const_try` + +The tracking issue for this feature is: [#74935] + +[#74935]: https://github.com/rust-lang/rust/issues/74935 + +------------------------ +"##, + }, + Lint { + label: "const_type_id", + description: r##"# `const_type_id` + +The tracking issue for this feature is: [#77125] + +[#77125]: https://github.com/rust-lang/rust/issues/77125 + +------------------------ +"##, + }, + Lint { + label: "const_type_name", + description: r##"# `const_type_name` + +The tracking issue for this feature is: [#63084] + +[#63084]: https://github.com/rust-lang/rust/issues/63084 + +------------------------ +"##, + }, + Lint { + label: "const_unicode_case_lookup", + description: r##"# `const_unicode_case_lookup` + +The tracking issue for this feature is: [#101400] + +[#101400]: https://github.com/rust-lang/rust/issues/101400 + +------------------------ +"##, + }, + Lint { + label: "const_unsafecell_get_mut", + description: r##"# `const_unsafecell_get_mut` + +The tracking issue for this feature is: [#88836] + +[#88836]: https://github.com/rust-lang/rust/issues/88836 + +------------------------ +"##, + }, + Lint { + label: "const_waker", + description: r##"# `const_waker` + +The tracking issue for this feature is: [#102012] + +[#102012]: https://github.com/rust-lang/rust/issues/102012 + +------------------------ +"##, + }, + Lint { + label: "container_error_extra", + description: r##"# `container_error_extra` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "control_flow_enum", + description: r##"# `control_flow_enum` + +The tracking issue for this feature is: [#75744] + +[#75744]: https://github.com/rust-lang/rust/issues/75744 + +------------------------ +"##, + }, + Lint { + label: "convert_float_to_int", + description: r##"# `convert_float_to_int` + +The tracking issue for this feature is: [#67057] + +[#67057]: https://github.com/rust-lang/rust/issues/67057 + +------------------------ "##, }, Lint { @@ -1944,6 +3846,81 @@ fn bar() { // ... } ``` +"##, + }, + Lint { + label: "cow_is_borrowed", + description: r##"# `cow_is_borrowed` + +The tracking issue for this feature is: [#65143] + +[#65143]: https://github.com/rust-lang/rust/issues/65143 + +------------------------ +"##, + }, + Lint { + label: "csky_target_feature", + description: r##"# `csky_target_feature` + +The tracking issue for this feature is: [#44839] + +[#44839]: https://github.com/rust-lang/rust/issues/44839 + +------------------------ +"##, + }, + Lint { + label: "cstr_count_bytes", + description: r##"# `cstr_count_bytes` + +The tracking issue for this feature is: [#114441] + +[#114441]: https://github.com/rust-lang/rust/issues/114441 + +------------------------ +"##, + }, + Lint { + label: "cursor_remaining", + description: r##"# `cursor_remaining` + +The tracking issue for this feature is: [#86369] + +[#86369]: https://github.com/rust-lang/rust/issues/86369 + +------------------------ +"##, + }, + Lint { + label: "custom_code_classes_in_docs", + description: r##"# `custom_code_classes_in_docs` + +The tracking issue for this feature is: [#79483] + +[#79483]: https://github.com/rust-lang/rust/issues/79483 + +------------------------ +"##, + }, + Lint { + label: "custom_inner_attributes", + description: r##"# `custom_inner_attributes` + +The tracking issue for this feature is: [#54726] + +[#54726]: https://github.com/rust-lang/rust/issues/54726 + +------------------------ +"##, + }, + Lint { + label: "custom_mir", + description: r##"# `custom_mir` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ "##, }, Lint { @@ -1980,6 +3957,17 @@ const WILL_PASS: i32 = 0; #[test_case] const WILL_FAIL: i32 = 4; ``` +"##, + }, + Lint { + label: "deadline_api", + description: r##"# `deadline_api` + +The tracking issue for this feature is: [#46316] + +[#46316]: https://github.com/rust-lang/rust/issues/46316 + +------------------------ "##, }, Lint { @@ -1988,6 +3976,50 @@ const WILL_FAIL: i32 = 4; This feature is internal to the Rust compiler and is not intended for general use. +------------------------ +"##, + }, + Lint { + label: "decl_macro", + description: r##"# `decl_macro` + +The tracking issue for this feature is: [#39412] + +[#39412]: https://github.com/rust-lang/rust/issues/39412 + +------------------------ +"##, + }, + Lint { + label: "default_type_parameter_fallback", + description: r##"# `default_type_parameter_fallback` + +The tracking issue for this feature is: [#27336] + +[#27336]: https://github.com/rust-lang/rust/issues/27336 + +------------------------ +"##, + }, + Lint { + label: "deprecated_safe", + description: r##"# `deprecated_safe` + +The tracking issue for this feature is: [#94978] + +[#94978]: https://github.com/rust-lang/rust/issues/94978 + +------------------------ +"##, + }, + Lint { + label: "deprecated_suggestion", + description: r##"# `deprecated_suggestion` + +The tracking issue for this feature is: [#94785] + +[#94785]: https://github.com/rust-lang/rust/issues/94785 + ------------------------ "##, }, @@ -1997,6 +4029,15 @@ This feature is internal to the Rust compiler and is not intended for general us This feature is internal to the Rust compiler and is not intended for general use. +------------------------ +"##, + }, + Lint { + label: "derive_const", + description: r##"# `derive_const` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + ------------------------ "##, }, @@ -2006,6 +4047,79 @@ This feature is internal to the Rust compiler and is not intended for general us This feature is internal to the Rust compiler and is not intended for general use. +------------------------ +"##, + }, + Lint { + label: "diagnostic_namespace", + description: r##"# `diagnostic_namespace` + +The tracking issue for this feature is: [#111996] + +[#111996]: https://github.com/rust-lang/rust/issues/111996 + +------------------------ +"##, + }, + Lint { + label: "dir_entry_ext2", + description: r##"# `dir_entry_ext2` + +The tracking issue for this feature is: [#85573] + +[#85573]: https://github.com/rust-lang/rust/issues/85573 + +------------------------ +"##, + }, + Lint { + label: "discriminant_kind", + description: r##"# `discriminant_kind` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "dispatch_from_dyn", + description: r##"# `dispatch_from_dyn` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "div_duration", + description: r##"# `div_duration` + +The tracking issue for this feature is: [#63139] + +[#63139]: https://github.com/rust-lang/rust/issues/63139 + +------------------------ +"##, + }, + Lint { + label: "do_not_recommend", + description: r##"# `do_not_recommend` + +The tracking issue for this feature is: [#51992] + +[#51992]: https://github.com/rust-lang/rust/issues/51992 + +------------------------ +"##, + }, + Lint { + label: "doc_auto_cfg", + description: r##"# `doc_auto_cfg` + +The tracking issue for this feature is: [#43781] + +[#43781]: https://github.com/rust-lang/rust/issues/43781 + ------------------------ "##, }, @@ -2057,6 +4171,17 @@ pub struct Icon { [#43781]: https://github.com/rust-lang/rust/issues/43781 [#43348]: https://github.com/rust-lang/rust/issues/43348 +"##, + }, + Lint { + label: "doc_cfg_hide", + description: r##"# `doc_cfg_hide` + +The tracking issue for this feature is: [#43781] + +[#43781]: https://github.com/rust-lang/rust/issues/43781 + +------------------------ "##, }, Lint { @@ -2122,6 +4247,180 @@ See also its documentation in [the rustdoc book][rustdoc-book-notable_trait]. [#45040]: https://github.com/rust-lang/rust/issues/45040 [#45039]: https://github.com/rust-lang/rust/pull/45039 [rustdoc-book-notable_trait]: ../../rustdoc/unstable-features.html#adding-your-trait-to-the-notable-traits-dialog +"##, + }, + Lint { + label: "downcast_unchecked", + description: r##"# `downcast_unchecked` + +The tracking issue for this feature is: [#90850] + +[#90850]: https://github.com/rust-lang/rust/issues/90850 + +------------------------ +"##, + }, + Lint { + label: "drain_keep_rest", + description: r##"# `drain_keep_rest` + +The tracking issue for this feature is: [#101122] + +[#101122]: https://github.com/rust-lang/rust/issues/101122 + +------------------------ +"##, + }, + Lint { + label: "dropck_eyepatch", + description: r##"# `dropck_eyepatch` + +The tracking issue for this feature is: [#34761] + +[#34761]: https://github.com/rust-lang/rust/issues/34761 + +------------------------ +"##, + }, + Lint { + label: "duration_constants", + description: r##"# `duration_constants` + +The tracking issue for this feature is: [#57391] + +[#57391]: https://github.com/rust-lang/rust/issues/57391 + +------------------------ +"##, + }, + Lint { + label: "duration_consts_float", + description: r##"# `duration_consts_float` + +The tracking issue for this feature is: [#72440] + +[#72440]: https://github.com/rust-lang/rust/issues/72440 + +------------------------ +"##, + }, + Lint { + label: "dyn_star", + description: r##"# `dyn_star` + +The tracking issue for this feature is: [#102425] + +[#102425]: https://github.com/rust-lang/rust/issues/102425 + +------------------------ +"##, + }, + Lint { + label: "edition_panic", + description: r##"# `edition_panic` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "effects", + description: r##"# `effects` + +The tracking issue for this feature is: [#102090] + +[#102090]: https://github.com/rust-lang/rust/issues/102090 + +------------------------ +"##, + }, + Lint { + label: "entry_insert", + description: r##"# `entry_insert` + +The tracking issue for this feature is: [#65225] + +[#65225]: https://github.com/rust-lang/rust/issues/65225 + +------------------------ +"##, + }, + Lint { + label: "ermsb_target_feature", + description: r##"# `ermsb_target_feature` + +The tracking issue for this feature is: [#44839] + +[#44839]: https://github.com/rust-lang/rust/issues/44839 + +------------------------ +"##, + }, + Lint { + label: "error_generic_member_access", + description: r##"# `error_generic_member_access` + +The tracking issue for this feature is: [#99301] + +[#99301]: https://github.com/rust-lang/rust/issues/99301 + +------------------------ +"##, + }, + Lint { + label: "error_in_core", + description: r##"# `error_in_core` + +The tracking issue for this feature is: [#103765] + +[#103765]: https://github.com/rust-lang/rust/issues/103765 + +------------------------ +"##, + }, + Lint { + label: "error_iter", + description: r##"# `error_iter` + +The tracking issue for this feature is: [#58520] + +[#58520]: https://github.com/rust-lang/rust/issues/58520 + +------------------------ +"##, + }, + Lint { + label: "error_reporter", + description: r##"# `error_reporter` + +The tracking issue for this feature is: [#90172] + +[#90172]: https://github.com/rust-lang/rust/issues/90172 + +------------------------ +"##, + }, + Lint { + label: "error_type_id", + description: r##"# `error_type_id` + +The tracking issue for this feature is: [#60784] + +[#60784]: https://github.com/rust-lang/rust/issues/60784 + +------------------------ +"##, + }, + Lint { + label: "exact_size_is_empty", + description: r##"# `exact_size_is_empty` + +The tracking issue for this feature is: [#35428] + +[#35428]: https://github.com/rust-lang/rust/issues/35428 + +------------------------ "##, }, Lint { @@ -2152,6 +4451,72 @@ stabilized. _ => println!("nor is everything else.") } ``` +"##, + }, + Lint { + label: "exclusive_wrapper", + description: r##"# `exclusive_wrapper` + +The tracking issue for this feature is: [#98407] + +[#98407]: https://github.com/rust-lang/rust/issues/98407 + +------------------------ +"##, + }, + Lint { + label: "exhaustive_patterns", + description: r##"# `exhaustive_patterns` + +The tracking issue for this feature is: [#51085] + +[#51085]: https://github.com/rust-lang/rust/issues/51085 + +------------------------ +"##, + }, + Lint { + label: "exit_status_error", + description: r##"# `exit_status_error` + +The tracking issue for this feature is: [#84908] + +[#84908]: https://github.com/rust-lang/rust/issues/84908 + +------------------------ +"##, + }, + Lint { + label: "exitcode_exit_method", + description: r##"# `exitcode_exit_method` + +The tracking issue for this feature is: [#97100] + +[#97100]: https://github.com/rust-lang/rust/issues/97100 + +------------------------ +"##, + }, + Lint { + label: "explicit_tail_calls", + description: r##"# `explicit_tail_calls` + +The tracking issue for this feature is: [#112788] + +[#112788]: https://github.com/rust-lang/rust/issues/112788 + +------------------------ +"##, + }, + Lint { + label: "extend_one", + description: r##"# `extend_one` + +The tracking issue for this feature is: [#72631] + +[#72631]: https://github.com/rust-lang/rust/issues/72631 + +------------------------ "##, }, Lint { @@ -2166,6 +4531,28 @@ The tracking issue for this feature is: [#100189] This feature adds the possibility of using `sysv64`, `win64` or `efiapi` calling conventions on functions with varargs. +"##, + }, + Lint { + label: "extern_types", + description: r##"# `extern_types` + +The tracking issue for this feature is: [#43467] + +[#43467]: https://github.com/rust-lang/rust/issues/43467 + +------------------------ +"##, + }, + Lint { + label: "extract_if", + description: r##"# `extract_if` + +The tracking issue for this feature is: [#43244] + +[#43244]: https://github.com/rust-lang/rust/issues/43244 + +------------------------ "##, }, Lint { @@ -2300,6 +4687,72 @@ against are compatible with those of the `#[ffi_pure]`. [ARM C/C++ compiler]: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0491c/Cacigdac.html [GCC]: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-pure-function-attribute [IBM ILE C/C++]: https://www.ibm.com/support/knowledgecenter/fr/ssw_ibm_i_71/rzarg/fn_attrib_pure.htm +"##, + }, + Lint { + label: "ffi_returns_twice", + description: r##"# `ffi_returns_twice` + +The tracking issue for this feature is: [#58314] + +[#58314]: https://github.com/rust-lang/rust/issues/58314 + +------------------------ +"##, + }, + Lint { + label: "file_create_new", + description: r##"# `file_create_new` + +The tracking issue for this feature is: [#105135] + +[#105135]: https://github.com/rust-lang/rust/issues/105135 + +------------------------ +"##, + }, + Lint { + label: "file_set_times", + description: r##"# `file_set_times` + +The tracking issue for this feature is: [#98245] + +[#98245]: https://github.com/rust-lang/rust/issues/98245 + +------------------------ +"##, + }, + Lint { + label: "float_gamma", + description: r##"# `float_gamma` + +The tracking issue for this feature is: [#99842] + +[#99842]: https://github.com/rust-lang/rust/issues/99842 + +------------------------ +"##, + }, + Lint { + label: "float_minimum_maximum", + description: r##"# `float_minimum_maximum` + +The tracking issue for this feature is: [#91079] + +[#91079]: https://github.com/rust-lang/rust/issues/91079 + +------------------------ +"##, + }, + Lint { + label: "float_next_up_down", + description: r##"# `float_next_up_down` + +The tracking issue for this feature is: [#91399] + +[#91399]: https://github.com/rust-lang/rust/issues/91399 + +------------------------ "##, }, Lint { @@ -2308,6 +4761,15 @@ against are compatible with those of the `#[ffi_pure]`. This feature is internal to the Rust compiler and is not intended for general use. +------------------------ +"##, + }, + Lint { + label: "fmt_helpers_for_derive", + description: r##"# `fmt_helpers_for_derive` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + ------------------------ "##, }, @@ -2317,6 +4779,26 @@ This feature is internal to the Rust compiler and is not intended for general us This feature is internal to the Rust compiler and is not intended for general use. +------------------------ +"##, + }, + Lint { + label: "fn_align", + description: r##"# `fn_align` + +The tracking issue for this feature is: [#82232] + +[#82232]: https://github.com/rust-lang/rust/issues/82232 + +------------------------ +"##, + }, + Lint { + label: "fn_ptr_trait", + description: r##"# `fn_ptr_trait` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + ------------------------ "##, }, @@ -2357,6 +4839,90 @@ fn main() { assert_eq!(adder(2), 5); } ``` +"##, + }, + Lint { + label: "forget_unsized", + description: r##"# `forget_unsized` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "format_args_nl", + description: r##"# `format_args_nl` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "fs_try_exists", + description: r##"# `fs_try_exists` + +The tracking issue for this feature is: [#83186] + +[#83186]: https://github.com/rust-lang/rust/issues/83186 + +------------------------ +"##, + }, + Lint { + label: "fundamental", + description: r##"# `fundamental` + +The tracking issue for this feature is: [#29635] + +[#29635]: https://github.com/rust-lang/rust/issues/29635 + +------------------------ +"##, + }, + Lint { + label: "future_join", + description: r##"# `future_join` + +The tracking issue for this feature is: [#91642] + +[#91642]: https://github.com/rust-lang/rust/issues/91642 + +------------------------ +"##, + }, + Lint { + label: "gen_future", + description: r##"# `gen_future` + +The tracking issue for this feature is: [#50547] + +[#50547]: https://github.com/rust-lang/rust/issues/50547 + +------------------------ +"##, + }, + Lint { + label: "generator_clone", + description: r##"# `generator_clone` + +The tracking issue for this feature is: [#95360] + +[#95360]: https://github.com/rust-lang/rust/issues/95360 + +------------------------ +"##, + }, + Lint { + label: "generator_trait", + description: r##"# `generator_trait` + +The tracking issue for this feature is: [#43122] + +[#43122]: https://github.com/rust-lang/rust/issues/43122 + +------------------------ "##, }, Lint { @@ -2607,6 +5173,92 @@ Here we can also note that the `Done` state, if resumed, panics immediately as it's invalid to resume a completed generator. It's also worth noting that this is just a rough desugaring, not a normative specification for what the compiler does. +"##, + }, + Lint { + label: "generic_arg_infer", + description: r##"# `generic_arg_infer` + +The tracking issue for this feature is: [#85077] + +[#85077]: https://github.com/rust-lang/rust/issues/85077 + +------------------------ +"##, + }, + Lint { + label: "generic_assert", + description: r##"# `generic_assert` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "generic_assert_internals", + description: r##"# `generic_assert_internals` + +The tracking issue for this feature is: [#44838] + +[#44838]: https://github.com/rust-lang/rust/issues/44838 + +------------------------ +"##, + }, + Lint { + label: "generic_associated_types_extended", + description: r##"# `generic_associated_types_extended` + +The tracking issue for this feature is: [#95451] + +[#95451]: https://github.com/rust-lang/rust/issues/95451 + +------------------------ +"##, + }, + Lint { + label: "generic_const_exprs", + description: r##"# `generic_const_exprs` + +The tracking issue for this feature is: [#76560] + +[#76560]: https://github.com/rust-lang/rust/issues/76560 + +------------------------ +"##, + }, + Lint { + label: "generic_const_items", + description: r##"# `generic_const_items` + +The tracking issue for this feature is: [#113521] + +[#113521]: https://github.com/rust-lang/rust/issues/113521 + +------------------------ +"##, + }, + Lint { + label: "get_many_mut", + description: r##"# `get_many_mut` + +The tracking issue for this feature is: [#104642] + +[#104642]: https://github.com/rust-lang/rust/issues/104642 + +------------------------ +"##, + }, + Lint { + label: "get_mut_unchecked", + description: r##"# `get_mut_unchecked` + +The tracking issue for this feature is: [#63292] + +[#63292]: https://github.com/rust-lang/rust/issues/63292 + +------------------------ "##, }, Lint { @@ -2641,6 +5293,136 @@ fn main() { let [(a @ 3..), c] = xs else { return; }; } ``` +"##, + }, + Lint { + label: "hash_extract_if", + description: r##"# `hash_extract_if` + +The tracking issue for this feature is: [#59618] + +[#59618]: https://github.com/rust-lang/rust/issues/59618 + +------------------------ +"##, + }, + Lint { + label: "hash_raw_entry", + description: r##"# `hash_raw_entry` + +The tracking issue for this feature is: [#56167] + +[#56167]: https://github.com/rust-lang/rust/issues/56167 + +------------------------ +"##, + }, + Lint { + label: "hash_set_entry", + description: r##"# `hash_set_entry` + +The tracking issue for this feature is: [#60896] + +[#60896]: https://github.com/rust-lang/rust/issues/60896 + +------------------------ +"##, + }, + Lint { + label: "hasher_prefixfree_extras", + description: r##"# `hasher_prefixfree_extras` + +The tracking issue for this feature is: [#96762] + +[#96762]: https://github.com/rust-lang/rust/issues/96762 + +------------------------ +"##, + }, + Lint { + label: "hashmap_internals", + description: r##"# `hashmap_internals` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "hexagon_target_feature", + description: r##"# `hexagon_target_feature` + +The tracking issue for this feature is: [#44839] + +[#44839]: https://github.com/rust-lang/rust/issues/44839 + +------------------------ +"##, + }, + Lint { + label: "hint_must_use", + description: r##"# `hint_must_use` + +The tracking issue for this feature is: [#94745] + +[#94745]: https://github.com/rust-lang/rust/issues/94745 + +------------------------ +"##, + }, + Lint { + label: "if_let_guard", + description: r##"# `if_let_guard` + +The tracking issue for this feature is: [#51114] + +[#51114]: https://github.com/rust-lang/rust/issues/51114 + +------------------------ +"##, + }, + Lint { + label: "impl_trait_in_assoc_type", + description: r##"# `impl_trait_in_assoc_type` + +The tracking issue for this feature is: [#63063] + +[#63063]: https://github.com/rust-lang/rust/issues/63063 + +------------------------ +"##, + }, + Lint { + label: "impl_trait_in_fn_trait_return", + description: r##"# `impl_trait_in_fn_trait_return` + +The tracking issue for this feature is: [#99697] + +[#99697]: https://github.com/rust-lang/rust/issues/99697 + +------------------------ +"##, + }, + Lint { + label: "imported_main", + description: r##"# `imported_main` + +The tracking issue for this feature is: [#28937] + +[#28937]: https://github.com/rust-lang/rust/issues/28937 + +------------------------ +"##, + }, + Lint { + label: "inherent_associated_types", + description: r##"# `inherent_associated_types` + +The tracking issue for this feature is: [#8995] + +[#8995]: https://github.com/rust-lang/rust/issues/8995 + +------------------------ "##, }, Lint { @@ -2705,6 +5487,46 @@ match some_int { ``` [#76001]: https://github.com/rust-lang/rust/issues/76001 +"##, + }, + Lint { + label: "inplace_iteration", + description: r##"# `inplace_iteration` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "int_roundings", + description: r##"# `int_roundings` + +The tracking issue for this feature is: [#88581] + +[#88581]: https://github.com/rust-lang/rust/issues/88581 + +------------------------ +"##, + }, + Lint { + label: "integer_atomics", + description: r##"# `integer_atomics` + +The tracking issue for this feature is: [#99069] + +[#99069]: https://github.com/rust-lang/rust/issues/99069 + +------------------------ +"##, + }, + Lint { + label: "internal_impls_macro", + description: r##"# `internal_impls_macro` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ "##, }, Lint { @@ -2767,6 +5589,92 @@ extern "rust-intrinsic" { ``` As with any other FFI functions, these are always `unsafe` to call. +"##, + }, + Lint { + label: "io_error_downcast", + description: r##"# `io_error_downcast` + +The tracking issue for this feature is: [#99262] + +[#99262]: https://github.com/rust-lang/rust/issues/99262 + +------------------------ +"##, + }, + Lint { + label: "io_error_more", + description: r##"# `io_error_more` + +The tracking issue for this feature is: [#86442] + +[#86442]: https://github.com/rust-lang/rust/issues/86442 + +------------------------ +"##, + }, + Lint { + label: "io_error_uncategorized", + description: r##"# `io_error_uncategorized` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "io_slice_advance", + description: r##"# `io_slice_advance` + +The tracking issue for this feature is: [#62726] + +[#62726]: https://github.com/rust-lang/rust/issues/62726 + +------------------------ +"##, + }, + Lint { + label: "ip", + description: r##"# `ip` + +The tracking issue for this feature is: [#27709] + +[#27709]: https://github.com/rust-lang/rust/issues/27709 + +------------------------ +"##, + }, + Lint { + label: "ip_bits", + description: r##"# `ip_bits` + +The tracking issue for this feature is: [#113744] + +[#113744]: https://github.com/rust-lang/rust/issues/113744 + +------------------------ +"##, + }, + Lint { + label: "ip_in_core", + description: r##"# `ip_in_core` + +The tracking issue for this feature is: [#108443] + +[#108443]: https://github.com/rust-lang/rust/issues/108443 + +------------------------ +"##, + }, + Lint { + label: "is_ascii_octdigit", + description: r##"# `is_ascii_octdigit` + +The tracking issue for this feature is: [#101288] + +[#101288]: https://github.com/rust-lang/rust/issues/101288 + +------------------------ "##, }, Lint { @@ -2782,6 +5690,160 @@ The tracking issue for this feature is: [#53485] Add the methods `is_sorted`, `is_sorted_by` and `is_sorted_by_key` to `[T]`; add the methods `is_sorted`, `is_sorted_by` and `is_sorted_by_key` to `Iterator`. +"##, + }, + Lint { + label: "isqrt", + description: r##"# `isqrt` + +The tracking issue for this feature is: [#116226] + +[#116226]: https://github.com/rust-lang/rust/issues/116226 + +------------------------ +"##, + }, + Lint { + label: "iter_advance_by", + description: r##"# `iter_advance_by` + +The tracking issue for this feature is: [#77404] + +[#77404]: https://github.com/rust-lang/rust/issues/77404 + +------------------------ +"##, + }, + Lint { + label: "iter_array_chunks", + description: r##"# `iter_array_chunks` + +The tracking issue for this feature is: [#100450] + +[#100450]: https://github.com/rust-lang/rust/issues/100450 + +------------------------ +"##, + }, + Lint { + label: "iter_collect_into", + description: r##"# `iter_collect_into` + +The tracking issue for this feature is: [#94780] + +[#94780]: https://github.com/rust-lang/rust/issues/94780 + +------------------------ +"##, + }, + Lint { + label: "iter_from_generator", + description: r##"# `iter_from_generator` + +The tracking issue for this feature is: [#43122] + +[#43122]: https://github.com/rust-lang/rust/issues/43122 + +------------------------ +"##, + }, + Lint { + label: "iter_intersperse", + description: r##"# `iter_intersperse` + +The tracking issue for this feature is: [#79524] + +[#79524]: https://github.com/rust-lang/rust/issues/79524 + +------------------------ +"##, + }, + Lint { + label: "iter_is_partitioned", + description: r##"# `iter_is_partitioned` + +The tracking issue for this feature is: [#62544] + +[#62544]: https://github.com/rust-lang/rust/issues/62544 + +------------------------ +"##, + }, + Lint { + label: "iter_map_windows", + description: r##"# `iter_map_windows` + +The tracking issue for this feature is: [#87155] + +[#87155]: https://github.com/rust-lang/rust/issues/87155 + +------------------------ +"##, + }, + Lint { + label: "iter_next_chunk", + description: r##"# `iter_next_chunk` + +The tracking issue for this feature is: [#98326] + +[#98326]: https://github.com/rust-lang/rust/issues/98326 + +------------------------ +"##, + }, + Lint { + label: "iter_order_by", + description: r##"# `iter_order_by` + +The tracking issue for this feature is: [#64295] + +[#64295]: https://github.com/rust-lang/rust/issues/64295 + +------------------------ +"##, + }, + Lint { + label: "iter_partition_in_place", + description: r##"# `iter_partition_in_place` + +The tracking issue for this feature is: [#62543] + +[#62543]: https://github.com/rust-lang/rust/issues/62543 + +------------------------ +"##, + }, + Lint { + label: "iter_repeat_n", + description: r##"# `iter_repeat_n` + +The tracking issue for this feature is: [#104434] + +[#104434]: https://github.com/rust-lang/rust/issues/104434 + +------------------------ +"##, + }, + Lint { + label: "iterator_try_collect", + description: r##"# `iterator_try_collect` + +The tracking issue for this feature is: [#94047] + +[#94047]: https://github.com/rust-lang/rust/issues/94047 + +------------------------ +"##, + }, + Lint { + label: "iterator_try_reduce", + description: r##"# `iterator_try_reduce` + +The tracking issue for this feature is: [#87053] + +[#87053]: https://github.com/rust-lang/rust/issues/87053 + +------------------------ "##, }, Lint { @@ -2901,6 +5963,81 @@ return a valid pointer, and so needs to do the check internally. An up-to-date list of all language items can be found [here] in the compiler code. [here]: https://github.com/rust-lang/rust/blob/master/compiler/rustc_hir/src/lang_items.rs +"##, + }, + Lint { + label: "large_assignments", + description: r##"# `large_assignments` + +The tracking issue for this feature is: [#83518] + +[#83518]: https://github.com/rust-lang/rust/issues/83518 + +------------------------ +"##, + }, + Lint { + label: "layout_for_ptr", + description: r##"# `layout_for_ptr` + +The tracking issue for this feature is: [#69835] + +[#69835]: https://github.com/rust-lang/rust/issues/69835 + +------------------------ +"##, + }, + Lint { + label: "lazy_cell", + description: r##"# `lazy_cell` + +The tracking issue for this feature is: [#109736] + +[#109736]: https://github.com/rust-lang/rust/issues/109736 + +------------------------ +"##, + }, + Lint { + label: "lazy_cell_consume", + description: r##"# `lazy_cell_consume` + +The tracking issue for this feature is: [#109736] + +[#109736]: https://github.com/rust-lang/rust/issues/109736 + +------------------------ +"##, + }, + Lint { + label: "lazy_type_alias", + description: r##"# `lazy_type_alias` + +The tracking issue for this feature is: [#112792] + +[#112792]: https://github.com/rust-lang/rust/issues/112792 + +------------------------ +"##, + }, + Lint { + label: "let_chains", + description: r##"# `let_chains` + +The tracking issue for this feature is: [#53667] + +[#53667]: https://github.com/rust-lang/rust/issues/53667 + +------------------------ +"##, + }, + Lint { + label: "liballoc_internals", + description: r##"# `liballoc_internals` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ "##, }, Lint { @@ -2918,6 +6055,127 @@ This feature is internal to the Rust compiler and is not intended for general us This feature is internal to the Rust compiler and is not intended for general use. +------------------------ +"##, + }, + Lint { + label: "link_llvm_intrinsics", + description: r##"# `link_llvm_intrinsics` + +The tracking issue for this feature is: [#29602] + +[#29602]: https://github.com/rust-lang/rust/issues/29602 + +------------------------ +"##, + }, + Lint { + label: "linkage", + description: r##"# `linkage` + +The tracking issue for this feature is: [#29603] + +[#29603]: https://github.com/rust-lang/rust/issues/29603 + +------------------------ +"##, + }, + Lint { + label: "linked_list_cursors", + description: r##"# `linked_list_cursors` + +The tracking issue for this feature is: [#58533] + +[#58533]: https://github.com/rust-lang/rust/issues/58533 + +------------------------ +"##, + }, + Lint { + label: "linked_list_remove", + description: r##"# `linked_list_remove` + +The tracking issue for this feature is: [#69210] + +[#69210]: https://github.com/rust-lang/rust/issues/69210 + +------------------------ +"##, + }, + Lint { + label: "lint_reasons", + description: r##"# `lint_reasons` + +The tracking issue for this feature is: [#54503] + +[#54503]: https://github.com/rust-lang/rust/issues/54503 + +------------------------ +"##, + }, + Lint { + label: "linux_pidfd", + description: r##"# `linux_pidfd` + +The tracking issue for this feature is: [#82971] + +[#82971]: https://github.com/rust-lang/rust/issues/82971 + +------------------------ +"##, + }, + Lint { + label: "log_syntax", + description: r##"# `log_syntax` + +The tracking issue for this feature is: [#29598] + +[#29598]: https://github.com/rust-lang/rust/issues/29598 + +------------------------ +"##, + }, + Lint { + label: "macro_metavar_expr", + description: r##"# `macro_metavar_expr` + +The tracking issue for this feature is: [#83527] + +[#83527]: https://github.com/rust-lang/rust/issues/83527 + +------------------------ +"##, + }, + Lint { + label: "map_entry_replace", + description: r##"# `map_entry_replace` + +The tracking issue for this feature is: [#44286] + +[#44286]: https://github.com/rust-lang/rust/issues/44286 + +------------------------ +"##, + }, + Lint { + label: "map_many_mut", + description: r##"# `map_many_mut` + +The tracking issue for this feature is: [#97601] + +[#97601]: https://github.com/rust-lang/rust/issues/97601 + +------------------------ +"##, + }, + Lint { + label: "map_try_insert", + description: r##"# `map_try_insert` + +The tracking issue for this feature is: [#82766] + +[#82766]: https://github.com/rust-lang/rust/issues/82766 + ------------------------ "##, }, @@ -2958,6 +6216,116 @@ fn cheap_clone(t: T) -> T { This is expected to replace the unstable `overlapping_marker_traits` feature, which applied to all empty traits (without needing an opt-in). +"##, + }, + Lint { + label: "maybe_uninit_array_assume_init", + description: r##"# `maybe_uninit_array_assume_init` + +The tracking issue for this feature is: [#96097] + +[#96097]: https://github.com/rust-lang/rust/issues/96097 + +------------------------ +"##, + }, + Lint { + label: "maybe_uninit_as_bytes", + description: r##"# `maybe_uninit_as_bytes` + +The tracking issue for this feature is: [#93092] + +[#93092]: https://github.com/rust-lang/rust/issues/93092 + +------------------------ +"##, + }, + Lint { + label: "maybe_uninit_slice", + description: r##"# `maybe_uninit_slice` + +The tracking issue for this feature is: [#63569] + +[#63569]: https://github.com/rust-lang/rust/issues/63569 + +------------------------ +"##, + }, + Lint { + label: "maybe_uninit_uninit_array", + description: r##"# `maybe_uninit_uninit_array` + +The tracking issue for this feature is: [#96097] + +[#96097]: https://github.com/rust-lang/rust/issues/96097 + +------------------------ +"##, + }, + Lint { + label: "maybe_uninit_uninit_array_transpose", + description: r##"# `maybe_uninit_uninit_array_transpose` + +The tracking issue for this feature is: [#96097] + +[#96097]: https://github.com/rust-lang/rust/issues/96097 + +------------------------ +"##, + }, + Lint { + label: "maybe_uninit_write_slice", + description: r##"# `maybe_uninit_write_slice` + +The tracking issue for this feature is: [#79995] + +[#79995]: https://github.com/rust-lang/rust/issues/79995 + +------------------------ +"##, + }, + Lint { + label: "mem_copy_fn", + description: r##"# `mem_copy_fn` + +The tracking issue for this feature is: [#98262] + +[#98262]: https://github.com/rust-lang/rust/issues/98262 + +------------------------ +"##, + }, + Lint { + label: "min_specialization", + description: r##"# `min_specialization` + +The tracking issue for this feature is: [#31844] + +[#31844]: https://github.com/rust-lang/rust/issues/31844 + +------------------------ +"##, + }, + Lint { + label: "mips_target_feature", + description: r##"# `mips_target_feature` + +The tracking issue for this feature is: [#44839] + +[#44839]: https://github.com/rust-lang/rust/issues/44839 + +------------------------ +"##, + }, + Lint { + label: "more_float_constants", + description: r##"# `more_float_constants` + +The tracking issue for this feature is: [#103883] + +[#103883]: https://github.com/rust-lang/rust/issues/103883 + +------------------------ "##, }, Lint { @@ -2991,6 +6359,59 @@ impl A for Foo { type Assoc = StructStruct; } ``` +"##, + }, + Lint { + label: "multiple_supertrait_upcastable", + description: r##"# `multiple_supertrait_upcastable` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "must_not_suspend", + description: r##"# `must_not_suspend` + +The tracking issue for this feature is: [#83310] + +[#83310]: https://github.com/rust-lang/rust/issues/83310 + +------------------------ +"##, + }, + Lint { + label: "mutex_unlock", + description: r##"# `mutex_unlock` + +The tracking issue for this feature is: [#81872] + +[#81872]: https://github.com/rust-lang/rust/issues/81872 + +------------------------ +"##, + }, + Lint { + label: "mutex_unpoison", + description: r##"# `mutex_unpoison` + +The tracking issue for this feature is: [#96469] + +[#96469]: https://github.com/rust-lang/rust/issues/96469 + +------------------------ +"##, + }, + Lint { + label: "naked_functions", + description: r##"# `naked_functions` + +The tracking issue for this feature is: [#32408] + +[#32408]: https://github.com/rust-lang/rust/issues/32408 + +------------------------ "##, }, Lint { @@ -3013,6 +6434,26 @@ This modifier translates to `--as-needed` for ld-like linkers, and to `-dead_str The modifier does nothing for linkers that don't support it (e.g. `link.exe`). The default for this modifier is unclear, some targets currently specify it as `+as-needed`, some do not. We may want to try making `+as-needed` a default for all targets. +"##, + }, + Lint { + label: "needs_panic_runtime", + description: r##"# `needs_panic_runtime` + +The tracking issue for this feature is: [#32837] + +[#32837]: https://github.com/rust-lang/rust/issues/32837 + +------------------------ +"##, + }, + Lint { + label: "negative_bounds", + description: r##"# `negative_bounds` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ "##, }, Lint { @@ -3074,6 +6515,50 @@ This serves two purposes: * For proving the correctness of unsafe code, we can use that impl as evidence that no `DerefMut` or `Clone` impl exists. * It prevents downstream crates from creating such impls. +"##, + }, + Lint { + label: "never_type", + description: r##"# `never_type` + +The tracking issue for this feature is: [#35121] + +[#35121]: https://github.com/rust-lang/rust/issues/35121 + +------------------------ +"##, + }, + Lint { + label: "never_type_fallback", + description: r##"# `never_type_fallback` + +The tracking issue for this feature is: [#65992] + +[#65992]: https://github.com/rust-lang/rust/issues/65992 + +------------------------ +"##, + }, + Lint { + label: "new_uninit", + description: r##"# `new_uninit` + +The tracking issue for this feature is: [#63291] + +[#63291]: https://github.com/rust-lang/rust/issues/63291 + +------------------------ +"##, + }, + Lint { + label: "no_core", + description: r##"# `no_core` + +The tracking issue for this feature is: [#29639] + +[#29639]: https://github.com/rust-lang/rust/issues/29639 + +------------------------ "##, }, Lint { @@ -3107,6 +6592,319 @@ fn foo() { // ... } ``` +"##, + }, + Lint { + label: "non_exhaustive_omitted_patterns_lint", + description: r##"# `non_exhaustive_omitted_patterns_lint` + +The tracking issue for this feature is: [#89554] + +[#89554]: https://github.com/rust-lang/rust/issues/89554 + +------------------------ +"##, + }, + Lint { + label: "non_lifetime_binders", + description: r##"# `non_lifetime_binders` + +The tracking issue for this feature is: [#108185] + +[#108185]: https://github.com/rust-lang/rust/issues/108185 + +------------------------ +"##, + }, + Lint { + label: "nonzero_ops", + description: r##"# `nonzero_ops` + +The tracking issue for this feature is: [#84186] + +[#84186]: https://github.com/rust-lang/rust/issues/84186 + +------------------------ +"##, + }, + Lint { + label: "noop_waker", + description: r##"# `noop_waker` + +The tracking issue for this feature is: [#98286] + +[#98286]: https://github.com/rust-lang/rust/issues/98286 + +------------------------ +"##, + }, + Lint { + label: "num_midpoint", + description: r##"# `num_midpoint` + +The tracking issue for this feature is: [#110840] + +[#110840]: https://github.com/rust-lang/rust/issues/110840 + +------------------------ +"##, + }, + Lint { + label: "numfmt", + description: r##"# `numfmt` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "object_safe_for_dispatch", + description: r##"# `object_safe_for_dispatch` + +The tracking issue for this feature is: [#43561] + +[#43561]: https://github.com/rust-lang/rust/issues/43561 + +------------------------ +"##, + }, + Lint { + label: "offset_of", + description: r##"# `offset_of` + +The tracking issue for this feature is: [#106655] + +[#106655]: https://github.com/rust-lang/rust/issues/106655 + +------------------------ +"##, + }, + Lint { + label: "omit_gdb_pretty_printer_section", + description: r##"# `omit_gdb_pretty_printer_section` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "once_cell_try", + description: r##"# `once_cell_try` + +The tracking issue for this feature is: [#109737] + +[#109737]: https://github.com/rust-lang/rust/issues/109737 + +------------------------ +"##, + }, + Lint { + label: "one_sided_range", + description: r##"# `one_sided_range` + +The tracking issue for this feature is: [#69780] + +[#69780]: https://github.com/rust-lang/rust/issues/69780 + +------------------------ +"##, + }, + Lint { + label: "optimize_attribute", + description: r##"# `optimize_attribute` + +The tracking issue for this feature is: [#54882] + +[#54882]: https://github.com/rust-lang/rust/issues/54882 + +------------------------ +"##, + }, + Lint { + label: "option_get_or_insert_default", + description: r##"# `option_get_or_insert_default` + +The tracking issue for this feature is: [#82901] + +[#82901]: https://github.com/rust-lang/rust/issues/82901 + +------------------------ +"##, + }, + Lint { + label: "option_take_if", + description: r##"# `option_take_if` + +The tracking issue for this feature is: [#98934] + +[#98934]: https://github.com/rust-lang/rust/issues/98934 + +------------------------ +"##, + }, + Lint { + label: "option_zip", + description: r##"# `option_zip` + +The tracking issue for this feature is: [#70086] + +[#70086]: https://github.com/rust-lang/rust/issues/70086 + +------------------------ +"##, + }, + Lint { + label: "panic_abort", + description: r##"# `panic_abort` + +The tracking issue for this feature is: [#32837] + +[#32837]: https://github.com/rust-lang/rust/issues/32837 + +------------------------ +"##, + }, + Lint { + label: "panic_always_abort", + description: r##"# `panic_always_abort` + +The tracking issue for this feature is: [#84438] + +[#84438]: https://github.com/rust-lang/rust/issues/84438 + +------------------------ +"##, + }, + Lint { + label: "panic_backtrace_config", + description: r##"# `panic_backtrace_config` + +The tracking issue for this feature is: [#93346] + +[#93346]: https://github.com/rust-lang/rust/issues/93346 + +------------------------ +"##, + }, + Lint { + label: "panic_can_unwind", + description: r##"# `panic_can_unwind` + +The tracking issue for this feature is: [#92988] + +[#92988]: https://github.com/rust-lang/rust/issues/92988 + +------------------------ +"##, + }, + Lint { + label: "panic_info_message", + description: r##"# `panic_info_message` + +The tracking issue for this feature is: [#66745] + +[#66745]: https://github.com/rust-lang/rust/issues/66745 + +------------------------ +"##, + }, + Lint { + label: "panic_internals", + description: r##"# `panic_internals` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "panic_runtime", + description: r##"# `panic_runtime` + +The tracking issue for this feature is: [#32837] + +[#32837]: https://github.com/rust-lang/rust/issues/32837 + +------------------------ +"##, + }, + Lint { + label: "panic_unwind", + description: r##"# `panic_unwind` + +The tracking issue for this feature is: [#32837] + +[#32837]: https://github.com/rust-lang/rust/issues/32837 + +------------------------ +"##, + }, + Lint { + label: "panic_update_hook", + description: r##"# `panic_update_hook` + +The tracking issue for this feature is: [#92649] + +[#92649]: https://github.com/rust-lang/rust/issues/92649 + +------------------------ +"##, + }, + Lint { + label: "path_file_prefix", + description: r##"# `path_file_prefix` + +The tracking issue for this feature is: [#86319] + +[#86319]: https://github.com/rust-lang/rust/issues/86319 + +------------------------ +"##, + }, + Lint { + label: "pattern", + description: r##"# `pattern` + +The tracking issue for this feature is: [#27721] + +[#27721]: https://github.com/rust-lang/rust/issues/27721 + +------------------------ +"##, + }, + Lint { + label: "peer_credentials_unix_socket", + description: r##"# `peer_credentials_unix_socket` + +The tracking issue for this feature is: [#42839] + +[#42839]: https://github.com/rust-lang/rust/issues/42839 + +------------------------ +"##, + }, + Lint { + label: "pin_deref_mut", + description: r##"# `pin_deref_mut` + +The tracking issue for this feature is: [#86918] + +[#86918]: https://github.com/rust-lang/rust/issues/86918 + +------------------------ +"##, + }, + Lint { + label: "platform_intrinsics", + description: r##"# `platform_intrinsics` + +The tracking issue for this feature is: [#27731] + +[#27731]: https://github.com/rust-lang/rust/issues/27731 + +------------------------ "##, }, Lint { @@ -3225,6 +7023,88 @@ conversion. You can run `rustc -W help foo.rs` to see a list of lints known to `rustc`, including those provided by plugins loaded by `foo.rs`. +"##, + }, + Lint { + label: "pointer_byte_offsets", + description: r##"# `pointer_byte_offsets` + +The tracking issue for this feature is: [#96283] + +[#96283]: https://github.com/rust-lang/rust/issues/96283 + +------------------------ +"##, + }, + Lint { + label: "pointer_is_aligned", + description: r##"# `pointer_is_aligned` + +The tracking issue for this feature is: [#96284] + +[#96284]: https://github.com/rust-lang/rust/issues/96284 + +------------------------ +"##, + }, + Lint { + label: "pointer_like_trait", + description: r##"# `pointer_like_trait` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "portable_simd", + description: r##"# `portable_simd` + +The tracking issue for this feature is: [#86656] + +[#86656]: https://github.com/rust-lang/rust/issues/86656 + +------------------------ +"##, + }, + Lint { + label: "powerpc_target_feature", + description: r##"# `powerpc_target_feature` + +The tracking issue for this feature is: [#44839] + +[#44839]: https://github.com/rust-lang/rust/issues/44839 + +------------------------ +"##, + }, + Lint { + label: "precise_pointer_size_matching", + description: r##"# `precise_pointer_size_matching` + +The tracking issue for this feature is: [#56354] + +[#56354]: https://github.com/rust-lang/rust/issues/56354 + +------------------------ +"##, + }, + Lint { + label: "prelude_2024", + description: r##"# `prelude_2024` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "prelude_import", + description: r##"# `prelude_import` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ "##, }, Lint { @@ -3233,6 +7113,123 @@ including those provided by plugins loaded by `foo.rs`. This feature is internal to the Rust compiler and is not intended for general use. +------------------------ +"##, + }, + Lint { + label: "proc_macro_byte_character", + description: r##"# `proc_macro_byte_character` + +The tracking issue for this feature is: [#115268] + +[#115268]: https://github.com/rust-lang/rust/issues/115268 + +------------------------ +"##, + }, + Lint { + label: "proc_macro_def_site", + description: r##"# `proc_macro_def_site` + +The tracking issue for this feature is: [#54724] + +[#54724]: https://github.com/rust-lang/rust/issues/54724 + +------------------------ +"##, + }, + Lint { + label: "proc_macro_diagnostic", + description: r##"# `proc_macro_diagnostic` + +The tracking issue for this feature is: [#54140] + +[#54140]: https://github.com/rust-lang/rust/issues/54140 + +------------------------ +"##, + }, + Lint { + label: "proc_macro_expand", + description: r##"# `proc_macro_expand` + +The tracking issue for this feature is: [#90765] + +[#90765]: https://github.com/rust-lang/rust/issues/90765 + +------------------------ +"##, + }, + Lint { + label: "proc_macro_hygiene", + description: r##"# `proc_macro_hygiene` + +The tracking issue for this feature is: [#54727] + +[#54727]: https://github.com/rust-lang/rust/issues/54727 + +------------------------ +"##, + }, + Lint { + label: "proc_macro_internals", + description: r##"# `proc_macro_internals` + +The tracking issue for this feature is: [#27812] + +[#27812]: https://github.com/rust-lang/rust/issues/27812 + +------------------------ +"##, + }, + Lint { + label: "proc_macro_quote", + description: r##"# `proc_macro_quote` + +The tracking issue for this feature is: [#54722] + +[#54722]: https://github.com/rust-lang/rust/issues/54722 + +------------------------ +"##, + }, + Lint { + label: "proc_macro_span", + description: r##"# `proc_macro_span` + +The tracking issue for this feature is: [#54725] + +[#54725]: https://github.com/rust-lang/rust/issues/54725 + +------------------------ +"##, + }, + Lint { + label: "proc_macro_tracked_env", + description: r##"# `proc_macro_tracked_env` + +The tracking issue for this feature is: [#99515] + +[#99515]: https://github.com/rust-lang/rust/issues/99515 + +------------------------ +"##, + }, + Lint { + label: "process_exitcode_internals", + description: r##"# `process_exitcode_internals` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "process_internals", + description: r##"# `process_internals` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + ------------------------ "##, }, @@ -3251,6 +7248,207 @@ The tracking issue for this feature is: [#42524](https://github.com/rust-lang/ru This feature is internal to the Rust compiler and is not intended for general use. +------------------------ +"##, + }, + Lint { + label: "ptr_addr_eq", + description: r##"# `ptr_addr_eq` + +The tracking issue for this feature is: [#116324] + +[#116324]: https://github.com/rust-lang/rust/issues/116324 + +------------------------ +"##, + }, + Lint { + label: "ptr_alignment_type", + description: r##"# `ptr_alignment_type` + +The tracking issue for this feature is: [#102070] + +[#102070]: https://github.com/rust-lang/rust/issues/102070 + +------------------------ +"##, + }, + Lint { + label: "ptr_as_uninit", + description: r##"# `ptr_as_uninit` + +The tracking issue for this feature is: [#75402] + +[#75402]: https://github.com/rust-lang/rust/issues/75402 + +------------------------ +"##, + }, + Lint { + label: "ptr_from_ref", + description: r##"# `ptr_from_ref` + +The tracking issue for this feature is: [#106116] + +[#106116]: https://github.com/rust-lang/rust/issues/106116 + +------------------------ +"##, + }, + Lint { + label: "ptr_internals", + description: r##"# `ptr_internals` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "ptr_mask", + description: r##"# `ptr_mask` + +The tracking issue for this feature is: [#98290] + +[#98290]: https://github.com/rust-lang/rust/issues/98290 + +------------------------ +"##, + }, + Lint { + label: "ptr_metadata", + description: r##"# `ptr_metadata` + +The tracking issue for this feature is: [#81513] + +[#81513]: https://github.com/rust-lang/rust/issues/81513 + +------------------------ +"##, + }, + Lint { + label: "ptr_sub_ptr", + description: r##"# `ptr_sub_ptr` + +The tracking issue for this feature is: [#95892] + +[#95892]: https://github.com/rust-lang/rust/issues/95892 + +------------------------ +"##, + }, + Lint { + label: "ptr_to_from_bits", + description: r##"# `ptr_to_from_bits` + +The tracking issue for this feature is: [#91126] + +[#91126]: https://github.com/rust-lang/rust/issues/91126 + +------------------------ +"##, + }, + Lint { + label: "pub_crate_should_not_need_unstable_attr", + description: r##"# `pub_crate_should_not_need_unstable_attr` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "raw_os_error_ty", + description: r##"# `raw_os_error_ty` + +The tracking issue for this feature is: [#107792] + +[#107792]: https://github.com/rust-lang/rust/issues/107792 + +------------------------ +"##, + }, + Lint { + label: "raw_os_nonzero", + description: r##"# `raw_os_nonzero` + +The tracking issue for this feature is: [#82363] + +[#82363]: https://github.com/rust-lang/rust/issues/82363 + +------------------------ +"##, + }, + Lint { + label: "raw_ref_op", + description: r##"# `raw_ref_op` + +The tracking issue for this feature is: [#64490] + +[#64490]: https://github.com/rust-lang/rust/issues/64490 + +------------------------ +"##, + }, + Lint { + label: "raw_slice_split", + description: r##"# `raw_slice_split` + +The tracking issue for this feature is: [#95595] + +[#95595]: https://github.com/rust-lang/rust/issues/95595 + +------------------------ +"##, + }, + Lint { + label: "raw_vec_internals", + description: r##"# `raw_vec_internals` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "read_buf", + description: r##"# `read_buf` + +The tracking issue for this feature is: [#78485] + +[#78485]: https://github.com/rust-lang/rust/issues/78485 + +------------------------ +"##, + }, + Lint { + label: "ready_into_inner", + description: r##"# `ready_into_inner` + +The tracking issue for this feature is: [#101196] + +[#101196]: https://github.com/rust-lang/rust/issues/101196 + +------------------------ +"##, + }, + Lint { + label: "receiver_trait", + description: r##"# `receiver_trait` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "register_tool", + description: r##"# `register_tool` + +The tracking issue for this feature is: [#66079] + +[#66079]: https://github.com/rust-lang/rust/issues/66079 + ------------------------ "##, }, @@ -3274,6 +7472,103 @@ enum Foo { Bar(u64), } ``` +"##, + }, + Lint { + label: "repr_simd", + description: r##"# `repr_simd` + +The tracking issue for this feature is: [#27731] + +[#27731]: https://github.com/rust-lang/rust/issues/27731 + +------------------------ +"##, + }, + Lint { + label: "restricted_std", + description: r##"# `restricted_std` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "result_flattening", + description: r##"# `result_flattening` + +The tracking issue for this feature is: [#70142] + +[#70142]: https://github.com/rust-lang/rust/issues/70142 + +------------------------ +"##, + }, + Lint { + label: "result_option_inspect", + description: r##"# `result_option_inspect` + +The tracking issue for this feature is: [#91345] + +[#91345]: https://github.com/rust-lang/rust/issues/91345 + +------------------------ +"##, + }, + Lint { + label: "return_position_impl_trait_in_trait", + description: r##"# `return_position_impl_trait_in_trait` + +The tracking issue for this feature is: [#91611] + +[#91611]: https://github.com/rust-lang/rust/issues/91611 + +------------------------ +"##, + }, + Lint { + label: "return_type_notation", + description: r##"# `return_type_notation` + +The tracking issue for this feature is: [#109417] + +[#109417]: https://github.com/rust-lang/rust/issues/109417 + +------------------------ +"##, + }, + Lint { + label: "riscv_target_feature", + description: r##"# `riscv_target_feature` + +The tracking issue for this feature is: [#44839] + +[#44839]: https://github.com/rust-lang/rust/issues/44839 + +------------------------ +"##, + }, + Lint { + label: "round_char_boundary", + description: r##"# `round_char_boundary` + +The tracking issue for this feature is: [#93743] + +[#93743]: https://github.com/rust-lang/rust/issues/93743 + +------------------------ +"##, + }, + Lint { + label: "round_ties_even", + description: r##"# `round_ties_even` + +The tracking issue for this feature is: [#96710] + +[#96710]: https://github.com/rust-lang/rust/issues/96710 + +------------------------ "##, }, Lint { @@ -3282,6 +7577,39 @@ enum Foo { This feature is internal to the Rust compiler and is not intended for general use. +------------------------ +"##, + }, + Lint { + label: "rtm_target_feature", + description: r##"# `rtm_target_feature` + +The tracking issue for this feature is: [#44839] + +[#44839]: https://github.com/rust-lang/rust/issues/44839 + +------------------------ +"##, + }, + Lint { + label: "rust_cold_cc", + description: r##"# `rust_cold_cc` + +The tracking issue for this feature is: [#97544] + +[#97544]: https://github.com/rust-lang/rust/issues/97544 + +------------------------ +"##, + }, + Lint { + label: "rustc_allow_const_fn_unstable", + description: r##"# `rustc_allow_const_fn_unstable` + +The tracking issue for this feature is: [#69399] + +[#69399]: https://github.com/rust-lang/rust/issues/69399 + ------------------------ "##, }, @@ -3340,6 +7668,326 @@ error: size: Size { raw: 16 } error: aborting due to 2 previous errors ``` +"##, + }, + Lint { + label: "rustc_private", + description: r##"# `rustc_private` + +The tracking issue for this feature is: [#27812] + +[#27812]: https://github.com/rust-lang/rust/issues/27812 + +------------------------ +"##, + }, + Lint { + label: "rustdoc_internals", + description: r##"# `rustdoc_internals` + +The tracking issue for this feature is: [#90418] + +[#90418]: https://github.com/rust-lang/rust/issues/90418 + +------------------------ +"##, + }, + Lint { + label: "rustdoc_missing_doc_code_examples", + description: r##"# `rustdoc_missing_doc_code_examples` + +The tracking issue for this feature is: [#101730] + +[#101730]: https://github.com/rust-lang/rust/issues/101730 + +------------------------ +"##, + }, + Lint { + label: "sealed", + description: r##"# `sealed` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "seek_stream_len", + description: r##"# `seek_stream_len` + +The tracking issue for this feature is: [#59359] + +[#59359]: https://github.com/rust-lang/rust/issues/59359 + +------------------------ +"##, + }, + Lint { + label: "set_ptr_value", + description: r##"# `set_ptr_value` + +The tracking issue for this feature is: [#75091] + +[#75091]: https://github.com/rust-lang/rust/issues/75091 + +------------------------ +"##, + }, + Lint { + label: "setgroups", + description: r##"# `setgroups` + +The tracking issue for this feature is: [#90747] + +[#90747]: https://github.com/rust-lang/rust/issues/90747 + +------------------------ +"##, + }, + Lint { + label: "sgx_platform", + description: r##"# `sgx_platform` + +The tracking issue for this feature is: [#56975] + +[#56975]: https://github.com/rust-lang/rust/issues/56975 + +------------------------ +"##, + }, + Lint { + label: "simd_ffi", + description: r##"# `simd_ffi` + +The tracking issue for this feature is: [#27731] + +[#27731]: https://github.com/rust-lang/rust/issues/27731 + +------------------------ +"##, + }, + Lint { + label: "sized_type_properties", + description: r##"# `sized_type_properties` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "slice_as_chunks", + description: r##"# `slice_as_chunks` + +The tracking issue for this feature is: [#74985] + +[#74985]: https://github.com/rust-lang/rust/issues/74985 + +------------------------ +"##, + }, + Lint { + label: "slice_concat_ext", + description: r##"# `slice_concat_ext` + +The tracking issue for this feature is: [#27747] + +[#27747]: https://github.com/rust-lang/rust/issues/27747 + +------------------------ +"##, + }, + Lint { + label: "slice_concat_trait", + description: r##"# `slice_concat_trait` + +The tracking issue for this feature is: [#27747] + +[#27747]: https://github.com/rust-lang/rust/issues/27747 + +------------------------ +"##, + }, + Lint { + label: "slice_first_last_chunk", + description: r##"# `slice_first_last_chunk` + +The tracking issue for this feature is: [#111774] + +[#111774]: https://github.com/rust-lang/rust/issues/111774 + +------------------------ +"##, + }, + Lint { + label: "slice_flatten", + description: r##"# `slice_flatten` + +The tracking issue for this feature is: [#95629] + +[#95629]: https://github.com/rust-lang/rust/issues/95629 + +------------------------ +"##, + }, + Lint { + label: "slice_from_ptr_range", + description: r##"# `slice_from_ptr_range` + +The tracking issue for this feature is: [#89792] + +[#89792]: https://github.com/rust-lang/rust/issues/89792 + +------------------------ +"##, + }, + Lint { + label: "slice_group_by", + description: r##"# `slice_group_by` + +The tracking issue for this feature is: [#80552] + +[#80552]: https://github.com/rust-lang/rust/issues/80552 + +------------------------ +"##, + }, + Lint { + label: "slice_index_methods", + description: r##"# `slice_index_methods` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "slice_internals", + description: r##"# `slice_internals` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "slice_iter_mut_as_mut_slice", + description: r##"# `slice_iter_mut_as_mut_slice` + +The tracking issue for this feature is: [#93079] + +[#93079]: https://github.com/rust-lang/rust/issues/93079 + +------------------------ +"##, + }, + Lint { + label: "slice_partition_dedup", + description: r##"# `slice_partition_dedup` + +The tracking issue for this feature is: [#54279] + +[#54279]: https://github.com/rust-lang/rust/issues/54279 + +------------------------ +"##, + }, + Lint { + label: "slice_pattern", + description: r##"# `slice_pattern` + +The tracking issue for this feature is: [#56345] + +[#56345]: https://github.com/rust-lang/rust/issues/56345 + +------------------------ +"##, + }, + Lint { + label: "slice_ptr_get", + description: r##"# `slice_ptr_get` + +The tracking issue for this feature is: [#74265] + +[#74265]: https://github.com/rust-lang/rust/issues/74265 + +------------------------ +"##, + }, + Lint { + label: "slice_ptr_len", + description: r##"# `slice_ptr_len` + +The tracking issue for this feature is: [#71146] + +[#71146]: https://github.com/rust-lang/rust/issues/71146 + +------------------------ +"##, + }, + Lint { + label: "slice_range", + description: r##"# `slice_range` + +The tracking issue for this feature is: [#76393] + +[#76393]: https://github.com/rust-lang/rust/issues/76393 + +------------------------ +"##, + }, + Lint { + label: "slice_split_at_unchecked", + description: r##"# `slice_split_at_unchecked` + +The tracking issue for this feature is: [#76014] + +[#76014]: https://github.com/rust-lang/rust/issues/76014 + +------------------------ +"##, + }, + Lint { + label: "slice_swap_unchecked", + description: r##"# `slice_swap_unchecked` + +The tracking issue for this feature is: [#88539] + +[#88539]: https://github.com/rust-lang/rust/issues/88539 + +------------------------ +"##, + }, + Lint { + label: "slice_take", + description: r##"# `slice_take` + +The tracking issue for this feature is: [#62280] + +[#62280]: https://github.com/rust-lang/rust/issues/62280 + +------------------------ +"##, + }, + Lint { + label: "solid_ext", + description: r##"# `solid_ext` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "sort_floats", + description: r##"# `sort_floats` + +The tracking issue for this feature is: [#93396] + +[#93396]: https://github.com/rust-lang/rust/issues/93396 + +------------------------ "##, }, Lint { @@ -3348,6 +7996,68 @@ error: aborting due to 2 previous errors This feature is internal to the Rust compiler and is not intended for general use. +------------------------ +"##, + }, + Lint { + label: "spec_option_partial_eq", + description: r##"# `spec_option_partial_eq` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "specialization", + description: r##"# `specialization` + +The tracking issue for this feature is: [#31844] + +[#31844]: https://github.com/rust-lang/rust/issues/31844 + +------------------------ +"##, + }, + Lint { + label: "split_array", + description: r##"# `split_array` + +The tracking issue for this feature is: [#90091] + +[#90091]: https://github.com/rust-lang/rust/issues/90091 + +------------------------ +"##, + }, + Lint { + label: "split_as_slice", + description: r##"# `split_as_slice` + +The tracking issue for this feature is: [#96137] + +[#96137]: https://github.com/rust-lang/rust/issues/96137 + +------------------------ +"##, + }, + Lint { + label: "sse4a_target_feature", + description: r##"# `sse4a_target_feature` + +The tracking issue for this feature is: [#44839] + +[#44839]: https://github.com/rust-lang/rust/issues/44839 + +------------------------ +"##, + }, + Lint { + label: "staged_api", + description: r##"# `staged_api` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + ------------------------ "##, }, @@ -3412,6 +8122,59 @@ fn start(_argc: isize, _argv: *const *const u8) -> isize { 0 } ``` +"##, + }, + Lint { + label: "std_internals", + description: r##"# `std_internals` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "stdio_makes_pipe", + description: r##"# `stdio_makes_pipe` + +The tracking issue for this feature is: [#98288] + +[#98288]: https://github.com/rust-lang/rust/issues/98288 + +------------------------ +"##, + }, + Lint { + label: "stdsimd", + description: r##"# `stdsimd` + +The tracking issue for this feature is: [#48556] + +[#48556]: https://github.com/rust-lang/rust/issues/48556 + +------------------------ +"##, + }, + Lint { + label: "step_trait", + description: r##"# `step_trait` + +The tracking issue for this feature is: [#42168] + +[#42168]: https://github.com/rust-lang/rust/issues/42168 + +------------------------ +"##, + }, + Lint { + label: "stmt_expr_attributes", + description: r##"# `stmt_expr_attributes` + +The tracking issue for this feature is: [#15701] + +[#15701]: https://github.com/rust-lang/rust/issues/15701 + +------------------------ "##, }, Lint { @@ -3420,6 +8183,39 @@ fn start(_argc: isize, _argv: *const *const u8) -> isize { This feature is internal to the Rust compiler and is not intended for general use. +------------------------ +"##, + }, + Lint { + label: "str_split_inclusive_remainder", + description: r##"# `str_split_inclusive_remainder` + +The tracking issue for this feature is: [#77998] + +[#77998]: https://github.com/rust-lang/rust/issues/77998 + +------------------------ +"##, + }, + Lint { + label: "str_split_remainder", + description: r##"# `str_split_remainder` + +The tracking issue for this feature is: [#77998] + +[#77998]: https://github.com/rust-lang/rust/issues/77998 + +------------------------ +"##, + }, + Lint { + label: "str_split_whitespace_remainder", + description: r##"# `str_split_whitespace_remainder` + +The tracking issue for this feature is: [#77998] + +[#77998]: https://github.com/rust-lang/rust/issues/77998 + ------------------------ "##, }, @@ -3447,6 +8243,127 @@ fn main() { //~^ WARNING: strict provenance disallows casting integer `usize` to pointer `*const u8` } ``` +"##, + }, + Lint { + label: "strict_provenance_atomic_ptr", + description: r##"# `strict_provenance_atomic_ptr` + +The tracking issue for this feature is: [#99108] + +[#99108]: https://github.com/rust-lang/rust/issues/99108 + +------------------------ +"##, + }, + Lint { + label: "string_deref_patterns", + description: r##"# `string_deref_patterns` + +The tracking issue for this feature is: [#87121] + +[#87121]: https://github.com/rust-lang/rust/issues/87121 + +------------------------ +"##, + }, + Lint { + label: "string_extend_from_within", + description: r##"# `string_extend_from_within` + +The tracking issue for this feature is: [#103806] + +[#103806]: https://github.com/rust-lang/rust/issues/103806 + +------------------------ +"##, + }, + Lint { + label: "string_remove_matches", + description: r##"# `string_remove_matches` + +The tracking issue for this feature is: [#72826] + +[#72826]: https://github.com/rust-lang/rust/issues/72826 + +------------------------ +"##, + }, + Lint { + label: "structural_match", + description: r##"# `structural_match` + +The tracking issue for this feature is: [#31434] + +[#31434]: https://github.com/rust-lang/rust/issues/31434 + +------------------------ +"##, + }, + Lint { + label: "sync_unsafe_cell", + description: r##"# `sync_unsafe_cell` + +The tracking issue for this feature is: [#95439] + +[#95439]: https://github.com/rust-lang/rust/issues/95439 + +------------------------ +"##, + }, + Lint { + label: "target_feature_11", + description: r##"# `target_feature_11` + +The tracking issue for this feature is: [#69098] + +[#69098]: https://github.com/rust-lang/rust/issues/69098 + +------------------------ +"##, + }, + Lint { + label: "tbm_target_feature", + description: r##"# `tbm_target_feature` + +The tracking issue for this feature is: [#44839] + +[#44839]: https://github.com/rust-lang/rust/issues/44839 + +------------------------ +"##, + }, + Lint { + label: "tcp_linger", + description: r##"# `tcp_linger` + +The tracking issue for this feature is: [#88494] + +[#88494]: https://github.com/rust-lang/rust/issues/88494 + +------------------------ +"##, + }, + Lint { + label: "tcp_quickack", + description: r##"# `tcp_quickack` + +The tracking issue for this feature is: [#96256] + +[#96256]: https://github.com/rust-lang/rust/issues/96256 + +------------------------ +"##, + }, + Lint { + label: "tcplistener_into_incoming", + description: r##"# `tcplistener_into_incoming` + +The tracking issue for this feature is: [#88339] + +[#88339]: https://github.com/rust-lang/rust/issues/88339 + +------------------------ "##, }, Lint { @@ -3609,6 +8526,57 @@ test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured However, the optimizer can still modify a testcase in an undesirable manner even when using either of the above. +"##, + }, + Lint { + label: "test_2018_feature", + description: r##"# `test_2018_feature` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "test_unstable_lint", + description: r##"# `test_unstable_lint` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "thin_box", + description: r##"# `thin_box` + +The tracking issue for this feature is: [#92791] + +[#92791]: https://github.com/rust-lang/rust/issues/92791 + +------------------------ +"##, + }, + Lint { + label: "thread_id_value", + description: r##"# `thread_id_value` + +The tracking issue for this feature is: [#67939] + +[#67939]: https://github.com/rust-lang/rust/issues/67939 + +------------------------ +"##, + }, + Lint { + label: "thread_local", + description: r##"# `thread_local` + +The tracking issue for this feature is: [#29594] + +[#29594]: https://github.com/rust-lang/rust/issues/29594 + +------------------------ "##, }, Lint { @@ -3617,6 +8585,28 @@ even when using either of the above. This feature is internal to the Rust compiler and is not intended for general use. +------------------------ +"##, + }, + Lint { + label: "thread_sleep_until", + description: r##"# `thread_sleep_until` + +The tracking issue for this feature is: [#113752] + +[#113752]: https://github.com/rust-lang/rust/issues/113752 + +------------------------ +"##, + }, + Lint { + label: "thread_spawn_unchecked", + description: r##"# `thread_spawn_unchecked` + +The tracking issue for this feature is: [#55132] + +[#55132]: https://github.com/rust-lang/rust/issues/55132 + ------------------------ "##, }, @@ -3661,6 +8651,17 @@ note: trace_macro Finished dev [unoptimized + debuginfo] target(s) in 0.60 secs ``` +"##, + }, + Lint { + label: "track_path", + description: r##"# `track_path` + +The tracking issue for this feature is: [#99515] + +[#99515]: https://github.com/rust-lang/rust/issues/99515 + +------------------------ "##, }, Lint { @@ -3730,6 +8731,28 @@ impl Bar for T {} let bar: &dyn Bar = &123; let foo: &dyn Foo = bar; ``` +"##, + }, + Lint { + label: "transmutability", + description: r##"# `transmutability` + +The tracking issue for this feature is: [#99571] + +[#99571]: https://github.com/rust-lang/rust/issues/99571 + +------------------------ +"##, + }, + Lint { + label: "transmute_generic_consts", + description: r##"# `transmute_generic_consts` + +The tracking issue for this feature is: [#109929] + +[#109929]: https://github.com/rust-lang/rust/issues/109929 + +------------------------ "##, }, Lint { @@ -3817,6 +8840,59 @@ example, it is unspecified whether `size_of::()` is equal to it is transparent). The Rust compiler is free to perform this optimization if possible, but is not required to, and different compiler versions may differ in their application of these optimizations. +"##, + }, + Lint { + label: "trivial_bounds", + description: r##"# `trivial_bounds` + +The tracking issue for this feature is: [#48214] + +[#48214]: https://github.com/rust-lang/rust/issues/48214 + +------------------------ +"##, + }, + Lint { + label: "trusted_len", + description: r##"# `trusted_len` + +The tracking issue for this feature is: [#37572] + +[#37572]: https://github.com/rust-lang/rust/issues/37572 + +------------------------ +"##, + }, + Lint { + label: "trusted_len_next_unchecked", + description: r##"# `trusted_len_next_unchecked` + +The tracking issue for this feature is: [#37572] + +[#37572]: https://github.com/rust-lang/rust/issues/37572 + +------------------------ +"##, + }, + Lint { + label: "trusted_random_access", + description: r##"# `trusted_random_access` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "trusted_step", + description: r##"# `trusted_step` + +The tracking issue for this feature is: [#85731] + +[#85731]: https://github.com/rust-lang/rust/issues/85731 + +------------------------ "##, }, Lint { @@ -3851,6 +8927,92 @@ let result: Result = try { }; assert!(result.is_err()); ``` +"##, + }, + Lint { + label: "try_find", + description: r##"# `try_find` + +The tracking issue for this feature is: [#63178] + +[#63178]: https://github.com/rust-lang/rust/issues/63178 + +------------------------ +"##, + }, + Lint { + label: "try_reserve_kind", + description: r##"# `try_reserve_kind` + +The tracking issue for this feature is: [#48043] + +[#48043]: https://github.com/rust-lang/rust/issues/48043 + +------------------------ +"##, + }, + Lint { + label: "try_trait_v2", + description: r##"# `try_trait_v2` + +The tracking issue for this feature is: [#84277] + +[#84277]: https://github.com/rust-lang/rust/issues/84277 + +------------------------ +"##, + }, + Lint { + label: "try_trait_v2_residual", + description: r##"# `try_trait_v2_residual` + +The tracking issue for this feature is: [#91285] + +[#91285]: https://github.com/rust-lang/rust/issues/91285 + +------------------------ +"##, + }, + Lint { + label: "try_trait_v2_yeet", + description: r##"# `try_trait_v2_yeet` + +The tracking issue for this feature is: [#96374] + +[#96374]: https://github.com/rust-lang/rust/issues/96374 + +------------------------ +"##, + }, + Lint { + label: "tuple_trait", + description: r##"# `tuple_trait` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "type_alias_impl_trait", + description: r##"# `type_alias_impl_trait` + +The tracking issue for this feature is: [#63063] + +[#63063]: https://github.com/rust-lang/rust/issues/63063 + +------------------------ +"##, + }, + Lint { + label: "type_ascription", + description: r##"# `type_ascription` + +The tracking issue for this feature is: [#23416] + +[#23416]: https://github.com/rust-lang/rust/issues/23416 + +------------------------ "##, }, Lint { @@ -3888,6 +9050,39 @@ fn main () { }; } ``` +"##, + }, + Lint { + label: "type_name_of_val", + description: r##"# `type_name_of_val` + +The tracking issue for this feature is: [#66359] + +[#66359]: https://github.com/rust-lang/rust/issues/66359 + +------------------------ +"##, + }, + Lint { + label: "type_privacy_lints", + description: r##"# `type_privacy_lints` + +The tracking issue for this feature is: [#48054] + +[#48054]: https://github.com/rust-lang/rust/issues/48054 + +------------------------ +"##, + }, + Lint { + label: "uefi_std", + description: r##"# `uefi_std` + +The tracking issue for this feature is: [#100499] + +[#100499]: https://github.com/rust-lang/rust/issues/100499 + +------------------------ "##, }, Lint { @@ -3917,6 +9112,59 @@ extern "rust-call" fn add_args(args: (u32, u32)) -> u32 { fn main() {} ``` +"##, + }, + Lint { + label: "unchecked_math", + description: r##"# `unchecked_math` + +The tracking issue for this feature is: [#85122] + +[#85122]: https://github.com/rust-lang/rust/issues/85122 + +------------------------ +"##, + }, + Lint { + label: "unicode_internals", + description: r##"# `unicode_internals` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "unique_rc_arc", + description: r##"# `unique_rc_arc` + +The tracking issue for this feature is: [#112566] + +[#112566]: https://github.com/rust-lang/rust/issues/112566 + +------------------------ +"##, + }, + Lint { + label: "unix_file_vectored_at", + description: r##"# `unix_file_vectored_at` + +The tracking issue for this feature is: [#89517] + +[#89517]: https://github.com/rust-lang/rust/issues/89517 + +------------------------ +"##, + }, + Lint { + label: "unix_set_mark", + description: r##"# `unix_set_mark` + +The tracking issue for this feature is: [#96467] + +[#96467]: https://github.com/rust-lang/rust/issues/96467 + +------------------------ "##, }, Lint { @@ -3983,6 +9231,81 @@ reset `SIGPIPE` to `SIG_DFL`. If `#[unix_sigpipe = "..."]` is specified, no matter what its value is, the signal disposition of `SIGPIPE` is no longer reset. This means that the child inherits the parent's `SIGPIPE` behavior. +"##, + }, + Lint { + label: "unix_socket_ancillary_data", + description: r##"# `unix_socket_ancillary_data` + +The tracking issue for this feature is: [#76915] + +[#76915]: https://github.com/rust-lang/rust/issues/76915 + +------------------------ +"##, + }, + Lint { + label: "unix_socket_peek", + description: r##"# `unix_socket_peek` + +The tracking issue for this feature is: [#76923] + +[#76923]: https://github.com/rust-lang/rust/issues/76923 + +------------------------ +"##, + }, + Lint { + label: "unnamed_fields", + description: r##"# `unnamed_fields` + +The tracking issue for this feature is: [#49804] + +[#49804]: https://github.com/rust-lang/rust/issues/49804 + +------------------------ +"##, + }, + Lint { + label: "unsafe_cell_from_mut", + description: r##"# `unsafe_cell_from_mut` + +The tracking issue for this feature is: [#111645] + +[#111645]: https://github.com/rust-lang/rust/issues/111645 + +------------------------ +"##, + }, + Lint { + label: "unsafe_pin_internals", + description: r##"# `unsafe_pin_internals` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "unsize", + description: r##"# `unsize` + +The tracking issue for this feature is: [#18598] + +[#18598]: https://github.com/rust-lang/rust/issues/18598 + +------------------------ +"##, + }, + Lint { + label: "unsized_fn_params", + description: r##"# `unsized_fn_params` + +The tracking issue for this feature is: [#48055] + +[#48055]: https://github.com/rust-lang/rust/issues/48055 + +------------------------ "##, }, Lint { @@ -4193,6 +9516,17 @@ fn main() { ``` [RFC0401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md +"##, + }, + Lint { + label: "unwrap_infallible", + description: r##"# `unwrap_infallible` + +The tracking issue for this feature is: [#61695] + +[#61695]: https://github.com/rust-lang/rust/issues/61695 + +------------------------ "##, }, Lint { @@ -4201,6 +9535,149 @@ fn main() { This feature is internal to the Rust compiler and is not intended for general use. +------------------------ +"##, + }, + Lint { + label: "used_with_arg", + description: r##"# `used_with_arg` + +The tracking issue for this feature is: [#93798] + +[#93798]: https://github.com/rust-lang/rust/issues/93798 + +------------------------ +"##, + }, + Lint { + label: "utf16_extra", + description: r##"# `utf16_extra` + +The tracking issue for this feature is: [#94919] + +[#94919]: https://github.com/rust-lang/rust/issues/94919 + +------------------------ +"##, + }, + Lint { + label: "utf16_extra_const", + description: r##"# `utf16_extra_const` + +The tracking issue for this feature is: [#94919] + +[#94919]: https://github.com/rust-lang/rust/issues/94919 + +------------------------ +"##, + }, + Lint { + label: "utf8_chunks", + description: r##"# `utf8_chunks` + +The tracking issue for this feature is: [#99543] + +[#99543]: https://github.com/rust-lang/rust/issues/99543 + +------------------------ +"##, + }, + Lint { + label: "variant_count", + description: r##"# `variant_count` + +The tracking issue for this feature is: [#73662] + +[#73662]: https://github.com/rust-lang/rust/issues/73662 + +------------------------ +"##, + }, + Lint { + label: "vec_into_raw_parts", + description: r##"# `vec_into_raw_parts` + +The tracking issue for this feature is: [#65816] + +[#65816]: https://github.com/rust-lang/rust/issues/65816 + +------------------------ +"##, + }, + Lint { + label: "vec_push_within_capacity", + description: r##"# `vec_push_within_capacity` + +The tracking issue for this feature is: [#100486] + +[#100486]: https://github.com/rust-lang/rust/issues/100486 + +------------------------ +"##, + }, + Lint { + label: "vec_split_at_spare", + description: r##"# `vec_split_at_spare` + +The tracking issue for this feature is: [#81944] + +[#81944]: https://github.com/rust-lang/rust/issues/81944 + +------------------------ +"##, + }, + Lint { + label: "waker_getters", + description: r##"# `waker_getters` + +The tracking issue for this feature is: [#87021] + +[#87021]: https://github.com/rust-lang/rust/issues/87021 + +------------------------ +"##, + }, + Lint { + label: "wasi_ext", + description: r##"# `wasi_ext` + +The tracking issue for this feature is: [#71213] + +[#71213]: https://github.com/rust-lang/rust/issues/71213 + +------------------------ +"##, + }, + Lint { + label: "wasm_abi", + description: r##"# `wasm_abi` + +The tracking issue for this feature is: [#83788] + +[#83788]: https://github.com/rust-lang/rust/issues/83788 + +------------------------ +"##, + }, + Lint { + label: "wasm_target_feature", + description: r##"# `wasm_target_feature` + +The tracking issue for this feature is: [#44839] + +[#44839]: https://github.com/rust-lang/rust/issues/44839 + +------------------------ +"##, + }, + Lint { + label: "windows_by_handle", + description: r##"# `windows_by_handle` + +The tracking issue for this feature is: [#63010] + +[#63010]: https://github.com/rust-lang/rust/issues/63010 + ------------------------ "##, }, @@ -4228,6 +9705,59 @@ This feature is internal to the Rust compiler and is not intended for general us This feature is internal to the Rust compiler and is not intended for general use. +------------------------ +"##, + }, + Lint { + label: "windows_process_exit_code_from", + description: r##"# `windows_process_exit_code_from` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "windows_process_extensions_async_pipes", + description: r##"# `windows_process_extensions_async_pipes` + +The tracking issue for this feature is: [#98289] + +[#98289]: https://github.com/rust-lang/rust/issues/98289 + +------------------------ +"##, + }, + Lint { + label: "windows_process_extensions_force_quotes", + description: r##"# `windows_process_extensions_force_quotes` + +The tracking issue for this feature is: [#82227] + +[#82227]: https://github.com/rust-lang/rust/issues/82227 + +------------------------ +"##, + }, + Lint { + label: "windows_process_extensions_main_thread_handle", + description: r##"# `windows_process_extensions_main_thread_handle` + +The tracking issue for this feature is: [#96723] + +[#96723]: https://github.com/rust-lang/rust/issues/96723 + +------------------------ +"##, + }, + Lint { + label: "windows_process_extensions_raw_attribute", + description: r##"# `windows_process_extensions_raw_attribute` + +The tracking issue for this feature is: [#114854] + +[#114854]: https://github.com/rust-lang/rust/issues/114854 + ------------------------ "##, }, @@ -4237,6 +9767,57 @@ This feature is internal to the Rust compiler and is not intended for general us This feature is internal to the Rust compiler and is not intended for general use. +------------------------ +"##, + }, + Lint { + label: "with_negative_coherence", + description: r##"# `with_negative_coherence` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "wrapping_int_impl", + description: r##"# `wrapping_int_impl` + +The tracking issue for this feature is: [#32463] + +[#32463]: https://github.com/rust-lang/rust/issues/32463 + +------------------------ +"##, + }, + Lint { + label: "wrapping_next_power_of_two", + description: r##"# `wrapping_next_power_of_two` + +The tracking issue for this feature is: [#32463] + +[#32463]: https://github.com/rust-lang/rust/issues/32463 + +------------------------ +"##, + }, + Lint { + label: "write_all_vectored", + description: r##"# `write_all_vectored` + +The tracking issue for this feature is: [#70436] + +[#70436]: https://github.com/rust-lang/rust/issues/70436 + +------------------------ +"##, + }, + Lint { + label: "yeet_desugar_details", + description: r##"# `yeet_desugar_details` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + ------------------------ "##, }, diff --git a/crates/ide-db/src/tests/sourcegen_lints.rs b/crates/ide-db/src/tests/sourcegen_lints.rs index 8d7117b0c902..c8cf87d3c205 100644 --- a/crates/ide-db/src/tests/sourcegen_lints.rs +++ b/crates/ide-db/src/tests/sourcegen_lints.rs @@ -1,4 +1,5 @@ -//! Generates descriptors structure for unstable feature from Unstable Book +//! Generates descriptor structures for unstable features from the unstable book +//! and lints from rustc, rustdoc, and clippy. use std::{borrow::Cow, fs, path::Path}; use itertools::Itertools; @@ -6,6 +7,8 @@ use stdx::format_to; use test_utils::project_root; use xshell::{cmd, Shell}; +const DESTINATION: &str = "crates/ide-db/src/generated/lints.rs"; + /// This clones rustc repo, and so is not worth to keep up-to-date. We update /// manually by un-ignoring the test from time to time. #[test] @@ -14,11 +17,21 @@ fn sourcegen_lint_completions() { let sh = &Shell::new().unwrap(); let rust_repo = project_root().join("./target/rust"); - if !rust_repo.exists() { + if rust_repo.exists() { + cmd!(sh, "git -C {rust_repo} pull --rebase").run().unwrap(); + } else { cmd!(sh, "git clone --depth=1 https://github.com/rust-lang/rust {rust_repo}") .run() .unwrap(); } + // need submodules for Cargo to parse the workspace correctly + cmd!( + sh, + "git -C {rust_repo} submodule update --init --recursive --depth=1 -- + compiler library src/tools" + ) + .run() + .unwrap(); let mut contents = String::from( r" @@ -27,17 +40,28 @@ pub struct Lint { pub label: &'static str, pub description: &'static str, } + pub struct LintGroup { pub lint: Lint, pub children: &'static [&'static str], } + ", ); generate_lint_descriptor(sh, &mut contents); contents.push('\n'); - generate_feature_descriptor(&mut contents, &rust_repo.join("src/doc/unstable-book/src")); + let cargo = std::env::var("CARGO").unwrap_or_else(|_| "cargo".to_string()); + let unstable_book = project_root().join("./target/unstable-book-gen"); + cmd!( + sh, + "{cargo} run --manifest-path {rust_repo}/src/tools/unstable-book-gen/Cargo.toml -- + {rust_repo}/library {rust_repo}/compiler {rust_repo}/src {unstable_book}" + ) + .run() + .unwrap(); + generate_feature_descriptor(&mut contents, &unstable_book.join("src")); contents.push('\n'); let lints_json = project_root().join("./target/clippy_lints.json"); @@ -51,7 +75,7 @@ pub struct LintGroup { let contents = sourcegen::add_preamble("sourcegen_lints", sourcegen::reformat(contents)); - let destination = project_root().join("crates/ide-db/src/generated/lints.rs"); + let destination = project_root().join(DESTINATION); sourcegen::ensure_file_contents(destination.as_path(), &contents); } @@ -179,8 +203,8 @@ fn find_and_slice<'a>(i: &'a str, p: &str) -> &'a str { &i[idx + p.len()..] } -/// Parses the unstable book root directory at `src_dir` and prints a constant -/// with the list of unstable features into `buf`. +/// Parses the unstable book `src_dir` and prints a constant with the list of +/// unstable features into `buf`. /// /// It does this by looking for all `.md` files in the `language-features` and /// `library-features` directories, and using the file name as the feature From e8372e04840a113c7aedb9cc5c7f387014d09e0b Mon Sep 17 00:00:00 2001 From: Elias Holzmann <9659253+EliasHolzmann@users.noreply.github.com> Date: Sun, 8 Oct 2023 03:52:15 +0200 Subject: [PATCH 117/435] vscode: Support opening local documentation if available Displaying local instead of web docs can have many benefits: - the web version may have different features enabled than locally selected - the standard library may be a different version than is available online - the user may not be online and therefore cannot access the web documentation - the documentation may not be available online at all, for example because it is for a new feature in a library the user is currently developing If the documentation is not available locally, the extension still falls back to the web version. --- editors/code/src/client.ts | 1 + editors/code/src/commands.ts | 20 +++++++++++++++++++- editors/code/src/lsp_ext.ts | 6 +++++- 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/editors/code/src/client.ts b/editors/code/src/client.ts index ba8546763ec8..96e888402baf 100644 --- a/editors/code/src/client.ts +++ b/editors/code/src/client.ts @@ -389,6 +389,7 @@ class ExperimentalFeatures implements lc.StaticFeature { serverStatusNotification: true, colorDiagnosticOutput: true, openServerLogs: true, + localDocs: true, commands: { commands: [ "rust-analyzer.runSingle", diff --git a/editors/code/src/commands.ts b/editors/code/src/commands.ts index 5e602510601a..4d5c3cf45764 100644 --- a/editors/code/src/commands.ts +++ b/editors/code/src/commands.ts @@ -21,6 +21,7 @@ import type { LanguageClient } from "vscode-languageclient/node"; import { LINKED_COMMANDS } from "./client"; import type { DependencyId } from "./dependencies_provider"; import { unwrapUndefinable } from "./undefinable"; +import { log } from "./util"; export * from "./ast_inspector"; export * from "./run"; @@ -947,7 +948,24 @@ export function openDocs(ctx: CtxInit): Cmd { const position = editor.selection.active; const textDocument = { uri: editor.document.uri.toString() }; - const doclink = await client.sendRequest(ra.openDocs, { position, textDocument }); + const doclinks = await client.sendRequest(ra.openDocs, { position, textDocument }); + + let fileType = vscode.FileType.Unknown; + if (typeof doclinks.local === "string") { + try { + fileType = (await vscode.workspace.fs.stat(vscode.Uri.parse(doclinks.local))).type; + } catch (e) { + log.debug("stat() threw error. Falling back to web version", e); + } + } + + let doclink; + if (fileType & vscode.FileType.File) { + // file does exist locally + doclink = doclinks.local; + } else { + doclink = doclinks.web; + } if (doclink != null) { await vscode.env.openExternal(vscode.Uri.parse(doclink)); diff --git a/editors/code/src/lsp_ext.ts b/editors/code/src/lsp_ext.ts index bb7896973f17..a1cd88b89c94 100644 --- a/editors/code/src/lsp_ext.ts +++ b/editors/code/src/lsp_ext.ts @@ -135,7 +135,11 @@ export const onEnter = new lc.RequestType( "experimental/openCargoToml", ); -export const openDocs = new lc.RequestType( +export interface DocsUrls { + local: string | void; + web: string | void; +} +export const openDocs = new lc.RequestType( "experimental/externalDocs", ); export const parentModule = new lc.RequestType< From 36eac9abee9d7beaa7e129c04ef9dd0cad3c6641 Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Tue, 3 Oct 2023 22:19:09 -0700 Subject: [PATCH 118/435] fix: add incorrect case diagnostics for module names --- crates/hir-def/src/lib.rs | 13 +++++ crates/hir-ty/src/diagnostics/decl_check.rs | 55 ++++++++++++++++++- crates/hir/src/lib.rs | 11 +--- .../src/handlers/incorrect_case.rs | 54 ++++++++++++++++++ 4 files changed, 123 insertions(+), 10 deletions(-) diff --git a/crates/hir-def/src/lib.rs b/crates/hir-def/src/lib.rs index 9c6f652f1ec7..495e2d476970 100644 --- a/crates/hir-def/src/lib.rs +++ b/crates/hir-def/src/lib.rs @@ -73,6 +73,7 @@ use hir_expand::{ db::ExpandDatabase, eager::expand_eager_macro_input, hygiene::Hygiene, + name::Name, proc_macro::ProcMacroExpander, AstId, ExpandError, ExpandResult, ExpandTo, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, UnresolvedMacro, @@ -174,6 +175,18 @@ impl ModuleId { self.krate } + pub fn name(self, db: &dyn db::DefDatabase) -> Option { + let def_map = self.def_map(db); + let parent = def_map[self.local_id].parent?; + def_map[parent].children.iter().find_map(|(name, module_id)| { + if *module_id == self.local_id { + Some(name.clone()) + } else { + None + } + }) + } + pub fn containing_module(self, db: &dyn db::DefDatabase) -> Option { self.def_map(db).containing_module(self.local_id) } diff --git a/crates/hir-ty/src/diagnostics/decl_check.rs b/crates/hir-ty/src/diagnostics/decl_check.rs index 36d69edf9d5d..4c7039f078fa 100644 --- a/crates/hir-ty/src/diagnostics/decl_check.rs +++ b/crates/hir-ty/src/diagnostics/decl_check.rs @@ -9,6 +9,7 @@ //! - constants (e.g. `const FOO: u8 = 10;`) //! - static items (e.g. `static FOO: u8 = 10;`) //! - match arm bindings (e.g. `foo @ Some(_)`) +//! - modules (e.g. `mod foo { ... }` or `mod foo;`) mod case_conv; @@ -19,7 +20,7 @@ use hir_def::{ hir::{Pat, PatId}, src::HasSource, AdtId, AttrDefId, ConstId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, ItemContainerId, - Lookup, ModuleDefId, StaticId, StructId, + Lookup, ModuleDefId, ModuleId, StaticId, StructId, }; use hir_expand::{ name::{AsName, Name}, @@ -83,6 +84,7 @@ pub enum IdentType { Structure, Variable, Variant, + Module, } impl fmt::Display for IdentType { @@ -97,6 +99,7 @@ impl fmt::Display for IdentType { IdentType::Structure => "Structure", IdentType::Variable => "Variable", IdentType::Variant => "Variant", + IdentType::Module => "Module", }; repr.fmt(f) @@ -132,6 +135,7 @@ impl<'a> DeclValidator<'a> { pub(super) fn validate_item(&mut self, item: ModuleDefId) { match item { + ModuleDefId::ModuleId(module_id) => self.validate_module(module_id), ModuleDefId::FunctionId(func) => self.validate_func(func), ModuleDefId::AdtId(adt) => self.validate_adt(adt), ModuleDefId::ConstId(const_id) => self.validate_const(const_id), @@ -230,6 +234,55 @@ impl<'a> DeclValidator<'a> { || parent() } + fn validate_module(&mut self, module_id: ModuleId) { + // Check whether non-snake case identifiers are allowed for this module. + if self.allowed(module_id.into(), allow::NON_SNAKE_CASE, false) { + return; + } + + // Check the module name. + let Some(module_name) = module_id.name(self.db.upcast()) else { return }; + let module_name_replacement = + module_name.as_str().and_then(to_lower_snake_case).map(|new_name| Replacement { + current_name: module_name, + suggested_text: new_name, + expected_case: CaseType::LowerSnakeCase, + }); + + if let Some(module_name_replacement) = module_name_replacement { + let module_data = &module_id.def_map(self.db.upcast())[module_id.local_id]; + let module_src = module_data.declaration_source(self.db.upcast()); + + if let Some(module_src) = module_src { + let ast_ptr = match module_src.value.name() { + Some(name) => name, + None => { + never!( + "Replacement ({:?}) was generated for a module without a name: {:?}", + module_name_replacement, + module_src + ); + return; + } + }; + + let diagnostic = IncorrectCase { + file: module_src.file_id, + ident_type: IdentType::Module, + ident: AstPtr::new(&ast_ptr), + expected_case: module_name_replacement.expected_case, + ident_text: module_name_replacement + .current_name + .display(self.db.upcast()) + .to_string(), + suggested_text: module_name_replacement.suggested_text, + }; + + self.sink.push(diagnostic); + } + } + } + fn validate_func(&mut self, func: FunctionId) { let data = self.db.function_data(func); if matches!(func.lookup(self.db.upcast()).container, ItemContainerId::ExternBlockId(_)) { diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index a6c6c0dbb8bf..c34e7ad91ff1 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -452,15 +452,7 @@ impl HasVisibility for ModuleDef { impl Module { /// Name of this module. pub fn name(self, db: &dyn HirDatabase) -> Option { - let def_map = self.id.def_map(db.upcast()); - let parent = def_map[self.id.local_id].parent?; - def_map[parent].children.iter().find_map(|(name, module_id)| { - if *module_id == self.id.local_id { - Some(name.clone()) - } else { - None - } - }) + self.id.name(db.upcast()) } /// Returns the crate this module is part of. @@ -571,6 +563,7 @@ impl Module { if def_map[m.id.local_id].origin.is_inline() { m.diagnostics(db, acc) } + acc.extend(def.diagnostics(db)) } ModuleDef::Trait(t) => { for diag in db.trait_data_with_diagnostics(t.id).1.iter() { diff --git a/crates/ide-diagnostics/src/handlers/incorrect_case.rs b/crates/ide-diagnostics/src/handlers/incorrect_case.rs index 7824011db67a..85dbb7e6f263 100644 --- a/crates/ide-diagnostics/src/handlers/incorrect_case.rs +++ b/crates/ide-diagnostics/src/handlers/incorrect_case.rs @@ -111,6 +111,31 @@ fn some_fn() { let what_aweird_formatting = 10; another_func(what_aweird_formatting); } +"#, + ); + + check_fix( + r#" +static S: i32 = M::A; + +mod $0M { + pub const A: i32 = 10; +} + +mod other { + use crate::M::A; +} +"#, + r#" +static S: i32 = m::A; + +mod m { + pub const A: i32 = 10; +} + +mod other { + use crate::m::A; +} "#, ); } @@ -518,17 +543,20 @@ fn NonSnakeCaseName(some_var: u8) -> u8 { #[deny(nonstandard_style)] mod CheckNonstandardStyle { + //^^^^^^^^^^^^^^^^^^^^^ 💡 error: Module `CheckNonstandardStyle` should have snake_case name, e.g. `check_nonstandard_style` fn HiImABadFnName() {} //^^^^^^^^^^^^^^ 💡 error: Function `HiImABadFnName` should have snake_case name, e.g. `hi_im_abad_fn_name` } #[deny(warnings)] mod CheckBadStyle { + //^^^^^^^^^^^^^ 💡 error: Module `CheckBadStyle` should have snake_case name, e.g. `check_bad_style` struct fooo; //^^^^ 💡 error: Structure `fooo` should have CamelCase name, e.g. `Fooo` } mod F { + //^ 💡 warn: Module `F` should have snake_case name, e.g. `f` #![deny(non_snake_case)] fn CheckItWorksWithModAttr() {} //^^^^^^^^^^^^^^^^^^^^^^^ 💡 error: Function `CheckItWorksWithModAttr` should have snake_case name, e.g. `check_it_works_with_mod_attr` @@ -649,4 +677,30 @@ enum E { "#, ); } + + #[test] + fn module_name_inline() { + check_diagnostics( + r#" +mod M { + //^ 💡 warn: Module `M` should have snake_case name, e.g. `m` + mod IncorrectCase {} + //^^^^^^^^^^^^^ 💡 warn: Module `IncorrectCase` should have snake_case name, e.g. `incorrect_case` +} +"#, + ); + } + + #[test] + fn module_name_decl() { + check_diagnostics( + r#" +//- /Foo.rs + +//- /main.rs +mod Foo; + //^^^ 💡 warn: Module `Foo` should have snake_case name, e.g. `foo` +"#, + ) + } } From a7fada46500dd15609d5846183b89f5a11399f19 Mon Sep 17 00:00:00 2001 From: Young-Flash <871946895@qq.com> Date: Wed, 11 Oct 2023 17:44:27 +0800 Subject: [PATCH 119/435] add replace_is_some_with_if_let_some assist --- .../replace_is_some_with_if_let_some.rs | 90 +++++++++++++++++++ crates/ide-assists/src/lib.rs | 2 + 2 files changed, 92 insertions(+) create mode 100644 crates/ide-assists/src/handlers/replace_is_some_with_if_let_some.rs diff --git a/crates/ide-assists/src/handlers/replace_is_some_with_if_let_some.rs b/crates/ide-assists/src/handlers/replace_is_some_with_if_let_some.rs new file mode 100644 index 000000000000..dfc2a8715003 --- /dev/null +++ b/crates/ide-assists/src/handlers/replace_is_some_with_if_let_some.rs @@ -0,0 +1,90 @@ +use syntax::ast::{self, AstNode}; + +use crate::{AssistContext, AssistId, AssistKind, Assists}; + +// Assist: replace_is_some_with_if_let +// +// Replace `if x.is_some()` with `if let Some(_tmp) = x`. +// +// ``` +// fn main() { +// let x = Some(1); +// if x.is_som$0e() {} +// } +// ``` +// -> +// ``` +// fn main() { +// let x = Some(1); +// if let Some(_tmp) = x {} +// } +// ``` +pub(crate) fn replace_is_some_with_if_let_some( + acc: &mut Assists, + ctx: &AssistContext<'_>, +) -> Option<()> { + let if_expr = ctx.find_node_at_offset::()?; + + let cond = if_expr.condition()?; + let call_expr = match cond { + ast::Expr::MethodCallExpr(call) => call, + _ => return None, + }; + + let name_ref = call_expr.name_ref()?; + if name_ref.text() != "is_some" { + return None; + } + + let receiver = call_expr.receiver()?; + let target = call_expr.syntax().text_range(); + + acc.add( + AssistId("replace_is_some_with_if_let_some", AssistKind::RefactorRewrite), + "Replace `is_some` with `if let Some`", + target, + |edit| { + let replacement = format!("let Some(_tmp) = {}", receiver); + edit.replace(target, replacement); + }, + ) +} + +#[cfg(test)] +mod tests { + use crate::tests::{check_assist, check_assist_not_applicable}; + + use super::replace_is_some_with_if_let_some; + + #[test] + fn replace_is_some_with_if_let_works() { + check_assist( + replace_is_some_with_if_let_some, + r#" +fn main() { + let x = Some(1); + if x.is_som$0e() {} +} +"#, + r#" +fn main() { + let x = Some(1); + if let Some(_tmp) = x {} +} +"#, + ); + } + + #[test] + fn replace_is_some_with_if_let_not_applicable() { + check_assist_not_applicable( + replace_is_some_with_if_let_some, + r#" +fn main() { + let x = Some(1); + if x.is_non$0e() {} +} +"#, + ); + } +} diff --git a/crates/ide-assists/src/lib.rs b/crates/ide-assists/src/lib.rs index 7b1961ae5493..d6accbb097ee 100644 --- a/crates/ide-assists/src/lib.rs +++ b/crates/ide-assists/src/lib.rs @@ -213,6 +213,7 @@ mod handlers { mod unwrap_block; mod unwrap_result_return_type; mod unqualify_method_call; + mod replace_is_some_with_if_let_some; mod wrap_return_type_in_result; mod into_to_qualified_from; @@ -332,6 +333,7 @@ mod handlers { unwrap_result_return_type::unwrap_result_return_type, unwrap_tuple::unwrap_tuple, unqualify_method_call::unqualify_method_call, + replace_is_some_with_if_let_some::replace_is_some_with_if_let_some, wrap_return_type_in_result::wrap_return_type_in_result, // These are manually sorted for better priorities. By default, // priority is determined by the size of the target range (smaller From 1fe6ac87e91f97ac28111863970aff6f5d2deb31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pol=20Valletb=C3=B3?= Date: Wed, 11 Oct 2023 12:19:00 +0200 Subject: [PATCH 120/435] add diagnosis messages for chars and byte literal errors --- crates/parser/src/lexed_str.rs | 55 +++++++++++ .../lexer/err/byte_char_literals.rast | 92 +++++++++++++++++++ .../test_data/lexer/err/byte_char_literals.rs | 47 ++++++++++ .../test_data/lexer/err/char_literals.rast | 92 +++++++++++++++++++ .../test_data/lexer/err/char_literals.rs | 47 ++++++++++ .../test_data/lexer/ok/byte_strings.rast | 6 -- .../parser/test_data/lexer/ok/byte_strings.rs | 6 +- crates/parser/test_data/lexer/ok/chars.rast | 2 - crates/parser/test_data/lexer/ok/chars.rs | 2 +- 9 files changed, 337 insertions(+), 12 deletions(-) create mode 100644 crates/parser/test_data/lexer/err/byte_char_literals.rast create mode 100644 crates/parser/test_data/lexer/err/byte_char_literals.rs create mode 100644 crates/parser/test_data/lexer/err/char_literals.rast create mode 100644 crates/parser/test_data/lexer/err/char_literals.rs diff --git a/crates/parser/src/lexed_str.rs b/crates/parser/src/lexed_str.rs index 30c1c4f8c75b..031ac27724e4 100644 --- a/crates/parser/src/lexed_str.rs +++ b/crates/parser/src/lexed_str.rs @@ -9,8 +9,11 @@ //! include info about comments and whitespace. use rustc_dependencies::lexer as rustc_lexer; + use std::ops; +use rustc_lexer::unescape::{Mode, EscapeError}; + use crate::{ SyntaxKind::{self, *}, T, @@ -254,13 +257,28 @@ impl<'a> Converter<'a> { rustc_lexer::LiteralKind::Char { terminated } => { if !terminated { err = "Missing trailing `'` symbol to terminate the character literal"; + } else { + let text = &self.res.text[self.offset + 1..][..len - 1]; + let i = text.rfind('\'').unwrap(); + let text = &text[..i]; + if let Err(e) = rustc_lexer::unescape::unescape_char(text) { + err = error_to_diagnostic_message(e, Mode::Char); + } } CHAR } rustc_lexer::LiteralKind::Byte { terminated } => { if !terminated { err = "Missing trailing `'` symbol to terminate the byte literal"; + } else { + let text = &self.res.text[self.offset + 2..][..len - 2]; + let i = text.rfind('\'').unwrap(); + let text = &text[..i]; + if let Err(e) = rustc_lexer::unescape::unescape_char(text) { + err = error_to_diagnostic_message(e, Mode::Byte); + } } + BYTE } rustc_lexer::LiteralKind::Str { terminated } => { @@ -305,3 +323,40 @@ impl<'a> Converter<'a> { self.push(syntax_kind, len, err); } } + +fn error_to_diagnostic_message(error: EscapeError, mode: Mode) -> &'static str { + match error { + EscapeError::ZeroChars => "empty character literal", + EscapeError::MoreThanOneChar => "character literal may only contain one codepoint", + EscapeError::LoneSlash => "", + EscapeError::InvalidEscape if mode == Mode::Byte || mode == Mode::ByteStr => { + "unknown byte escape" + } + EscapeError::InvalidEscape => "unknown character escape", + EscapeError::BareCarriageReturn => "", + EscapeError::BareCarriageReturnInRawString => "", + EscapeError::EscapeOnlyChar if mode == Mode::Byte => "byte constant must be escaped", + EscapeError::EscapeOnlyChar => "character constant must be escaped", + EscapeError::TooShortHexEscape => "numeric character escape is too short", + EscapeError::InvalidCharInHexEscape => "invalid character in numeric character escape", + EscapeError::OutOfRangeHexEscape => "out of range hex escape", + EscapeError::NoBraceInUnicodeEscape => "incorrect unicode escape sequence", + EscapeError::InvalidCharInUnicodeEscape => "invalid character in unicode escape", + EscapeError::EmptyUnicodeEscape => "empty unicode escape", + EscapeError::UnclosedUnicodeEscape => "unterminated unicode escape", + EscapeError::LeadingUnderscoreUnicodeEscape => "invalid start of unicode escape", + EscapeError::OverlongUnicodeEscape => "overlong unicode escape", + EscapeError::LoneSurrogateUnicodeEscape => "invalid unicode character escape", + EscapeError::OutOfRangeUnicodeEscape => "invalid unicode character escape", + EscapeError::UnicodeEscapeInByte => "unicode escape in byte string", + EscapeError::NonAsciiCharInByte if mode == Mode::Byte => { + "non-ASCII character in byte literal" + } + EscapeError::NonAsciiCharInByte if mode == Mode::ByteStr => { + "non-ASCII character in byte string literal" + } + EscapeError::NonAsciiCharInByte => "non-ASCII character in raw byte string literal", + EscapeError::UnskippedWhitespaceWarning => "", + EscapeError::MultipleSkippedLinesWarning => "", + } +} diff --git a/crates/parser/test_data/lexer/err/byte_char_literals.rast b/crates/parser/test_data/lexer/err/byte_char_literals.rast new file mode 100644 index 000000000000..24892bc23948 --- /dev/null +++ b/crates/parser/test_data/lexer/err/byte_char_literals.rast @@ -0,0 +1,92 @@ +BYTE "b''" error: empty character literal +WHITESPACE "\n" +BYTE "b'\\'" error: Missing trailing `'` symbol to terminate the byte literal +WHITESPACE "\n" +BYTE "b'\n'" error: byte constant must be escaped +WHITESPACE "\n" +BYTE "b'spam'" error: character literal may only contain one codepoint +WHITESPACE "\n" +BYTE "b'\\x0ff'" error: character literal may only contain one codepoint +WHITESPACE "\n" +BYTE "b'\\\"a'" error: character literal may only contain one codepoint +WHITESPACE "\n" +BYTE "b'\\na'" error: character literal may only contain one codepoint +WHITESPACE "\n" +BYTE "b'\\ra'" error: character literal may only contain one codepoint +WHITESPACE "\n" +BYTE "b'\\ta'" error: character literal may only contain one codepoint +WHITESPACE "\n" +BYTE "b'\\\\a'" error: character literal may only contain one codepoint +WHITESPACE "\n" +BYTE "b'\\'a'" error: character literal may only contain one codepoint +WHITESPACE "\n" +BYTE "b'\\0a'" error: character literal may only contain one codepoint +WHITESPACE "\n" +BYTE "b'\\u{0}x'" error: character literal may only contain one codepoint +WHITESPACE "\n" +BYTE "b'\\u{1F63b}}'" error: character literal may only contain one codepoint +WHITESPACE "\n" +BYTE "b'\\v'" error: unknown byte escape +WHITESPACE "\n" +BYTE "b'\\💩'" error: unknown byte escape +WHITESPACE "\n" +BYTE "b'\\●'" error: unknown byte escape +WHITESPACE "\n" +BYTE "b'\\\\\\r'" error: character literal may only contain one codepoint +WHITESPACE "\n" +BYTE "b'\\x'" error: numeric character escape is too short +WHITESPACE "\n" +BYTE "b'\\x0'" error: numeric character escape is too short +WHITESPACE "\n" +BYTE "b'\\xf'" error: numeric character escape is too short +WHITESPACE "\n" +BYTE "b'\\xa'" error: numeric character escape is too short +WHITESPACE "\n" +BYTE "b'\\xx'" error: invalid character in numeric character escape +WHITESPACE "\n" +BYTE "b'\\xы'" error: invalid character in numeric character escape +WHITESPACE "\n" +BYTE "b'\\x🦀'" error: invalid character in numeric character escape +WHITESPACE "\n" +BYTE "b'\\xtt'" error: invalid character in numeric character escape +WHITESPACE "\n" +BYTE "b'\\xff'" error: out of range hex escape +WHITESPACE "\n" +BYTE "b'\\xFF'" error: out of range hex escape +WHITESPACE "\n" +BYTE "b'\\x80'" error: out of range hex escape +WHITESPACE "\n" +BYTE "b'\\u'" error: incorrect unicode escape sequence +WHITESPACE "\n" +BYTE "b'\\u[0123]'" error: incorrect unicode escape sequence +WHITESPACE "\n" +BYTE "b'\\u{0x}'" error: invalid character in unicode escape +WHITESPACE "\n" +BYTE "b'\\u{'" error: unterminated unicode escape +WHITESPACE "\n" +BYTE "b'\\u{0000'" error: unterminated unicode escape +WHITESPACE "\n" +BYTE "b'\\u{}'" error: empty unicode escape +WHITESPACE "\n" +BYTE "b'\\u{_0000}'" error: invalid start of unicode escape +WHITESPACE "\n" +BYTE "b'\\u{0000000}'" error: overlong unicode escape +WHITESPACE "\n" +BYTE "b'\\u{FFFFFF}'" error: invalid unicode character escape +WHITESPACE "\n" +BYTE "b'\\u{ffffff}'" error: invalid unicode character escape +WHITESPACE "\n" +BYTE "b'\\u{ffffff}'" error: invalid unicode character escape +WHITESPACE "\n" +BYTE "b'\\u{DC00}'" error: invalid unicode character escape +WHITESPACE "\n" +BYTE "b'\\u{DDDD}'" error: invalid unicode character escape +WHITESPACE "\n" +BYTE "b'\\u{DFFF}'" error: invalid unicode character escape +WHITESPACE "\n" +BYTE "b'\\u{D800}'" error: invalid unicode character escape +WHITESPACE "\n" +BYTE "b'\\u{DAAA}'" error: invalid unicode character escape +WHITESPACE "\n" +BYTE "b'\\u{DBFF}'" error: invalid unicode character escape +WHITESPACE "\n" diff --git a/crates/parser/test_data/lexer/err/byte_char_literals.rs b/crates/parser/test_data/lexer/err/byte_char_literals.rs new file mode 100644 index 000000000000..9f2f4309e769 --- /dev/null +++ b/crates/parser/test_data/lexer/err/byte_char_literals.rs @@ -0,0 +1,47 @@ +b'' +b'\' +b' +' +b'spam' +b'\x0ff' +b'\"a' +b'\na' +b'\ra' +b'\ta' +b'\\a' +b'\'a' +b'\0a' +b'\u{0}x' +b'\u{1F63b}}' +b'\v' +b'\💩' +b'\●' +b'\\\r' +b'\x' +b'\x0' +b'\xf' +b'\xa' +b'\xx' +b'\xы' +b'\x🦀' +b'\xtt' +b'\xff' +b'\xFF' +b'\x80' +b'\u' +b'\u[0123]' +b'\u{0x}' +b'\u{' +b'\u{0000' +b'\u{}' +b'\u{_0000}' +b'\u{0000000}' +b'\u{FFFFFF}' +b'\u{ffffff}' +b'\u{ffffff}' +b'\u{DC00}' +b'\u{DDDD}' +b'\u{DFFF}' +b'\u{D800}' +b'\u{DAAA}' +b'\u{DBFF}' diff --git a/crates/parser/test_data/lexer/err/char_literals.rast b/crates/parser/test_data/lexer/err/char_literals.rast new file mode 100644 index 000000000000..b1e1364d4c2c --- /dev/null +++ b/crates/parser/test_data/lexer/err/char_literals.rast @@ -0,0 +1,92 @@ +CHAR "'hello'" error: character literal may only contain one codepoint +WHITESPACE "\n" +CHAR "''" error: empty character literal +WHITESPACE "\n" +CHAR "'\n'" error: character constant must be escaped +WHITESPACE "\n" +CHAR "'spam'" error: character literal may only contain one codepoint +WHITESPACE "\n" +CHAR "'\\x0ff'" error: character literal may only contain one codepoint +WHITESPACE "\n" +CHAR "'\\\"a'" error: character literal may only contain one codepoint +WHITESPACE "\n" +CHAR "'\\na'" error: character literal may only contain one codepoint +WHITESPACE "\n" +CHAR "'\\ra'" error: character literal may only contain one codepoint +WHITESPACE "\n" +CHAR "'\\ta'" error: character literal may only contain one codepoint +WHITESPACE "\n" +CHAR "'\\\\a'" error: character literal may only contain one codepoint +WHITESPACE "\n" +CHAR "'\\'a'" error: character literal may only contain one codepoint +WHITESPACE "\n" +CHAR "'\\0a'" error: character literal may only contain one codepoint +WHITESPACE "\n" +CHAR "'\\u{0}x'" error: character literal may only contain one codepoint +WHITESPACE "\n" +CHAR "'\\u{1F63b}}'" error: character literal may only contain one codepoint +WHITESPACE "\n" +CHAR "'\\v'" error: unknown character escape +WHITESPACE "\n" +CHAR "'\\💩'" error: unknown character escape +WHITESPACE "\n" +CHAR "'\\●'" error: unknown character escape +WHITESPACE "\n" +CHAR "'\\\\\\r'" error: character literal may only contain one codepoint +WHITESPACE "\n" +CHAR "'\\x'" error: numeric character escape is too short +WHITESPACE "\n" +CHAR "'\\x0'" error: numeric character escape is too short +WHITESPACE "\n" +CHAR "'\\xf'" error: numeric character escape is too short +WHITESPACE "\n" +CHAR "'\\xa'" error: numeric character escape is too short +WHITESPACE "\n" +CHAR "'\\xx'" error: invalid character in numeric character escape +WHITESPACE "\n" +CHAR "'\\xы'" error: invalid character in numeric character escape +WHITESPACE "\n" +CHAR "'\\x🦀'" error: invalid character in numeric character escape +WHITESPACE "\n" +CHAR "'\\xtt'" error: invalid character in numeric character escape +WHITESPACE "\n" +CHAR "'\\xff'" error: out of range hex escape +WHITESPACE "\n" +CHAR "'\\xFF'" error: out of range hex escape +WHITESPACE "\n" +CHAR "'\\x80'" error: out of range hex escape +WHITESPACE "\n" +CHAR "'\\u'" error: incorrect unicode escape sequence +WHITESPACE "\n" +CHAR "'\\u[0123]'" error: incorrect unicode escape sequence +WHITESPACE "\n" +CHAR "'\\u{0x}'" error: invalid character in unicode escape +WHITESPACE "\n" +CHAR "'\\u{'" error: unterminated unicode escape +WHITESPACE "\n" +CHAR "'\\u{0000'" error: unterminated unicode escape +WHITESPACE "\n" +CHAR "'\\u{}'" error: empty unicode escape +WHITESPACE "\n" +CHAR "'\\u{_0000}'" error: invalid start of unicode escape +WHITESPACE "\n" +CHAR "'\\u{0000000}'" error: overlong unicode escape +WHITESPACE "\n" +CHAR "'\\u{FFFFFF}'" error: invalid unicode character escape +WHITESPACE "\n" +CHAR "'\\u{ffffff}'" error: invalid unicode character escape +WHITESPACE "\n" +CHAR "'\\u{ffffff}'" error: invalid unicode character escape +WHITESPACE "\n" +CHAR "'\\u{DC00}'" error: invalid unicode character escape +WHITESPACE "\n" +CHAR "'\\u{DDDD}'" error: invalid unicode character escape +WHITESPACE "\n" +CHAR "'\\u{DFFF}'" error: invalid unicode character escape +WHITESPACE "\n" +CHAR "'\\u{D800}'" error: invalid unicode character escape +WHITESPACE "\n" +CHAR "'\\u{DAAA}'" error: invalid unicode character escape +WHITESPACE "\n" +CHAR "'\\u{DBFF}'" error: invalid unicode character escape +WHITESPACE "\n" diff --git a/crates/parser/test_data/lexer/err/char_literals.rs b/crates/parser/test_data/lexer/err/char_literals.rs new file mode 100644 index 000000000000..291f99d8020c --- /dev/null +++ b/crates/parser/test_data/lexer/err/char_literals.rs @@ -0,0 +1,47 @@ +'hello' +'' +' +' +'spam' +'\x0ff' +'\"a' +'\na' +'\ra' +'\ta' +'\\a' +'\'a' +'\0a' +'\u{0}x' +'\u{1F63b}}' +'\v' +'\💩' +'\●' +'\\\r' +'\x' +'\x0' +'\xf' +'\xa' +'\xx' +'\xы' +'\x🦀' +'\xtt' +'\xff' +'\xFF' +'\x80' +'\u' +'\u[0123]' +'\u{0x}' +'\u{' +'\u{0000' +'\u{}' +'\u{_0000}' +'\u{0000000}' +'\u{FFFFFF}' +'\u{ffffff}' +'\u{ffffff}' +'\u{DC00}' +'\u{DDDD}' +'\u{DFFF}' +'\u{D800}' +'\u{DAAA}' +'\u{DBFF}' diff --git a/crates/parser/test_data/lexer/ok/byte_strings.rast b/crates/parser/test_data/lexer/ok/byte_strings.rast index c848ac368e4f..fd20ca57ac6c 100644 --- a/crates/parser/test_data/lexer/ok/byte_strings.rast +++ b/crates/parser/test_data/lexer/ok/byte_strings.rast @@ -1,13 +1,9 @@ -BYTE "b''" -WHITESPACE " " BYTE "b'x'" WHITESPACE " " BYTE_STRING "b\"foo\"" WHITESPACE " " BYTE_STRING "br\"\"" WHITESPACE "\n" -BYTE "b''suf" -WHITESPACE " " BYTE_STRING "b\"\"ix" WHITESPACE " " BYTE_STRING "br\"\"br" @@ -17,6 +13,4 @@ WHITESPACE " " BYTE "b'\\\\'" WHITESPACE " " BYTE "b'\\''" -WHITESPACE " " -BYTE "b'hello'" WHITESPACE "\n" diff --git a/crates/parser/test_data/lexer/ok/byte_strings.rs b/crates/parser/test_data/lexer/ok/byte_strings.rs index b54930f5e699..65460d02cb27 100644 --- a/crates/parser/test_data/lexer/ok/byte_strings.rs +++ b/crates/parser/test_data/lexer/ok/byte_strings.rs @@ -1,3 +1,3 @@ -b'' b'x' b"foo" br"" -b''suf b""ix br""br -b'\n' b'\\' b'\'' b'hello' +b'x' b"foo" br"" +b""ix br""br +b'\n' b'\\' b'\'' diff --git a/crates/parser/test_data/lexer/ok/chars.rast b/crates/parser/test_data/lexer/ok/chars.rast index 66e58cc298f4..07172a4ecc0a 100644 --- a/crates/parser/test_data/lexer/ok/chars.rast +++ b/crates/parser/test_data/lexer/ok/chars.rast @@ -4,8 +4,6 @@ CHAR "' '" WHITESPACE " " CHAR "'0'" WHITESPACE " " -CHAR "'hello'" -WHITESPACE " " CHAR "'\\x7f'" WHITESPACE " " CHAR "'\\n'" diff --git a/crates/parser/test_data/lexer/ok/chars.rs b/crates/parser/test_data/lexer/ok/chars.rs index 454ee0a5f617..15f52c113c11 100644 --- a/crates/parser/test_data/lexer/ok/chars.rs +++ b/crates/parser/test_data/lexer/ok/chars.rs @@ -1 +1 @@ -'x' ' ' '0' 'hello' '\x7f' '\n' '\\' '\'' +'x' ' ' '0' '\x7f' '\n' '\\' '\'' From f58a8250dc3104e336ec8611702d015bd47f508a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pol=20Valletb=C3=B3?= Date: Wed, 11 Oct 2023 12:36:53 +0200 Subject: [PATCH 121/435] fix: cargo fmt --- crates/parser/src/lexed_str.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/parser/src/lexed_str.rs b/crates/parser/src/lexed_str.rs index 031ac27724e4..8e8bdce1eef2 100644 --- a/crates/parser/src/lexed_str.rs +++ b/crates/parser/src/lexed_str.rs @@ -12,7 +12,7 @@ use rustc_dependencies::lexer as rustc_lexer; use std::ops; -use rustc_lexer::unescape::{Mode, EscapeError}; +use rustc_lexer::unescape::{EscapeError, Mode}; use crate::{ SyntaxKind::{self, *}, From 677e6f3439b91769a9b54c18afe5c136c14d9e8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pol=20Valletb=C3=B3?= Date: Wed, 11 Oct 2023 13:09:12 +0200 Subject: [PATCH 122/435] fix: use unescape_byte function for Byte literals --- crates/parser/src/lexed_str.rs | 2 +- .../lexer/err/byte_char_literals.rast | 28 ++++++++----------- .../test_data/lexer/err/byte_char_literals.rs | 3 -- 3 files changed, 12 insertions(+), 21 deletions(-) diff --git a/crates/parser/src/lexed_str.rs b/crates/parser/src/lexed_str.rs index 8e8bdce1eef2..84cedc1fa3f0 100644 --- a/crates/parser/src/lexed_str.rs +++ b/crates/parser/src/lexed_str.rs @@ -274,7 +274,7 @@ impl<'a> Converter<'a> { let text = &self.res.text[self.offset + 2..][..len - 2]; let i = text.rfind('\'').unwrap(); let text = &text[..i]; - if let Err(e) = rustc_lexer::unescape::unescape_char(text) { + if let Err(e) = rustc_lexer::unescape::unescape_byte(text) { err = error_to_diagnostic_message(e, Mode::Byte); } } diff --git a/crates/parser/test_data/lexer/err/byte_char_literals.rast b/crates/parser/test_data/lexer/err/byte_char_literals.rast index 24892bc23948..7603c9099daa 100644 --- a/crates/parser/test_data/lexer/err/byte_char_literals.rast +++ b/crates/parser/test_data/lexer/err/byte_char_literals.rast @@ -22,9 +22,9 @@ BYTE "b'\\'a'" error: character literal may only contain one codepoint WHITESPACE "\n" BYTE "b'\\0a'" error: character literal may only contain one codepoint WHITESPACE "\n" -BYTE "b'\\u{0}x'" error: character literal may only contain one codepoint +BYTE "b'\\u{0}x'" error: unicode escape in byte string WHITESPACE "\n" -BYTE "b'\\u{1F63b}}'" error: character literal may only contain one codepoint +BYTE "b'\\u{1F63b}}'" error: unicode escape in byte string WHITESPACE "\n" BYTE "b'\\v'" error: unknown byte escape WHITESPACE "\n" @@ -50,12 +50,6 @@ BYTE "b'\\x🦀'" error: invalid character in numeric character escape WHITESPACE "\n" BYTE "b'\\xtt'" error: invalid character in numeric character escape WHITESPACE "\n" -BYTE "b'\\xff'" error: out of range hex escape -WHITESPACE "\n" -BYTE "b'\\xFF'" error: out of range hex escape -WHITESPACE "\n" -BYTE "b'\\x80'" error: out of range hex escape -WHITESPACE "\n" BYTE "b'\\u'" error: incorrect unicode escape sequence WHITESPACE "\n" BYTE "b'\\u[0123]'" error: incorrect unicode escape sequence @@ -72,21 +66,21 @@ BYTE "b'\\u{_0000}'" error: invalid start of unicode escape WHITESPACE "\n" BYTE "b'\\u{0000000}'" error: overlong unicode escape WHITESPACE "\n" -BYTE "b'\\u{FFFFFF}'" error: invalid unicode character escape +BYTE "b'\\u{FFFFFF}'" error: unicode escape in byte string WHITESPACE "\n" -BYTE "b'\\u{ffffff}'" error: invalid unicode character escape +BYTE "b'\\u{ffffff}'" error: unicode escape in byte string WHITESPACE "\n" -BYTE "b'\\u{ffffff}'" error: invalid unicode character escape +BYTE "b'\\u{ffffff}'" error: unicode escape in byte string WHITESPACE "\n" -BYTE "b'\\u{DC00}'" error: invalid unicode character escape +BYTE "b'\\u{DC00}'" error: unicode escape in byte string WHITESPACE "\n" -BYTE "b'\\u{DDDD}'" error: invalid unicode character escape +BYTE "b'\\u{DDDD}'" error: unicode escape in byte string WHITESPACE "\n" -BYTE "b'\\u{DFFF}'" error: invalid unicode character escape +BYTE "b'\\u{DFFF}'" error: unicode escape in byte string WHITESPACE "\n" -BYTE "b'\\u{D800}'" error: invalid unicode character escape +BYTE "b'\\u{D800}'" error: unicode escape in byte string WHITESPACE "\n" -BYTE "b'\\u{DAAA}'" error: invalid unicode character escape +BYTE "b'\\u{DAAA}'" error: unicode escape in byte string WHITESPACE "\n" -BYTE "b'\\u{DBFF}'" error: invalid unicode character escape +BYTE "b'\\u{DBFF}'" error: unicode escape in byte string WHITESPACE "\n" diff --git a/crates/parser/test_data/lexer/err/byte_char_literals.rs b/crates/parser/test_data/lexer/err/byte_char_literals.rs index 9f2f4309e769..b2d06e490bd6 100644 --- a/crates/parser/test_data/lexer/err/byte_char_literals.rs +++ b/crates/parser/test_data/lexer/err/byte_char_literals.rs @@ -25,9 +25,6 @@ b'\xx' b'\xы' b'\x🦀' b'\xtt' -b'\xff' -b'\xFF' -b'\x80' b'\u' b'\u[0123]' b'\u{0x}' From e1aeb7fa794e228ca9099ac7679e8a1d0b22238a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pol=20Valletb=C3=B3?= Date: Wed, 11 Oct 2023 15:25:52 +0200 Subject: [PATCH 123/435] fix: handle errors for string byte string and c_string --- crates/parser/src/lexed_str.rs | 42 ++++++++++++++++++- .../test_data/lexer/err/byte_strings.rast | 28 +++++++++++++ .../test_data/lexer/err/byte_strings.rs | 14 +++++++ .../parser/test_data/lexer/err/c_strings.rast | 28 +++++++++++++ .../parser/test_data/lexer/err/c_strings.rs | 14 +++++++ .../parser/test_data/lexer/err/strings.rast | 28 +++++++++++++ crates/parser/test_data/lexer/err/strings.rs | 14 +++++++ 7 files changed, 167 insertions(+), 1 deletion(-) create mode 100644 crates/parser/test_data/lexer/err/byte_strings.rast create mode 100644 crates/parser/test_data/lexer/err/byte_strings.rs create mode 100644 crates/parser/test_data/lexer/err/c_strings.rast create mode 100644 crates/parser/test_data/lexer/err/c_strings.rs create mode 100644 crates/parser/test_data/lexer/err/strings.rast create mode 100644 crates/parser/test_data/lexer/err/strings.rs diff --git a/crates/parser/src/lexed_str.rs b/crates/parser/src/lexed_str.rs index 84cedc1fa3f0..c2e25daf37f6 100644 --- a/crates/parser/src/lexed_str.rs +++ b/crates/parser/src/lexed_str.rs @@ -8,7 +8,10 @@ //! Note that these tokens, unlike the tokens we feed into the parser, do //! include info about comments and whitespace. -use rustc_dependencies::lexer as rustc_lexer; +use rustc_dependencies::lexer::{ + self as rustc_lexer, + unescape::{unescape_c_string, unescape_literal}, +}; use std::ops; @@ -284,18 +287,45 @@ impl<'a> Converter<'a> { rustc_lexer::LiteralKind::Str { terminated } => { if !terminated { err = "Missing trailing `\"` symbol to terminate the string literal"; + } else { + let text = &self.res.text[self.offset + 1..][..len - 1]; + let i = text.rfind('"').unwrap(); + let text = &text[..i]; + rustc_lexer::unescape::unescape_literal(text, Mode::Str, &mut |_, res| { + if let Err(e) = res { + err = error_to_diagnostic_message(e, Mode::Str); + } + }); } STRING } rustc_lexer::LiteralKind::ByteStr { terminated } => { if !terminated { err = "Missing trailing `\"` symbol to terminate the byte string literal"; + } else { + let text = &self.res.text[self.offset + 2..][..len - 2]; + let i = text.rfind('"').unwrap(); + let text = &text[..i]; + rustc_lexer::unescape::unescape_literal(text, Mode::ByteStr, &mut |_, res| { + if let Err(e) = res { + err = error_to_diagnostic_message(e, Mode::ByteStr); + } + }) } BYTE_STRING } rustc_lexer::LiteralKind::CStr { terminated } => { if !terminated { err = "Missing trailing `\"` symbol to terminate the string literal"; + } else { + let text = &self.res.text[self.offset + 2..][..len - 2]; + let i = text.rfind('"').unwrap(); + let text = &text[..i]; + rustc_lexer::unescape::unescape_c_string(text, Mode::CStr, &mut |_, res| { + if let Err(e) = res { + err = error_to_diagnostic_message(e, Mode::CStr); + } + }) } C_STRING } @@ -360,3 +390,13 @@ fn error_to_diagnostic_message(error: EscapeError, mode: Mode) -> &'static str { EscapeError::MultipleSkippedLinesWarning => "", } } + +fn fill_unescape_string_error(text: &str, mode: Mode, mut error_message: &str) { + + rustc_lexer::unescape::unescape_c_string(text, mode, &mut |_, res| { + if let Err(e) = res { + error_message = error_to_diagnostic_message(e, mode); + } + }); +} + diff --git a/crates/parser/test_data/lexer/err/byte_strings.rast b/crates/parser/test_data/lexer/err/byte_strings.rast new file mode 100644 index 000000000000..e8d8ff8cefb4 --- /dev/null +++ b/crates/parser/test_data/lexer/err/byte_strings.rast @@ -0,0 +1,28 @@ +BYTE_STRING "b\"\\💩\"" error: unknown byte escape +WHITESPACE "\n" +BYTE_STRING "b\"\\●\"" error: unknown byte escape +WHITESPACE "\n" +BYTE_STRING "b\"\\u{_0000}\"" error: invalid start of unicode escape +WHITESPACE "\n" +BYTE_STRING "b\"\\u{0000000}\"" error: overlong unicode escape +WHITESPACE "\n" +BYTE_STRING "b\"\\u{FFFFFF}\"" error: unicode escape in byte string +WHITESPACE "\n" +BYTE_STRING "b\"\\u{ffffff}\"" error: unicode escape in byte string +WHITESPACE "\n" +BYTE_STRING "b\"\\u{ffffff}\"" error: unicode escape in byte string +WHITESPACE "\n" +BYTE_STRING "b\"\\u{DC00}\"" error: unicode escape in byte string +WHITESPACE "\n" +BYTE_STRING "b\"\\u{DDDD}\"" error: unicode escape in byte string +WHITESPACE "\n" +BYTE_STRING "b\"\\u{DFFF}\"" error: unicode escape in byte string +WHITESPACE "\n" +BYTE_STRING "b\"\\u{D800}\"" error: unicode escape in byte string +WHITESPACE "\n" +BYTE_STRING "b\"\\u{DAAA}\"" error: unicode escape in byte string +WHITESPACE "\n" +BYTE_STRING "b\"\\u{DBFF}\"" error: unicode escape in byte string +WHITESPACE "\n" +BYTE_STRING "b\"\\xы\"" error: invalid character in numeric character escape +WHITESPACE "\n" diff --git a/crates/parser/test_data/lexer/err/byte_strings.rs b/crates/parser/test_data/lexer/err/byte_strings.rs new file mode 100644 index 000000000000..e74847137b1e --- /dev/null +++ b/crates/parser/test_data/lexer/err/byte_strings.rs @@ -0,0 +1,14 @@ +b"\💩" +b"\●" +b"\u{_0000}" +b"\u{0000000}" +b"\u{FFFFFF}" +b"\u{ffffff}" +b"\u{ffffff}" +b"\u{DC00}" +b"\u{DDDD}" +b"\u{DFFF}" +b"\u{D800}" +b"\u{DAAA}" +b"\u{DBFF}" +b"\xы" diff --git a/crates/parser/test_data/lexer/err/c_strings.rast b/crates/parser/test_data/lexer/err/c_strings.rast new file mode 100644 index 000000000000..1b4424ba5c78 --- /dev/null +++ b/crates/parser/test_data/lexer/err/c_strings.rast @@ -0,0 +1,28 @@ +C_STRING "c\"\\💩\"" error: unknown character escape +WHITESPACE "\n" +C_STRING "c\"\\●\"" error: unknown character escape +WHITESPACE "\n" +C_STRING "c\"\\u{_0000}\"" error: invalid start of unicode escape +WHITESPACE "\n" +C_STRING "c\"\\u{0000000}\"" error: overlong unicode escape +WHITESPACE "\n" +C_STRING "c\"\\u{FFFFFF}\"" error: invalid unicode character escape +WHITESPACE "\n" +C_STRING "c\"\\u{ffffff}\"" error: invalid unicode character escape +WHITESPACE "\n" +C_STRING "c\"\\u{ffffff}\"" error: invalid unicode character escape +WHITESPACE "\n" +C_STRING "c\"\\u{DC00}\"" error: invalid unicode character escape +WHITESPACE "\n" +C_STRING "c\"\\u{DDDD}\"" error: invalid unicode character escape +WHITESPACE "\n" +C_STRING "c\"\\u{DFFF}\"" error: invalid unicode character escape +WHITESPACE "\n" +C_STRING "c\"\\u{D800}\"" error: invalid unicode character escape +WHITESPACE "\n" +C_STRING "c\"\\u{DAAA}\"" error: invalid unicode character escape +WHITESPACE "\n" +C_STRING "c\"\\u{DBFF}\"" error: invalid unicode character escape +WHITESPACE "\n" +C_STRING "c\"\\xы\"" error: invalid character in numeric character escape +WHITESPACE "\n" diff --git a/crates/parser/test_data/lexer/err/c_strings.rs b/crates/parser/test_data/lexer/err/c_strings.rs new file mode 100644 index 000000000000..1b78ffc28a00 --- /dev/null +++ b/crates/parser/test_data/lexer/err/c_strings.rs @@ -0,0 +1,14 @@ +c"\💩" +c"\●" +c"\u{_0000}" +c"\u{0000000}" +c"\u{FFFFFF}" +c"\u{ffffff}" +c"\u{ffffff}" +c"\u{DC00}" +c"\u{DDDD}" +c"\u{DFFF}" +c"\u{D800}" +c"\u{DAAA}" +c"\u{DBFF}" +c"\xы" diff --git a/crates/parser/test_data/lexer/err/strings.rast b/crates/parser/test_data/lexer/err/strings.rast new file mode 100644 index 000000000000..0cd1747208e4 --- /dev/null +++ b/crates/parser/test_data/lexer/err/strings.rast @@ -0,0 +1,28 @@ +STRING "\"\\💩\"" error: unknown character escape +WHITESPACE "\n" +STRING "\"\\●\"" error: unknown character escape +WHITESPACE "\n" +STRING "\"\\u{_0000}\"" error: invalid start of unicode escape +WHITESPACE "\n" +STRING "\"\\u{0000000}\"" error: overlong unicode escape +WHITESPACE "\n" +STRING "\"\\u{FFFFFF}\"" error: invalid unicode character escape +WHITESPACE "\n" +STRING "\"\\u{ffffff}\"" error: invalid unicode character escape +WHITESPACE "\n" +STRING "\"\\u{ffffff}\"" error: invalid unicode character escape +WHITESPACE "\n" +STRING "\"\\u{DC00}\"" error: invalid unicode character escape +WHITESPACE "\n" +STRING "\"\\u{DDDD}\"" error: invalid unicode character escape +WHITESPACE "\n" +STRING "\"\\u{DFFF}\"" error: invalid unicode character escape +WHITESPACE "\n" +STRING "\"\\u{D800}\"" error: invalid unicode character escape +WHITESPACE "\n" +STRING "\"\\u{DAAA}\"" error: invalid unicode character escape +WHITESPACE "\n" +STRING "\"\\u{DBFF}\"" error: invalid unicode character escape +WHITESPACE "\n" +STRING "\"\\xы\"" error: invalid character in numeric character escape +WHITESPACE "\n" diff --git a/crates/parser/test_data/lexer/err/strings.rs b/crates/parser/test_data/lexer/err/strings.rs new file mode 100644 index 000000000000..2499516d3fa9 --- /dev/null +++ b/crates/parser/test_data/lexer/err/strings.rs @@ -0,0 +1,14 @@ +"\💩" +"\●" +"\u{_0000}" +"\u{0000000}" +"\u{FFFFFF}" +"\u{ffffff}" +"\u{ffffff}" +"\u{DC00}" +"\u{DDDD}" +"\u{DFFF}" +"\u{D800}" +"\u{DAAA}" +"\u{DBFF}" +"\xы" From 2e713a7a2f33a1ded183036f71c6242ae814f783 Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Wed, 11 Oct 2023 15:45:16 +0200 Subject: [PATCH 124/435] docs: Add Zed to IDE list. --- docs/user/manual.adoc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/user/manual.adoc b/docs/user/manual.adoc index 5dafd1a4c8c9..f5a1cec814c6 100644 --- a/docs/user/manual.adoc +++ b/docs/user/manual.adoc @@ -555,6 +555,11 @@ There is a package named `ra_ap_rust_analyzer` available on https://crates.io/cr For more details, see https://github.com/rust-lang/rust-analyzer/blob/master/.github/workflows/publish.yml[the publish workflow]. +=== Zed + +https://zed.dev[Zed] has native `rust-analyzer` support. +If the LSP binary is not available, Zed can install it when opening a Rust file. + == Troubleshooting Start with looking at the rust-analyzer version. From b769f34f6371b13f7ce81cefe65579911331eb16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pol=20Valletb=C3=B3?= Date: Wed, 11 Oct 2023 15:45:45 +0200 Subject: [PATCH 125/435] chore: move common code to function --- crates/parser/src/lexed_str.rs | 46 ++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/crates/parser/src/lexed_str.rs b/crates/parser/src/lexed_str.rs index c2e25daf37f6..4d322f21ae70 100644 --- a/crates/parser/src/lexed_str.rs +++ b/crates/parser/src/lexed_str.rs @@ -291,11 +291,7 @@ impl<'a> Converter<'a> { let text = &self.res.text[self.offset + 1..][..len - 1]; let i = text.rfind('"').unwrap(); let text = &text[..i]; - rustc_lexer::unescape::unescape_literal(text, Mode::Str, &mut |_, res| { - if let Err(e) = res { - err = error_to_diagnostic_message(e, Mode::Str); - } - }); + err = unescape_string_error_message(text, Mode::Str); } STRING } @@ -306,11 +302,7 @@ impl<'a> Converter<'a> { let text = &self.res.text[self.offset + 2..][..len - 2]; let i = text.rfind('"').unwrap(); let text = &text[..i]; - rustc_lexer::unescape::unescape_literal(text, Mode::ByteStr, &mut |_, res| { - if let Err(e) = res { - err = error_to_diagnostic_message(e, Mode::ByteStr); - } - }) + err = unescape_string_error_message(text, Mode::ByteStr); } BYTE_STRING } @@ -321,11 +313,7 @@ impl<'a> Converter<'a> { let text = &self.res.text[self.offset + 2..][..len - 2]; let i = text.rfind('"').unwrap(); let text = &text[..i]; - rustc_lexer::unescape::unescape_c_string(text, Mode::CStr, &mut |_, res| { - if let Err(e) = res { - err = error_to_diagnostic_message(e, Mode::CStr); - } - }) + err = unescape_string_error_message(text, Mode::CStr); } C_STRING } @@ -391,12 +379,26 @@ fn error_to_diagnostic_message(error: EscapeError, mode: Mode) -> &'static str { } } -fn fill_unescape_string_error(text: &str, mode: Mode, mut error_message: &str) { - - rustc_lexer::unescape::unescape_c_string(text, mode, &mut |_, res| { - if let Err(e) = res { - error_message = error_to_diagnostic_message(e, mode); +fn unescape_string_error_message(text: &str, mode: Mode) -> &'static str { + let mut error_message = ""; + match mode { + Mode::CStr => { + rustc_lexer::unescape::unescape_c_string(text, mode, &mut |_, res| { + if let Err(e) = res { + error_message = error_to_diagnostic_message(e, mode); + } + }); } - }); + Mode::ByteStr | Mode::Str => { + rustc_lexer::unescape::unescape_literal(text, mode, &mut |_, res| { + if let Err(e) = res { + error_message = error_to_diagnostic_message(e, mode); + } + }); + } + _ => { + // Other Modes are not supported yet or do not apply + } + } + error_message } - From 4b281ffdf2c0315722729ec090f74c0d49feca1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pol=20Valletb=C3=B3?= Date: Wed, 11 Oct 2023 15:52:05 +0200 Subject: [PATCH 126/435] chore: format imports --- crates/parser/src/lexed_str.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/crates/parser/src/lexed_str.rs b/crates/parser/src/lexed_str.rs index 4d322f21ae70..13189b8bd003 100644 --- a/crates/parser/src/lexed_str.rs +++ b/crates/parser/src/lexed_str.rs @@ -7,11 +7,9 @@ //! //! Note that these tokens, unlike the tokens we feed into the parser, do //! include info about comments and whitespace. +// -use rustc_dependencies::lexer::{ - self as rustc_lexer, - unescape::{unescape_c_string, unescape_literal}, -}; +use rustc_dependencies::lexer as rustc_lexer; use std::ops; From 6845c80a2fd52e2d8c58bda0e55c39c4bb836ad1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pol=20Valletb=C3=B3?= Date: Wed, 11 Oct 2023 15:52:22 +0200 Subject: [PATCH 127/435] fix: format --- crates/parser/src/lexed_str.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/parser/src/lexed_str.rs b/crates/parser/src/lexed_str.rs index 13189b8bd003..b9e7566fdf9b 100644 --- a/crates/parser/src/lexed_str.rs +++ b/crates/parser/src/lexed_str.rs @@ -7,7 +7,6 @@ //! //! Note that these tokens, unlike the tokens we feed into the parser, do //! include info about comments and whitespace. -// use rustc_dependencies::lexer as rustc_lexer; From 3605bb38ff7ecb1b0c9cde25a1c1d9938ac3bb51 Mon Sep 17 00:00:00 2001 From: Young-Flash <871946895@qq.com> Date: Thu, 12 Oct 2023 11:50:44 +0800 Subject: [PATCH 128/435] fix CI: generate doctest --- .../replace_is_some_with_if_let_some.rs | 6 +++--- crates/ide-assists/src/tests/generated.rs | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/crates/ide-assists/src/handlers/replace_is_some_with_if_let_some.rs b/crates/ide-assists/src/handlers/replace_is_some_with_if_let_some.rs index dfc2a8715003..70892fe27025 100644 --- a/crates/ide-assists/src/handlers/replace_is_some_with_if_let_some.rs +++ b/crates/ide-assists/src/handlers/replace_is_some_with_if_let_some.rs @@ -2,7 +2,7 @@ use syntax::ast::{self, AstNode}; use crate::{AssistContext, AssistId, AssistKind, Assists}; -// Assist: replace_is_some_with_if_let +// Assist: replace_is_some_with_if_let_some // // Replace `if x.is_some()` with `if let Some(_tmp) = x`. // @@ -57,7 +57,7 @@ mod tests { use super::replace_is_some_with_if_let_some; #[test] - fn replace_is_some_with_if_let_works() { + fn replace_is_some_with_if_let_some_works() { check_assist( replace_is_some_with_if_let_some, r#" @@ -76,7 +76,7 @@ fn main() { } #[test] - fn replace_is_some_with_if_let_not_applicable() { + fn replace_is_some_with_if_let_some_not_applicable() { check_assist_not_applicable( replace_is_some_with_if_let_some, r#" diff --git a/crates/ide-assists/src/tests/generated.rs b/crates/ide-assists/src/tests/generated.rs index 18f7591cf082..d2b801336a55 100644 --- a/crates/ide-assists/src/tests/generated.rs +++ b/crates/ide-assists/src/tests/generated.rs @@ -2558,6 +2558,25 @@ fn handle(action: Action) { ) } +#[test] +fn doctest_replace_is_some_with_if_let_some() { + check_doc_test( + "replace_is_some_with_if_let_some", + r#####" +fn main() { + let x = Some(1); + if x.is_som$0e() {} +} +"#####, + r#####" +fn main() { + let x = Some(1); + if let Some(_tmp) = x {} +} +"#####, + ) +} + #[test] fn doctest_replace_let_with_if_let() { check_doc_test( From 506b1e515b7c9f834d9fd2523f57f9a3221af42f Mon Sep 17 00:00:00 2001 From: Young-Flash <871946895@qq.com> Date: Thu, 12 Oct 2023 23:26:42 +0800 Subject: [PATCH 129/435] feat: add replace_is_ok_with_if_let_ok assist --- .../replace_is_method_with_if_let_method.rs | 124 ++++++++++++++++++ .../replace_is_some_with_if_let_some.rs | 90 ------------- crates/ide-assists/src/lib.rs | 4 +- 3 files changed, 126 insertions(+), 92 deletions(-) create mode 100644 crates/ide-assists/src/handlers/replace_is_method_with_if_let_method.rs delete mode 100644 crates/ide-assists/src/handlers/replace_is_some_with_if_let_some.rs diff --git a/crates/ide-assists/src/handlers/replace_is_method_with_if_let_method.rs b/crates/ide-assists/src/handlers/replace_is_method_with_if_let_method.rs new file mode 100644 index 000000000000..b897ddc24578 --- /dev/null +++ b/crates/ide-assists/src/handlers/replace_is_method_with_if_let_method.rs @@ -0,0 +1,124 @@ +use syntax::ast::{self, AstNode}; + +use crate::{AssistContext, AssistId, AssistKind, Assists}; + +// Assist: replace_is_some_with_if_let_some +// +// Replace `if x.is_some()` with `if let Some(_tmp) = x` or `if x.is_ok()` with `if let Ok(_tmp) = x`. +// +// ``` +// fn main() { +// let x = Some(1); +// if x.is_som$0e() {} +// } +// ``` +// -> +// ``` +// fn main() { +// let x = Some(1); +// if let Some(_tmp) = x {} +// } +// ``` +pub(crate) fn replace_is_method_with_if_let_method( + acc: &mut Assists, + ctx: &AssistContext<'_>, +) -> Option<()> { + let if_expr = ctx.find_node_at_offset::()?; + + let cond = if_expr.condition()?; + let call_expr = match cond { + ast::Expr::MethodCallExpr(call) => call, + _ => return None, + }; + + let name_ref = call_expr.name_ref()?; + match name_ref.text().as_str() { + "is_some" | "is_ok" => { + let receiver = call_expr.receiver()?; + let target = call_expr.syntax().text_range(); + + let (assist_id, message, text) = if name_ref.text() == "is_some" { + ("replace_is_some_with_if_let_some", "Replace `is_some` with `if let Some`", "Some") + } else { + ("replace_is_ok_with_if_let_ok", "Replace `is_ok` with `if let Ok`", "Ok") + }; + + acc.add(AssistId(assist_id, AssistKind::RefactorRewrite), message, target, |edit| { + let replacement = format!("let {}(_tmp) = {}", text, receiver); + edit.replace(target, replacement); + }) + } + _ => return None, + } +} + +#[cfg(test)] +mod tests { + use crate::tests::{check_assist, check_assist_not_applicable}; + + use super::replace_is_method_with_if_let_method; + + #[test] + fn replace_is_some_with_if_let_some_works() { + check_assist( + replace_is_method_with_if_let_method, + r#" +fn main() { + let x = Some(1); + if x.is_som$0e() {} +} +"#, + r#" +fn main() { + let x = Some(1); + if let Some(_tmp) = x {} +} +"#, + ); + } + + #[test] + fn replace_is_some_with_if_let_some_not_applicable() { + check_assist_not_applicable( + replace_is_method_with_if_let_method, + r#" +fn main() { + let x = Some(1); + if x.is_non$0e() {} +} +"#, + ); + } + + #[test] + fn replace_is_ok_with_if_let_ok_works() { + check_assist( + replace_is_method_with_if_let_method, + r#" +fn main() { + let x = Ok(1); + if x.is_o$0k() {} +} +"#, + r#" +fn main() { + let x = Ok(1); + if let Ok(_tmp) = x {} +} +"#, + ); + } + + #[test] + fn replace_is_ok_with_if_let_ok_not_applicable() { + check_assist_not_applicable( + replace_is_method_with_if_let_method, + r#" +fn main() { + let x = Ok(1); + if x.is_e$0rr() {} +} +"#, + ); + } +} diff --git a/crates/ide-assists/src/handlers/replace_is_some_with_if_let_some.rs b/crates/ide-assists/src/handlers/replace_is_some_with_if_let_some.rs deleted file mode 100644 index 70892fe27025..000000000000 --- a/crates/ide-assists/src/handlers/replace_is_some_with_if_let_some.rs +++ /dev/null @@ -1,90 +0,0 @@ -use syntax::ast::{self, AstNode}; - -use crate::{AssistContext, AssistId, AssistKind, Assists}; - -// Assist: replace_is_some_with_if_let_some -// -// Replace `if x.is_some()` with `if let Some(_tmp) = x`. -// -// ``` -// fn main() { -// let x = Some(1); -// if x.is_som$0e() {} -// } -// ``` -// -> -// ``` -// fn main() { -// let x = Some(1); -// if let Some(_tmp) = x {} -// } -// ``` -pub(crate) fn replace_is_some_with_if_let_some( - acc: &mut Assists, - ctx: &AssistContext<'_>, -) -> Option<()> { - let if_expr = ctx.find_node_at_offset::()?; - - let cond = if_expr.condition()?; - let call_expr = match cond { - ast::Expr::MethodCallExpr(call) => call, - _ => return None, - }; - - let name_ref = call_expr.name_ref()?; - if name_ref.text() != "is_some" { - return None; - } - - let receiver = call_expr.receiver()?; - let target = call_expr.syntax().text_range(); - - acc.add( - AssistId("replace_is_some_with_if_let_some", AssistKind::RefactorRewrite), - "Replace `is_some` with `if let Some`", - target, - |edit| { - let replacement = format!("let Some(_tmp) = {}", receiver); - edit.replace(target, replacement); - }, - ) -} - -#[cfg(test)] -mod tests { - use crate::tests::{check_assist, check_assist_not_applicable}; - - use super::replace_is_some_with_if_let_some; - - #[test] - fn replace_is_some_with_if_let_some_works() { - check_assist( - replace_is_some_with_if_let_some, - r#" -fn main() { - let x = Some(1); - if x.is_som$0e() {} -} -"#, - r#" -fn main() { - let x = Some(1); - if let Some(_tmp) = x {} -} -"#, - ); - } - - #[test] - fn replace_is_some_with_if_let_some_not_applicable() { - check_assist_not_applicable( - replace_is_some_with_if_let_some, - r#" -fn main() { - let x = Some(1); - if x.is_non$0e() {} -} -"#, - ); - } -} diff --git a/crates/ide-assists/src/lib.rs b/crates/ide-assists/src/lib.rs index d6accbb097ee..a8adedc1273b 100644 --- a/crates/ide-assists/src/lib.rs +++ b/crates/ide-assists/src/lib.rs @@ -213,7 +213,7 @@ mod handlers { mod unwrap_block; mod unwrap_result_return_type; mod unqualify_method_call; - mod replace_is_some_with_if_let_some; + mod replace_is_method_with_if_let_method; mod wrap_return_type_in_result; mod into_to_qualified_from; @@ -333,7 +333,7 @@ mod handlers { unwrap_result_return_type::unwrap_result_return_type, unwrap_tuple::unwrap_tuple, unqualify_method_call::unqualify_method_call, - replace_is_some_with_if_let_some::replace_is_some_with_if_let_some, + replace_is_method_with_if_let_method::replace_is_method_with_if_let_method, wrap_return_type_in_result::wrap_return_type_in_result, // These are manually sorted for better priorities. By default, // priority is determined by the size of the target range (smaller From 5bbca22720508798d4eda888d8c91f58d29e1f34 Mon Sep 17 00:00:00 2001 From: Young-Flash <871946895@qq.com> Date: Fri, 13 Oct 2023 00:09:13 +0800 Subject: [PATCH 130/435] update mod order to adapt alphabetically sorted --- crates/ide-assists/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/ide-assists/src/lib.rs b/crates/ide-assists/src/lib.rs index a8adedc1273b..d2b291631c8a 100644 --- a/crates/ide-assists/src/lib.rs +++ b/crates/ide-assists/src/lib.rs @@ -195,6 +195,7 @@ mod handlers { mod replace_try_expr_with_match; mod replace_derive_with_manual_impl; mod replace_if_let_with_match; + mod replace_is_method_with_if_let_method; mod replace_method_eager_lazy; mod replace_arith_op; mod introduce_named_generic; @@ -213,7 +214,6 @@ mod handlers { mod unwrap_block; mod unwrap_result_return_type; mod unqualify_method_call; - mod replace_is_method_with_if_let_method; mod wrap_return_type_in_result; mod into_to_qualified_from; @@ -314,6 +314,7 @@ mod handlers { replace_derive_with_manual_impl::replace_derive_with_manual_impl, replace_if_let_with_match::replace_if_let_with_match, replace_if_let_with_match::replace_match_with_if_let, + replace_is_method_with_if_let_method::replace_is_method_with_if_let_method, replace_let_with_if_let::replace_let_with_if_let, replace_method_eager_lazy::replace_with_eager_method, replace_method_eager_lazy::replace_with_lazy_method, @@ -333,7 +334,6 @@ mod handlers { unwrap_result_return_type::unwrap_result_return_type, unwrap_tuple::unwrap_tuple, unqualify_method_call::unqualify_method_call, - replace_is_method_with_if_let_method::replace_is_method_with_if_let_method, wrap_return_type_in_result::wrap_return_type_in_result, // These are manually sorted for better priorities. By default, // priority is determined by the size of the target range (smaller From bc34e8f1ad252aeda6064708abe3af944b6faf5d Mon Sep 17 00:00:00 2001 From: Young-Flash <871946895@qq.com> Date: Sat, 14 Oct 2023 11:05:38 +0800 Subject: [PATCH 131/435] feat: make cursor select at _tmp --- .../src/handlers/replace_is_method_with_if_let_method.rs | 8 ++++---- crates/ide-assists/src/tests/generated.rs | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/ide-assists/src/handlers/replace_is_method_with_if_let_method.rs b/crates/ide-assists/src/handlers/replace_is_method_with_if_let_method.rs index b897ddc24578..e5b4c33eb34f 100644 --- a/crates/ide-assists/src/handlers/replace_is_method_with_if_let_method.rs +++ b/crates/ide-assists/src/handlers/replace_is_method_with_if_let_method.rs @@ -16,7 +16,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists}; // ``` // fn main() { // let x = Some(1); -// if let Some(_tmp) = x {} +// if let Some(${0:_tmp}) = x {} // } // ``` pub(crate) fn replace_is_method_with_if_let_method( @@ -44,7 +44,7 @@ pub(crate) fn replace_is_method_with_if_let_method( }; acc.add(AssistId(assist_id, AssistKind::RefactorRewrite), message, target, |edit| { - let replacement = format!("let {}(_tmp) = {}", text, receiver); + let replacement = format!("let {}({}) = {}", text, "${0:_tmp}", receiver); edit.replace(target, replacement); }) } @@ -71,7 +71,7 @@ fn main() { r#" fn main() { let x = Some(1); - if let Some(_tmp) = x {} + if let Some(${0:_tmp}) = x {} } "#, ); @@ -103,7 +103,7 @@ fn main() { r#" fn main() { let x = Ok(1); - if let Ok(_tmp) = x {} + if let Ok(${0:_tmp}) = x {} } "#, ); diff --git a/crates/ide-assists/src/tests/generated.rs b/crates/ide-assists/src/tests/generated.rs index d2b801336a55..6b4a97440877 100644 --- a/crates/ide-assists/src/tests/generated.rs +++ b/crates/ide-assists/src/tests/generated.rs @@ -2571,7 +2571,7 @@ fn main() { r#####" fn main() { let x = Some(1); - if let Some(_tmp) = x {} + if let Some(${0:_tmp}) = x {} } "#####, ) From 3f4368a090157d631cd3715baa60e823d679f07d Mon Sep 17 00:00:00 2001 From: harpsword Date: Sat, 14 Oct 2023 11:28:23 +0800 Subject: [PATCH 132/435] fix: fix typo in mbe/lib.rs comment --- crates/mbe/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/mbe/src/lib.rs b/crates/mbe/src/lib.rs index 9d886a1c979a..a439c9c50d6c 100644 --- a/crates/mbe/src/lib.rs +++ b/crates/mbe/src/lib.rs @@ -3,7 +3,7 @@ //! interface, although it contains some code to bridge `SyntaxNode`s and //! `TokenTree`s as well! //! -//! The tes for this functionality live in another crate: +//! The tests for this functionality live in another crate: //! `hir_def::macro_expansion_tests::mbe`. #![warn(rust_2018_idioms, unused_lifetimes, semicolon_in_expressions_from_macros)] From 8217ff9c1651201645316877694a7a58d2fd469d Mon Sep 17 00:00:00 2001 From: Christian Schott <56631269+ChristianSchott@users.noreply.github.com> Date: Sat, 14 Oct 2023 19:20:11 +0200 Subject: [PATCH 133/435] make ProjectionStore-impls pub-accessible --- crates/hir-ty/src/mir.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/hir-ty/src/mir.rs b/crates/hir-ty/src/mir.rs index 797f4c1248d6..747ca54858c8 100644 --- a/crates/hir-ty/src/mir.rs +++ b/crates/hir-ty/src/mir.rs @@ -243,16 +243,16 @@ impl Default for ProjectionStore { } impl ProjectionStore { - fn shrink_to_fit(&mut self) { + pub fn shrink_to_fit(&mut self) { self.id_to_proj.shrink_to_fit(); self.proj_to_id.shrink_to_fit(); } - fn intern_if_exist(&self, projection: &[PlaceElem]) -> Option { + pub fn intern_if_exist(&self, projection: &[PlaceElem]) -> Option { self.proj_to_id.get(projection).copied() } - fn intern(&mut self, projection: Box<[PlaceElem]>) -> ProjectionId { + pub fn intern(&mut self, projection: Box<[PlaceElem]>) -> ProjectionId { let new_id = ProjectionId(self.proj_to_id.len() as u32); match self.proj_to_id.entry(projection) { Entry::Occupied(id) => *id.get(), @@ -267,13 +267,13 @@ impl ProjectionStore { } impl ProjectionId { - const EMPTY: ProjectionId = ProjectionId(0); + pub const EMPTY: ProjectionId = ProjectionId(0); - fn lookup(self, store: &ProjectionStore) -> &[PlaceElem] { + pub fn lookup(self, store: &ProjectionStore) -> &[PlaceElem] { store.id_to_proj.get(&self).unwrap() } - fn project(self, projection: PlaceElem, store: &mut ProjectionStore) -> ProjectionId { + pub fn project(self, projection: PlaceElem, store: &mut ProjectionStore) -> ProjectionId { let mut current = self.lookup(store).to_vec(); current.push(projection); store.intern(current.into()) From d33fd15ecfe385b8fdd787c813074f9aa451ef37 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sun, 15 Oct 2023 17:58:50 +0200 Subject: [PATCH 134/435] Fix metrics workflow to use deploy key --- .github/workflows/metrics.yaml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/metrics.yaml b/.github/workflows/metrics.yaml index bbeccd1621df..91615f1b79fb 100644 --- a/.github/workflows/metrics.yaml +++ b/.github/workflows/metrics.yaml @@ -140,11 +140,12 @@ jobs: - name: Combine json run: | - git clone --depth 1 https://$METRICS_TOKEN@github.com/rust-analyzer/metrics.git + echo "${{ secrets.METRICS_DEPLOY_KEY }}" > ~/.ssh/id_ed25519 + chmod 600 ~/.ssh/id_ed25519 + + git clone --depth 1 git@github.com/rust-analyzer/metrics.git jq -s ".[0] * .[1] * .[2] * .[3] * .[4] * .[5]" build.json self.json ripgrep-13.0.0.json webrender-2022.json diesel-1.4.8.json hyper-0.14.18.json -c >> metrics/metrics.json cd metrics git add . git -c user.name=Bot -c user.email=dummy@example.com commit --message 📈 git push origin master - env: - METRICS_TOKEN: ${{ secrets.METRICS_TOKEN }} From 2b858b7eb83e02baac4bb5b5b63407c2456668cc Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Tue, 29 Aug 2023 12:47:42 +0200 Subject: [PATCH 135/435] Format macro const literals with pretty printer --- compiler/rustc_metadata/src/lib.rs | 1 + compiler/rustc_metadata/src/rmeta/encoder.rs | 31 +++++++------- .../issue-115295-macro-const-display.rs | 40 +++++++++++++++++++ 3 files changed, 57 insertions(+), 15 deletions(-) create mode 100644 tests/rustdoc/issue-115295-macro-const-display.rs diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs index ddeb39669dc7..1b897c3652d8 100644 --- a/compiler/rustc_metadata/src/lib.rs +++ b/compiler/rustc_metadata/src/lib.rs @@ -7,6 +7,7 @@ #![feature(generators)] #![feature(iter_from_generator)] #![feature(let_chains)] +#![feature(if_let_guard)] #![feature(proc_macro_internals)] #![feature(macro_metavar_expr)] #![feature(min_specialization)] diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index dee2326ae327..b0ab74afa355 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -2375,31 +2375,32 @@ pub fn rendered_const<'tcx>(tcx: TyCtxt<'tcx>, body: hir::BodyId) -> String { } } - let classification = classify(value); - - if classification == Literal - && !value.span.from_expansion() - && let Ok(snippet) = tcx.sess.source_map().span_to_snippet(value.span) - { - // For literals, we avoid invoking the pretty-printer and use the source snippet instead to - // preserve certain stylistic choices the user likely made for the sake legibility like + match classify(value) { + // For non-macro literals, we avoid invoking the pretty-printer and use the source snippet + // instead to preserve certain stylistic choices the user likely made for the sake of + // legibility, like: // // * hexadecimal notation // * underscores // * character escapes // // FIXME: This passes through `-/*spacer*/0` verbatim. - snippet - } else if classification == Simple { + Literal if !value.span.from_expansion() + && let Ok(snippet) = tcx.sess.source_map().span_to_snippet(value.span) => { + snippet + } + // Otherwise we prefer pretty-printing to get rid of extraneous whitespace, comments and // other formatting artifacts. - id_to_string(&hir, body.hir_id) - } else if tcx.def_kind(hir.body_owner_def_id(body).to_def_id()) == DefKind::AnonConst { + Literal | Simple => id_to_string(&hir, body.hir_id), + // FIXME: Omit the curly braces if the enclosing expression is an array literal // with a repeated element (an `ExprKind::Repeat`) as in such case it // would not actually need any disambiguation. - "{ _ }".to_owned() - } else { - "_".to_owned() + Complex => if tcx.def_kind(hir.body_owner_def_id(body).to_def_id()) == DefKind::AnonConst { + "{ _ }".to_owned() + } else { + "_".to_owned() + } } } diff --git a/tests/rustdoc/issue-115295-macro-const-display.rs b/tests/rustdoc/issue-115295-macro-const-display.rs new file mode 100644 index 000000000000..2916c7a84a1f --- /dev/null +++ b/tests/rustdoc/issue-115295-macro-const-display.rs @@ -0,0 +1,40 @@ +#![crate_name = "foo"] + +// @has foo/trait.Trait.html +pub trait Trait {} + +// @has foo/struct.WithConst.html +pub struct WithConst; + +macro_rules! spans_from_macro { + () => { + impl WithConst<42> { + pub fn new() -> Self { + Self + } + } + impl Trait> for WithConst<42> {} + impl Trait> for WithConst<{ 43 }> {} + impl Trait> for WithConst<44> {} + pub struct Other { + pub field: WithConst<42>, + } + }; +} + +// @has - '//*[@class="impl"]//h3[@class="code-header"]' \ +// "impl Trait> for WithConst<41>" +impl Trait> for WithConst<41> {} + +// @has - '//*[@class="impl"]//h3[@class="code-header"]' \ +// "impl WithConst<42>" +// @has - '//*[@class="impl"]//h3[@class="code-header"]' \ +// "impl Trait> for WithConst<42>" +// @has - '//*[@class="impl"]//h3[@class="code-header"]' \ +// "impl Trait> for WithConst<{ 43 }>" +// @has - '//*[@class="impl"]//h3[@class="code-header"]' \ +// "impl Trait> for WithConst<44>" + +// @has foo/struct.Other.html +// @has - //pre "pub field: WithConst<42>" +spans_from_macro!(); From 40acc5250f2d3cb146b8abe12933402b107895cb Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 29 Sep 2023 20:42:26 +0200 Subject: [PATCH 136/435] Update rustc_abi dependency --- Cargo.lock | 50 +++++++----------- crates/hir-def/src/data/adt.rs | 2 +- crates/hir-ty/src/layout.rs | 78 ++++++++++++++++++---------- crates/hir-ty/src/layout/adt.rs | 9 ++-- crates/hir/src/lib.rs | 24 +++++++-- crates/ide/src/hover/render.rs | 3 +- crates/ide/src/view_memory_layout.rs | 18 +++---- crates/rustc-dependencies/Cargo.toml | 10 ++-- crates/rustc-dependencies/src/lib.rs | 39 ++++++++------ 9 files changed, 135 insertions(+), 98 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 476c0475ce43..2a56bddb76ca 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -608,27 +608,6 @@ dependencies = [ "typed-arena", ] -[[package]] -name = "hkalbasi-rustc-ap-rustc_abi" -version = "0.0.20221221" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adabaadad9aa7576f97af02241cdf5554d62fb3d51a84cb05d77ba28edd3013f" -dependencies = [ - "bitflags 1.3.2", - "hkalbasi-rustc-ap-rustc_index", - "tracing", -] - -[[package]] -name = "hkalbasi-rustc-ap-rustc_index" -version = "0.0.20221221" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4d3c48474e09afb0f5efbd6f758e05411699301a113c47d454d28ec7059d00e" -dependencies = [ - "arrayvec", - "smallvec", -] - [[package]] name = "home" version = "0.5.5" @@ -1474,10 +1453,21 @@ dependencies = [ ] [[package]] -name = "ra-ap-rustc_index" -version = "0.10.0" +name = "ra-ap-rustc_abi" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07b5fa61d34da18e148dc3a81f654488ea07f40938d8aefb17f8b64bb78c6120" +checksum = "a51b7a02377b3246ec5c095b852b5cf1678bd9ed6b572b2a79efbf7ad711c292" +dependencies = [ + "bitflags 1.3.2", + "ra-ap-rustc_index", + "tracing", +] + +[[package]] +name = "ra-ap-rustc_index" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "643ca3609870b1778d9cd1f2a8e4ccb4af0f48f3637cc257a09494d087bd93dc" dependencies = [ "arrayvec", "smallvec", @@ -1485,9 +1475,9 @@ dependencies = [ [[package]] name = "ra-ap-rustc_lexer" -version = "0.10.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2e2f6b48422e4eed5218277ab7cc9733e60dd8f3167f4f36a49a0cafe4dc195" +checksum = "30ffd24f9ba4f1d25ff27ca1469b8d22a3bdfb12cf644fc8bfcb63121fa5da6b" dependencies = [ "unicode-properties", "unicode-xid", @@ -1495,9 +1485,9 @@ dependencies = [ [[package]] name = "ra-ap-rustc_parse_format" -version = "0.10.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3c7369ad01cc79f9e3513c9f6a6326f6b980100e4862a7ac71b9991c88108bb" +checksum = "207b5ac1a21d4926695e03b605ffb9f63d4968e0488e9197c04c512c37303aa7" dependencies = [ "ra-ap-rustc_index", "ra-ap-rustc_lexer", @@ -1623,8 +1613,8 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" name = "rustc-dependencies" version = "0.0.0" dependencies = [ - "hkalbasi-rustc-ap-rustc_abi", - "hkalbasi-rustc-ap-rustc_index", + "ra-ap-rustc_abi", + "ra-ap-rustc_index", "ra-ap-rustc_lexer", "ra-ap-rustc_parse_format", ] diff --git a/crates/hir-def/src/data/adt.rs b/crates/hir-def/src/data/adt.rs index b163112db918..76c8d9a0c367 100644 --- a/crates/hir-def/src/data/adt.rs +++ b/crates/hir-def/src/data/adt.rs @@ -178,7 +178,7 @@ fn parse_repr_tt(tt: &Subtree) -> Option { } } - Some(ReprOptions { int, align: max_align, pack: min_pack, flags, field_shuffle_seed: 0 }) + Some(ReprOptions { int, align: max_align, pack: min_pack, flags }) } impl StructData { diff --git a/crates/hir-ty/src/layout.rs b/crates/hir-ty/src/layout.rs index ee558956a761..603e58f9d462 100644 --- a/crates/hir-ty/src/layout.rs +++ b/crates/hir-ty/src/layout.rs @@ -9,6 +9,10 @@ use hir_def::{ LocalEnumVariantId, LocalFieldId, StructId, }; use la_arena::{Idx, RawIdx}; +use rustc_dependencies::{ + abi::AddressSpace, + index::{IndexSlice, IndexVec}, +}; use stdx::never; use triomphe::Arc; @@ -34,7 +38,7 @@ mod target; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct RustcEnumVariantIdx(pub LocalEnumVariantId); -impl rustc_dependencies::index::vec::Idx for RustcEnumVariantIdx { +impl rustc_dependencies::index::Idx for RustcEnumVariantIdx { fn new(idx: usize) -> Self { RustcEnumVariantIdx(Idx::from_raw(RawIdx::from(idx as u32))) } @@ -44,9 +48,28 @@ impl rustc_dependencies::index::vec::Idx for RustcEnumVariantIdx { } } -pub type Layout = LayoutS; +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct RustcFieldIdx(pub LocalFieldId); + +impl RustcFieldIdx { + pub fn new(idx: usize) -> Self { + RustcFieldIdx(Idx::from_raw(RawIdx::from(idx as u32))) + } +} + +impl rustc_dependencies::index::Idx for RustcFieldIdx { + fn new(idx: usize) -> Self { + RustcFieldIdx(Idx::from_raw(RawIdx::from(idx as u32))) + } + + fn index(self) -> usize { + u32::from(self.0.into_raw()) as usize + } +} + +pub type Layout = LayoutS; pub type TagEncoding = hir_def::layout::TagEncoding; -pub type Variants = hir_def::layout::Variants; +pub type Variants = hir_def::layout::Variants; #[derive(Debug, PartialEq, Eq, Clone)] pub enum LayoutError { @@ -66,7 +89,7 @@ struct LayoutCx<'a> { impl<'a> LayoutCalculator for LayoutCx<'a> { type TargetDataLayoutRef = &'a TargetDataLayout; - fn delay_bug(&self, txt: &str) { + fn delay_bug(&self, txt: String) { never!("{}", txt); } @@ -145,6 +168,8 @@ fn layout_of_simd_ty( largest_niche: e_ly.largest_niche, size, align, + max_repr_align: None, + unadjusted_abi_align: align.abi, })) } @@ -230,7 +255,7 @@ pub fn layout_of_ty_query( .map(|k| db.layout_of_ty(k.assert_ty_ref(Interner).clone(), trait_env.clone())) .collect::, _>>()?; let fields = fields.iter().map(|it| &**it).collect::>(); - let fields = fields.iter().collect::>(); + let fields = fields.iter().collect::>(); cx.univariant(dl, &fields, &ReprOptions::default(), kind).ok_or(LayoutError::Unknown)? } TyKind::Array(element, count) => { @@ -255,6 +280,8 @@ pub fn layout_of_ty_query( largest_niche, align: element.align, size, + max_repr_align: None, + unadjusted_abi_align: element.align.abi, } } TyKind::Slice(element) => { @@ -266,11 +293,23 @@ pub fn layout_of_ty_query( largest_niche: None, align: element.align, size: Size::ZERO, + max_repr_align: None, + unadjusted_abi_align: element.align.abi, } } + TyKind::Str => Layout { + variants: Variants::Single { index: struct_variant_idx() }, + fields: FieldsShape::Array { stride: Size::from_bytes(1), count: 0 }, + abi: Abi::Aggregate { sized: false }, + largest_niche: None, + align: dl.i8_align, + size: Size::ZERO, + max_repr_align: None, + unadjusted_abi_align: dl.i8_align.abi, + }, // Potentially-wide pointers. TyKind::Ref(_, _, pointee) | TyKind::Raw(_, pointee) => { - let mut data_ptr = scalar_unit(dl, Primitive::Pointer); + let mut data_ptr = scalar_unit(dl, Primitive::Pointer(AddressSpace::DATA)); if matches!(ty.kind(Interner), TyKind::Ref(..)) { data_ptr.valid_range_mut().start = 1; } @@ -294,7 +333,7 @@ pub fn layout_of_ty_query( scalar_unit(dl, Primitive::Int(dl.ptr_sized_integer(), false)) } TyKind::Dyn(..) => { - let mut vtable = scalar_unit(dl, Primitive::Pointer); + let mut vtable = scalar_unit(dl, Primitive::Pointer(AddressSpace::DATA)); vtable.valid_range_mut().start = 1; vtable } @@ -308,22 +347,7 @@ pub fn layout_of_ty_query( cx.scalar_pair(data_ptr, metadata) } TyKind::FnDef(_, _) => layout_of_unit(&cx, dl)?, - TyKind::Str => Layout { - variants: Variants::Single { index: struct_variant_idx() }, - fields: FieldsShape::Array { stride: Size::from_bytes(1), count: 0 }, - abi: Abi::Aggregate { sized: false }, - largest_niche: None, - align: dl.i8_align, - size: Size::ZERO, - }, - TyKind::Never => Layout { - variants: Variants::Single { index: struct_variant_idx() }, - fields: FieldsShape::Primitive, - abi: Abi::Uninhabited, - largest_niche: None, - align: dl.i8_align, - size: Size::ZERO, - }, + TyKind::Never => cx.layout_of_never_type(), TyKind::Dyn(_) | TyKind::Foreign(_) => { let mut unit = layout_of_unit(&cx, dl)?; match unit.abi { @@ -333,7 +357,7 @@ pub fn layout_of_ty_query( unit } TyKind::Function(_) => { - let mut ptr = scalar_unit(dl, Primitive::Pointer); + let mut ptr = scalar_unit(dl, Primitive::Pointer(dl.instruction_address_space)); ptr.valid_range_mut().start = 1; Layout::scalar(dl, ptr) } @@ -363,7 +387,7 @@ pub fn layout_of_ty_query( }) .collect::, _>>()?; let fields = fields.iter().map(|it| &**it).collect::>(); - let fields = fields.iter().collect::>(); + let fields = fields.iter().collect::>(); cx.univariant(dl, &fields, &ReprOptions::default(), StructKind::AlwaysSized) .ok_or(LayoutError::Unknown)? } @@ -398,9 +422,9 @@ pub fn layout_of_ty_recover( } fn layout_of_unit(cx: &LayoutCx<'_>, dl: &TargetDataLayout) -> Result { - cx.univariant::( + cx.univariant::( dl, - &[], + IndexSlice::empty(), &ReprOptions::default(), StructKind::AlwaysSized, ) diff --git a/crates/hir-ty/src/layout/adt.rs b/crates/hir-ty/src/layout/adt.rs index c2778b9a8ea0..5e713c17cf81 100644 --- a/crates/hir-ty/src/layout/adt.rs +++ b/crates/hir-ty/src/layout/adt.rs @@ -8,6 +8,7 @@ use hir_def::{ AdtId, EnumVariantId, LocalEnumVariantId, VariantId, }; use la_arena::RawIdx; +use rustc_dependencies::index::IndexVec; use smallvec::SmallVec; use triomphe::Arc; @@ -20,8 +21,8 @@ use crate::{ use super::LayoutCx; -pub(crate) fn struct_variant_idx() -> RustcEnumVariantIdx { - RustcEnumVariantIdx(LocalEnumVariantId::from_raw(RawIdx::from(0))) +pub(crate) const fn struct_variant_idx() -> RustcEnumVariantIdx { + RustcEnumVariantIdx(LocalEnumVariantId::from_raw(RawIdx::from_u32(0))) } pub fn layout_of_adt_query( @@ -74,7 +75,7 @@ pub fn layout_of_adt_query( .iter() .map(|it| it.iter().map(|it| &**it).collect::>()) .collect::>(); - let variants = variants.iter().map(|it| it.iter().collect()).collect(); + let variants = variants.iter().map(|it| it.iter().collect()).collect::>(); let result = if matches!(def, AdtId::UnionId(..)) { cx.layout_of_union(&repr, &variants).ok_or(LayoutError::Unknown)? } else { @@ -105,7 +106,7 @@ pub fn layout_of_adt_query( && variants .iter() .next() - .and_then(|it| it.last().map(|it| !it.is_unsized())) + .and_then(|it| it.iter().last().map(|it| !it.is_unsized())) .unwrap_or(true), ) .ok_or(LayoutError::SizeOverflow)? diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 8246297705ca..2883229d11e2 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -64,7 +64,7 @@ use hir_ty::{ consteval::{try_const_usize, unknown_const_as_generic, ConstEvalError, ConstExt}, diagnostics::BodyValidationDiagnostic, known_const_to_ast, - layout::{Layout as TyLayout, RustcEnumVariantIdx, TagEncoding}, + layout::{Layout as TyLayout, RustcEnumVariantIdx, RustcFieldIdx, TagEncoding}, method_resolution::{self, TyFingerprint}, mir::{self, interpret_mir}, primitive::UintTy, @@ -4540,15 +4540,31 @@ impl Layout { Some(self.0.largest_niche?.available(&*self.1)) } - pub fn field_offset(&self, idx: usize) -> Option { + pub fn field_offset(&self, field: Field) -> Option { match self.0.fields { layout::FieldsShape::Primitive => None, layout::FieldsShape::Union(_) => Some(0), layout::FieldsShape::Array { stride, count } => { - let i = u64::try_from(idx).ok()?; + let i = u64::try_from(field.index()).ok()?; (i < count).then_some((stride * i).bytes()) } - layout::FieldsShape::Arbitrary { ref offsets, .. } => Some(offsets.get(idx)?.bytes()), + layout::FieldsShape::Arbitrary { ref offsets, .. } => { + Some(offsets.get(RustcFieldIdx(field.id))?.bytes()) + } + } + } + + pub fn tuple_field_offset(&self, field: usize) -> Option { + match self.0.fields { + layout::FieldsShape::Primitive => None, + layout::FieldsShape::Union(_) => Some(0), + layout::FieldsShape::Array { stride, count } => { + let i = u64::try_from(field).ok()?; + (i < count).then_some((stride * i).bytes()) + } + layout::FieldsShape::Arbitrary { ref offsets, .. } => { + Some(offsets.get(RustcFieldIdx::new(field))?.bytes()) + } } } diff --git a/crates/ide/src/hover/render.rs b/crates/ide/src/hover/render.rs index f72ce37d1d94..d0a02fd0dba2 100644 --- a/crates/ide/src/hover/render.rs +++ b/crates/ide/src/hover/render.rs @@ -402,10 +402,9 @@ pub(super) fn definition( |&it| it.layout(db), |_| { let var_def = it.parent_def(db); - let id = it.index(); match var_def { hir::VariantDef::Struct(s) => { - Adt::from(s).layout(db).ok().and_then(|layout| layout.field_offset(id)) + Adt::from(s).layout(db).ok().and_then(|layout| layout.field_offset(it)) } _ => None, } diff --git a/crates/ide/src/view_memory_layout.rs b/crates/ide/src/view_memory_layout.rs index 2f6332abd259..3802978f4941 100644 --- a/crates/ide/src/view_memory_layout.rs +++ b/crates/ide/src/view_memory_layout.rs @@ -55,6 +55,7 @@ impl fmt::Display for RecursiveMemoryLayout { } } +#[derive(Copy, Clone)] enum FieldOrTupleIdx { Field(Field), TupleIdx(usize), @@ -71,13 +72,6 @@ impl FieldOrTupleIdx { FieldOrTupleIdx::TupleIdx(i) => format!(".{i}").to_owned(), } } - - fn index(&self) -> usize { - match *self { - FieldOrTupleIdx::Field(f) => f.index(), - FieldOrTupleIdx::TupleIdx(i) => i, - } - } } // Feature: View Memory Layout @@ -138,7 +132,10 @@ pub(crate) fn view_memory_layout( return; } - fields.sort_by_key(|(f, _)| layout.field_offset(f.index()).unwrap()); + fields.sort_by_key(|&(f, _)| match f { + FieldOrTupleIdx::Field(f) => layout.field_offset(f).unwrap_or(0), + FieldOrTupleIdx::TupleIdx(f) => layout.tuple_field_offset(f).unwrap_or(0), + }); let children_start = nodes.len(); nodes[parent_idx].children_start = children_start as i64; @@ -151,7 +148,10 @@ pub(crate) fn view_memory_layout( typename: child_ty.display(db).to_string(), size: child_layout.size(), alignment: child_layout.align(), - offset: layout.field_offset(field.index()).unwrap_or(0), + offset: match *field { + FieldOrTupleIdx::Field(f) => layout.field_offset(f).unwrap_or(0), + FieldOrTupleIdx::TupleIdx(f) => layout.tuple_field_offset(f).unwrap_or(0), + }, parent_idx: parent_idx as i64, children_start: -1, children_len: 0, diff --git a/crates/rustc-dependencies/Cargo.toml b/crates/rustc-dependencies/Cargo.toml index 5c5a3cd8bf32..7ead3d84cd3c 100644 --- a/crates/rustc-dependencies/Cargo.toml +++ b/crates/rustc-dependencies/Cargo.toml @@ -11,12 +11,10 @@ authors.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -ra-ap-rustc_lexer = { version = "0.10.0" } -ra-ap-rustc_parse_format = { version = "0.10.0", default-features = false } - -# Upstream broke this for us so we can't update it -hkalbasi-rustc-ap-rustc_abi = { version = "0.0.20221221", default-features = false } -hkalbasi-rustc-ap-rustc_index = { version = "0.0.20221221", default-features = false } +ra-ap-rustc_lexer = { version = "0.14.0" } +ra-ap-rustc_parse_format = { version = "0.14.0", default-features = false } +ra-ap-rustc_index = { version = "0.14.0", default-features = false } +ra-ap-rustc_abi = { version = "0.14.0", default-features = false } [features] in-rust-tree = [] diff --git a/crates/rustc-dependencies/src/lib.rs b/crates/rustc-dependencies/src/lib.rs index c1d3f05f34e7..13fcbc491937 100644 --- a/crates/rustc-dependencies/src/lib.rs +++ b/crates/rustc-dependencies/src/lib.rs @@ -6,34 +6,43 @@ #[cfg(feature = "in-rust-tree")] extern crate rustc_lexer; -#[cfg(feature = "in-rust-tree")] -pub mod lexer { - pub use ::rustc_lexer::*; -} - -#[cfg(not(feature = "in-rust-tree"))] pub mod lexer { + #[cfg(not(feature = "in-rust-tree"))] pub use ::ra_ap_rustc_lexer::*; + + #[cfg(feature = "in-rust-tree")] + pub use ::rustc_lexer::*; } #[cfg(feature = "in-rust-tree")] extern crate rustc_parse_format; -#[cfg(feature = "in-rust-tree")] pub mod parse_format { + #[cfg(not(feature = "in-rust-tree"))] + pub use ::ra_ap_rustc_parse_format::*; + + #[cfg(feature = "in-rust-tree")] pub use ::rustc_parse_format::*; } -#[cfg(not(feature = "in-rust-tree"))] -pub mod parse_format { - pub use ::ra_ap_rustc_parse_format::*; +#[cfg(feature = "in-rust-tree")] +extern crate rustc_abi; + +pub mod abi { + #[cfg(not(feature = "in-rust-tree"))] + pub use ::ra_ap_rustc_abi::*; + + #[cfg(feature = "in-rust-tree")] + pub use ::rustc_abi::*; } -// Upstream broke this for us so we can't update it -pub mod abi { - pub use ::hkalbasi_rustc_ap_rustc_abi::*; -} +#[cfg(feature = "in-rust-tree")] +extern crate rustc_index; pub mod index { - pub use ::hkalbasi_rustc_ap_rustc_index::*; + #[cfg(not(feature = "in-rust-tree"))] + pub use ::ra_ap_rustc_index::*; + + #[cfg(feature = "in-rust-tree")] + pub use ::rustc_index::*; } From 03bec1112ad5594b31fe7489f448b4f69117df5b Mon Sep 17 00:00:00 2001 From: Wilfred Hughes Date: Sun, 15 Oct 2023 16:34:23 -0700 Subject: [PATCH 137/435] Expand Emacs documentation Emacs 29 is now released, and include an example of enabling clippy. --- docs/user/manual.adoc | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/docs/user/manual.adoc b/docs/user/manual.adoc index f5a1cec814c6..b605de4c7b82 100644 --- a/docs/user/manual.adoc +++ b/docs/user/manual.adoc @@ -237,7 +237,7 @@ To use `rust-analyzer`, you need to install and enable one of the two popular LS ==== Eglot -Eglot is the more minimalistic and lightweight LSP client for Emacs, integrates well with existing Emacs functionality and will be built into Emacs starting from release 29. +Eglot is the more minimalistic and lightweight LSP client for Emacs, integrates well with existing Emacs functionality and is built into Emacs starting from release 29. After installing Eglot, e.g. via `M-x package-install` (not needed from Emacs 29), you can enable it via the `M-x eglot` command or load it automatically in `rust-mode` via @@ -246,6 +246,15 @@ After installing Eglot, e.g. via `M-x package-install` (not needed from Emacs 29 (add-hook 'rust-mode-hook 'eglot-ensure) ---- +To enable clippy, you will need to configure the initialization options to pass the `check.command` setting. + +[source,emacs-lisp] +---- +(add-to-list 'eglot-server-programs + '((rust-ts-mode rust-mode) . + ("rust-analyzer" :initializationOptions (:check (:command "clippy"))))) +---- + For more detailed instructions and options see the https://joaotavora.github.io/eglot[Eglot manual] (also available from Emacs via `M-x info`) and the https://github.com/joaotavora/eglot/blob/master/README.md[Eglot readme]. From 222be4885877ed8a7e1f78139f97547e8a44682b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Mon, 16 Oct 2023 15:13:48 +0300 Subject: [PATCH 138/435] Create .ssh before writing deploy key --- .github/workflows/metrics.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/metrics.yaml b/.github/workflows/metrics.yaml index 91615f1b79fb..e43149916ebc 100644 --- a/.github/workflows/metrics.yaml +++ b/.github/workflows/metrics.yaml @@ -140,8 +140,10 @@ jobs: - name: Combine json run: | + mkdir ~/.ssh echo "${{ secrets.METRICS_DEPLOY_KEY }}" > ~/.ssh/id_ed25519 chmod 600 ~/.ssh/id_ed25519 + chmod 700 ~/.ssh git clone --depth 1 git@github.com/rust-analyzer/metrics.git jq -s ".[0] * .[1] * .[2] * .[3] * .[4] * .[5]" build.json self.json ripgrep-13.0.0.json webrender-2022.json diesel-1.4.8.json hyper-0.14.18.json -c >> metrics/metrics.json From 490cdfecb59f3d60db97318b2fa90414685702ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Mon, 16 Oct 2023 16:34:03 +0300 Subject: [PATCH 139/435] Fix metrics repo url --- .github/workflows/metrics.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/metrics.yaml b/.github/workflows/metrics.yaml index e43149916ebc..741e559953fc 100644 --- a/.github/workflows/metrics.yaml +++ b/.github/workflows/metrics.yaml @@ -145,7 +145,7 @@ jobs: chmod 600 ~/.ssh/id_ed25519 chmod 700 ~/.ssh - git clone --depth 1 git@github.com/rust-analyzer/metrics.git + git clone --depth 1 git@github.com:rust-analyzer/metrics.git jq -s ".[0] * .[1] * .[2] * .[3] * .[4] * .[5]" build.json self.json ripgrep-13.0.0.json webrender-2022.json diesel-1.4.8.json hyper-0.14.18.json -c >> metrics/metrics.json cd metrics git add . From 1a0fe58d81b5703082c06711bfb08c7563dc1701 Mon Sep 17 00:00:00 2001 From: Young-Flash <871946895@qq.com> Date: Tue, 17 Oct 2023 17:34:11 +0800 Subject: [PATCH 140/435] refactor: change generated variable name --- .../replace_is_method_with_if_let_method.rs | 58 +++++++++++++++++-- crates/ide-assists/src/tests/generated.rs | 2 +- 2 files changed, 54 insertions(+), 6 deletions(-) diff --git a/crates/ide-assists/src/handlers/replace_is_method_with_if_let_method.rs b/crates/ide-assists/src/handlers/replace_is_method_with_if_let_method.rs index e5b4c33eb34f..b1daaea1ed1b 100644 --- a/crates/ide-assists/src/handlers/replace_is_method_with_if_let_method.rs +++ b/crates/ide-assists/src/handlers/replace_is_method_with_if_let_method.rs @@ -1,6 +1,6 @@ use syntax::ast::{self, AstNode}; -use crate::{AssistContext, AssistId, AssistKind, Assists}; +use crate::{utils::suggest_name, AssistContext, AssistId, AssistKind, Assists}; // Assist: replace_is_some_with_if_let_some // @@ -16,7 +16,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists}; // ``` // fn main() { // let x = Some(1); -// if let Some(${0:_tmp}) = x {} +// if let Some(${0:x}) = x {} // } // ``` pub(crate) fn replace_is_method_with_if_let_method( @@ -35,6 +35,13 @@ pub(crate) fn replace_is_method_with_if_let_method( match name_ref.text().as_str() { "is_some" | "is_ok" => { let receiver = call_expr.receiver()?; + + let var_name = if let ast::Expr::PathExpr(path_expr) = receiver.clone() { + path_expr.path()?.to_string() + } else { + suggest_name::for_variable(&receiver, &ctx.sema) + }; + let target = call_expr.syntax().text_range(); let (assist_id, message, text) = if name_ref.text() == "is_some" { @@ -44,7 +51,8 @@ pub(crate) fn replace_is_method_with_if_let_method( }; acc.add(AssistId(assist_id, AssistKind::RefactorRewrite), message, target, |edit| { - let replacement = format!("let {}({}) = {}", text, "${0:_tmp}", receiver); + let var_name = format!("${{0:{}}}", var_name); + let replacement = format!("let {}({}) = {}", text, var_name, receiver); edit.replace(target, replacement); }) } @@ -71,7 +79,27 @@ fn main() { r#" fn main() { let x = Some(1); - if let Some(${0:_tmp}) = x {} + if let Some(${0:x}) = x {} +} +"#, + ); + + check_assist( + replace_is_method_with_if_let_method, + r#" +fn test() -> Option { + Some(1) +} +fn main() { + if test().is_som$0e() {} +} +"#, + r#" +fn test() -> Option { + Some(1) +} +fn main() { + if let Some(${0:test}) = test() {} } "#, ); @@ -103,7 +131,27 @@ fn main() { r#" fn main() { let x = Ok(1); - if let Ok(${0:_tmp}) = x {} + if let Ok(${0:x}) = x {} +} +"#, + ); + + check_assist( + replace_is_method_with_if_let_method, + r#" +fn test() -> Result { + Ok(1) +} +fn main() { + if test().is_o$0k() {} +} +"#, + r#" +fn test() -> Result { + Ok(1) +} +fn main() { + if let Ok(${0:test}) = test() {} } "#, ); diff --git a/crates/ide-assists/src/tests/generated.rs b/crates/ide-assists/src/tests/generated.rs index 6b4a97440877..e9d0d373ee7c 100644 --- a/crates/ide-assists/src/tests/generated.rs +++ b/crates/ide-assists/src/tests/generated.rs @@ -2571,7 +2571,7 @@ fn main() { r#####" fn main() { let x = Some(1); - if let Some(${0:_tmp}) = x {} + if let Some(${0:x}) = x {} } "#####, ) From 9eb70d63357606ab3e70337aee7606b4fa185f60 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 21 Sep 2023 12:43:11 +1000 Subject: [PATCH 141/435] Don't pass `-stdlib=libc++` when building C files on macOS When using *Command Line Tools for Xcode* version 15.0, clang will warn about `argument unused during compilation: '-stdlib=libc++'` if this flag is present when compiling C files only (i.e. no C++ files). To avoid this warning, we can add the flag only to CXXFLAGS and not to CFLAGS. --- src/bootstrap/src/lib.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 97c743074af4..4a96acd9c1aa 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -1146,11 +1146,10 @@ impl Build { .filter(|s| !s.starts_with("-O") && !s.starts_with("/O")) .collect::>(); - // If we're compiling on macOS then we add a few unconditional flags - // indicating that we want libc++ (more filled out than libstdc++) and - // we want to compile for 10.7. This way we can ensure that + // If we're compiling C++ on macOS then we add a flag indicating that + // we want libc++ (more filled out than libstdc++), ensuring that // LLVM/etc are all properly compiled. - if target.contains("apple-darwin") { + if matches!(c, CLang::Cxx) && target.contains("apple-darwin") { base.push("-stdlib=libc++".into()); } From 10e6372a83d94e69f792c1bd33c0c435e8073c61 Mon Sep 17 00:00:00 2001 From: Slanterns Date: Wed, 18 Oct 2023 07:35:23 +0800 Subject: [PATCH 142/435] Stabilize `result_option_inspect` --- library/core/src/option.rs | 9 ++------- library/core/src/result.rs | 8 ++------ 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index bdaeea666221..10efd9061c0f 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -1072,8 +1072,6 @@ impl Option { /// # Examples /// /// ``` - /// #![feature(result_option_inspect)] - /// /// let v = vec![1, 2, 3, 4, 5]; /// /// // prints "got: 4" @@ -1083,11 +1081,8 @@ impl Option { /// let x: Option<&usize> = v.get(5).inspect(|x| println!("got: {x}")); /// ``` #[inline] - #[unstable(feature = "result_option_inspect", issue = "91345")] - pub fn inspect(self, f: F) -> Self - where - F: FnOnce(&T), - { + #[stable(feature = "result_option_inspect", since = "CURRENT_RUSTC_VERSION")] + pub fn inspect(self, f: F) -> Self { if let Some(ref x) = self { f(x); } diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 50127b27f8bf..90c346e98bcc 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -835,8 +835,6 @@ impl Result { /// # Examples /// /// ``` - /// #![feature(result_option_inspect)] - /// /// let x: u8 = "4" /// .parse::() /// .inspect(|x| println!("original: {x}")) @@ -844,7 +842,7 @@ impl Result { /// .expect("failed to parse number"); /// ``` #[inline] - #[unstable(feature = "result_option_inspect", issue = "91345")] + #[stable(feature = "result_option_inspect", since = "CURRENT_RUSTC_VERSION")] pub fn inspect(self, f: F) -> Self { if let Ok(ref t) = self { f(t); @@ -858,8 +856,6 @@ impl Result { /// # Examples /// /// ``` - /// #![feature(result_option_inspect)] - /// /// use std::{fs, io}; /// /// fn read() -> io::Result { @@ -868,7 +864,7 @@ impl Result { /// } /// ``` #[inline] - #[unstable(feature = "result_option_inspect", issue = "91345")] + #[stable(feature = "result_option_inspect", since = "CURRENT_RUSTC_VERSION")] pub fn inspect_err(self, f: F) -> Self { if let Err(ref e) = self { f(e); From ed512e91d0318cb06ea2b3729198e64090b5648e Mon Sep 17 00:00:00 2001 From: Slanterns Date: Wed, 18 Oct 2023 07:35:57 +0800 Subject: [PATCH 143/435] Remove `#![feature(result_option_inspect)]` from the compiler --- compiler/rustc_errors/src/lib.rs | 1 - compiler/rustc_middle/src/lib.rs | 1 - compiler/rustc_trait_selection/src/lib.rs | 1 - 3 files changed, 3 deletions(-) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index da74ee6391ae..fad3cb202eec 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -10,7 +10,6 @@ #![feature(if_let_guard)] #![feature(let_chains)] #![feature(never_type)] -#![feature(result_option_inspect)] #![feature(rustc_attrs)] #![feature(yeet_expr)] #![feature(try_blocks)] diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index dee18dc11628..cd0944f6985a 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -58,7 +58,6 @@ #![feature(extract_if)] #![feature(intra_doc_pointers)] #![feature(yeet_expr)] -#![feature(result_option_inspect)] #![feature(const_option)] #![feature(trait_alias)] #![feature(ptr_alignment_type)] diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index 5ba29f878558..6fab9441bdc2 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -21,7 +21,6 @@ #![feature(let_chains)] #![feature(if_let_guard)] #![feature(never_type)] -#![feature(result_option_inspect)] #![feature(type_alias_impl_trait)] #![feature(min_specialization)] #![recursion_limit = "512"] // For rustdoc From 4296fe52baba36de060691db9ef482b68845aeb4 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 18 Oct 2023 14:02:56 +0200 Subject: [PATCH 144/435] Add command for only opening external docs and attempt to fix vscode-remote issue --- editors/code/package.json | 9 +++++-- editors/code/src/commands.ts | 46 +++++++++++++++++++++++++++--------- editors/code/src/lsp_ext.ts | 8 +++---- editors/code/src/main.ts | 1 + 4 files changed, 47 insertions(+), 17 deletions(-) diff --git a/editors/code/package.json b/editors/code/package.json index fc6597a0d402..2dde66c97006 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -248,6 +248,11 @@ "title": "Open Docs", "category": "rust-analyzer" }, + { + "command": "rust-analyzer.openExternalDocs", + "title": "Open External Docs", + "category": "rust-analyzer" + }, { "command": "rust-analyzer.openCargoToml", "title": "Open Cargo.toml", @@ -260,12 +265,12 @@ }, { "command": "rust-analyzer.moveItemUp", - "title": "Move item up", + "title": "Move Item Up", "category": "rust-analyzer" }, { "command": "rust-analyzer.moveItemDown", - "title": "Move item down", + "title": "Move Item Down", "category": "rust-analyzer" }, { diff --git a/editors/code/src/commands.ts b/editors/code/src/commands.ts index 4d5c3cf45764..7e24de664e9e 100644 --- a/editors/code/src/commands.ts +++ b/editors/code/src/commands.ts @@ -948,27 +948,51 @@ export function openDocs(ctx: CtxInit): Cmd { const position = editor.selection.active; const textDocument = { uri: editor.document.uri.toString() }; - const doclinks = await client.sendRequest(ra.openDocs, { position, textDocument }); + const docLinks = await client.sendRequest(ra.openDocs, { position, textDocument }); + log.debug(docLinks); let fileType = vscode.FileType.Unknown; - if (typeof doclinks.local === "string") { + if (docLinks.local !== undefined) { try { - fileType = (await vscode.workspace.fs.stat(vscode.Uri.parse(doclinks.local))).type; + fileType = (await vscode.workspace.fs.stat(vscode.Uri.parse(docLinks.local))).type; } catch (e) { log.debug("stat() threw error. Falling back to web version", e); } } - let doclink; - if (fileType & vscode.FileType.File) { - // file does exist locally - doclink = doclinks.local; - } else { - doclink = doclinks.web; + let docLink = fileType & vscode.FileType.File ? docLinks.local : docLinks.web; + if (docLink) { + // instruct vscode to handle the vscode-remote link directly + if (docLink.startsWith("vscode-remote://")) { + docLink = docLink.replace("vscode-remote://", "vscode://vscode-remote/"); + } + const docUri = vscode.Uri.parse(docLink); + await vscode.env.openExternal(docUri); } + }; +} - if (doclink != null) { - await vscode.env.openExternal(vscode.Uri.parse(doclink)); +export function openExternalDocs(ctx: CtxInit): Cmd { + return async () => { + const editor = vscode.window.activeTextEditor; + if (!editor) { + return; + } + const client = ctx.client; + + const position = editor.selection.active; + const textDocument = { uri: editor.document.uri.toString() }; + + const docLinks = await client.sendRequest(ra.openDocs, { position, textDocument }); + + let docLink = docLinks.web; + if (docLink) { + // instruct vscode to handle the vscode-remote link directly + if (docLink.startsWith("vscode-remote://")) { + docLink = docLink.replace("vscode-remote://", "vscode://vscode-remote/"); + } + const docUri = vscode.Uri.parse(docLink); + await vscode.env.openExternal(docUri); } }; } diff --git a/editors/code/src/lsp_ext.ts b/editors/code/src/lsp_ext.ts index a1cd88b89c94..f959a76639e0 100644 --- a/editors/code/src/lsp_ext.ts +++ b/editors/code/src/lsp_ext.ts @@ -74,8 +74,8 @@ export interface FetchDependencyListParams {} export interface FetchDependencyListResult { crates: { - name: string | undefined; - version: string | undefined; + name?: string; + version?: string; path: string; }[]; } @@ -136,8 +136,8 @@ export const openCargoToml = new lc.RequestType( "experimental/externalDocs", diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts index ee5e5b1b80c8..5de5aabc39f7 100644 --- a/editors/code/src/main.ts +++ b/editors/code/src/main.ts @@ -170,6 +170,7 @@ function createCommands(): Record { debug: { enabled: commands.debug }, newDebugConfig: { enabled: commands.newDebugConfig }, openDocs: { enabled: commands.openDocs }, + openExternalDocs: { enabled: commands.openExternalDocs }, openCargoToml: { enabled: commands.openCargoToml }, peekTests: { enabled: commands.peekTests }, moveItemUp: { enabled: commands.moveItemUp }, From 3fea7cc7da6dadd2012af3f42f870e204470e479 Mon Sep 17 00:00:00 2001 From: Joshua Liebow-Feeser Date: Wed, 18 Oct 2023 09:14:31 -0700 Subject: [PATCH 145/435] Guarantee that `char` has the same size and alignment as `u32` --- library/core/src/primitive_docs.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index 380a21b376bd..9914225367ce 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -283,7 +283,7 @@ mod prim_never {} /// `char` type. For technical reasons, there is additional, separate /// documentation in [the `std::char` module](char/index.html) as well. /// -/// # Validity +/// # Validity and Layout /// /// A `char` is a '[Unicode scalar value]', which is any '[Unicode code point]' /// other than a [surrogate code point]. This has a fixed numerical definition: @@ -330,6 +330,9 @@ mod prim_never {} /// ("noncharacters"); and some may be given different meanings by different /// users ("private use"). /// +/// `char` is guaranteed to have the same size and alignment as `u32` on all +/// platforms. +/// /// [Unicode code point]: https://www.unicode.org/glossary/#code_point /// [Unicode scalar value]: https://www.unicode.org/glossary/#unicode_scalar_value /// [non-exhaustive match]: ../book/ch06-02-match.html#matches-are-exhaustive From a7f77d89a952a0e93276afb91c470e9da1dd5f77 Mon Sep 17 00:00:00 2001 From: Young-Flash <871946895@qq.com> Date: Wed, 18 Oct 2023 22:40:07 +0800 Subject: [PATCH 146/435] fix: auto import trait if needed --- .../src/handlers/unqualify_method_call.rs | 45 ++++++++++++++++++- crates/ide-assists/src/tests/generated.rs | 2 + 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/crates/ide-assists/src/handlers/unqualify_method_call.rs b/crates/ide-assists/src/handlers/unqualify_method_call.rs index e9d4e270cdcf..e1f812b0bfda 100644 --- a/crates/ide-assists/src/handlers/unqualify_method_call.rs +++ b/crates/ide-assists/src/handlers/unqualify_method_call.rs @@ -1,3 +1,4 @@ +use ide_db::imports::insert_use::ImportScope; use syntax::{ ast::{self, make, AstNode, HasArgList}, TextRange, @@ -17,6 +18,8 @@ use crate::{AssistContext, AssistId, AssistKind, Assists}; // ``` // -> // ``` +// use std::ops::Add; +// // fn main() { // 1.add(2); // } @@ -38,7 +41,7 @@ pub(crate) fn unqualify_method_call(acc: &mut Assists, ctx: &AssistContext<'_>) let first_arg = args_iter.next()?; let second_arg = args_iter.next(); - _ = path.qualifier()?; + let qualifier = path.qualifier()?; let method_name = path.segment()?.name_ref()?; let res = ctx.sema.resolve_path(&path)?; @@ -76,10 +79,44 @@ pub(crate) fn unqualify_method_call(acc: &mut Assists, ctx: &AssistContext<'_>) edit.insert(close, ")"); } edit.replace(replace_comma, format!(".{method_name}(")); + add_import(qualifier, ctx, edit); }, ) } +fn add_import( + qualifier: ast::Path, + ctx: &AssistContext<'_>, + edit: &mut ide_db::source_change::SourceChangeBuilder, +) { + // for `` + let path_type = + qualifier.segment().unwrap().syntax().children().filter_map(ast::PathType::cast).last(); + let import = match path_type { + Some(it) => it.path().unwrap(), + None => qualifier, + }; + + // in case for `<_>` + if import.coloncolon_token().is_none() { + return; + } + + let scope = ide_db::imports::insert_use::ImportScope::find_insert_use_container( + import.syntax(), + &ctx.sema, + ); + + if let Some(scope) = scope { + let scope = match scope { + ImportScope::File(it) => ImportScope::File(edit.make_mut(it)), + ImportScope::Module(it) => ImportScope::Module(edit.make_mut(it)), + ImportScope::Block(it) => ImportScope::Block(edit.make_mut(it)), + }; + ide_db::imports::insert_use::insert_use(&scope, import, &ctx.config.insert_use); + } +} + fn needs_parens_as_receiver(expr: &ast::Expr) -> bool { // Make `(expr).dummy()` let dummy_call = make::expr_method_call( @@ -127,6 +164,8 @@ fn f() { S.f(S); }"#, //- minicore: add fn f() { ::$0add(2, 2); }"#, r#" +use core::ops::Add; + fn f() { 2.add(2); }"#, ); @@ -136,6 +175,8 @@ fn f() { 2.add(2); }"#, //- minicore: add fn f() { core::ops::Add::$0add(2, 2); }"#, r#" +use core::ops::Add; + fn f() { 2.add(2); }"#, ); @@ -179,6 +220,8 @@ impl core::ops::Deref for S { } fn f() { core::ops::Deref::$0deref(&S); }"#, r#" +use core::ops::Deref; + struct S; impl core::ops::Deref for S { type Target = S; diff --git a/crates/ide-assists/src/tests/generated.rs b/crates/ide-assists/src/tests/generated.rs index 6b4a97440877..99624306b7ea 100644 --- a/crates/ide-assists/src/tests/generated.rs +++ b/crates/ide-assists/src/tests/generated.rs @@ -2948,6 +2948,8 @@ fn main() { mod std { pub mod ops { pub trait Add { fn add(self, _: Self) {} } impl Add for i32 {} } } "#####, r#####" +use std::ops::Add; + fn main() { 1.add(2); } From 94eb142e6d34192ab918d20f20905653cf86ebdf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Thu, 19 Oct 2023 19:03:10 +0300 Subject: [PATCH 147/435] Free up some disk space on auto-publish --- .github/workflows/autopublish.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/autopublish.yaml b/.github/workflows/autopublish.yaml index 310a8a5be7ad..9a5015005b3d 100644 --- a/.github/workflows/autopublish.yaml +++ b/.github/workflows/autopublish.yaml @@ -19,6 +19,10 @@ jobs: with: fetch-depth: 0 + # https://github.com/jlumbroso/free-disk-space/blob/main/action.yml + - name: Free up some disk space + run: sudo rm -rf /usr/local/lib/android /usr/share/dotnet /opt/ghc /usr/local/.ghcup + - name: Install Rust toolchain run: rustup update --no-self-update stable From 98d54da1eebb0e0b68169b776fe6c83c44e8f8b4 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 20 Oct 2023 19:10:16 +0200 Subject: [PATCH 148/435] document that the null pointer has the 0 address --- library/core/src/ptr/mod.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 84b179df8c19..63e42a8784c6 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -505,6 +505,10 @@ pub unsafe fn drop_in_place(to_drop: *mut T) { /// Creates a null raw pointer. /// +/// This function is equivalent to zero-initializing the pointer: +/// `MaybeUninit::<*const T>::zeroed().assume_init()`. +/// The resulting pointer has the address 0. +/// /// # Examples /// /// ``` @@ -512,6 +516,7 @@ pub unsafe fn drop_in_place(to_drop: *mut T) { /// /// let p: *const i32 = ptr::null(); /// assert!(p.is_null()); +/// assert_eq!(p as usize, 0); // this pointer has the address 0 /// ``` #[inline(always)] #[must_use] @@ -526,6 +531,10 @@ pub const fn null() -> *const T { /// Creates a null mutable raw pointer. /// +/// This function is equivalent to zero-initializing the pointer: +/// `MaybeUninit::<*mut T>::zeroed().assume_init()`. +/// The resulting pointer has the address 0. +/// /// # Examples /// /// ``` @@ -533,6 +542,7 @@ pub const fn null() -> *const T { /// /// let p: *mut i32 = ptr::null_mut(); /// assert!(p.is_null()); +/// assert_eq!(p as usize, 0); // this pointer has the address 0 /// ``` #[inline(always)] #[must_use] From 094cecd3bdc4979f382de39ced770445fb147e38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Sat, 21 Oct 2023 19:08:41 +0300 Subject: [PATCH 149/435] Fix VS Code detection for Insiders version --- crates/rust-analyzer/src/bin/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/rust-analyzer/src/bin/main.rs b/crates/rust-analyzer/src/bin/main.rs index b8875ef87a4c..9748990b7a3f 100644 --- a/crates/rust-analyzer/src/bin/main.rs +++ b/crates/rust-analyzer/src/bin/main.rs @@ -193,7 +193,7 @@ fn run_server() -> anyhow::Result<()> { let mut is_visual_studio_code = false; if let Some(client_info) = client_info { tracing::info!("Client '{}' {}", client_info.name, client_info.version.unwrap_or_default()); - is_visual_studio_code = client_info.name == "Visual Studio Code"; + is_visual_studio_code = client_info.name.starts_with("Visual Studio Code"); } let workspace_roots = workspace_folders From 2c13ee8970126261dd30a7b1be865af6d26afaea Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sat, 21 Oct 2023 21:32:06 -0700 Subject: [PATCH 150/435] Clarify UB in `get_unchecked(_mut)` --- library/core/src/slice/mod.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 45080eda2ce2..5866a8888197 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -640,6 +640,11 @@ impl [T] { /// Calling this method with an out-of-bounds index is *[undefined behavior]* /// even if the resulting reference is not used. /// + /// You can think of this like `.get(index).unwrap_unchecked()`. It's UB + /// to call `.get_unchecked(len)`, even if you immediately convert to a + /// pointer. And it's UB to call `.get_unchecked(..len +1)` or + /// `.get_unchecked(..=len)` similar. + /// /// [`get`]: slice::get /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html /// @@ -675,6 +680,11 @@ impl [T] { /// Calling this method with an out-of-bounds index is *[undefined behavior]* /// even if the resulting reference is not used. /// + /// You can think of this like `.get_mut(index).unwrap_unchecked()`. It's + /// UB to call `.get_unchecked_mut(len)`, even if you immediately convert + /// to a pointer. And it's UB to call `.get_unchecked_mut(..len +1)` or + /// `.get_unchecked_mut(..=len)` similar. + /// /// [`get_mut`]: slice::get_mut /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html /// From 4f5f7e280025783a0c9d3f82f4a4cb989255b7ca Mon Sep 17 00:00:00 2001 From: Young-Flash <871946895@qq.com> Date: Sun, 22 Oct 2023 21:39:00 +0800 Subject: [PATCH 151/435] feat: import trait with alias --- .../ide-assists/src/handlers/auto_import.rs | 52 +++++++++++++++---- crates/ide-db/src/imports/insert_use.rs | 37 +++++++++++-- 2 files changed, 77 insertions(+), 12 deletions(-) diff --git a/crates/ide-assists/src/handlers/auto_import.rs b/crates/ide-assists/src/handlers/auto_import.rs index 7acf2ea0a0de..a2efa4d10bd6 100644 --- a/crates/ide-assists/src/handlers/auto_import.rs +++ b/crates/ide-assists/src/handlers/auto_import.rs @@ -5,7 +5,7 @@ use ide_db::{ helpers::mod_path_to_ast, imports::{ import_assets::{ImportAssets, ImportCandidate, LocatedImport}, - insert_use::{insert_use, ImportScope}, + insert_use::{insert_use, insert_use_as_alias, ImportScope}, }, }; use syntax::{ast, AstNode, NodeOrToken, SyntaxElement}; @@ -129,10 +129,12 @@ pub(crate) fn auto_import(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option< for import in proposed_imports { let import_path = import.import_path; + let (assist_id, import_name) = + (AssistId("auto_import", AssistKind::QuickFix), import_path.display(ctx.db())); acc.add_group( &group_label, - AssistId("auto_import", AssistKind::QuickFix), - format!("Import `{}`", import_path.display(ctx.db())), + assist_id, + format!("Import `{}`", import_name), range, |builder| { let scope = match scope.clone() { @@ -143,6 +145,38 @@ pub(crate) fn auto_import(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option< insert_use(&scope, mod_path_to_ast(&import_path), &ctx.config.insert_use); }, ); + + match import_assets.import_candidate() { + ImportCandidate::TraitAssocItem(name) | ImportCandidate::TraitMethod(name) => { + let is_method = + matches!(import_assets.import_candidate(), ImportCandidate::TraitMethod(_)); + let type_ = if is_method { "method" } else { "item" }; + let group_label = GroupLabel(format!( + "Import a trait for {} {} by alias", + type_, + name.assoc_item_name.text() + )); + acc.add_group( + &group_label, + assist_id, + format!("Import `{} as _`", import_name), + range, + |builder| { + let scope = match scope.clone() { + ImportScope::File(it) => ImportScope::File(builder.make_mut(it)), + ImportScope::Module(it) => ImportScope::Module(builder.make_mut(it)), + ImportScope::Block(it) => ImportScope::Block(builder.make_mut(it)), + }; + insert_use_as_alias( + &scope, + mod_path_to_ast(&import_path), + &ctx.config.insert_use, + ); + }, + ); + } + _ => {} + } } Some(()) } @@ -723,7 +757,7 @@ fn main() { } ", r" - use test_mod::TestTrait; + use test_mod::TestTrait as _; mod test_mod { pub trait TestTrait { @@ -794,7 +828,7 @@ fn main() { } ", r" - use test_mod::TestTrait; + use test_mod::TestTrait as _; mod test_mod { pub trait TestTrait { @@ -866,7 +900,7 @@ fn main() { } ", r" - use test_mod::TestTrait; + use test_mod::TestTrait as _; mod test_mod { pub trait TestTrait { @@ -908,7 +942,7 @@ fn main() { } ", r" - use dep::test_mod::TestTrait; + use dep::test_mod::TestTrait as _; fn main() { let test_struct = dep::test_mod::TestStruct {}; @@ -939,7 +973,7 @@ fn main() { } ", r" - use dep::test_mod::TestTrait; + use dep::test_mod::TestTrait as _; fn main() { dep::test_mod::TestStruct::test_function @@ -969,7 +1003,7 @@ fn main() { } ", r" - use dep::test_mod::TestTrait; + use dep::test_mod::TestTrait as _; fn main() { dep::test_mod::TestStruct::CONST diff --git a/crates/ide-db/src/imports/insert_use.rs b/crates/ide-db/src/imports/insert_use.rs index 9be1d3663493..6caa6e3511cd 100644 --- a/crates/ide-db/src/imports/insert_use.rs +++ b/crates/ide-db/src/imports/insert_use.rs @@ -9,7 +9,7 @@ use syntax::{ algo, ast::{ self, edit_in_place::Removable, make, AstNode, HasAttrs, HasModuleItem, HasVisibility, - PathSegmentKind, + PathSegmentKind, Rename, UseTree, }, ted, Direction, NodeOrToken, SyntaxKind, SyntaxNode, }; @@ -157,6 +157,33 @@ impl ImportScope { /// Insert an import path into the given file/node. A `merge` value of none indicates that no import merging is allowed to occur. pub fn insert_use(scope: &ImportScope, path: ast::Path, cfg: &InsertUseConfig) { + insert_use_with_alias_option(scope, path, cfg, None); +} + +pub fn insert_use_as_alias(scope: &ImportScope, path: ast::Path, cfg: &InsertUseConfig) { + let text: &str = "use foo as _"; + let parse = syntax::SourceFile::parse(text); + let node = match parse.tree().syntax().descendants().find_map(UseTree::cast) { + Some(it) => it, + None => { + panic!( + "Failed to make ast node `{}` from text {}", + std::any::type_name::(), + text + ) + } + }; + let alias = node.rename(); + + insert_use_with_alias_option(scope, path, cfg, alias); +} + +fn insert_use_with_alias_option( + scope: &ImportScope, + path: ast::Path, + cfg: &InsertUseConfig, + alias: Option, +) { let _p = profile::span("insert_use"); let mut mb = match cfg.granularity { ImportGranularity::Crate => Some(MergeBehavior::Crate), @@ -175,8 +202,12 @@ pub fn insert_use(scope: &ImportScope, path: ast::Path, cfg: &InsertUseConfig) { }; } - let use_item = - make::use_(None, make::use_tree(path.clone(), None, None, false)).clone_for_update(); + let use_item = if alias.is_some() { + make::use_(None, make::use_tree(path.clone(), None, alias, false)).clone_for_update() + } else { + make::use_(None, make::use_tree(path.clone(), None, None, false)).clone_for_update() + }; + // merge into existing imports if possible if let Some(mb) = mb { let filter = |it: &_| !(cfg.skip_glob_imports && ast::Use::is_simple_glob(it)); From 8b82ea4f51b0288a2e318aca352cee6df06e244e Mon Sep 17 00:00:00 2001 From: hkalbasi Date: Sun, 22 Oct 2023 23:34:27 +0330 Subject: [PATCH 152/435] Store binding mode for each instance independently --- crates/hir-ty/src/consteval/tests.rs | 14 ++++++++++++++ crates/hir-ty/src/diagnostics/match_check.rs | 2 +- crates/hir-ty/src/infer.rs | 14 +++++++++++++- crates/hir-ty/src/infer/closure.rs | 6 +++--- crates/hir-ty/src/infer/pat.rs | 2 +- crates/hir-ty/src/mir/lower/pattern_matching.rs | 5 ++++- crates/hir/src/source_analyzer.rs | 4 ++-- .../src/handlers/moved_out_of_ref.rs | 15 +++++++++++++++ 8 files changed, 53 insertions(+), 9 deletions(-) diff --git a/crates/hir-ty/src/consteval/tests.rs b/crates/hir-ty/src/consteval/tests.rs index 7ad3659a4f6d..b395e7f4a813 100644 --- a/crates/hir-ty/src/consteval/tests.rs +++ b/crates/hir-ty/src/consteval/tests.rs @@ -1159,6 +1159,20 @@ fn pattern_matching_slice() { "#, 33213, ); + check_number( + r#" + //- minicore: slice, index, coerce_unsized, copy + const fn f(mut slice: &[u32]) -> usize { + slice = match slice { + [0, rest @ ..] | rest => rest, + }; + slice.len() + } + const GOAL: usize = f(&[]) + f(&[10]) + f(&[0, 100]) + + f(&[1000, 1000, 1000]) + f(&[0, 57, 34, 46, 10000, 10000]); + "#, + 10, + ); } #[test] diff --git a/crates/hir-ty/src/diagnostics/match_check.rs b/crates/hir-ty/src/diagnostics/match_check.rs index f8cdeaa5e354..2e04bbfee83b 100644 --- a/crates/hir-ty/src/diagnostics/match_check.rs +++ b/crates/hir-ty/src/diagnostics/match_check.rs @@ -147,7 +147,7 @@ impl<'a> PatCtxt<'a> { } hir_def::hir::Pat::Bind { id, subpat, .. } => { - let bm = self.infer.binding_modes[id]; + let bm = self.infer.binding_modes[pat]; ty = &self.infer[id]; let name = &self.body.bindings[id].name; match (bm, ty.kind(Interner)) { diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs index 78d3c667a1f8..3d5ed1f93c0f 100644 --- a/crates/hir-ty/src/infer.rs +++ b/crates/hir-ty/src/infer.rs @@ -420,7 +420,19 @@ pub struct InferenceResult { standard_types: InternedStandardTypes, /// Stores the types which were implicitly dereferenced in pattern binding modes. pub pat_adjustments: FxHashMap>, - pub binding_modes: ArenaMap, + /// Stores the binding mode (`ref` in `let ref x = 2`) of bindings. + /// + /// This one is tied to the `PatId` instead of `BindingId`, because in some rare cases, a binding in an + /// or pattern can have multiple binding modes. For example: + /// ``` + /// fn foo(mut slice: &[u32]) -> usize { + /// slice = match slice { + /// [0, rest @ ..] | rest => rest, + /// }; + /// } + /// ``` + /// the first `rest` has implicit `ref` binding mode, but the second `rest` binding mode is `move`. + pub binding_modes: ArenaMap, pub expr_adjustments: FxHashMap>, pub(crate) closure_info: FxHashMap, FnTrait)>, // FIXME: remove this field diff --git a/crates/hir-ty/src/infer/closure.rs b/crates/hir-ty/src/infer/closure.rs index 13d6b5643ac4..0805e20447a7 100644 --- a/crates/hir-ty/src/infer/closure.rs +++ b/crates/hir-ty/src/infer/closure.rs @@ -679,7 +679,7 @@ impl InferenceContext<'_> { | Pat::Range { .. } => { update_result(CaptureKind::ByRef(BorrowKind::Shared)); } - Pat::Bind { id, .. } => match self.result.binding_modes[*id] { + Pat::Bind { id, .. } => match self.result.binding_modes[p] { crate::BindingMode::Move => { if self.is_ty_copy(self.result.type_of_binding[*id].clone()) { update_result(CaptureKind::ByRef(BorrowKind::Shared)); @@ -838,8 +838,8 @@ impl InferenceContext<'_> { | Pat::ConstBlock(_) | Pat::Path(_) | Pat::Lit(_) => self.consume_place(place, pat.into()), - Pat::Bind { id, subpat: _ } => { - let mode = self.result.binding_modes[*id]; + Pat::Bind { id: _, subpat: _ } => { + let mode = self.result.binding_modes[pat]; let capture_kind = match mode { BindingMode::Move => { self.consume_place(place, pat.into()); diff --git a/crates/hir-ty/src/infer/pat.rs b/crates/hir-ty/src/infer/pat.rs index 4e28ec06023e..7ff12e5b7f85 100644 --- a/crates/hir-ty/src/infer/pat.rs +++ b/crates/hir-ty/src/infer/pat.rs @@ -421,7 +421,7 @@ impl InferenceContext<'_> { } else { BindingMode::convert(mode) }; - self.result.binding_modes.insert(binding, mode); + self.result.binding_modes.insert(pat, mode); let inner_ty = match subpat { Some(subpat) => self.infer_pat(subpat, &expected, default_bm), diff --git a/crates/hir-ty/src/mir/lower/pattern_matching.rs b/crates/hir-ty/src/mir/lower/pattern_matching.rs index 270f75ad9674..1120bb1c1123 100644 --- a/crates/hir-ty/src/mir/lower/pattern_matching.rs +++ b/crates/hir-ty/src/mir/lower/pattern_matching.rs @@ -284,6 +284,7 @@ impl MirLowerCtx<'_> { ); (current, current_else) = self.pattern_match_binding( id, + *slice, next_place, (*slice).into(), current, @@ -395,6 +396,7 @@ impl MirLowerCtx<'_> { if mode == MatchingMode::Bind { self.pattern_match_binding( *id, + pattern, cond_place, pattern.into(), current, @@ -431,13 +433,14 @@ impl MirLowerCtx<'_> { fn pattern_match_binding( &mut self, id: BindingId, + pat: PatId, cond_place: Place, span: MirSpan, current: BasicBlockId, current_else: Option, ) -> Result<(BasicBlockId, Option)> { let target_place = self.binding_local(id)?; - let mode = self.infer.binding_modes[id]; + let mode = self.infer.binding_modes[pat]; self.push_storage_live(id, current)?; self.push_assignment( current, diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs index 8d8ba48ad923..55c2f8324c6d 100644 --- a/crates/hir/src/source_analyzer.rs +++ b/crates/hir/src/source_analyzer.rs @@ -236,9 +236,9 @@ impl SourceAnalyzer { _db: &dyn HirDatabase, pat: &ast::IdentPat, ) -> Option { - let binding_id = self.binding_id_of_pat(pat)?; + let id = self.pat_id(&pat.clone().into())?; let infer = self.infer.as_ref()?; - infer.binding_modes.get(binding_id).map(|bm| match bm { + infer.binding_modes.get(id).map(|bm| match bm { hir_ty::BindingMode::Move => BindingMode::Move, hir_ty::BindingMode::Ref(hir_ty::Mutability::Mut) => BindingMode::Ref(Mutability::Mut), hir_ty::BindingMode::Ref(hir_ty::Mutability::Not) => { diff --git a/crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs b/crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs index 20175b3fd535..886aefeb575f 100644 --- a/crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs +++ b/crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs @@ -175,4 +175,19 @@ fn main() { "#, ); } + + #[test] + fn regression_15787() { + check_diagnostics( + r#" +//- minicore: coerce_unsized, slice, copy +fn foo(mut slice: &[u32]) -> usize { + slice = match slice { + [0, rest @ ..] | rest => rest, + }; + slice.len() +} +"#, + ); + } } From 45ee88f9cb7536a725c359efc89b73c904d5d0aa Mon Sep 17 00:00:00 2001 From: Young-Flash <871946895@qq.com> Date: Mon, 23 Oct 2023 23:12:07 +0800 Subject: [PATCH 153/435] fix: remove unwrap --- .../src/handlers/unqualify_method_call.rs | 55 +++++++++++-------- 1 file changed, 31 insertions(+), 24 deletions(-) diff --git a/crates/ide-assists/src/handlers/unqualify_method_call.rs b/crates/ide-assists/src/handlers/unqualify_method_call.rs index e1f812b0bfda..0bf1782a489d 100644 --- a/crates/ide-assists/src/handlers/unqualify_method_call.rs +++ b/crates/ide-assists/src/handlers/unqualify_method_call.rs @@ -89,31 +89,38 @@ fn add_import( ctx: &AssistContext<'_>, edit: &mut ide_db::source_change::SourceChangeBuilder, ) { - // for `` - let path_type = - qualifier.segment().unwrap().syntax().children().filter_map(ast::PathType::cast).last(); - let import = match path_type { - Some(it) => it.path().unwrap(), - None => qualifier, - }; - - // in case for `<_>` - if import.coloncolon_token().is_none() { - return; - } - - let scope = ide_db::imports::insert_use::ImportScope::find_insert_use_container( - import.syntax(), - &ctx.sema, - ); - - if let Some(scope) = scope { - let scope = match scope { - ImportScope::File(it) => ImportScope::File(edit.make_mut(it)), - ImportScope::Module(it) => ImportScope::Module(edit.make_mut(it)), - ImportScope::Block(it) => ImportScope::Block(edit.make_mut(it)), + if let Some(path_segment) = qualifier.segment() { + // for `` + let path_type = path_segment.syntax().children().filter_map(ast::PathType::cast).last(); + let import = match path_type { + Some(it) => { + if let Some(path) = it.path() { + path + } else { + return; + } + } + None => qualifier, }; - ide_db::imports::insert_use::insert_use(&scope, import, &ctx.config.insert_use); + + // in case for `<_>` + if import.coloncolon_token().is_none() { + return; + } + + let scope = ide_db::imports::insert_use::ImportScope::find_insert_use_container( + import.syntax(), + &ctx.sema, + ); + + if let Some(scope) = scope { + let scope = match scope { + ImportScope::File(it) => ImportScope::File(edit.make_mut(it)), + ImportScope::Module(it) => ImportScope::Module(edit.make_mut(it)), + ImportScope::Block(it) => ImportScope::Block(edit.make_mut(it)), + }; + ide_db::imports::insert_use::insert_use(&scope, import, &ctx.config.insert_use); + } } } From 545cc830e1fb22fe180dea2f713e6472b52707f9 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Tue, 24 Oct 2023 12:03:30 +0200 Subject: [PATCH 154/435] allow configuring the parent GitHub repository The git integration in build_helper hardcoded `rust-lang/rust` as the parent GitHub repository, and `master` as the branch name. This works great for `rust-lang/rust`, but causes problems in downstream forks like Ferrocene whenever those functions are invoked (like `./x fmt`). In `src/stage0.json` there was already a configuration key for the name of the nightly branch, but it wasn't used by build_helper. This commit adds the `github_repository` key to the file, and requires both values to be passed to build_helper whenever a git function is called. This will allow downstream forks to tweak the values. --- src/bootstrap/src/core/build_steps/format.rs | 2 +- src/bootstrap/src/core/build_steps/llvm.rs | 4 +- src/bootstrap/src/core/config/config.rs | 9 +++++ src/stage0.json | 1 + src/tools/build_helper/src/git.rs | 41 ++++++++++++++------ src/tools/compiletest/src/common.rs | 12 ++++++ src/tools/compiletest/src/header/tests.rs | 2 + src/tools/compiletest/src/lib.rs | 12 ++++-- 8 files changed, 66 insertions(+), 17 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/format.rs b/src/bootstrap/src/core/build_steps/format.rs index 0e260e69c85a..86f1d925f73d 100644 --- a/src/bootstrap/src/core/build_steps/format.rs +++ b/src/bootstrap/src/core/build_steps/format.rs @@ -89,7 +89,7 @@ fn get_modified_rs_files(build: &Builder<'_>) -> Result>, Str return Ok(None); } - get_git_modified_files(Some(&build.config.src), &vec!["rs"]) + get_git_modified_files(&build.config.git_config(), Some(&build.config.src), &vec!["rs"]) } #[derive(serde_derive::Deserialize)] diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index 24351118a5aa..53a64e2b3fcc 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -132,8 +132,8 @@ pub(crate) fn detect_llvm_sha(config: &Config, is_git: bool) -> String { // walk back further to the last bors merge commit that actually changed LLVM. The first // step will fail on CI because only the `auto` branch exists; we just fall back to `HEAD` // in that case. - let closest_upstream = - get_git_merge_base(Some(&config.src)).unwrap_or_else(|_| "HEAD".into()); + let closest_upstream = get_git_merge_base(&config.git_config(), Some(&config.src)) + .unwrap_or_else(|_| "HEAD".into()); let mut rev_list = config.git(); rev_list.args(&[ PathBuf::from("rev-list"), diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 5b5334b0a557..d3345f2d2a11 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -30,6 +30,7 @@ use serde::{Deserialize, Deserializer}; use serde_derive::Deserialize; pub use crate::core::config::flags::Subcommand; +use build_helper::git::GitConfig; macro_rules! check_ci_llvm { ($name:expr) => { @@ -318,6 +319,7 @@ pub struct Stage0Config { pub artifacts_server: String, pub artifacts_with_llvm_assertions_server: String, pub git_merge_commit_email: String, + pub github_repository: String, pub nightly_branch: String, } #[derive(Default, Deserialize, Clone)] @@ -2005,6 +2007,13 @@ impl Config { self.rust_codegen_backends.get(0).cloned() } + pub fn git_config(&self) -> GitConfig<'_> { + GitConfig { + github_repository: &self.stage0_metadata.config.github_repository, + nightly_branch: &self.stage0_metadata.config.nightly_branch, + } + } + pub fn check_build_rustc_version(&self, rustc_path: &str) { if self.dry_run() { return; diff --git a/src/stage0.json b/src/stage0.json index 32dc8a2f83c6..8e6c43dc46d4 100644 --- a/src/stage0.json +++ b/src/stage0.json @@ -4,6 +4,7 @@ "artifacts_server": "https://ci-artifacts.rust-lang.org/rustc-builds", "artifacts_with_llvm_assertions_server": "https://ci-artifacts.rust-lang.org/rustc-builds-alt", "git_merge_commit_email": "bors@rust-lang.org", + "github_repository": "rust-lang/rust", "nightly_branch": "master" }, "__comments": [ diff --git a/src/tools/build_helper/src/git.rs b/src/tools/build_helper/src/git.rs index f20b7a2b4d72..66f694dc919d 100644 --- a/src/tools/build_helper/src/git.rs +++ b/src/tools/build_helper/src/git.rs @@ -1,6 +1,11 @@ use std::process::Stdio; use std::{path::Path, process::Command}; +pub struct GitConfig<'a> { + pub github_repository: &'a str, + pub nightly_branch: &'a str, +} + /// Runs a command and returns the output fn output_result(cmd: &mut Command) -> Result { let output = match cmd.stderr(Stdio::inherit()).output() { @@ -27,7 +32,10 @@ fn output_result(cmd: &mut Command) -> Result { /// upstream https://github.com/rust-lang/rust (fetch) /// upstream https://github.com/rust-lang/rust (push) /// ``` -pub fn get_rust_lang_rust_remote(git_dir: Option<&Path>) -> Result { +pub fn get_rust_lang_rust_remote( + config: &GitConfig<'_>, + git_dir: Option<&Path>, +) -> Result { let mut git = Command::new("git"); if let Some(git_dir) = git_dir { git.current_dir(git_dir); @@ -37,8 +45,8 @@ pub fn get_rust_lang_rust_remote(git_dir: Option<&Path>) -> Result) -> Result { /// This could be because the user is updating their forked master branch using the GitHub UI /// and therefore doesn't need an upstream master branch checked out. /// We will then fall back to origin/master in the hope that at least this exists. -pub fn updated_master_branch(git_dir: Option<&Path>) -> Result { - let upstream_remote = get_rust_lang_rust_remote(git_dir)?; - for upstream_master in [format!("{upstream_remote}/master"), format!("origin/master")] { +pub fn updated_master_branch( + config: &GitConfig<'_>, + git_dir: Option<&Path>, +) -> Result { + let upstream_remote = get_rust_lang_rust_remote(config, git_dir)?; + let branch = config.nightly_branch; + for upstream_master in [format!("{upstream_remote}/{branch}"), format!("origin/{branch}")] { if rev_exists(&upstream_master, git_dir)? { return Ok(upstream_master); } @@ -87,8 +99,11 @@ pub fn updated_master_branch(git_dir: Option<&Path>) -> Result { Err(format!("Cannot find any suitable upstream master branch")) } -pub fn get_git_merge_base(git_dir: Option<&Path>) -> Result { - let updated_master = updated_master_branch(git_dir)?; +pub fn get_git_merge_base( + config: &GitConfig<'_>, + git_dir: Option<&Path>, +) -> Result { + let updated_master = updated_master_branch(config, git_dir)?; let mut git = Command::new("git"); if let Some(git_dir) = git_dir { git.current_dir(git_dir); @@ -100,10 +115,11 @@ pub fn get_git_merge_base(git_dir: Option<&Path>) -> Result { /// The `extensions` parameter can be used to filter the files by their extension. /// If `extensions` is empty, all files will be returned. pub fn get_git_modified_files( + config: &GitConfig<'_>, git_dir: Option<&Path>, extensions: &Vec<&str>, ) -> Result>, String> { - let merge_base = get_git_merge_base(git_dir)?; + let merge_base = get_git_merge_base(config, git_dir)?; let mut git = Command::new("git"); if let Some(git_dir) = git_dir { @@ -122,8 +138,11 @@ pub fn get_git_modified_files( } /// Returns the files that haven't been added to git yet. -pub fn get_git_untracked_files(git_dir: Option<&Path>) -> Result>, String> { - let Ok(_updated_master) = updated_master_branch(git_dir) else { +pub fn get_git_untracked_files( + config: &GitConfig<'_>, + git_dir: Option<&Path>, +) -> Result>, String> { + let Ok(_updated_master) = updated_master_branch(config, git_dir) else { return Ok(None); }; let mut git = Command::new("git"); diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 0e1bf0c6c2dc..cd9cf748aff0 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -8,6 +8,7 @@ use std::process::Command; use std::str::FromStr; use crate::util::{add_dylib_path, PathBufExt}; +use build_helper::git::GitConfig; use lazycell::AtomicLazyCell; use serde::de::{Deserialize, Deserializer, Error as _}; use std::collections::{HashMap, HashSet}; @@ -370,6 +371,10 @@ pub struct Config { pub target_cfgs: AtomicLazyCell, pub nocapture: bool, + + // Needed both to construct build_helper::git::GitConfig + pub github_repository: String, + pub nightly_branch: String, } impl Config { @@ -441,6 +446,13 @@ impl Config { ]; ASM_SUPPORTED_ARCHS.contains(&self.target_cfg().arch.as_str()) } + + pub fn git_config(&self) -> GitConfig<'_> { + GitConfig { + github_repository: &self.github_repository, + nightly_branch: &self.nightly_branch, + } + } } #[derive(Debug, Clone)] diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs index 2fd80b52ceee..1c89f8ba7639 100644 --- a/src/tools/compiletest/src/header/tests.rs +++ b/src/tools/compiletest/src/header/tests.rs @@ -126,6 +126,8 @@ impl ConfigBuilder { self.host.as_deref().unwrap_or("x86_64-unknown-linux-gnu"), "--target", self.target.as_deref().unwrap_or("x86_64-unknown-linux-gnu"), + "--github-repository=", + "--nightly-branch=", ]; let mut args: Vec = args.iter().map(ToString::to_string).collect(); diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index 619ff9b32211..52e7f4174f10 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -144,7 +144,9 @@ pub fn parse_config(args: Vec) -> Config { .optflag("h", "help", "show this message") .reqopt("", "channel", "current Rust channel", "CHANNEL") .optflag("", "git-hash", "run tests which rely on commit version being compiled into the binaries") - .optopt("", "edition", "default Rust edition", "EDITION"); + .optopt("", "edition", "default Rust edition", "EDITION") + .reqopt("", "github-repository", "name of the GitHub repository", "ORG/REPO") + .reqopt("", "nightly-branch", "name of the git branch for nightly", "BRANCH"); let (argv0, args_) = args.split_first().unwrap(); if args.len() == 1 || args[1] == "-h" || args[1] == "--help" { @@ -307,6 +309,9 @@ pub fn parse_config(args: Vec) -> Config { target_cfgs: AtomicLazyCell::new(), nocapture: matches.opt_present("nocapture"), + + github_repository: matches.opt_str("github-repository").unwrap(), + nightly_branch: matches.opt_str("nightly-branch").unwrap(), } } @@ -609,9 +614,10 @@ fn modified_tests(config: &Config, dir: &Path) -> Result, String> { return Ok(vec![]); } let files = - get_git_modified_files(Some(dir), &vec!["rs", "stderr", "fixed"])?.unwrap_or(vec![]); + get_git_modified_files(&config.git_config(), Some(dir), &vec!["rs", "stderr", "fixed"])? + .unwrap_or(vec![]); // Add new test cases to the list, it will be convenient in daily development. - let untracked_files = get_git_untracked_files(None)?.unwrap_or(vec![]); + let untracked_files = get_git_untracked_files(&config.git_config(), None)?.unwrap_or(vec![]); let all_paths = [&files[..], &untracked_files[..]].concat(); let full_paths = { From 5a562d962edacea1420e25ffee4d7ef73e91670f Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Tue, 24 Oct 2023 12:46:12 +0200 Subject: [PATCH 155/435] pass the correct args to compiletest --- src/bootstrap/src/core/build_steps/test.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 831a86940fb4..6c166332c18b 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -1873,6 +1873,10 @@ note: if you're sure you want to do this, please open an issue as to why. In the cmd.arg("--git-hash"); } + let git_config = builder.config.git_config(); + cmd.arg("--github-repository").arg(git_config.github_repository); + cmd.arg("--nightly-branch").arg(git_config.nightly_branch); + builder.ci_env.force_coloring_in_ci(&mut cmd); #[cfg(feature = "build-metrics")] From 4a0873533ff94855882802c4d6f0349d66e8c04a Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Tue, 24 Oct 2023 14:27:03 +0200 Subject: [PATCH 156/435] update suggest-tests --- src/bootstrap/src/core/build_steps/suggest.rs | 9 ++++++-- src/tools/suggest-tests/src/main.rs | 21 +++++++++++++++++-- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/suggest.rs b/src/bootstrap/src/core/build_steps/suggest.rs index 82fb10cebe07..70b46fa92390 100644 --- a/src/bootstrap/src/core/build_steps/suggest.rs +++ b/src/bootstrap/src/core/build_steps/suggest.rs @@ -9,8 +9,13 @@ use crate::core::builder::Builder; /// Suggests a list of possible `x.py` commands to run based on modified files in branch. pub fn suggest(builder: &Builder<'_>, run: bool) { - let suggestions = - builder.tool_cmd(Tool::SuggestTests).output().expect("failed to run `suggest-tests` tool"); + let git_config = builder.config.git_config(); + let suggestions = builder + .tool_cmd(Tool::SuggestTests) + .env("SUGGEST_TESTS_GITHUB_REPOSITORY", git_config.github_repository) + .env("SUGGEST_TESTS_NIGHTLY_BRANCH", git_config.nightly_branch) + .output() + .expect("failed to run `suggest-tests` tool"); if !suggestions.status.success() { println!("failed to run `suggest-tests` tool ({})", suggestions.status); diff --git a/src/tools/suggest-tests/src/main.rs b/src/tools/suggest-tests/src/main.rs index 0b541b60cba9..be3dde4f0bb7 100644 --- a/src/tools/suggest-tests/src/main.rs +++ b/src/tools/suggest-tests/src/main.rs @@ -1,10 +1,17 @@ use std::process::ExitCode; -use build_helper::git::get_git_modified_files; +use build_helper::git::{get_git_modified_files, GitConfig}; use suggest_tests::get_suggestions; fn main() -> ExitCode { - let modified_files = get_git_modified_files(None, &Vec::new()); + let modified_files = get_git_modified_files( + &GitConfig { + github_repository: &env("SUGGEST_TESTS_GITHUB_REPOSITORY"), + nightly_branch: &env("SUGGEST_TESTS_NIGHTLY_BRANCH"), + }, + None, + &Vec::new(), + ); let modified_files = match modified_files { Ok(Some(files)) => files, Ok(None) => { @@ -25,3 +32,13 @@ fn main() -> ExitCode { ExitCode::SUCCESS } + +fn env(key: &str) -> String { + match std::env::var(key) { + Ok(var) => var, + Err(err) => { + eprintln!("suggest-tests: failed to read environment variable {key}: {err}"); + std::process::exit(1); + } + } +} From c278bc1f8188a956dd94a1c173c46b70cb0b43a3 Mon Sep 17 00:00:00 2001 From: Joshua Liebow-Feeser Date: Wed, 25 Oct 2023 08:26:07 -0700 Subject: [PATCH 157/435] Update library/core/src/primitive_docs.rs Co-authored-by: scottmcm --- library/core/src/primitive_docs.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index 9914225367ce..1adb3807171a 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -332,6 +332,10 @@ mod prim_never {} /// /// `char` is guaranteed to have the same size and alignment as `u32` on all /// platforms. +/// ``` +/// use std::alloc::Layout; +/// assert_eq!(Layout::new::(), Layout::new::()); +/// ``` /// /// [Unicode code point]: https://www.unicode.org/glossary/#code_point /// [Unicode scalar value]: https://www.unicode.org/glossary/#unicode_scalar_value From 01ca7a0cb05e5684049a1ebb6179d63796e24e5c Mon Sep 17 00:00:00 2001 From: scottmcm Date: Wed, 25 Oct 2023 15:31:05 +0000 Subject: [PATCH 158/435] Add the missing word --- library/core/src/slice/mod.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 5866a8888197..fdf265cb3bfb 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -642,8 +642,8 @@ impl [T] { /// /// You can think of this like `.get(index).unwrap_unchecked()`. It's UB /// to call `.get_unchecked(len)`, even if you immediately convert to a - /// pointer. And it's UB to call `.get_unchecked(..len +1)` or - /// `.get_unchecked(..=len)` similar. + /// pointer. And it's UB to call `.get_unchecked(..len +1)`, + /// `.get_unchecked(..=len)`, or similar. /// /// [`get`]: slice::get /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html @@ -682,8 +682,8 @@ impl [T] { /// /// You can think of this like `.get_mut(index).unwrap_unchecked()`. It's /// UB to call `.get_unchecked_mut(len)`, even if you immediately convert - /// to a pointer. And it's UB to call `.get_unchecked_mut(..len +1)` or - /// `.get_unchecked_mut(..=len)` similar. + /// to a pointer. And it's UB to call `.get_unchecked_mut(..len +1)`, + /// `.get_unchecked_mut(..=len)`, or similar. /// /// [`get_mut`]: slice::get_mut /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html From e501add1f9addf72a30a333ec57ccb4e2ac5a8e4 Mon Sep 17 00:00:00 2001 From: Lukas Bergdoll Date: Wed, 25 Oct 2023 19:37:14 +0200 Subject: [PATCH 159/435] Avoid unnecessary comparison in partition_equal The branchy Hoare partition `partition_equal` as part of `slice::sort_unstable` has a bug that makes it perform a comparison of the last element twice. Measuring inputs with a Zipfian distribution with characterizing exponent s == 1.0, yields a ~0.05% reduction in the total number of comparisons performed. --- library/core/src/slice/sort.rs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/library/core/src/slice/sort.rs b/library/core/src/slice/sort.rs index db76d26257aa..993a608f42b6 100644 --- a/library/core/src/slice/sort.rs +++ b/library/core/src/slice/sort.rs @@ -628,9 +628,14 @@ where let _pivot_guard = InsertionHole { src: &*tmp, dest: pivot }; let pivot = &*tmp; + let len = v.len(); + if len == 0 { + return 0; + } + // Now partition the slice. let mut l = 0; - let mut r = v.len(); + let mut r = len; loop { // SAFETY: The unsafety below involves indexing an array. // For the first one: We already do the bounds checking here with `l < r`. @@ -643,8 +648,11 @@ where } // Find the last element equal to the pivot. - while l < r && is_less(pivot, v.get_unchecked(r - 1)) { + loop { r -= 1; + if l >= r || !is_less(pivot, v.get_unchecked(r)) { + break; + } } // Are we done? @@ -653,7 +661,6 @@ where } // Swap the found pair of out-of-order elements. - r -= 1; let ptr = v.as_mut_ptr(); ptr::swap(ptr.add(l), ptr.add(r)); l += 1; From 0e8f15519745c788d976ce43991978963fe79e7a Mon Sep 17 00:00:00 2001 From: Skgland Date: Wed, 25 Oct 2023 23:13:30 +0200 Subject: [PATCH 160/435] generate beta manifests as pre-requisit rust-lang/rustup#1329 mentioned this would be the next step --- src/tools/build-manifest/src/main.rs | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index b768722acf89..c4f3ae8c45b1 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -265,6 +265,29 @@ impl Builder { // channel-rust-1.XX.toml let major_minor = rust_version.split('.').take(2).collect::>().join("."); self.write_channel_files(&major_minor, &manifest); + } else if channel == "beta" { + // channel-rust-1.XX.YY-beta.Z.toml + let rust_version = self + .versions + .version(&PkgType::Rust) + .expect("missing Rust tarball") + .version + .expect("missing Rust version") + .split(' ') + .next() + .unwrap() + .to_string(); + self.write_channel_files(&rust_version, &manifest); + + // channel-rust-1.XX.YY-beta.toml + let major_minor_patch_beta = + rust_version.split('.').take(3).collect::>().join("."); + self.write_channel_files(&major_minor_patch_beta, &manifest); + + // channel-rust-1.XX-beta.toml + let major_minor_beta = + format!("{}-beta", rust_version.split('.').take(2).collect::>().join(".")); + self.write_channel_files(&major_minor_beta, &manifest); } if let Some(path) = std::env::var_os("BUILD_MANIFEST_SHIPPED_FILES_PATH") { From 99ec3aa8a34695a9c6889959edf1691dd08bfcdb Mon Sep 17 00:00:00 2001 From: Roberto Bampi Date: Thu, 26 Oct 2023 16:16:38 +0200 Subject: [PATCH 161/435] scip: update crate to version 0.3.1. While the git repo has been updated constantly, crates.io has only now been updated after more than a year of activity. --- Cargo.lock | 12 ++++++------ crates/rust-analyzer/Cargo.toml | 2 +- crates/rust-analyzer/src/cli/scip.rs | 6 ++++++ 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2a56bddb76ca..0a3d38645f52 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1405,9 +1405,9 @@ dependencies = [ [[package]] name = "protobuf" -version = "3.1.0" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ee4a7d8b91800c8f167a6268d1a1026607368e1adc84e98fe044aeb905302f7" +checksum = "b55bad9126f378a853655831eb7363b7b01b81d19f8cb1218861086ca4a1a61e" dependencies = [ "once_cell", "protobuf-support", @@ -1416,9 +1416,9 @@ dependencies = [ [[package]] name = "protobuf-support" -version = "3.1.0" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ca157fe12fc7ee2e315f2f735e27df41b3d97cdd70ea112824dac1ffb08ee1c" +checksum = "a5d4d7b8601c814cfb36bcebb79f0e61e45e1e93640cf778837833bbed05c372" dependencies = [ "thiserror", ] @@ -1671,9 +1671,9 @@ dependencies = [ [[package]] name = "scip" -version = "0.1.1" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2bfbb10286f69fad7c78db71004b7839bf957788359fe0c479f029f9849136b" +checksum = "3e84d21062a3ba08d58870c8c36b0c005b2b2261c6ad1bf7042585427c781883" dependencies = [ "protobuf", ] diff --git a/crates/rust-analyzer/Cargo.toml b/crates/rust-analyzer/Cargo.toml index 0a5412c638c3..ee5df984b68e 100644 --- a/crates/rust-analyzer/Cargo.toml +++ b/crates/rust-analyzer/Cargo.toml @@ -23,7 +23,7 @@ anyhow = "1.0.62" crossbeam-channel = "0.5.5" dissimilar = "1.0.4" itertools = "0.10.5" -scip = "0.1.1" +scip = "0.3.1" lsp-types = { version = "=0.94.0", features = ["proposed"] } parking_lot = "0.12.1" xflags = "0.3.0" diff --git a/crates/rust-analyzer/src/cli/scip.rs b/crates/rust-analyzer/src/cli/scip.rs index b058e6d153f0..30e11402cd8d 100644 --- a/crates/rust-analyzer/src/cli/scip.rs +++ b/crates/rust-analyzer/src/cli/scip.rs @@ -133,6 +133,10 @@ impl flags::Scip { documentation: documentation.unwrap_or_default(), relationships: Vec::new(), special_fields: Default::default(), + kind: Default::default(), + display_name: String::new(), + signature_documentation: Default::default(), + enclosing_symbol: String::new(), }; symbols.push(symbol_info) @@ -147,6 +151,7 @@ impl flags::Scip { syntax_kind: Default::default(), diagnostics: Vec::new(), special_fields: Default::default(), + enclosing_range: Vec::new(), }); }); @@ -160,6 +165,7 @@ impl flags::Scip { occurrences, symbols, special_fields: Default::default(), + text: String::new(), }); } From 00cdbe6c963310ce174e723ccf22262ab08b04f9 Mon Sep 17 00:00:00 2001 From: Young-Flash <871946895@qq.com> Date: Fri, 27 Oct 2023 21:16:34 +0800 Subject: [PATCH 162/435] feat: make extract_variable assist in place --- .../src/handlers/extract_variable.rs | 135 ++++++++++++++++-- 1 file changed, 125 insertions(+), 10 deletions(-) diff --git a/crates/ide-assists/src/handlers/extract_variable.rs b/crates/ide-assists/src/handlers/extract_variable.rs index 014c23197fac..7aaa8c0778fe 100644 --- a/crates/ide-assists/src/handlers/extract_variable.rs +++ b/crates/ide-assists/src/handlers/extract_variable.rs @@ -29,22 +29,31 @@ use crate::{utils::suggest_name, AssistContext, AssistId, AssistKind, Assists}; // } // ``` pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { - if ctx.has_empty_selection() { - return None; - } - - let node = match ctx.covering_element() { - NodeOrToken::Node(it) => it, - NodeOrToken::Token(it) if it.kind() == COMMENT => { - cov_mark::hit!(extract_var_in_comment_is_not_applicable); + let node = if ctx.has_empty_selection() { + if let Some(expr_stmt) = ctx.find_node_at_offset::() { + expr_stmt.syntax().clone() + } else if let Some(expr) = ctx.find_node_at_offset::() { + expr.syntax().ancestors().find_map(valid_target_expr)?.syntax().clone() + } else { return None; } - NodeOrToken::Token(it) => it.parent()?, + } else { + match ctx.covering_element() { + NodeOrToken::Node(it) => it, + NodeOrToken::Token(it) if it.kind() == COMMENT => { + cov_mark::hit!(extract_var_in_comment_is_not_applicable); + return None; + } + NodeOrToken::Token(it) => it.parent()?, + } }; + let node = node.ancestors().take_while(|anc| anc.text_range() == node.text_range()).last()?; + let range = node.text_range(); + let to_extract = node .descendants() - .take_while(|it| ctx.selection_trimmed().contains_range(it.text_range())) + .take_while(|it| range.contains_range(it.text_range())) .find_map(valid_target_expr)?; let ty = ctx.sema.type_of_expr(&to_extract).map(TypeInfo::adjusted); @@ -235,6 +244,112 @@ mod tests { use super::*; + #[test] + fn test_extract_var_simple_without_select() { + check_assist( + extract_variable, + r#" +fn main() -> i32 { + if true { + 1 + } else { + 2 + }$0 +} +"#, + r#" +fn main() -> i32 { + let $0var_name = if true { + 1 + } else { + 2 + }; + var_name +} +"#, + ); + + check_assist( + extract_variable, + r#" +fn foo() -> i32 { 1 } +fn main() { + foo();$0 +} +"#, + r#" +fn foo() -> i32 { 1 } +fn main() { + let $0foo = foo(); +} +"#, + ); + + check_assist( + extract_variable, + r#" +fn main() { + let a = Some(2); + a.is_some();$0 +} +"#, + r#" +fn main() { + let a = Some(2); + let $0is_some = a.is_some(); +} +"#, + ); + + check_assist( + extract_variable, + r#" +fn main() { + "hello"$0; +} +"#, + r#" +fn main() { + let $0var_name = "hello"; +} +"#, + ); + + check_assist( + extract_variable, + r#" +fn main() { + 1 + 2$0; +} +"#, + r#" +fn main() { + let $0var_name = 1 + 2; +} +"#, + ); + + check_assist( + extract_variable, + r#" +fn main() { + match () { + () if true => 1, + _ => 2, + };$0 +} +"#, + r#" +fn main() { + let $0var_name = match () { + () if true => 1, + _ => 2, + }; +} +"#, + ); + } + #[test] fn test_extract_var_simple() { check_assist( From 231f93524d19cdcd241f314f812479c429a5c5ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 27 Oct 2023 17:19:32 +0000 Subject: [PATCH 163/435] Detect misparsed binop caused by missing semi When encountering ```rust foo() *bar = baz; ``` We currently emit potentially two errors, one for the return type of `foo` not being multiplyiable by the type of `bar`, and another for `foo() * bar` not being assignable. We now check for this case and suggest adding a semicolon in the right place. Fix #80446. --- compiler/rustc_hir_typeck/src/expr.rs | 21 +++++++++++++ compiler/rustc_hir_typeck/src/op.rs | 16 ++++++++++ .../false-binop-caused-by-missing-semi.rs | 9 ++++++ .../false-binop-caused-by-missing-semi.stderr | 31 +++++++++++++++++++ 4 files changed, 77 insertions(+) create mode 100644 tests/ui/binop/false-binop-caused-by-missing-semi.rs create mode 100644 tests/ui/binop/false-binop-caused-by-missing-semi.stderr diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index be225ceb8432..9a2f242ec4e1 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -953,12 +953,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Applicability::MachineApplicable, ); }); + self.check_for_missing_semi(lhs, &mut err); adjust_err(&mut err); err.emit(); } + /// Check if the expression that could not be assigned to was a typoed expression that + fn check_for_missing_semi(&self, expr: &'tcx hir::Expr<'tcx>, err: &mut Diagnostic) { + if let hir::ExprKind::Binary(binop, lhs, rhs) = expr.kind + && let hir::BinOpKind::Mul = binop.node + && self.tcx.sess.source_map().is_multiline(lhs.span.between(rhs.span)) + && rhs.is_syntactic_place_expr() + { + // v missing semicolon here + // foo() + // *bar = baz; + // (#80446). + err.span_suggestion_verbose( + lhs.span.shrink_to_hi(), + "you might have meant to write a semicolon here", + ";".to_string(), + Applicability::MachineApplicable, + ); + } + } + // Check if an expression `original_expr_id` comes from the condition of a while loop, /// as opposed from the body of a while loop, which we can naively check by iterating /// parents until we find a loop... diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs index d0d3b0e5b73c..92075c7832a9 100644 --- a/compiler/rustc_hir_typeck/src/op.rs +++ b/compiler/rustc_hir_typeck/src/op.rs @@ -379,6 +379,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (err, output_def_id) } }; + if self.tcx.sess.source_map().is_multiline(lhs_expr.span.between(rhs_expr.span)) + && let IsAssign::No = is_assign + && let hir::BinOpKind::Mul = op.node + && rhs_expr.is_syntactic_place_expr() + { + // v missing semicolon here + // foo() + // *bar = baz; + // (#80446). + err.span_suggestion_verbose( + lhs_expr.span.shrink_to_hi(), + "you might have meant to write a semicolon here", + ";".to_string(), + Applicability::MaybeIncorrect, + ); + } let suggest_deref_binop = |err: &mut DiagnosticBuilder<'_, _>, lhs_deref_ty: Ty<'tcx>| { diff --git a/tests/ui/binop/false-binop-caused-by-missing-semi.rs b/tests/ui/binop/false-binop-caused-by-missing-semi.rs new file mode 100644 index 000000000000..9cd32e1db500 --- /dev/null +++ b/tests/ui/binop/false-binop-caused-by-missing-semi.rs @@ -0,0 +1,9 @@ +fn foo() {} +fn main() { + let mut y = 42; + let x = &mut y; + foo() + *x = 0; //~ ERROR invalid left-hand side of assignment + //~^ ERROR cannot multiply `()` by `&mut {integer}` + println!("{y}"); +} diff --git a/tests/ui/binop/false-binop-caused-by-missing-semi.stderr b/tests/ui/binop/false-binop-caused-by-missing-semi.stderr new file mode 100644 index 000000000000..8d0f15fe2ea1 --- /dev/null +++ b/tests/ui/binop/false-binop-caused-by-missing-semi.stderr @@ -0,0 +1,31 @@ +error[E0369]: cannot multiply `()` by `&mut {integer}` + --> $DIR/false-binop-caused-by-missing-semi.rs:6:5 + | +LL | foo() + | ----- () +LL | *x = 0; + | ^- &mut {integer} + | +help: you might have meant to write a semicolon here + | +LL | foo(); + | + + +error[E0070]: invalid left-hand side of assignment + --> $DIR/false-binop-caused-by-missing-semi.rs:6:8 + | +LL | / foo() +LL | | *x = 0; + | | - ^ + | |______| + | cannot assign to this expression + | +help: you might have meant to write a semicolon here + | +LL | foo(); + | + + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0070, E0369. +For more information about an error, try `rustc --explain E0070`. From be0b42fabe4b4abe10e7b6eb5e57ea12b6fa07c9 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Fri, 27 Oct 2023 13:22:10 +0000 Subject: [PATCH 164/435] Recover from incorrectly ordered/duplicated function keywords --- compiler/rustc_parse/src/parser/item.rs | 40 +++++++++++++++++-- tests/ui/async-await/no-async-const.rs | 1 + tests/ui/async-await/no-async-const.stderr | 11 ++++- tests/ui/async-await/no-unsafe-async.rs | 2 + tests/ui/async-await/no-unsafe-async.stderr | 5 --- .../const-async-const.rs | 5 +++ .../const-async-const.stderr | 11 ++++- .../issue-87217-keyword-order/recovery.rs | 22 ++++++++++ .../issue-87217-keyword-order/recovery.stderr | 28 +++++++++++++ .../several-kw-jump.rs | 5 +++ .../several-kw-jump.stderr | 11 ++++- .../issue-87217-keyword-order/wrong-async.rs | 2 + .../issue-87217-keyword-order/wrong-const.rs | 2 + .../issue-87217-keyword-order/wrong-unsafe.rs | 2 + 14 files changed, 136 insertions(+), 11 deletions(-) create mode 100644 tests/ui/parser/issues/issue-87217-keyword-order/recovery.rs create mode 100644 tests/ui/parser/issues/issue-87217-keyword-order/recovery.stderr diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 982f601c0d5a..884ae7be2efc 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -2382,22 +2382,39 @@ impl<'a> Parser<'a> { Misplaced(Span), } + // We may be able to recover + let mut recover_constness = constness; + let mut recover_asyncness = asyncness; + let mut recover_unsafety = unsafety; // This will allow the machine fix to directly place the keyword in the correct place or to indicate // that the keyword is already present and the second instance should be removed. let wrong_kw = if self.check_keyword(kw::Const) { match constness { Const::Yes(sp) => Some(WrongKw::Duplicated(sp)), - Const::No => Some(WrongKw::Misplaced(async_start_sp)), + Const::No => { + recover_constness = Const::Yes(self.token.span); + Some(WrongKw::Misplaced(async_start_sp)) + } } } else if self.check_keyword(kw::Async) { match asyncness { Async::Yes { span, .. } => Some(WrongKw::Duplicated(span)), - Async::No => Some(WrongKw::Misplaced(unsafe_start_sp)), + Async::No => { + recover_asyncness = Async::Yes { + span: self.token.span, + closure_id: DUMMY_NODE_ID, + return_impl_trait_id: DUMMY_NODE_ID, + }; + Some(WrongKw::Misplaced(unsafe_start_sp)) + } } } else if self.check_keyword(kw::Unsafe) { match unsafety { Unsafe::Yes(sp) => Some(WrongKw::Duplicated(sp)), - Unsafe::No => Some(WrongKw::Misplaced(ext_start_sp)), + Unsafe::No => { + recover_unsafety = Unsafe::Yes(self.token.span); + Some(WrongKw::Misplaced(ext_start_sp)) + } } } else { None @@ -2467,6 +2484,23 @@ impl<'a> Parser<'a> { } } } + + if wrong_kw.is_some() + && self.may_recover() + && self.look_ahead(1, |tok| tok.is_keyword_case(kw::Fn, case)) + { + // Advance past the misplaced keyword and `fn` + self.bump(); + self.bump(); + err.emit(); + return Ok(FnHeader { + constness: recover_constness, + unsafety: recover_unsafety, + asyncness: recover_asyncness, + ext, + }); + } + return Err(err); } } diff --git a/tests/ui/async-await/no-async-const.rs b/tests/ui/async-await/no-async-const.rs index 963460c11824..c9941d1c5a00 100644 --- a/tests/ui/async-await/no-async-const.rs +++ b/tests/ui/async-await/no-async-const.rs @@ -3,3 +3,4 @@ pub async const fn x() {} //~^ ERROR expected one of `extern`, `fn`, or `unsafe`, found keyword `const` +//~| ERROR functions cannot be both `const` and `async` diff --git a/tests/ui/async-await/no-async-const.stderr b/tests/ui/async-await/no-async-const.stderr index a51dc88a4ede..524d778c09b8 100644 --- a/tests/ui/async-await/no-async-const.stderr +++ b/tests/ui/async-await/no-async-const.stderr @@ -9,5 +9,14 @@ LL | pub async const fn x() {} | = note: keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern` -error: aborting due to previous error +error: functions cannot be both `const` and `async` + --> $DIR/no-async-const.rs:4:5 + | +LL | pub async const fn x() {} + | ----^^^^^-^^^^^---------- + | | | + | | `const` because of this + | `async` because of this + +error: aborting due to 2 previous errors diff --git a/tests/ui/async-await/no-unsafe-async.rs b/tests/ui/async-await/no-unsafe-async.rs index f40154e16f34..7c6811d81eea 100644 --- a/tests/ui/async-await/no-unsafe-async.rs +++ b/tests/ui/async-await/no-unsafe-async.rs @@ -9,3 +9,5 @@ impl S { #[cfg(FALSE)] unsafe async fn f() {} //~ ERROR expected one of `extern` or `fn`, found keyword `async` + +fn main() {} diff --git a/tests/ui/async-await/no-unsafe-async.stderr b/tests/ui/async-await/no-unsafe-async.stderr index f23d17d6bfa5..49b112f9313d 100644 --- a/tests/ui/async-await/no-unsafe-async.stderr +++ b/tests/ui/async-await/no-unsafe-async.stderr @@ -1,16 +1,11 @@ error: expected one of `extern` or `fn`, found keyword `async` --> $DIR/no-unsafe-async.rs:7:12 | -LL | impl S { - | - while parsing this item list starting here -LL | #[cfg(FALSE)] LL | unsafe async fn g() {} | -------^^^^^ | | | | | expected one of `extern` or `fn` | help: `async` must come before `unsafe`: `async unsafe` -LL | } - | - the item list ends here | = note: keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern` diff --git a/tests/ui/parser/issues/issue-87217-keyword-order/const-async-const.rs b/tests/ui/parser/issues/issue-87217-keyword-order/const-async-const.rs index df0cd54399a5..099178a7d50f 100644 --- a/tests/ui/parser/issues/issue-87217-keyword-order/const-async-const.rs +++ b/tests/ui/parser/issues/issue-87217-keyword-order/const-async-const.rs @@ -7,3 +7,8 @@ const async const fn test() {} //~| NOTE expected one of `extern`, `fn`, or `unsafe` //~| HELP `const` already used earlier, remove this one //~| NOTE `const` first seen here +//~| ERROR functions cannot be both `const` and `async` +//~| NOTE `const` because of this +//~| NOTE `async` because of this + +fn main() {} diff --git a/tests/ui/parser/issues/issue-87217-keyword-order/const-async-const.stderr b/tests/ui/parser/issues/issue-87217-keyword-order/const-async-const.stderr index 977c6ebfef35..4c55179ce237 100644 --- a/tests/ui/parser/issues/issue-87217-keyword-order/const-async-const.stderr +++ b/tests/ui/parser/issues/issue-87217-keyword-order/const-async-const.stderr @@ -13,5 +13,14 @@ note: `const` first seen here LL | const async const fn test() {} | ^^^^^ -error: aborting due to previous error +error: functions cannot be both `const` and `async` + --> $DIR/const-async-const.rs:5:1 + | +LL | const async const fn test() {} + | ^^^^^-^^^^^------------------- + | | | + | | `async` because of this + | `const` because of this + +error: aborting due to 2 previous errors diff --git a/tests/ui/parser/issues/issue-87217-keyword-order/recovery.rs b/tests/ui/parser/issues/issue-87217-keyword-order/recovery.rs new file mode 100644 index 000000000000..9d7fe43893e7 --- /dev/null +++ b/tests/ui/parser/issues/issue-87217-keyword-order/recovery.rs @@ -0,0 +1,22 @@ +// test for #115714 + +struct Misplaced; + +impl Misplaced { + unsafe const fn from_u32(val: u32) {} + //~^ ERROR expected one of `extern` or `fn` + fn oof(self){} +} + +struct Duplicated; + +impl Duplicated { + unsafe unsafe fn from_u32(val: u32) {} + //~^ ERROR expected one of `extern` or `fn` + fn oof(self){} +} + +fn main() { + Misplaced.oof(); + Duplicated.oof(); +} diff --git a/tests/ui/parser/issues/issue-87217-keyword-order/recovery.stderr b/tests/ui/parser/issues/issue-87217-keyword-order/recovery.stderr new file mode 100644 index 000000000000..3f504a9ebfc4 --- /dev/null +++ b/tests/ui/parser/issues/issue-87217-keyword-order/recovery.stderr @@ -0,0 +1,28 @@ +error: expected one of `extern` or `fn`, found keyword `const` + --> $DIR/recovery.rs:6:12 + | +LL | unsafe const fn from_u32(val: u32) {} + | -------^^^^^ + | | | + | | expected one of `extern` or `fn` + | help: `const` must come before `unsafe`: `const unsafe` + | + = note: keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern` + +error: expected one of `extern` or `fn`, found keyword `unsafe` + --> $DIR/recovery.rs:14:12 + | +LL | unsafe unsafe fn from_u32(val: u32) {} + | ^^^^^^ + | | + | expected one of `extern` or `fn` + | help: `unsafe` already used earlier, remove this one + | +note: `unsafe` first seen here + --> $DIR/recovery.rs:14:5 + | +LL | unsafe unsafe fn from_u32(val: u32) {} + | ^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/issues/issue-87217-keyword-order/several-kw-jump.rs b/tests/ui/parser/issues/issue-87217-keyword-order/several-kw-jump.rs index bbebc99e94b8..479426626858 100644 --- a/tests/ui/parser/issues/issue-87217-keyword-order/several-kw-jump.rs +++ b/tests/ui/parser/issues/issue-87217-keyword-order/several-kw-jump.rs @@ -12,3 +12,8 @@ async unsafe const fn test() {} //~| HELP `const` must come before `async unsafe` //~| SUGGESTION const async unsafe //~| NOTE keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern` +//~| ERROR functions cannot be both `const` and `async` +//~| NOTE `const` because of this +//~| NOTE `async` because of this + +fn main() {} diff --git a/tests/ui/parser/issues/issue-87217-keyword-order/several-kw-jump.stderr b/tests/ui/parser/issues/issue-87217-keyword-order/several-kw-jump.stderr index f455caba158c..489e8eefb052 100644 --- a/tests/ui/parser/issues/issue-87217-keyword-order/several-kw-jump.stderr +++ b/tests/ui/parser/issues/issue-87217-keyword-order/several-kw-jump.stderr @@ -9,5 +9,14 @@ LL | async unsafe const fn test() {} | = note: keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern` -error: aborting due to previous error +error: functions cannot be both `const` and `async` + --> $DIR/several-kw-jump.rs:9:1 + | +LL | async unsafe const fn test() {} + | ^^^^^--------^^^^^------------- + | | | + | | `const` because of this + | `async` because of this + +error: aborting due to 2 previous errors diff --git a/tests/ui/parser/issues/issue-87217-keyword-order/wrong-async.rs b/tests/ui/parser/issues/issue-87217-keyword-order/wrong-async.rs index 4ff4cf5c8ca8..867f71c12040 100644 --- a/tests/ui/parser/issues/issue-87217-keyword-order/wrong-async.rs +++ b/tests/ui/parser/issues/issue-87217-keyword-order/wrong-async.rs @@ -12,3 +12,5 @@ unsafe async fn test() {} //~| HELP `async` must come before `unsafe` //~| SUGGESTION async unsafe //~| NOTE keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern` + +fn main() {} diff --git a/tests/ui/parser/issues/issue-87217-keyword-order/wrong-const.rs b/tests/ui/parser/issues/issue-87217-keyword-order/wrong-const.rs index 2f5fbc513ee3..9a7f28210f93 100644 --- a/tests/ui/parser/issues/issue-87217-keyword-order/wrong-const.rs +++ b/tests/ui/parser/issues/issue-87217-keyword-order/wrong-const.rs @@ -12,3 +12,5 @@ unsafe const fn test() {} //~| HELP `const` must come before `unsafe` //~| SUGGESTION const unsafe //~| NOTE keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern` + +fn main() {} diff --git a/tests/ui/parser/issues/issue-87217-keyword-order/wrong-unsafe.rs b/tests/ui/parser/issues/issue-87217-keyword-order/wrong-unsafe.rs index df2412e3e9b3..8305ff4f6238 100644 --- a/tests/ui/parser/issues/issue-87217-keyword-order/wrong-unsafe.rs +++ b/tests/ui/parser/issues/issue-87217-keyword-order/wrong-unsafe.rs @@ -12,3 +12,5 @@ extern unsafe fn test() {} //~| HELP `unsafe` must come before `extern` //~| SUGGESTION unsafe extern //~| NOTE keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern` + +fn main() {} From 7186a287173cfa17c968b7b4248d58199d96ed14 Mon Sep 17 00:00:00 2001 From: Young-Flash <871946895@qq.com> Date: Sat, 28 Oct 2023 10:06:09 +0800 Subject: [PATCH 165/435] chore: add unapplicable test for extract_variable without select --- .../src/handlers/extract_variable.rs | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/crates/ide-assists/src/handlers/extract_variable.rs b/crates/ide-assists/src/handlers/extract_variable.rs index 7aaa8c0778fe..e7c884dcb706 100644 --- a/crates/ide-assists/src/handlers/extract_variable.rs +++ b/crates/ide-assists/src/handlers/extract_variable.rs @@ -350,6 +350,32 @@ fn main() { ); } + #[test] + fn test_extract_var_unit_expr_without_select_not_applicable() { + check_assist_not_applicable( + extract_variable, + r#" +fn foo() {} +fn main() { + foo()$0; +} +"#, + ); + + check_assist_not_applicable( + extract_variable, + r#" +fn foo() { + let mut i = 3; + if i >= 0 { + i += 1; + } else { + i -= 1; + }$0 +}"#, + ); + } + #[test] fn test_extract_var_simple() { check_assist( From bad4be6e29e141ec331e25259ab27ca4c20f86a3 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 28 Oct 2023 15:39:54 +0200 Subject: [PATCH 166/435] interpret: call caller_location logic the same way codegen does, and share some code --- src/common.rs | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/common.rs b/src/common.rs index 9771f44f62cf..38dba016c23e 100644 --- a/src/common.rs +++ b/src/common.rs @@ -433,16 +433,7 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> { // Note: must be kept in sync with get_caller_location from cg_ssa pub(crate) fn get_caller_location(&mut self, mut source_info: mir::SourceInfo) -> CValue<'tcx> { let span_to_caller_location = |fx: &mut FunctionCx<'_, '_, 'tcx>, span: Span| { - use rustc_session::RemapFileNameExt; - let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span); - let caller = fx.tcx.sess.source_map().lookup_char_pos(topmost.lo()); - let const_loc = fx.tcx.const_caller_location(( - rustc_span::symbol::Symbol::intern( - &caller.file.name.for_codegen(&fx.tcx.sess).to_string_lossy(), - ), - caller.line as u32, - caller.col_display as u32 + 1, - )); + let const_loc = fx.tcx.span_as_caller_location(span); crate::constant::codegen_const_value(fx, const_loc, fx.tcx.caller_location_ty()) }; From c6f50902940f3160a929e71c42ac631178304734 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 28 Oct 2023 16:16:15 +0200 Subject: [PATCH 167/435] share the track_caller handling within a mir::Body --- src/common.rs | 37 +++++-------------------------------- 1 file changed, 5 insertions(+), 32 deletions(-) diff --git a/src/common.rs b/src/common.rs index 38dba016c23e..63562d335089 100644 --- a/src/common.rs +++ b/src/common.rs @@ -430,38 +430,11 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> { } } - // Note: must be kept in sync with get_caller_location from cg_ssa - pub(crate) fn get_caller_location(&mut self, mut source_info: mir::SourceInfo) -> CValue<'tcx> { - let span_to_caller_location = |fx: &mut FunctionCx<'_, '_, 'tcx>, span: Span| { - let const_loc = fx.tcx.span_as_caller_location(span); - crate::constant::codegen_const_value(fx, const_loc, fx.tcx.caller_location_ty()) - }; - - // Walk up the `SourceScope`s, in case some of them are from MIR inlining. - // If so, the starting `source_info.span` is in the innermost inlined - // function, and will be replaced with outer callsite spans as long - // as the inlined functions were `#[track_caller]`. - loop { - let scope_data = &self.mir.source_scopes[source_info.scope]; - - if let Some((callee, callsite_span)) = scope_data.inlined { - // Stop inside the most nested non-`#[track_caller]` function, - // before ever reaching its caller (which is irrelevant). - if !callee.def.requires_caller_location(self.tcx) { - return span_to_caller_location(self, source_info.span); - } - source_info.span = callsite_span; - } - - // Skip past all of the parents with `inlined: None`. - match scope_data.inlined_parent_scope { - Some(parent) => source_info.scope = parent, - None => break, - } - } - - // No inlined `SourceScope`s, or all of them were `#[track_caller]`. - self.caller_location.unwrap_or_else(|| span_to_caller_location(self, source_info.span)) + pub(crate) fn get_caller_location(&mut self, source_info: mir::SourceInfo) -> CValue<'tcx> { + self.mir.caller_location_span(source_info, self.caller_location, self.tcx, |span| { + let const_loc = self.tcx.span_as_caller_location(span); + crate::constant::codegen_const_value(self, const_loc, self.tcx.caller_location_ty()) + }) } pub(crate) fn anonymous_str(&mut self, msg: &str) -> Value { From bec88ad4aa004a22d719a0ccacf60bb3b75799f7 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 19 Oct 2023 08:36:24 +0200 Subject: [PATCH 168/435] patterns: reject raw pointers that are not just integers --- .../src/const_eval/valtrees.rs | 37 ++++++++++++++----- compiler/rustc_lint_defs/src/builtin.rs | 5 ++- compiler/rustc_mir_build/messages.ftl | 2 +- .../src/thir/pattern/const_to_pat.rs | 33 +++++++++++++---- .../issue-34784-match-on-non-int-raw-ptr.rs} | 10 ++--- ...ssue-34784-match-on-non-int-raw-ptr.stderr | 25 +++++++++++++ .../ui/consts/const_in_pattern/issue-44333.rs | 4 +- .../const_in_pattern/issue-44333.stderr | 4 +- .../issue-63479-match-fnptr.rs | 2 +- .../issue-63479-match-fnptr.stderr | 2 +- 10 files changed, 92 insertions(+), 32 deletions(-) rename tests/ui/consts/{issue-34784.rs => const_in_pattern/issue-34784-match-on-non-int-raw-ptr.rs} (50%) create mode 100644 tests/ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.stderr diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs index d6dc1a62f4d0..76bd9a828368 100644 --- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs +++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs @@ -97,11 +97,27 @@ pub(crate) fn const_to_valtree_inner<'tcx>( Ok(ty::ValTree::Leaf(val.assert_int())) } - // Raw pointers are not allowed in type level constants, as we cannot properly test them for - // equality at compile-time (see `ptr_guaranteed_cmp`). + ty::RawPtr(_) => { + // Not all raw pointers are allowed, as we cannot properly test them for + // equality at compile-time (see `ptr_guaranteed_cmp`). + // However we allow those that are just integers in disguise. + // (We could allow wide raw pointers where both sides are integers in the future, + // but for now we reject them.) + let Ok(val) = ecx.read_scalar(place) else { + return Err(ValTreeCreationError::Other); + }; + // We are in the CTFE machine, so ptr-to-int casts will fail. + // This can only be `Ok` if `val` already is an integer. + let Ok(val) = val.try_to_int() else { + return Err(ValTreeCreationError::Other); + }; + // It's just a ScalarInt! + Ok(ty::ValTree::Leaf(val)) + } + // Technically we could allow function pointers (represented as `ty::Instance`), but this is not guaranteed to // agree with runtime equality tests. - ty::FnPtr(_) | ty::RawPtr(_) => Err(ValTreeCreationError::NonSupportedType), + ty::FnPtr(_) => Err(ValTreeCreationError::NonSupportedType), ty::Ref(_, _, _) => { let Ok(derefd_place)= ecx.deref_pointer(place) else { @@ -222,12 +238,14 @@ pub fn valtree_to_const_value<'tcx>( assert!(valtree.unwrap_branch().is_empty()); mir::ConstValue::ZeroSized } - ty::Bool | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Char => match valtree { - ty::ValTree::Leaf(scalar_int) => mir::ConstValue::Scalar(Scalar::Int(scalar_int)), - ty::ValTree::Branch(_) => bug!( - "ValTrees for Bool, Int, Uint, Float or Char should have the form ValTree::Leaf" - ), - }, + ty::Bool | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Char | ty::RawPtr(_) => { + match valtree { + ty::ValTree::Leaf(scalar_int) => mir::ConstValue::Scalar(Scalar::Int(scalar_int)), + ty::ValTree::Branch(_) => bug!( + "ValTrees for Bool, Int, Uint, Float, Char or RawPtr should have the form ValTree::Leaf" + ), + } + } ty::Ref(_, inner_ty, _) => { let mut ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, CanAccessStatics::No); let imm = valtree_to_ref(&mut ecx, valtree, *inner_ty); @@ -281,7 +299,6 @@ pub fn valtree_to_const_value<'tcx>( | ty::Coroutine(..) | ty::CoroutineWitness(..) | ty::FnPtr(_) - | ty::RawPtr(_) | ty::Str | ty::Slice(_) | ty::Dynamic(..) => bug!("no ValTree should have been created for type {:?}", ty.kind()), diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 918e484b9f44..f033504c5238 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -2217,13 +2217,14 @@ declare_lint! { /// /// ### Explanation /// - /// Previous versions of Rust allowed function pointers and wide raw pointers in patterns. + /// Previous versions of Rust allowed function pointers and all raw pointers in patterns. /// While these work in many cases as expected by users, it is possible that due to /// optimizations pointers are "not equal to themselves" or pointers to different functions /// compare as equal during runtime. This is because LLVM optimizations can deduplicate /// functions if their bodies are the same, thus also making pointers to these functions point /// to the same location. Additionally functions may get duplicated if they are instantiated - /// in different crates and not deduplicated again via LTO. + /// in different crates and not deduplicated again via LTO. Pointer identity for memory + /// created by `const` is similarly unreliable. pub POINTER_STRUCTURAL_MATCH, Allow, "pointers are not structural-match", diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl index 32711c23dc4e..dfd0bc238c19 100644 --- a/compiler/rustc_mir_build/messages.ftl +++ b/compiler/rustc_mir_build/messages.ftl @@ -242,7 +242,7 @@ mir_build_overlapping_range_endpoints = multiple patterns overlap on their endpo mir_build_pattern_not_covered = refutable pattern in {$origin} .pattern_ty = the matched value is of type `{$pattern_ty}` -mir_build_pointer_pattern = function pointers and unsized pointers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +mir_build_pointer_pattern = function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. mir_build_privately_uninhabited = pattern `{$witness_1}` is currently uninhabited, but this variant contains private fields which may become inhabited in the future diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index fc03f7891a86..ad386b129ce8 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -123,6 +123,8 @@ impl<'tcx> ConstToPat<'tcx> { }); debug!(?check_body_for_struct_match_violation, ?mir_structural_match_violation); + let have_valtree = + matches!(cv, mir::Const::Ty(c) if matches!(c.kind(), ty::ConstKind::Value(_))); let inlined_const_as_pat = match cv { mir::Const::Ty(c) => match c.kind() { ty::ConstKind::Param(_) @@ -238,7 +240,9 @@ impl<'tcx> ConstToPat<'tcx> { } } else if !self.saw_const_match_lint.get() { match cv.ty().kind() { - ty::RawPtr(pointee) if pointee.ty.is_sized(self.tcx(), self.param_env) => {} + ty::RawPtr(..) if have_valtree => { + // This is a good raw pointer, it was accepted by valtree construction. + } ty::FnPtr(..) | ty::RawPtr(..) => { self.tcx().emit_spanned_lint( lint::builtin::POINTER_STRUCTURAL_MATCH, @@ -389,11 +393,19 @@ impl<'tcx> ConstToPat<'tcx> { subpatterns: self .field_pats(cv.unwrap_branch().iter().copied().zip(fields.iter()))?, }, - ty::Adt(def, args) => PatKind::Leaf { - subpatterns: self.field_pats(cv.unwrap_branch().iter().copied().zip( - def.non_enum_variant().fields.iter().map(|field| field.ty(self.tcx(), args)), - ))?, - }, + ty::Adt(def, args) => { + assert!(!def.is_union()); // Valtree construction would never succeed for unions. + PatKind::Leaf { + subpatterns: self.field_pats( + cv.unwrap_branch().iter().copied().zip( + def.non_enum_variant() + .fields + .iter() + .map(|field| field.ty(self.tcx(), args)), + ), + )?, + } + } ty::Slice(elem_ty) => PatKind::Slice { prefix: cv .unwrap_branch() @@ -480,10 +492,15 @@ impl<'tcx> ConstToPat<'tcx> { } } }, - ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) => { + ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::RawPtr(..) => { + // The raw pointers we see here have been "vetted" by valtree construction to be + // just integers, so we simply allow them. PatKind::Constant { value: mir::Const::Ty(ty::Const::new_value(tcx, cv, ty)) } } - ty::FnPtr(..) | ty::RawPtr(..) => unreachable!(), + ty::FnPtr(..) => { + // Valtree construction would never succeed for these, so this is unreachable. + unreachable!() + } _ => { let err = InvalidPattern { span, non_sm_ty: ty }; let e = tcx.sess.emit_err(err); diff --git a/tests/ui/consts/issue-34784.rs b/tests/ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.rs similarity index 50% rename from tests/ui/consts/issue-34784.rs rename to tests/ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.rs index 98d943470a7f..bbb98a162c33 100644 --- a/tests/ui/consts/issue-34784.rs +++ b/tests/ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.rs @@ -1,12 +1,11 @@ -// run-pass - -#![warn(pointer_structural_match)] +#![deny(pointer_structural_match)] #![allow(dead_code)] const C: *const u8 = &0; fn foo(x: *const u8) { match x { - C => {} + C => {} //~ERROR: behave unpredictably + //~| previously accepted _ => {} } } @@ -15,7 +14,8 @@ const D: *const [u8; 4] = b"abcd"; fn main() { match D { - D => {} + D => {} //~ERROR: behave unpredictably + //~| previously accepted _ => {} } } diff --git a/tests/ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.stderr b/tests/ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.stderr new file mode 100644 index 000000000000..af7caaf5b742 --- /dev/null +++ b/tests/ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.stderr @@ -0,0 +1,25 @@ +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:7:9 + | +LL | C => {} + | ^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 +note: the lint level is defined here + --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:1:9 + | +LL | #![deny(pointer_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:17:9 + | +LL | D => {} + | ^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + +error: aborting due to 2 previous errors + diff --git a/tests/ui/consts/const_in_pattern/issue-44333.rs b/tests/ui/consts/const_in_pattern/issue-44333.rs index 96e8795e52d5..aaf1edb6fe6e 100644 --- a/tests/ui/consts/const_in_pattern/issue-44333.rs +++ b/tests/ui/consts/const_in_pattern/issue-44333.rs @@ -16,9 +16,9 @@ const BAR: Func = bar; fn main() { match test(std::env::consts::ARCH.len()) { - FOO => println!("foo"), //~ WARN pointers in patterns behave unpredictably + FOO => println!("foo"), //~ WARN behave unpredictably //~^ WARN will become a hard error - BAR => println!("bar"), //~ WARN pointers in patterns behave unpredictably + BAR => println!("bar"), //~ WARN behave unpredictably //~^ WARN will become a hard error _ => unreachable!(), } diff --git a/tests/ui/consts/const_in_pattern/issue-44333.stderr b/tests/ui/consts/const_in_pattern/issue-44333.stderr index 731ef509ccad..441aeecbc6d9 100644 --- a/tests/ui/consts/const_in_pattern/issue-44333.stderr +++ b/tests/ui/consts/const_in_pattern/issue-44333.stderr @@ -1,4 +1,4 @@ -warning: function pointers and unsized pointers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/issue-44333.rs:19:9 | LL | FOO => println!("foo"), @@ -12,7 +12,7 @@ note: the lint level is defined here LL | #![warn(pointer_structural_match)] | ^^^^^^^^^^^^^^^^^^^^^^^^ -warning: function pointers and unsized pointers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/issue-44333.rs:21:9 | LL | BAR => println!("bar"), diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.rs index 567685950e9e..767d9754299f 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.rs +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.rs @@ -33,7 +33,7 @@ fn main() { let s = B(my_fn); match s { B(TEST) => println!("matched"), - //~^ WARN pointers in patterns behave unpredictably + //~^ WARN behave unpredictably //~| WARN this was previously accepted by the compiler but is being phased out _ => panic!("didn't match") }; diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr index d6afc0255ec4..1aa627a80350 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr @@ -1,4 +1,4 @@ -warning: function pointers and unsized pointers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/issue-63479-match-fnptr.rs:35:7 | LL | B(TEST) => println!("matched"), From af6c7e0ca154fe4c14b29405e1970b824095920d Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 20 Oct 2023 08:35:36 +0200 Subject: [PATCH 169/435] also lint against fn ptr and raw ptr nested inside the const --- .../src/thir/pattern/const_to_pat.rs | 22 ++++++++----------- .../issue-34784-match-on-non-int-raw-ptr.rs | 11 ++++++++++ ...ssue-34784-match-on-non-int-raw-ptr.stderr | 15 ++++++++++--- .../issue-63479-match-fnptr.rs | 9 +++++++- .../issue-63479-match-fnptr.stderr | 13 +++++++++-- 5 files changed, 51 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index ad386b129ce8..53823c9226cd 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -239,19 +239,15 @@ impl<'tcx> ConstToPat<'tcx> { } } } else if !self.saw_const_match_lint.get() { - match cv.ty().kind() { - ty::RawPtr(..) if have_valtree => { - // This is a good raw pointer, it was accepted by valtree construction. - } - ty::FnPtr(..) | ty::RawPtr(..) => { - self.tcx().emit_spanned_lint( - lint::builtin::POINTER_STRUCTURAL_MATCH, - self.id, - self.span, - PointerPattern, - ); - } - _ => {} + if !have_valtree { + // The only way valtree construction can fail without the structural match + // checker finding a violation is if there is a pointer somewhere. + self.tcx().emit_spanned_lint( + lint::builtin::POINTER_STRUCTURAL_MATCH, + self.id, + self.span, + PointerPattern, + ); } } diff --git a/tests/ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.rs b/tests/ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.rs index bbb98a162c33..2491071d1e1d 100644 --- a/tests/ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.rs +++ b/tests/ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.rs @@ -1,6 +1,9 @@ #![deny(pointer_structural_match)] #![allow(dead_code)] + const C: *const u8 = &0; +// Make sure we also find pointers nested in other types. +const C_INNER: (*const u8, u8) = (C, 0); fn foo(x: *const u8) { match x { @@ -10,6 +13,14 @@ fn foo(x: *const u8) { } } +fn foo2(x: *const u8) { + match (x, 1) { + C_INNER => {} //~ERROR: behave unpredictably + //~| previously accepted + _ => {} + } +} + const D: *const [u8; 4] = b"abcd"; fn main() { diff --git a/tests/ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.stderr b/tests/ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.stderr index af7caaf5b742..ab53346b5eed 100644 --- a/tests/ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.stderr +++ b/tests/ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.stderr @@ -1,5 +1,5 @@ error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. - --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:7:9 + --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:10:9 | LL | C => {} | ^ @@ -13,7 +13,16 @@ LL | #![deny(pointer_structural_match)] | ^^^^^^^^^^^^^^^^^^^^^^^^ error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. - --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:17:9 + --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:18:9 + | +LL | C_INNER => {} + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:28:9 | LL | D => {} | ^ @@ -21,5 +30,5 @@ LL | D => {} = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #62411 -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.rs index 767d9754299f..b05b8c8da1f3 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.rs +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.rs @@ -26,6 +26,7 @@ fn my_fn(_args: &[A]) { } const TEST: Fn = my_fn; +const TEST2: (Fn, u8) = (TEST, 0); struct B(Fn); @@ -33,8 +34,14 @@ fn main() { let s = B(my_fn); match s { B(TEST) => println!("matched"), - //~^ WARN behave unpredictably + //~^ WARN behave unpredictably //~| WARN this was previously accepted by the compiler but is being phased out _ => panic!("didn't match") }; + match (s.0, 0) { + TEST2 => println!("matched"), + //~^ WARN behave unpredictably + //~| WARN this was previously accepted by the compiler but is being phased out + _ => panic!("didn't match") + } } diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr index 1aa627a80350..4fdfce60bb86 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr @@ -1,5 +1,5 @@ warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. - --> $DIR/issue-63479-match-fnptr.rs:35:7 + --> $DIR/issue-63479-match-fnptr.rs:36:7 | LL | B(TEST) => println!("matched"), | ^^^^ @@ -12,5 +12,14 @@ note: the lint level is defined here LL | #![warn(pointer_structural_match)] | ^^^^^^^^^^^^^^^^^^^^^^^^ -warning: 1 warning emitted +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/issue-63479-match-fnptr.rs:42:5 + | +LL | TEST2 => println!("matched"), + | ^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + +warning: 2 warnings emitted From 70a8e157ab485a775c1f648ad7967ffc3535c5b9 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 20 Oct 2023 08:39:54 +0200 Subject: [PATCH 170/435] make pointer_structural_match warn-by-default --- compiler/rustc_lint_defs/src/builtin.rs | 2 +- library/core/src/marker.rs | 1 + .../match/match-edge-cases_1.rs | 3 +- .../match/match-edge-cases_1.stderr | 12 +++ tests/ui/pattern/usefulness/consts-opaque.rs | 24 +++-- .../pattern/usefulness/consts-opaque.stderr | 84 +++++++++++++++-- .../fn-ptr-is-structurally-matchable.rs | 30 ++++-- .../fn-ptr-is-structurally-matchable.stderr | 93 +++++++++++++++++++ 8 files changed, 223 insertions(+), 26 deletions(-) create mode 100644 tests/ui/closures/2229_closure_analysis/match/match-edge-cases_1.stderr create mode 100644 tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.stderr diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index f033504c5238..bef9f469cc65 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -2226,7 +2226,7 @@ declare_lint! { /// in different crates and not deduplicated again via LTO. Pointer identity for memory /// created by `const` is similarly unreliable. pub POINTER_STRUCTURAL_MATCH, - Allow, + Warn, "pointers are not structural-match", @future_incompatible = FutureIncompatibleInfo { reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index f1594501d408..9e49f146f733 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -247,6 +247,7 @@ marker_impls! { /// /// const CFN: Wrap = Wrap(higher_order); /// +/// #[allow(pointer_structural_match)] /// fn main() { /// match CFN { /// CFN => {} diff --git a/tests/ui/closures/2229_closure_analysis/match/match-edge-cases_1.rs b/tests/ui/closures/2229_closure_analysis/match/match-edge-cases_1.rs index 914ebbe26a57..106485e04eea 100644 --- a/tests/ui/closures/2229_closure_analysis/match/match-edge-cases_1.rs +++ b/tests/ui/closures/2229_closure_analysis/match/match-edge-cases_1.rs @@ -26,7 +26,8 @@ pub fn edge_case_str(event: String) { pub fn edge_case_raw_ptr(event: *const i32) { let _ = || { match event { - NUMBER_POINTER => (), + NUMBER_POINTER => (), //~WARN behave unpredictably + //~| previously accepted _ => (), }; }; diff --git a/tests/ui/closures/2229_closure_analysis/match/match-edge-cases_1.stderr b/tests/ui/closures/2229_closure_analysis/match/match-edge-cases_1.stderr new file mode 100644 index 000000000000..c83ba41976bc --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/match/match-edge-cases_1.stderr @@ -0,0 +1,12 @@ +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/match-edge-cases_1.rs:29:13 + | +LL | NUMBER_POINTER => (), + | ^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + = note: `#[warn(pointer_structural_match)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/pattern/usefulness/consts-opaque.rs b/tests/ui/pattern/usefulness/consts-opaque.rs index 6dc1425cf037..27e305a39724 100644 --- a/tests/ui/pattern/usefulness/consts-opaque.rs +++ b/tests/ui/pattern/usefulness/consts-opaque.rs @@ -95,8 +95,10 @@ fn main() { const QUUX: Quux = quux; match QUUX { - QUUX => {} - QUUX => {} + QUUX => {} //~WARN behave unpredictably + //~| previously accepted + QUUX => {} //~WARN behave unpredictably + //~| previously accepted _ => {} } @@ -105,14 +107,17 @@ fn main() { const WRAPQUUX: Wrap = Wrap(quux); match WRAPQUUX { - WRAPQUUX => {} - WRAPQUUX => {} + WRAPQUUX => {} //~WARN behave unpredictably + //~| previously accepted + WRAPQUUX => {} //~WARN behave unpredictably + //~| previously accepted Wrap(_) => {} } match WRAPQUUX { Wrap(_) => {} - WRAPQUUX => {} + WRAPQUUX => {} //~WARN behave unpredictably + //~| previously accepted } match WRAPQUUX { @@ -121,7 +126,8 @@ fn main() { match WRAPQUUX { //~^ ERROR: non-exhaustive patterns: `Wrap(_)` not covered - WRAPQUUX => {} + WRAPQUUX => {} //~WARN behave unpredictably + //~| previously accepted } #[derive(PartialEq, Eq)] @@ -132,9 +138,11 @@ fn main() { const WHOKNOWSQUUX: WhoKnows = WhoKnows::Yay(quux); match WHOKNOWSQUUX { - WHOKNOWSQUUX => {} + WHOKNOWSQUUX => {} //~WARN behave unpredictably + //~| previously accepted WhoKnows::Yay(_) => {} - WHOKNOWSQUUX => {} + WHOKNOWSQUUX => {} //~WARN behave unpredictably + //~| previously accepted WhoKnows::Nope => {} } } diff --git a/tests/ui/pattern/usefulness/consts-opaque.stderr b/tests/ui/pattern/usefulness/consts-opaque.stderr index 51f2f276bbe2..09f72ba927e1 100644 --- a/tests/ui/pattern/usefulness/consts-opaque.stderr +++ b/tests/ui/pattern/usefulness/consts-opaque.stderr @@ -91,24 +91,96 @@ LL | BAZ => {} = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/consts-opaque.rs:98:9 + | +LL | QUUX => {} + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + = note: `#[warn(pointer_structural_match)]` on by default + +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/consts-opaque.rs:100:9 + | +LL | QUUX => {} + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/consts-opaque.rs:110:9 + | +LL | WRAPQUUX => {} + | ^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/consts-opaque.rs:112:9 + | +LL | WRAPQUUX => {} + | ^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/consts-opaque.rs:119:9 + | +LL | WRAPQUUX => {} + | ^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/consts-opaque.rs:129:9 + | +LL | WRAPQUUX => {} + | ^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/consts-opaque.rs:141:9 + | +LL | WHOKNOWSQUUX => {} + | ^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/consts-opaque.rs:144:9 + | +LL | WHOKNOWSQUUX => {} + | ^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + error[E0004]: non-exhaustive patterns: `Wrap(_)` not covered - --> $DIR/consts-opaque.rs:122:11 + --> $DIR/consts-opaque.rs:127:11 | LL | match WRAPQUUX { | ^^^^^^^^ pattern `Wrap(_)` not covered | note: `Wrap usize>` defined here - --> $DIR/consts-opaque.rs:104:12 + --> $DIR/consts-opaque.rs:106:12 | LL | struct Wrap(T); | ^^^^ = note: the matched value is of type `Wrap usize>` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ WRAPQUUX => {}, -LL + Wrap(_) => todo!() - | +LL | WRAPQUUX => {}, Wrap(_) => todo!() + | ++++++++++++++++++++ -error: aborting due to 10 previous errors; 1 warning emitted +error: aborting due to 10 previous errors; 9 warnings emitted For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.rs index 2b3fbd2a4d28..e591b2a93e12 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.rs +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.rs @@ -40,7 +40,8 @@ fn main() { const CFN1: Wrap = Wrap(trivial); let input: Wrap = Wrap(trivial); match Wrap(input) { - Wrap(CFN1) => count += 1, + Wrap(CFN1) => count += 1, //~WARN behave unpredictably + //~| previously accepted Wrap(_) => {} }; @@ -48,7 +49,8 @@ fn main() { const CFN2: Wrap = Wrap(sm_to); let input: Wrap = Wrap(sm_to); match Wrap(input) { - Wrap(CFN2) => count += 1, + Wrap(CFN2) => count += 1, //~WARN behave unpredictably + //~| previously accepted Wrap(_) => {} }; @@ -56,7 +58,8 @@ fn main() { const CFN3: Wrap SM> = Wrap(to_sm); let input: Wrap SM> = Wrap(to_sm); match Wrap(input) { - Wrap(CFN3) => count += 1, + Wrap(CFN3) => count += 1, //~WARN behave unpredictably + //~| previously accepted Wrap(_) => {} }; @@ -64,7 +67,8 @@ fn main() { const CFN4: Wrap = Wrap(not_sm_to); let input: Wrap = Wrap(not_sm_to); match Wrap(input) { - Wrap(CFN4) => count += 1, + Wrap(CFN4) => count += 1, //~WARN behave unpredictably + //~| previously accepted Wrap(_) => {} }; @@ -72,7 +76,8 @@ fn main() { const CFN5: Wrap NotSM> = Wrap(to_not_sm); let input: Wrap NotSM> = Wrap(to_not_sm); match Wrap(input) { - Wrap(CFN5) => count += 1, + Wrap(CFN5) => count += 1, //~WARN behave unpredictably + //~| previously accepted Wrap(_) => {} }; @@ -80,7 +85,8 @@ fn main() { const CFN6: Wrap = Wrap(r_sm_to); let input: Wrap = Wrap(r_sm_to); match Wrap(input) { - Wrap(CFN6) => count += 1, + Wrap(CFN6) => count += 1, //~WARN behave unpredictably + //~| previously accepted Wrap(_) => {} }; @@ -88,7 +94,8 @@ fn main() { const CFN7: Wrap &SM> = Wrap(r_to_r_sm); let input: Wrap &SM> = Wrap(r_to_r_sm); match Wrap(input) { - Wrap(CFN7) => count += 1, + Wrap(CFN7) => count += 1, //~WARN behave unpredictably + //~| previously accepted Wrap(_) => {} }; @@ -96,7 +103,8 @@ fn main() { const CFN8: Wrap = Wrap(r_not_sm_to); let input: Wrap = Wrap(r_not_sm_to); match Wrap(input) { - Wrap(CFN8) => count += 1, + Wrap(CFN8) => count += 1, //~WARN behave unpredictably + //~| previously accepted Wrap(_) => {} }; @@ -104,7 +112,8 @@ fn main() { const CFN9: Wrap &NotSM> = Wrap(r_to_r_not_sm); let input: Wrap &NotSM> = Wrap(r_to_r_not_sm); match Wrap(input) { - Wrap(CFN9) => count += 1, + Wrap(CFN9) => count += 1, //~WARN behave unpredictably + //~| previously accepted Wrap(_) => {} }; @@ -126,7 +135,8 @@ fn main() { let input = Foo { alpha: not_sm_to, beta: to_not_sm, gamma: sm_to, delta: to_sm }; match input { - CFOO => count += 1, + CFOO => count += 1, //~WARN behave unpredictably + //~| previously accepted Foo { .. } => {} }; diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.stderr new file mode 100644 index 000000000000..080bf5885ba7 --- /dev/null +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.stderr @@ -0,0 +1,93 @@ +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/fn-ptr-is-structurally-matchable.rs:43:14 + | +LL | Wrap(CFN1) => count += 1, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + = note: `#[warn(pointer_structural_match)]` on by default + +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/fn-ptr-is-structurally-matchable.rs:52:14 + | +LL | Wrap(CFN2) => count += 1, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/fn-ptr-is-structurally-matchable.rs:61:14 + | +LL | Wrap(CFN3) => count += 1, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/fn-ptr-is-structurally-matchable.rs:70:14 + | +LL | Wrap(CFN4) => count += 1, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/fn-ptr-is-structurally-matchable.rs:79:14 + | +LL | Wrap(CFN5) => count += 1, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/fn-ptr-is-structurally-matchable.rs:88:14 + | +LL | Wrap(CFN6) => count += 1, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/fn-ptr-is-structurally-matchable.rs:97:14 + | +LL | Wrap(CFN7) => count += 1, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/fn-ptr-is-structurally-matchable.rs:106:14 + | +LL | Wrap(CFN8) => count += 1, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/fn-ptr-is-structurally-matchable.rs:115:14 + | +LL | Wrap(CFN9) => count += 1, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/fn-ptr-is-structurally-matchable.rs:138:9 + | +LL | CFOO => count += 1, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + +warning: 10 warnings emitted + From 41dcb52153cfb2e3a5eb74af0626e6e984e2ddc4 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 29 Oct 2023 20:30:50 +0000 Subject: [PATCH 171/435] Merge commit 'dde58803fd6cbb270c7a437f36a8a3a29fbef679' into sync_cg_clif-2023-10-29 --- Cargo.toml | 4 +- patches/stdlib-lock.toml | 17 --- rust-toolchain | 2 +- scripts/setup_rust_fork.sh | 4 +- scripts/test_bootstrap.sh | 4 +- src/global_asm.rs | 113 ++++++++++++++------ src/inline_asm.rs | 214 ++----------------------------------- src/intrinsics/cpuid.rs | 74 ------------- src/intrinsics/mod.rs | 2 - 9 files changed, 100 insertions(+), 334 deletions(-) delete mode 100644 src/intrinsics/cpuid.rs diff --git a/Cargo.toml b/Cargo.toml index b5e6f431123e..30db10f74571 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,9 +35,9 @@ smallvec = "1.8.1" [features] # Enable features not ready to be enabled when compiling as part of rustc -unstable-features = ["jit", "inline_asm"] +unstable-features = ["jit", "inline_asm_sym"] jit = ["cranelift-jit", "libloading"] -inline_asm = [] +inline_asm_sym = [] [package.metadata.rust-analyzer] rustc_private = true diff --git a/patches/stdlib-lock.toml b/patches/stdlib-lock.toml index f10b4d6b9d4f..9902bca8eab2 100644 --- a/patches/stdlib-lock.toml +++ b/patches/stdlib-lock.toml @@ -40,22 +40,6 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56fc6cf8dc8c4158eed8649f9b8b0ea1518eb62b544fe9490d66fa0b349eafe9" -[[package]] -name = "auxv" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e50430f9beb8effb02399fa81c76eeaa26b05e4f03b09285cad8d079c1af5a3d" -dependencies = [ - "byteorder", - "gcc", -] - -[[package]] -name = "byteorder" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" - [[package]] name = "cc" version = "1.0.79" @@ -388,7 +372,6 @@ dependencies = [ name = "std_detect" version = "0.1.5" dependencies = [ - "auxv", "cfg-if", "compiler_builtins", "cupid", diff --git a/rust-toolchain b/rust-toolchain index 3735ac1c17b1..7e3eaacf8ef0 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2023-10-21" +channel = "nightly-2023-10-29" components = ["rust-src", "rustc-dev", "llvm-tools"] diff --git a/scripts/setup_rust_fork.sh b/scripts/setup_rust_fork.sh index 3e48fb006dea..bbb8a010d965 100644 --- a/scripts/setup_rust_fork.sh +++ b/scripts/setup_rust_fork.sh @@ -4,7 +4,9 @@ set -e # Compiletest expects all standard library paths to start with /rustc/FAKE_PREFIX. # CG_CLIF_STDLIB_REMAP_PATH_PREFIX will cause cg_clif's build system to pass # --remap-path-prefix to handle this. -CG_CLIF_STDLIB_REMAP_PATH_PREFIX=/rustc/FAKE_PREFIX ./y.sh build +# CG_CLIF_FORCE_GNU_AS will force usage of as instead of the LLVM backend of rustc as we +# the LLVM backend isn't compiled in here. +CG_CLIF_FORCE_GNU_AS=1 CG_CLIF_STDLIB_REMAP_PATH_PREFIX=/rustc/FAKE_PREFIX ./y.sh build echo "[SETUP] Rust fork" git clone https://github.com/rust-lang/rust.git || true diff --git a/scripts/test_bootstrap.sh b/scripts/test_bootstrap.sh index 791d457993de..a8f6d7a20248 100755 --- a/scripts/test_bootstrap.sh +++ b/scripts/test_bootstrap.sh @@ -11,5 +11,7 @@ rm -r compiler/rustc_codegen_cranelift/{Cargo.*,src} cp ../Cargo.* compiler/rustc_codegen_cranelift/ cp -r ../src compiler/rustc_codegen_cranelift/src -./x.py build --stage 1 library/std +# CG_CLIF_FORCE_GNU_AS will force usage of as instead of the LLVM backend of rustc as we +# the LLVM backend isn't compiled in here. +CG_CLIF_FORCE_GNU_AS=1 ./x.py build --stage 1 library/std popd diff --git a/src/global_asm.rs b/src/global_asm.rs index 6692d1b85eac..b14007f4e523 100644 --- a/src/global_asm.rs +++ b/src/global_asm.rs @@ -46,6 +46,13 @@ pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String, global_asm.push_str(&string); } InlineAsmOperand::SymFn { anon_const } => { + if cfg!(not(feature = "inline_asm_sym")) { + tcx.sess.span_err( + item.span, + "asm! and global_asm! sym operands are not yet supported", + ); + } + let ty = tcx.typeck_body(anon_const.body).node_type(anon_const.hir_id); let instance = match ty.kind() { &ty::FnDef(def_id, args) => Instance::new(def_id, args), @@ -57,6 +64,13 @@ pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String, global_asm.push_str(symbol.name); } InlineAsmOperand::SymStatic { path: _, def_id } => { + if cfg!(not(feature = "inline_asm_sym")) { + tcx.sess.span_err( + item.span, + "asm! and global_asm! sym operands are not yet supported", + ); + } + let instance = Instance::mono(tcx, def_id).polymorphize(tcx); let symbol = tcx.symbol_name(instance); global_asm.push_str(symbol.name); @@ -81,22 +95,23 @@ pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String, } } -pub(crate) fn asm_supported(tcx: TyCtxt<'_>) -> bool { - cfg!(feature = "inline_asm") && !tcx.sess.target.is_like_windows -} - #[derive(Debug)] pub(crate) struct GlobalAsmConfig { - asm_enabled: bool, assembler: PathBuf, + target: String, pub(crate) output_filenames: Arc, } impl GlobalAsmConfig { pub(crate) fn new(tcx: TyCtxt<'_>) -> Self { GlobalAsmConfig { - asm_enabled: asm_supported(tcx), assembler: crate::toolchain::get_toolchain_binary(tcx.sess, "as"), + target: match &tcx.sess.opts.target_triple { + rustc_target::spec::TargetTriple::TargetTriple(triple) => triple.clone(), + rustc_target::spec::TargetTriple::TargetJson { path_for_rustdoc, .. } => { + path_for_rustdoc.to_str().unwrap().to_owned() + } + }, output_filenames: tcx.output_filenames(()).clone(), } } @@ -111,21 +126,6 @@ pub(crate) fn compile_global_asm( return Ok(None); } - if !config.asm_enabled { - if global_asm.contains("__rust_probestack") { - return Ok(None); - } - - if cfg!(not(feature = "inline_asm")) { - return Err( - "asm! and global_asm! support is disabled while compiling rustc_codegen_cranelift" - .to_owned(), - ); - } else { - return Err("asm! and global_asm! are not yet supported on Windows".to_owned()); - } - } - // Remove all LLVM style comments let mut global_asm = global_asm .lines() @@ -134,20 +134,67 @@ pub(crate) fn compile_global_asm( .join("\n"); global_asm.push('\n'); - let output_object_file = config.output_filenames.temp_path(OutputType::Object, Some(cgu_name)); + let global_asm_object_file = add_file_stem_postfix( + config.output_filenames.temp_path(OutputType::Object, Some(cgu_name)), + ".asm", + ); // Assemble `global_asm` - let global_asm_object_file = add_file_stem_postfix(output_object_file, ".asm"); - let mut child = Command::new(&config.assembler) - .arg("-o") - .arg(&global_asm_object_file) - .stdin(Stdio::piped()) - .spawn() - .expect("Failed to spawn `as`."); - child.stdin.take().unwrap().write_all(global_asm.as_bytes()).unwrap(); - let status = child.wait().expect("Failed to wait for `as`."); - if !status.success() { - return Err(format!("Failed to assemble `{}`", global_asm)); + if option_env!("CG_CLIF_FORCE_GNU_AS").is_some() { + let mut child = Command::new(&config.assembler) + .arg("-o") + .arg(&global_asm_object_file) + .stdin(Stdio::piped()) + .spawn() + .expect("Failed to spawn `as`."); + child.stdin.take().unwrap().write_all(global_asm.as_bytes()).unwrap(); + let status = child.wait().expect("Failed to wait for `as`."); + if !status.success() { + return Err(format!("Failed to assemble `{}`", global_asm)); + } + } else { + let mut child = Command::new(std::env::current_exe().unwrap()) + .arg("--target") + .arg(&config.target) + .arg("--crate-type") + .arg("staticlib") + .arg("--emit") + .arg("obj") + .arg("-o") + .arg(&global_asm_object_file) + .arg("-") + .arg("-Abad_asm_style") + .arg("-Zcodegen-backend=llvm") + .stdin(Stdio::piped()) + .spawn() + .expect("Failed to spawn `as`."); + let mut stdin = child.stdin.take().unwrap(); + stdin + .write_all( + br####" + #![feature(decl_macro, no_core, rustc_attrs)] + #![allow(internal_features)] + #![no_core] + #[rustc_builtin_macro] + #[rustc_macro_transparency = "semitransparent"] + macro global_asm() { /* compiler built-in */ } + global_asm!(r###" + "####, + ) + .unwrap(); + stdin.write_all(global_asm.as_bytes()).unwrap(); + stdin + .write_all( + br####" + "###); + "####, + ) + .unwrap(); + std::mem::drop(stdin); + let status = child.wait().expect("Failed to wait for `as`."); + if !status.success() { + return Err(format!("Failed to assemble `{}`", global_asm)); + } } Ok(Some(global_asm_object_file)) diff --git a/src/inline_asm.rs b/src/inline_asm.rs index 0517c609337b..331649b2ec24 100644 --- a/src/inline_asm.rs +++ b/src/inline_asm.rs @@ -8,7 +8,6 @@ use rustc_span::sym; use rustc_target::asm::*; use target_lexicon::BinaryFormat; -use crate::global_asm::asm_supported; use crate::prelude::*; enum CInlineAsmOperand<'tcx> { @@ -45,208 +44,11 @@ pub(crate) fn codegen_inline_asm<'tcx>( ) { // FIXME add .eh_frame unwind info directives - if !asm_supported(fx.tcx) { - if template.is_empty() { - let destination_block = fx.get_block(destination.unwrap()); - fx.bcx.ins().jump(destination_block, &[]); - return; - } - - // Used by panic_abort - if template[0] == InlineAsmTemplatePiece::String("int $$0x29".to_string()) { - fx.bcx.ins().trap(TrapCode::User(1)); - return; - } - - // Used by stdarch - if template[0] == InlineAsmTemplatePiece::String("mov ".to_string()) - && matches!( - template[1], - InlineAsmTemplatePiece::Placeholder { - operand_idx: 0, - modifier: Some('r'), - span: _ - } - ) - && template[2] == InlineAsmTemplatePiece::String(", rbx".to_string()) - && template[3] == InlineAsmTemplatePiece::String("\n".to_string()) - && template[4] == InlineAsmTemplatePiece::String("cpuid".to_string()) - && template[5] == InlineAsmTemplatePiece::String("\n".to_string()) - && template[6] == InlineAsmTemplatePiece::String("xchg ".to_string()) - && matches!( - template[7], - InlineAsmTemplatePiece::Placeholder { - operand_idx: 0, - modifier: Some('r'), - span: _ - } - ) - && template[8] == InlineAsmTemplatePiece::String(", rbx".to_string()) - { - assert_eq!(operands.len(), 4); - let (leaf, eax_place) = match operands[1] { - InlineAsmOperand::InOut { - reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::ax)), - late: _, - ref in_value, - out_place: Some(out_place), - } => ( - crate::base::codegen_operand(fx, in_value).load_scalar(fx), - crate::base::codegen_place(fx, out_place), - ), - _ => unreachable!(), - }; - let ebx_place = match operands[0] { - InlineAsmOperand::Out { - reg: - InlineAsmRegOrRegClass::RegClass(InlineAsmRegClass::X86( - X86InlineAsmRegClass::reg, - )), - late: _, - place: Some(place), - } => crate::base::codegen_place(fx, place), - _ => unreachable!(), - }; - let (sub_leaf, ecx_place) = match operands[2] { - InlineAsmOperand::InOut { - reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::cx)), - late: _, - ref in_value, - out_place: Some(out_place), - } => ( - crate::base::codegen_operand(fx, in_value).load_scalar(fx), - crate::base::codegen_place(fx, out_place), - ), - _ => unreachable!(), - }; - let edx_place = match operands[3] { - InlineAsmOperand::Out { - reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::dx)), - late: _, - place: Some(place), - } => crate::base::codegen_place(fx, place), - _ => unreachable!(), - }; - - let (eax, ebx, ecx, edx) = crate::intrinsics::codegen_cpuid_call(fx, leaf, sub_leaf); - - eax_place.write_cvalue(fx, CValue::by_val(eax, fx.layout_of(fx.tcx.types.u32))); - ebx_place.write_cvalue(fx, CValue::by_val(ebx, fx.layout_of(fx.tcx.types.u32))); - ecx_place.write_cvalue(fx, CValue::by_val(ecx, fx.layout_of(fx.tcx.types.u32))); - edx_place.write_cvalue(fx, CValue::by_val(edx, fx.layout_of(fx.tcx.types.u32))); - let destination_block = fx.get_block(destination.unwrap()); - fx.bcx.ins().jump(destination_block, &[]); - return; - } - - // Used by compiler-builtins - if fx.tcx.symbol_name(fx.instance).name.starts_with("___chkstk") { - // ___chkstk, ___chkstk_ms and __alloca are only used on Windows - crate::trap::trap_unimplemented(fx, "Stack probes are not supported"); - return; - } else if fx.tcx.symbol_name(fx.instance).name == "__alloca" { - crate::trap::trap_unimplemented(fx, "Alloca is not supported"); - return; - } - - // Used by core::hint::spin_loop() - if template[0] - == InlineAsmTemplatePiece::String(".insn i 0x0F, 0, x0, x0, 0x010".to_string()) - && template.len() == 1 - { - let destination_block = fx.get_block(destination.unwrap()); - fx.bcx.ins().jump(destination_block, &[]); - return; - } - - // Used by measureme - if template[0] == InlineAsmTemplatePiece::String("xor %eax, %eax".to_string()) - && template[1] == InlineAsmTemplatePiece::String("\n".to_string()) - && template[2] == InlineAsmTemplatePiece::String("mov %rbx, ".to_string()) - && matches!( - template[3], - InlineAsmTemplatePiece::Placeholder { - operand_idx: 0, - modifier: Some('r'), - span: _ - } - ) - && template[4] == InlineAsmTemplatePiece::String("\n".to_string()) - && template[5] == InlineAsmTemplatePiece::String("cpuid".to_string()) - && template[6] == InlineAsmTemplatePiece::String("\n".to_string()) - && template[7] == InlineAsmTemplatePiece::String("mov ".to_string()) - && matches!( - template[8], - InlineAsmTemplatePiece::Placeholder { - operand_idx: 0, - modifier: Some('r'), - span: _ - } - ) - && template[9] == InlineAsmTemplatePiece::String(", %rbx".to_string()) - { - let destination_block = fx.get_block(destination.unwrap()); - fx.bcx.ins().jump(destination_block, &[]); - return; - } else if template[0] == InlineAsmTemplatePiece::String("rdpmc".to_string()) { - // Return zero dummy values for all performance counters - match operands[0] { - InlineAsmOperand::In { - reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::cx)), - value: _, - } => {} - _ => unreachable!(), - }; - let lo = match operands[1] { - InlineAsmOperand::Out { - reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::ax)), - late: true, - place: Some(place), - } => crate::base::codegen_place(fx, place), - _ => unreachable!(), - }; - let hi = match operands[2] { - InlineAsmOperand::Out { - reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::dx)), - late: true, - place: Some(place), - } => crate::base::codegen_place(fx, place), - _ => unreachable!(), - }; - - let u32_layout = fx.layout_of(fx.tcx.types.u32); - let zero = fx.bcx.ins().iconst(types::I32, 0); - lo.write_cvalue(fx, CValue::by_val(zero, u32_layout)); - hi.write_cvalue(fx, CValue::by_val(zero, u32_layout)); - - let destination_block = fx.get_block(destination.unwrap()); - fx.bcx.ins().jump(destination_block, &[]); - return; - } else if template[0] == InlineAsmTemplatePiece::String("lock xadd ".to_string()) - && matches!( - template[1], - InlineAsmTemplatePiece::Placeholder { operand_idx: 1, modifier: None, span: _ } - ) - && template[2] == InlineAsmTemplatePiece::String(", (".to_string()) - && matches!( - template[3], - InlineAsmTemplatePiece::Placeholder { operand_idx: 0, modifier: None, span: _ } - ) - && template[4] == InlineAsmTemplatePiece::String(")".to_string()) - { - let destination_block = fx.get_block(destination.unwrap()); - fx.bcx.ins().jump(destination_block, &[]); - return; - } - - if cfg!(not(feature = "inline_asm")) { - fx.tcx.sess.span_err( - span, - "asm! and global_asm! support is disabled while compiling rustc_codegen_cranelift", - ); - } else { - fx.tcx.sess.span_err(span, "asm! and global_asm! are not yet supported on Windows"); - } + // Used by panic_abort on Windows, but uses a syntax which only happens to work with + // asm!() by accident and breaks with the GNU assembler as well as global_asm!() for + // the LLVM backend. + if template[0] == InlineAsmTemplatePiece::String("int $$0x29".to_string()) { + fx.bcx.ins().trap(TrapCode::User(1)); return; } @@ -280,6 +82,12 @@ pub(crate) fn codegen_inline_asm<'tcx>( CInlineAsmOperand::Const { value } } InlineAsmOperand::SymFn { ref value } => { + if cfg!(not(feature = "inline_asm_sym")) { + fx.tcx + .sess + .span_err(span, "asm! and global_asm! sym operands are not yet supported"); + } + let const_ = fx.monomorphize(value.const_); if let ty::FnDef(def_id, args) = *const_.ty().kind() { let instance = ty::Instance::resolve_for_fn_ptr( diff --git a/src/intrinsics/cpuid.rs b/src/intrinsics/cpuid.rs deleted file mode 100644 index 5120b89c4e8b..000000000000 --- a/src/intrinsics/cpuid.rs +++ /dev/null @@ -1,74 +0,0 @@ -//! Emulation of a subset of the cpuid x86 instruction. - -use crate::prelude::*; - -/// Emulates a subset of the cpuid x86 instruction. -/// -/// This emulates an intel cpu with sse and sse2 support, but which doesn't support anything else. -pub(crate) fn codegen_cpuid_call<'tcx>( - fx: &mut FunctionCx<'_, '_, 'tcx>, - leaf: Value, - _sub_leaf: Value, -) -> (Value, Value, Value, Value) { - let leaf_0 = fx.bcx.create_block(); - let leaf_1 = fx.bcx.create_block(); - let leaf_7 = fx.bcx.create_block(); - let leaf_8000_0000 = fx.bcx.create_block(); - let leaf_8000_0001 = fx.bcx.create_block(); - let unsupported_leaf = fx.bcx.create_block(); - - let dest = fx.bcx.create_block(); - let eax = fx.bcx.append_block_param(dest, types::I32); - let ebx = fx.bcx.append_block_param(dest, types::I32); - let ecx = fx.bcx.append_block_param(dest, types::I32); - let edx = fx.bcx.append_block_param(dest, types::I32); - - let mut switch = cranelift_frontend::Switch::new(); - switch.set_entry(0, leaf_0); - switch.set_entry(1, leaf_1); - switch.set_entry(7, leaf_7); - switch.set_entry(0x8000_0000, leaf_8000_0000); - switch.set_entry(0x8000_0001, leaf_8000_0001); - switch.emit(&mut fx.bcx, leaf, unsupported_leaf); - - fx.bcx.switch_to_block(leaf_0); - let max_basic_leaf = fx.bcx.ins().iconst(types::I32, 1); - let vend0 = fx.bcx.ins().iconst(types::I32, i64::from(u32::from_le_bytes(*b"Genu"))); - let vend2 = fx.bcx.ins().iconst(types::I32, i64::from(u32::from_le_bytes(*b"ineI"))); - let vend1 = fx.bcx.ins().iconst(types::I32, i64::from(u32::from_le_bytes(*b"ntel"))); - fx.bcx.ins().jump(dest, &[max_basic_leaf, vend0, vend1, vend2]); - - fx.bcx.switch_to_block(leaf_1); - let cpu_signature = fx.bcx.ins().iconst(types::I32, 0); - let additional_information = fx.bcx.ins().iconst(types::I32, 0); - let ecx_features = fx.bcx.ins().iconst(types::I32, 0); - let edx_features = fx.bcx.ins().iconst(types::I32, 1 << 25 /* sse */ | 1 << 26 /* sse2 */); - fx.bcx.ins().jump(dest, &[cpu_signature, additional_information, ecx_features, edx_features]); - - fx.bcx.switch_to_block(leaf_7); - // This leaf technically has subleaves, but we just return zero for all subleaves. - let zero = fx.bcx.ins().iconst(types::I32, 0); - fx.bcx.ins().jump(dest, &[zero, zero, zero, zero]); - - fx.bcx.switch_to_block(leaf_8000_0000); - let extended_max_basic_leaf = fx.bcx.ins().iconst(types::I32, 0); - let zero = fx.bcx.ins().iconst(types::I32, 0); - fx.bcx.ins().jump(dest, &[extended_max_basic_leaf, zero, zero, zero]); - - fx.bcx.switch_to_block(leaf_8000_0001); - let zero = fx.bcx.ins().iconst(types::I32, 0); - let proc_info_ecx = fx.bcx.ins().iconst(types::I32, 0); - let proc_info_edx = fx.bcx.ins().iconst(types::I32, 0); - fx.bcx.ins().jump(dest, &[zero, zero, proc_info_ecx, proc_info_edx]); - - fx.bcx.switch_to_block(unsupported_leaf); - crate::trap::trap_unimplemented( - fx, - "__cpuid_count arch intrinsic doesn't yet support specified leaf", - ); - - fx.bcx.switch_to_block(dest); - fx.bcx.ins().nop(); - - (eax, ebx, ecx, edx) -} diff --git a/src/intrinsics/mod.rs b/src/intrinsics/mod.rs index e94091e6a25e..83d5d53624eb 100644 --- a/src/intrinsics/mod.rs +++ b/src/intrinsics/mod.rs @@ -12,7 +12,6 @@ macro_rules! intrinsic_args { } } -mod cpuid; mod llvm; mod llvm_aarch64; mod llvm_x86; @@ -25,7 +24,6 @@ use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths}; use rustc_middle::ty::GenericArgsRef; use rustc_span::symbol::{kw, sym, Symbol}; -pub(crate) use self::cpuid::codegen_cpuid_call; pub(crate) use self::llvm::codegen_llvm_intrinsic_call; use crate::prelude::*; From 9c99afe3aa4bbab8da3d69fef66b399cb8c15304 Mon Sep 17 00:00:00 2001 From: cui fliter Date: Sun, 29 Oct 2023 11:50:40 +0800 Subject: [PATCH 172/435] Fix some typos Signed-off-by: cui fliter --- crates/hir-ty/src/mir/eval.rs | 4 ++-- crates/rust-analyzer/src/handlers/request.rs | 2 +- crates/syntax/src/tests/sourcegen_ast.rs | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/hir-ty/src/mir/eval.rs b/crates/hir-ty/src/mir/eval.rs index 7823c3203413..62efb858511b 100644 --- a/crates/hir-ty/src/mir/eval.rs +++ b/crates/hir-ty/src/mir/eval.rs @@ -162,7 +162,7 @@ pub struct Evaluator<'a> { not_special_fn_cache: RefCell>, mir_or_dyn_index_cache: RefCell>, /// Constantly dropping and creating `Locals` is very costly. We store - /// old locals that we normaly want to drop here, to reuse their allocations + /// old locals that we normally want to drop here, to reuse their allocations /// later. unused_locals_store: RefCell>>, cached_ptr_size: usize, @@ -2299,7 +2299,7 @@ impl Evaluator<'_> { match self.get_mir_or_dyn_index(def, generic_args.clone(), locals, span)? { MirOrDynIndex::Dyn(self_ty_idx) => { // In the layout of current possible receiver, which at the moment of writing this code is one of - // `&T`, `&mut T`, `Box`, `Rc`, `Arc`, and `Pin

` where `P` is one of possible recievers, + // `&T`, `&mut T`, `Box`, `Rc`, `Arc`, and `Pin

List of all crates

", - krates - .iter() - .map(|s| { - format!( - "
  • {s}
  • ", - trailing_slash = ensure_trailing_slash(s), - ) - }) - .collect::() + krates.iter().format_with("", |k, f| { + f(&format_args!( + "
  • {k}
  • ", + trailing_slash = ensure_trailing_slash(k), + )) + }) ); let v = layout::render(&shared.layout, &page, "", content, &shared.style_files); shared.fs.write(dst, v)?; diff --git a/src/librustdoc/passes/lint/redundant_explicit_links.rs b/src/librustdoc/passes/lint/redundant_explicit_links.rs index 0c15bf5f764f..472781e7d229 100644 --- a/src/librustdoc/passes/lint/redundant_explicit_links.rs +++ b/src/librustdoc/passes/lint/redundant_explicit_links.rs @@ -87,7 +87,7 @@ fn check_redundant_explicit_link<'md>( let link_data = collect_link_data(&mut offset_iter); if let Some(resolvable_link) = link_data.resolvable_link.as_ref() { - if &link_data.display_link.replace("`", "") != resolvable_link { + if &link_data.display_link.replace('`', "") != resolvable_link { // Skips if display link does not match to actual // resolvable link, usually happens if display link // has several segments, e.g. From fcdd99edcad6e77ecc11fb5066cec3db10ee6054 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Mon, 6 Nov 2023 19:55:05 -0500 Subject: [PATCH 331/435] Add -Zcross-crate-inline-threshold=yes --- compiler/rustc_interface/src/tests.rs | 12 +++++----- .../src/cross_crate_inline.rs | 10 ++++++-- compiler/rustc_session/src/config.rs | 22 +++++++++++++---- compiler/rustc_session/src/options.rs | 24 ++++++++++++++++++- .../cross-crate-inlining/always-inline.rs | 13 ++++++++++ .../cross-crate-inlining/auxiliary/always.rs | 20 ++++++++++++++++ .../cross-crate-inlining/auxiliary/leaf.rs | 20 ++++++++++++++++ .../cross-crate-inlining/auxiliary/never.rs | 20 ++++++++++++++++ .../cross-crate-inlining/leaf-inlining.rs | 20 ++++++++++++++++ .../cross-crate-inlining/never-inline.rs | 13 ++++++++++ 10 files changed, 161 insertions(+), 13 deletions(-) create mode 100644 tests/codegen/cross-crate-inlining/always-inline.rs create mode 100644 tests/codegen/cross-crate-inlining/auxiliary/always.rs create mode 100644 tests/codegen/cross-crate-inlining/auxiliary/leaf.rs create mode 100644 tests/codegen/cross-crate-inlining/auxiliary/never.rs create mode 100644 tests/codegen/cross-crate-inlining/leaf-inlining.rs create mode 100644 tests/codegen/cross-crate-inlining/never-inline.rs diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 8e66083a390f..d30816955231 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -4,11 +4,11 @@ use rustc_data_structures::profiling::TimePassesFormat; use rustc_errors::{emitter::HumanReadableErrorType, registry, ColorConfig}; use rustc_session::config::{ build_configuration, build_session_options, rustc_optgroups, BranchProtection, CFGuard, Cfg, - DebugInfo, DumpMonoStatsFormat, ErrorOutputType, ExternEntry, ExternLocation, Externs, Input, - InstrumentCoverage, InstrumentXRay, LinkSelfContained, LinkerPluginLto, LocationDetail, LtoCli, - MirSpanview, OomStrategy, Options, OutFileName, OutputType, OutputTypes, PAuthKey, PacRet, - Passes, Polonius, ProcMacroExecutionStrategy, Strip, SwitchWithOptPath, SymbolManglingVersion, - TraitSolver, WasiExecModel, + DebugInfo, DumpMonoStatsFormat, ErrorOutputType, ExternEntry, ExternLocation, Externs, + InliningThreshold, Input, InstrumentCoverage, InstrumentXRay, LinkSelfContained, + LinkerPluginLto, LocationDetail, LtoCli, MirSpanview, OomStrategy, Options, OutFileName, + OutputType, OutputTypes, PAuthKey, PacRet, Passes, Polonius, ProcMacroExecutionStrategy, Strip, + SwitchWithOptPath, SymbolManglingVersion, TraitSolver, WasiExecModel, }; use rustc_session::lint::Level; use rustc_session::search_paths::SearchPath; @@ -748,7 +748,7 @@ fn test_unstable_options_tracking_hash() { ); tracked!(codegen_backend, Some("abc".to_string())); tracked!(crate_attr, vec!["abc".to_string()]); - tracked!(cross_crate_inline_threshold, Some(200)); + tracked!(cross_crate_inline_threshold, InliningThreshold::Always); tracked!(debug_info_for_profiling, true); tracked!(debug_macros, true); tracked!(dep_info_omit_d_target, true); diff --git a/compiler/rustc_mir_transform/src/cross_crate_inline.rs b/compiler/rustc_mir_transform/src/cross_crate_inline.rs index 4d0e261ed1fd..261d9dd448d4 100644 --- a/compiler/rustc_mir_transform/src/cross_crate_inline.rs +++ b/compiler/rustc_mir_transform/src/cross_crate_inline.rs @@ -7,6 +7,7 @@ use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::*; use rustc_middle::query::Providers; use rustc_middle::ty::TyCtxt; +use rustc_session::config::InliningThreshold; use rustc_session::config::OptLevel; pub fn provide(providers: &mut Providers) { @@ -54,6 +55,12 @@ fn cross_crate_inlinable(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { return false; } + let threshold = match tcx.sess.opts.unstable_opts.cross_crate_inline_threshold { + InliningThreshold::Always => return true, + InliningThreshold::Sometimes(threshold) => threshold, + InliningThreshold::Never => return false, + }; + let mir = tcx.optimized_mir(def_id); let mut checker = CostChecker { tcx, callee_body: mir, calls: 0, statements: 0, landing_pads: 0, resumes: 0 }; @@ -61,8 +68,7 @@ fn cross_crate_inlinable(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { checker.calls == 0 && checker.resumes == 0 && checker.landing_pads == 0 - && checker.statements - <= tcx.sess.opts.unstable_opts.cross_crate_inline_threshold.unwrap_or(100) + && checker.statements <= threshold } struct CostChecker<'b, 'tcx> { diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index c94e0d0ed394..3cb8ec3a930f 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -3161,10 +3161,10 @@ impl PpMode { pub(crate) mod dep_tracking { use super::{ BranchProtection, CFGuard, CFProtection, CrateType, DebugInfo, DebugInfoCompression, - ErrorOutputType, InstrumentCoverage, InstrumentXRay, LinkerPluginLto, LocationDetail, - LtoCli, OomStrategy, OptLevel, OutFileName, OutputType, OutputTypes, Polonius, - RemapPathScopeComponents, ResolveDocLinks, SourceFileHashAlgorithm, SplitDwarfKind, - SwitchWithOptPath, SymbolManglingVersion, TraitSolver, TrimmedDefPaths, + ErrorOutputType, InliningThreshold, InstrumentCoverage, InstrumentXRay, LinkerPluginLto, + LocationDetail, LtoCli, OomStrategy, OptLevel, OutFileName, OutputType, OutputTypes, + Polonius, RemapPathScopeComponents, ResolveDocLinks, SourceFileHashAlgorithm, + SplitDwarfKind, SwitchWithOptPath, SymbolManglingVersion, TraitSolver, TrimmedDefPaths, }; use crate::lint; use crate::options::WasiExecModel; @@ -3270,6 +3270,7 @@ pub(crate) mod dep_tracking { LanguageIdentifier, TraitSolver, Polonius, + InliningThreshold, ); impl DepTrackingHash for (T1, T2) @@ -3435,3 +3436,16 @@ impl Polonius { matches!(self, Polonius::Next) } } + +#[derive(Clone, Copy, PartialEq, Hash, Debug)] +pub enum InliningThreshold { + Always, + Sometimes(usize), + Never, +} + +impl Default for InliningThreshold { + fn default() -> Self { + Self::Sometimes(100) + } +} diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 7510a41485af..964a26e94fed 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -428,6 +428,8 @@ mod desc { "one of supported execution strategies (`same-thread`, or `cross-thread`)"; pub const parse_dump_solver_proof_tree: &str = "one of: `always`, `on-request`, `on-error`"; pub const parse_remap_path_scope: &str = "comma separated list of scopes: `macro`, `diagnostics`, `unsplit-debuginfo`, `split-debuginfo`, `split-debuginfo-path`, `object`, `all`"; + pub const parse_inlining_threshold: &str = + "either a boolean (`yes`, `no`, `on`, `off`, etc), or a non-negative number"; } mod parse { @@ -1310,6 +1312,26 @@ mod parse { }; true } + + pub(crate) fn parse_inlining_threshold(slot: &mut InliningThreshold, v: Option<&str>) -> bool { + match v { + Some("always" | "yes") => { + *slot = InliningThreshold::Always; + } + Some("never") => { + *slot = InliningThreshold::Never; + } + Some(v) => { + if let Ok(threshold) = v.parse() { + *slot = InliningThreshold::Sometimes(threshold); + } else { + return false; + } + } + None => return false, + } + true + } } options! { @@ -1479,7 +1501,7 @@ options! { "combine CGUs into a single one"), crate_attr: Vec = (Vec::new(), parse_string_push, [TRACKED], "inject the given attribute in the crate"), - cross_crate_inline_threshold: Option = (None, parse_opt_number, [TRACKED], + cross_crate_inline_threshold: InliningThreshold = (InliningThreshold::Sometimes(100), parse_inlining_threshold, [TRACKED], "threshold to allow cross crate inlining of functions"), debug_info_for_profiling: bool = (false, parse_bool, [TRACKED], "emit discriminators and other data necessary for AutoFDO"), diff --git a/tests/codegen/cross-crate-inlining/always-inline.rs b/tests/codegen/cross-crate-inlining/always-inline.rs new file mode 100644 index 000000000000..f3f08bf116ae --- /dev/null +++ b/tests/codegen/cross-crate-inlining/always-inline.rs @@ -0,0 +1,13 @@ +// compile-flags: -O +// aux-build:always.rs + +#![crate_type = "lib"] + +extern crate always; + +// Check that we inline a cross-crate call, even though it isn't a leaf +#[no_mangle] +pub fn outer() -> String { + // CHECK-NOT: call {{.*}}stem_fn + always::stem_fn() +} diff --git a/tests/codegen/cross-crate-inlining/auxiliary/always.rs b/tests/codegen/cross-crate-inlining/auxiliary/always.rs new file mode 100644 index 000000000000..3670307ec813 --- /dev/null +++ b/tests/codegen/cross-crate-inlining/auxiliary/always.rs @@ -0,0 +1,20 @@ +// compile-flags: -O -Zcross-crate-inline-threshold=always + +#![crate_type = "lib"] + +// This function *looks* like it contains a call, but that call will be optimized out by MIR +// optimizations. +pub fn leaf_fn() -> String { + String::new() +} + +// This function contains a call, even after MIR optimizations. It is only eligible for +// cross-crate-inlining with "always". +pub fn stem_fn() -> String { + inner() +} + +#[inline(never)] +fn inner() -> String { + String::from("test") +} diff --git a/tests/codegen/cross-crate-inlining/auxiliary/leaf.rs b/tests/codegen/cross-crate-inlining/auxiliary/leaf.rs new file mode 100644 index 000000000000..963f087f22d4 --- /dev/null +++ b/tests/codegen/cross-crate-inlining/auxiliary/leaf.rs @@ -0,0 +1,20 @@ +// compile-flags: -O + +#![crate_type = "lib"] + +// This function *looks* like it contains a call, but that call will be optimized out by MIR +// optimizations. +pub fn leaf_fn() -> String { + String::new() +} + +// This function contains a call, even after MIR optimizations. It is only eligible for +// cross-crate-inlining with "always". +pub fn stem_fn() -> String { + inner() +} + +#[inline(never)] +fn inner() -> String { + String::from("test") +} diff --git a/tests/codegen/cross-crate-inlining/auxiliary/never.rs b/tests/codegen/cross-crate-inlining/auxiliary/never.rs new file mode 100644 index 000000000000..e222a6dea387 --- /dev/null +++ b/tests/codegen/cross-crate-inlining/auxiliary/never.rs @@ -0,0 +1,20 @@ +// compile-flags: -O -Zcross-crate-inline-threshold=never + +#![crate_type = "lib"] + +// This function *looks* like it contains a call, but that call will be optimized out by MIR +// optimizations. +pub fn leaf_fn() -> String { + String::new() +} + +// This function contains a call, even after MIR optimizations. It is only eligible for +// cross-crate-inlining with "always". +pub fn stem_fn() -> String { + inner() +} + +#[inline(never)] +fn inner() -> String { + String::from("test") +} diff --git a/tests/codegen/cross-crate-inlining/leaf-inlining.rs b/tests/codegen/cross-crate-inlining/leaf-inlining.rs new file mode 100644 index 000000000000..73b1a520b06c --- /dev/null +++ b/tests/codegen/cross-crate-inlining/leaf-inlining.rs @@ -0,0 +1,20 @@ +// compile-flags: -O -Zcross-crate-inline-threshold=yes +// aux-build:leaf.rs + +#![crate_type = "lib"] + +extern crate leaf; + +// Check that we inline a leaf cross-crate call +#[no_mangle] +pub fn leaf_outer() -> String { + // CHECK-NOT: call {{.*}}leaf_fn + leaf::leaf_fn() +} + +// Check that we do not inline a non-leaf cross-crate call +#[no_mangle] +pub fn stem_outer() -> String { + // CHECK: call {{.*}}stem_fn + leaf::stem_fn() +} diff --git a/tests/codegen/cross-crate-inlining/never-inline.rs b/tests/codegen/cross-crate-inlining/never-inline.rs new file mode 100644 index 000000000000..4e7bc3e5154c --- /dev/null +++ b/tests/codegen/cross-crate-inlining/never-inline.rs @@ -0,0 +1,13 @@ +// compile-flags: -O +// aux-build:never.rs + +#![crate_type = "lib"] + +extern crate never; + +// Check that we do not inline a cross-crate call, even though it is a leaf +#[no_mangle] +pub fn outer() -> String { + // CHECK: call {{.*}}leaf_fn + never::leaf_fn() +} From 1b8dee19e8ddf560498e29a29b1efb62c080fa20 Mon Sep 17 00:00:00 2001 From: LuuuX Date: Wed, 18 Oct 2023 09:55:18 +0800 Subject: [PATCH 332/435] Fix issue #110087 Three tasks have been implemented here. Add a new `download-ci-llvm = if-unchange` option and enable if by default for `profile = codegen`. Include all build artifacts by traversing the llvm-project build output, Keep the downloadable llvm the same state as if you have just run a full source build. After selecting the codegen profile during ./x.py setup, the submodule will be automatically downloaded. --- config.example.toml | 10 +- src/bootstrap/defaults/config.codegen.toml | 2 +- src/bootstrap/download-ci-llvm-stamp | 2 +- src/bootstrap/src/core/build_steps/dist.rs | 26 +++-- src/bootstrap/src/core/build_steps/setup.rs | 9 ++ src/bootstrap/src/core/config/config.rs | 101 +++++++++++++++++--- src/bootstrap/src/lib.rs | 2 +- 7 files changed, 120 insertions(+), 32 deletions(-) diff --git a/config.example.toml b/config.example.toml index 4984cf8ba1e7..e5df28a49af6 100644 --- a/config.example.toml +++ b/config.example.toml @@ -30,7 +30,7 @@ # # If `change-id` does not match the version that is currently running, # `x.py` will prompt you to update it and check the related PR for more details. -change-id = 117435 +change-id = 116881 # ============================================================================= # Tweaking how LLVM is compiled @@ -42,11 +42,15 @@ change-id = 117435 # Unless you're developing for a target where Rust CI doesn't build a compiler # toolchain or changing LLVM locally, you probably want to leave this enabled. # -# All tier 1 targets are currently supported; set this to `"if-available"` if -# you are not sure whether you're on a tier 1 target. +# Set this to `"if-available"` if you are not sure whether you're on a tier 1 +# target. All tier 1 targets are currently supported; # # We also currently only support this when building LLVM for the build triple. # +# Set this to `"if-unchanged"` to only download if the llvm-project have not +# been modified. (If there are no changes or if built from tarball source, +# the logic is the same as "if-available") +# # Note that many of the LLVM options are not currently supported for # downloading. Currently only the "assertions" option can be toggled. #download-ci-llvm = if rust.channel == "dev" { "if-available" } else { false } diff --git a/src/bootstrap/defaults/config.codegen.toml b/src/bootstrap/defaults/config.codegen.toml index 113df88d7c34..7c33ce958c92 100644 --- a/src/bootstrap/defaults/config.codegen.toml +++ b/src/bootstrap/defaults/config.codegen.toml @@ -10,7 +10,7 @@ assertions = true # enable warnings during the llvm compilation enable-warnings = true # build llvm from source -download-ci-llvm = false +download-ci-llvm = "if-unchanged" [rust] # This enables `RUSTC_LOG=debug`, avoiding confusing situations diff --git a/src/bootstrap/download-ci-llvm-stamp b/src/bootstrap/download-ci-llvm-stamp index ffc38057900a..9998fe2f5db8 100644 --- a/src/bootstrap/download-ci-llvm-stamp +++ b/src/bootstrap/download-ci-llvm-stamp @@ -1,4 +1,4 @@ Change this file to make users of the `download-ci-llvm` configuration download a new version of LLVM from CI, even if the LLVM submodule hasn’t changed. -Last change is for: https://github.com/rust-lang/rust/pull/113996 +Last change is for: https://github.com/rust-lang/rust/pull/116881 diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index 6e80c55c8ce3..950845b736f8 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -2219,23 +2219,19 @@ impl Step for RustDev { builder.ensure(crate::core::build_steps::llvm::Lld { target }); let src_bindir = builder.llvm_out(target).join("bin"); - // If updating this list, you likely want to change + // If updating this, you likely want to change // src/bootstrap/download-ci-llvm-stamp as well, otherwise local users // will not pick up the extra file until LLVM gets bumped. - for bin in &[ - "llvm-config", - "llvm-ar", - "llvm-objdump", - "llvm-profdata", - "llvm-bcanalyzer", - "llvm-cov", - "llvm-dwp", - "llvm-nm", - "llvm-dwarfdump", - "llvm-dis", - "llvm-tblgen", - ] { - tarball.add_file(src_bindir.join(exe(bin, target)), "bin", 0o755); + // We should include all the build artifacts obtained from a source build, + // so that you can use the downloadable LLVM as if you’ve just run a full source build. + if src_bindir.exists() { + for entry in walkdir::WalkDir::new(&src_bindir) { + let entry = t!(entry); + if entry.file_type().is_file() && !entry.path_is_symlink() { + let name = entry.file_name().to_str().unwrap(); + tarball.add_file(src_bindir.join(name), "bin", 0o755); + } + } } // We don't build LLD on some platforms, so only add it if it exists diff --git a/src/bootstrap/src/core/build_steps/setup.rs b/src/bootstrap/src/core/build_steps/setup.rs index b4540641bfa2..04a164437703 100644 --- a/src/bootstrap/src/core/build_steps/setup.rs +++ b/src/bootstrap/src/core/build_steps/setup.rs @@ -147,6 +147,15 @@ impl Step for Profile { } fn run(self, builder: &Builder<'_>) { + // During ./x.py setup once you select the codegen profile. + // The submodule will be downloaded. It does not work in the + // tarball case since they don't include Git and submodules + // are already included. + if !builder.rust_info().is_from_tarball() { + if self == Profile::Codegen { + builder.update_submodule(&Path::new("src/llvm-project")); + } + } setup(&builder.build.config, self) } } diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index a871399453e4..2eb5d06bcb3b 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -19,6 +19,7 @@ use std::process::Command; use std::str::FromStr; use crate::core::build_steps::compile::CODEGEN_BACKEND_PREFIX; +use crate::core::build_steps::llvm; use crate::core::config::flags::{Color, Flags, Warnings}; use crate::utils::cache::{Interned, INTERNER}; use crate::utils::channel::{self, GitInfo}; @@ -1530,17 +1531,7 @@ impl Config { config.llvm_build_config = llvm.build_config.clone().unwrap_or(Default::default()); let asserts = llvm_assertions.unwrap_or(false); - config.llvm_from_ci = match llvm.download_ci_llvm { - Some(StringOrBool::String(s)) => { - assert_eq!(s, "if-available", "unknown option `{s}` for download-ci-llvm"); - crate::core::build_steps::llvm::is_ci_llvm_available(&config, asserts) - } - Some(StringOrBool::Bool(b)) => b, - None => { - config.channel == "dev" - && crate::core::build_steps::llvm::is_ci_llvm_available(&config, asserts) - } - }; + config.llvm_from_ci = config.parse_download_ci_llvm(llvm.download_ci_llvm, asserts); if config.llvm_from_ci { // None of the LLVM options, except assertions, are supported @@ -2104,6 +2095,94 @@ impl Config { Some(commit.to_string()) } + + fn parse_download_ci_llvm( + &self, + download_ci_llvm: Option, + asserts: bool, + ) -> bool { + match download_ci_llvm { + None => self.channel == "dev" && llvm::is_ci_llvm_available(&self, asserts), + Some(StringOrBool::Bool(b)) => b, + Some(StringOrBool::String(s)) if s == "if-available" => { + llvm::is_ci_llvm_available(&self, asserts) + } + Some(StringOrBool::String(s)) if s == "if-unchanged" => { + // Git is needed to track modifications here, but tarball source is not available. + // If not modified here or built through tarball source, we maintain consistency + // with '"if available"'. + if !self.rust_info.is_from_tarball() + && self + .last_modified_commit(&["src/llvm-project"], "download-ci-llvm", true) + .is_none() + { + // there are some untracked changes in the the given paths. + false + } else { + llvm::is_ci_llvm_available(&self, asserts) + } + } + Some(StringOrBool::String(other)) => { + panic!("unrecognized option for download-ci-llvm: {:?}", other) + } + } + } + + /// Returns the last commit in which any of `modified_paths` were changed, + /// or `None` if there are untracked changes in the working directory and `if_unchanged` is true. + pub fn last_modified_commit( + &self, + modified_paths: &[&str], + option_name: &str, + if_unchanged: bool, + ) -> Option { + // Handle running from a directory other than the top level + let top_level = output(self.git().args(&["rev-parse", "--show-toplevel"])); + let top_level = top_level.trim_end(); + + // Look for a version to compare to based on the current commit. + // Only commits merged by bors will have CI artifacts. + let merge_base = output( + self.git() + .arg("rev-list") + .arg(format!("--author={}", self.stage0_metadata.config.git_merge_commit_email)) + .args(&["-n1", "--first-parent", "HEAD"]), + ); + let commit = merge_base.trim_end(); + if commit.is_empty() { + println!("error: could not find commit hash for downloading components from CI"); + println!("help: maybe your repository history is too shallow?"); + println!("help: consider disabling `{option_name}`"); + println!("help: or fetch enough history to include one upstream commit"); + crate::exit!(1); + } + + // Warn if there were changes to the compiler or standard library since the ancestor commit. + let mut git = self.git(); + git.args(&["diff-index", "--quiet", &commit, "--"]); + + for path in modified_paths { + git.arg(format!("{top_level}/{path}")); + } + + let has_changes = !t!(git.status()).success(); + if has_changes { + if if_unchanged { + if self.verbose > 0 { + println!( + "warning: saw changes to one of {modified_paths:?} since {commit}; \ + ignoring `{option_name}`" + ); + } + return None; + } + println!( + "warning: `{option_name}` is enabled, but there are changes to one of {modified_paths:?}" + ); + } + + Some(commit.to_string()) + } } fn set(field: &mut T, val: Option) { diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 27922c9fbbe7..fc3413a3c817 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -77,7 +77,7 @@ const LLD_FILE_NAMES: &[&str] = &["ld.lld", "ld64.lld", "lld-link", "wasm-ld"]; /// /// If you make any major changes (such as adding new values or changing default values), please /// ensure that the associated PR ID is added to the end of this list. -pub const CONFIG_CHANGE_HISTORY: &[usize] = &[115898, 116998, 117435]; +pub const CONFIG_CHANGE_HISTORY: &[usize] = &[115898, 116998, 117435, 116881]; /// Extra --check-cfg to add when building /// (Mode restriction, config name, config values (if any)) From 97c9d8f405e1b93bf69334b239f89d92d28847a0 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 3 Nov 2023 14:34:08 +0000 Subject: [PATCH 333/435] Only use normalize_param_env when normalizing predicate in check_item_bounds --- .../src/check/compare_impl_item.rs | 10 ++++++-- ...sume-gat-normalization-for-nested-goals.rs | 2 +- ...-gat-normalization-for-nested-goals.stderr | 24 +++++++++++++++++++ .../higher-ranked-self-impl-requirement.rs | 20 ++++++++++++++++ .../new-solver/specialization-transmute.rs | 2 +- .../specialization-transmute.stderr | 11 +++++++-- .../specialization-unconstrained.rs | 2 +- .../specialization-unconstrained.stderr | 11 +++++++-- 8 files changed, 73 insertions(+), 9 deletions(-) create mode 100644 tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.stderr create mode 100644 tests/ui/generic-associated-types/higher-ranked-self-impl-requirement.rs diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 90babbb63a00..857515f971a8 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -2162,7 +2162,7 @@ pub(super) fn check_type_bounds<'tcx>( impl_ty: ty::AssocItem, impl_trait_ref: ty::TraitRef<'tcx>, ) -> Result<(), ErrorGuaranteed> { - let param_env = param_env_with_gat_bounds(tcx, impl_ty, impl_trait_ref); + let param_env = tcx.param_env(impl_ty.def_id); debug!(?param_env); let container_id = impl_ty.container_id(tcx); @@ -2217,8 +2217,14 @@ pub(super) fn check_type_bounds<'tcx>( .collect(); debug!("check_type_bounds: item_bounds={:?}", obligations); + // Normalize predicates with the assumption that the GAT may always normalize + // to its definition type. This should be the param-env we use to *prove* the + // predicate too, but we don't do that because of performance issues. + // See . + let normalize_param_env = param_env_with_gat_bounds(tcx, impl_ty, impl_trait_ref); for mut obligation in util::elaborate(tcx, obligations) { - let normalized_predicate = ocx.normalize(&normalize_cause, param_env, obligation.predicate); + let normalized_predicate = + ocx.normalize(&normalize_cause, normalize_param_env, obligation.predicate); debug!("compare_projection_bounds: normalized predicate = {:?}", normalized_predicate); obligation.predicate = normalized_predicate; diff --git a/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.rs b/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.rs index 7b1687072397..e2d51c6649ab 100644 --- a/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.rs +++ b/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.rs @@ -1,4 +1,4 @@ -// check-pass +// known-bug: #117606 #![feature(associated_type_defaults)] diff --git a/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.stderr b/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.stderr new file mode 100644 index 000000000000..abad0f25c0f4 --- /dev/null +++ b/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.stderr @@ -0,0 +1,24 @@ +error[E0277]: the trait bound `::Bar<()>: Eq` is not satisfied + --> $DIR/assume-gat-normalization-for-nested-goals.rs:6:30 + | +LL | type Bar: Baz = i32; + | ^^^ the trait `Eq` is not implemented for `::Bar<()>` + | +note: required for `i32` to implement `Baz` + --> $DIR/assume-gat-normalization-for-nested-goals.rs:13:23 + | +LL | impl Baz for i32 where T::Bar<()>: Eq {} + | ^^^^^^ ^^^ ------- unsatisfied trait bound introduced here +note: required by a bound in `Foo::Bar` + --> $DIR/assume-gat-normalization-for-nested-goals.rs:6:18 + | +LL | type Bar: Baz = i32; + | ^^^^^^^^^ required by this bound in `Foo::Bar` +help: consider further restricting the associated type + | +LL | trait Foo where ::Bar<()>: Eq { + | +++++++++++++++++++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generic-associated-types/higher-ranked-self-impl-requirement.rs b/tests/ui/generic-associated-types/higher-ranked-self-impl-requirement.rs new file mode 100644 index 000000000000..5ef9437c9687 --- /dev/null +++ b/tests/ui/generic-associated-types/higher-ranked-self-impl-requirement.rs @@ -0,0 +1,20 @@ +// check-pass + +trait Database: for<'r> HasValueRef<'r, Database = Self> {} + +trait HasValueRef<'r> { + type Database: Database; +} + +struct Any; + +impl Database for Any {} + +impl<'r> HasValueRef<'r> for Any { + // Make sure we don't have issues when the GAT assumption + // `>::Database = Any` isn't universally + // parameterized over `'r`. + type Database = Any; +} + +fn main() {} diff --git a/tests/ui/traits/new-solver/specialization-transmute.rs b/tests/ui/traits/new-solver/specialization-transmute.rs index f6b19e7adf51..fac7d76f8cf5 100644 --- a/tests/ui/traits/new-solver/specialization-transmute.rs +++ b/tests/ui/traits/new-solver/specialization-transmute.rs @@ -10,7 +10,7 @@ trait Default { } impl Default for T { - default type Id = T; + default type Id = T; //~ ERROR type annotations needed // This will be fixed by #111994 fn intu(&self) -> &Self::Id { //~ ERROR type annotations needed self diff --git a/tests/ui/traits/new-solver/specialization-transmute.stderr b/tests/ui/traits/new-solver/specialization-transmute.stderr index 09b1405fefbf..18965a465b3f 100644 --- a/tests/ui/traits/new-solver/specialization-transmute.stderr +++ b/tests/ui/traits/new-solver/specialization-transmute.stderr @@ -16,6 +16,13 @@ LL | fn intu(&self) -> &Self::Id { | = note: cannot satisfy `::Id == _` -error: aborting due to previous error; 1 warning emitted +error[E0282]: type annotations needed + --> $DIR/specialization-transmute.rs:13:23 + | +LL | default type Id = T; + | ^ cannot infer type for associated type `::Id` -For more information about this error, try `rustc --explain E0284`. +error: aborting due to 2 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0282, E0284. +For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/traits/new-solver/specialization-unconstrained.rs b/tests/ui/traits/new-solver/specialization-unconstrained.rs index 02150689ee5c..7fd753109be2 100644 --- a/tests/ui/traits/new-solver/specialization-unconstrained.rs +++ b/tests/ui/traits/new-solver/specialization-unconstrained.rs @@ -11,7 +11,7 @@ trait Default { } impl Default for T { - default type Id = T; + default type Id = T; //~ ERROR type annotations needed } fn test, U>() {} diff --git a/tests/ui/traits/new-solver/specialization-unconstrained.stderr b/tests/ui/traits/new-solver/specialization-unconstrained.stderr index 910925cbaeb0..ed4dafa1484c 100644 --- a/tests/ui/traits/new-solver/specialization-unconstrained.stderr +++ b/tests/ui/traits/new-solver/specialization-unconstrained.stderr @@ -20,6 +20,13 @@ note: required by a bound in `test` LL | fn test, U>() {} | ^^^^^^ required by this bound in `test` -error: aborting due to previous error; 1 warning emitted +error[E0282]: type annotations needed + --> $DIR/specialization-unconstrained.rs:14:22 + | +LL | default type Id = T; + | ^ cannot infer type for associated type `::Id` -For more information about this error, try `rustc --explain E0284`. +error: aborting due to 2 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0282, E0284. +For more information about an error, try `rustc --explain E0282`. From 545175ce87a9de4ea371f9d88bafd4d35984a533 Mon Sep 17 00:00:00 2001 From: scottmcm Date: Tue, 7 Nov 2023 18:39:09 -0800 Subject: [PATCH 334/435] Fix addition formatting --- library/core/src/slice/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index fdf265cb3bfb..6cf5d48a1678 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -642,7 +642,7 @@ impl [T] { /// /// You can think of this like `.get(index).unwrap_unchecked()`. It's UB /// to call `.get_unchecked(len)`, even if you immediately convert to a - /// pointer. And it's UB to call `.get_unchecked(..len +1)`, + /// pointer. And it's UB to call `.get_unchecked(..len + 1)`, /// `.get_unchecked(..=len)`, or similar. /// /// [`get`]: slice::get @@ -682,7 +682,7 @@ impl [T] { /// /// You can think of this like `.get_mut(index).unwrap_unchecked()`. It's /// UB to call `.get_unchecked_mut(len)`, even if you immediately convert - /// to a pointer. And it's UB to call `.get_unchecked_mut(..len +1)`, + /// to a pointer. And it's UB to call `.get_unchecked_mut(..len + 1)`, /// `.get_unchecked_mut(..=len)`, or similar. /// /// [`get_mut`]: slice::get_mut From 783d4b8b2629c31ff8359ce744060afdcb0a5bea Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 31 Oct 2023 11:25:13 +1100 Subject: [PATCH 335/435] Clarify `space_between`. To avoid `!matches!(...)`, which is hard to think about. Instead every case now uses direct pattern matching and returns true or false. Also add a couple of cases to the `stringify.rs` test that currently print badly. --- compiler/rustc_ast_pretty/src/pprust/state.rs | 72 +++++++++++-------- tests/ui/macros/stringify.rs | 2 + 2 files changed, 44 insertions(+), 30 deletions(-) diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index e71f421659e2..48421ff71409 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -146,37 +146,49 @@ pub fn print_crate<'a>( s.s.eof() } -/// This makes printed token streams look slightly nicer, -/// and also addresses some specific regressions described in #63896 and #73345. -fn space_between(prev: &TokenTree, curr: &TokenTree) -> bool { - if let TokenTree::Token(token, _) = prev { - // No space after these tokens, e.g. `x.y`, `$e` - // (The carets point to `prev`.) ^ ^ - if matches!(token.kind, token::Dot | token::Dollar) { - return false; - } - if let token::DocComment(comment_kind, ..) = token.kind { - return comment_kind != CommentKind::Line; - } - } - match curr { - // No space before these tokens, e.g. `foo,`, `println!`, `x.y` - // (The carets point to `curr`.) ^ ^ ^ +/// Should two consecutive tokens be printed with a space between them? +/// +/// Note: some old proc macros parse pretty-printed output, so changes here can +/// break old code. For example: +/// - #63896: `#[allow(unused,` must be printed rather than `#[allow(unused ,` +/// - #73345: `#[allow(unused)] must be printed rather than `# [allow(unused)] +/// +fn space_between(tt1: &TokenTree, tt2: &TokenTree) -> bool { + use token::*; + use Delimiter::*; + use TokenTree::Delimited as Del; + use TokenTree::Token as Tok; + + // Each match arm has one or more examples in comments. The default is to + // insert space between adjacent tokens, except for the cases listed in + // this match. + match (tt1, tt2) { + // No space after line doc comments. + (Tok(Token { kind: DocComment(CommentKind::Line, ..), .. }, _), _) => false, + + // `.` + ANYTHING: `x.y`, `tup.0` + // `$` + ANYTHING: `$e` + (Tok(Token { kind: Dot | Dollar, .. }, _), _) => false, + + // ANYTHING + `,`: `foo,` + // ANYTHING + `.`: `x.y`, `tup.0` + // ANYTHING + `!`: `foo! { ... }` // - // FIXME: having `Not` here works well for macro invocations like - // `println!()`, but is bad when `!` means "logical not" or "the never - // type", where the lack of space causes ugliness like this: - // `Fn() ->!`, `x =! y`, `if! x { f(); }`. - TokenTree::Token(token, _) => !matches!(token.kind, token::Comma | token::Not | token::Dot), - // No space before parentheses if preceded by these tokens, e.g. `foo(...)` - TokenTree::Delimited(_, Delimiter::Parenthesis, _) => { - !matches!(prev, TokenTree::Token(Token { kind: token::Ident(..), .. }, _)) - } - // No space before brackets if preceded by these tokens, e.g. `#[...]` - TokenTree::Delimited(_, Delimiter::Bracket, _) => { - !matches!(prev, TokenTree::Token(Token { kind: token::Pound, .. }, _)) - } - TokenTree::Delimited(..) => true, + // FIXME: Incorrect cases: + // - Logical not: `x =! y`, `if! x { f(); }` + // - Never type: `Fn() ->!` + (_, Tok(Token { kind: Comma | Dot | Not, .. }, _)) => false, + + // IDENT + `(`: `f(3)` + // + // FIXME: Incorrect cases: + // - Let: `let(a, b) = (1, 2)` + (Tok(Token { kind: Ident(..), .. }, _), Del(_, Parenthesis, _)) => false, + + // `#` + `[`: `#[attr]` + (Tok(Token { kind: Pound, .. }, _), Del(_, Bracket, _)) => false, + + _ => true, } } diff --git a/tests/ui/macros/stringify.rs b/tests/ui/macros/stringify.rs index f1bbd4a62109..31e0d30c78b8 100644 --- a/tests/ui/macros/stringify.rs +++ b/tests/ui/macros/stringify.rs @@ -115,6 +115,7 @@ fn test_expr() { "a + b * c - d + -1 * -2 - -3", "a + b * c - d + - 1 * - 2 - - 3" ); + c2!(expr, [ x = !y ], "x = !y", "x =! y"); // FIXME // ExprKind::Unary c2!(expr, [ *expr ], "*expr", "* expr"); @@ -137,6 +138,7 @@ fn test_expr() { // ExprKind::If c1!(expr, [ if true {} ], "if true {}"); + c2!(expr, [ if !true {} ], "if !true {}", "if! true {}"); // FIXME c2!(expr, [ if ::std::blah() { } else { } ], "if ::std::blah() {} else {}", From 438b9a6e82cd74102bd41636dc48b6b846101a59 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 1 Nov 2023 08:35:13 +1100 Subject: [PATCH 336/435] More tests for token stream pretty-printing with adjacent punctuation. We currently do the wrong thing on a lot of these. The next commit will fix things. --- tests/ui/macros/stringify.rs | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/tests/ui/macros/stringify.rs b/tests/ui/macros/stringify.rs index 31e0d30c78b8..70ca00285c49 100644 --- a/tests/ui/macros/stringify.rs +++ b/tests/ui/macros/stringify.rs @@ -801,3 +801,32 @@ fn test_vis() { assert_eq!(inherited_vis!(struct), ""); assert_eq!(stringify!(), ""); } + +macro_rules! p { + ([$($tt:tt)*], $s:literal) => { + assert_eq!(stringify!($($tt)*), $s); + }; +} + +#[test] +fn test_punct() { + // For all these cases, we must preserve spaces between the tokens. + // Otherwise, any old proc macro that parses pretty-printed code might glue + // together tokens that shouldn't be glued. + p!([ = = < < <= <= == == != != >= >= > > ], "= = < < <= <= == == != != >= >= > >"); + p!([ && && & & || || | | ! ! ], "&& && & & || || | |!!"); // FIXME + p!([ ~ ~ @ @ # # ], "~ ~ @ @ # #"); + p!([ . . .. .. ... ... ..= ..=], ".... .. ... ... ..= ..="); // FIXME + p!([ , , ; ; : : :: :: ], ",, ; ; : : :: ::"); // FIXME + p!([ -> -> <- <- => =>], "-> -> <- <- => =>"); + p!([ $ $ ? ? ' ' ], "$$? ? ' '"); // FIXME + p!([ + + += += - - -= -= * * *= *= / / /= /= ], "+ + += += - - -= -= * * *= *= / / /= /="); + p!([ % % %= %= ^ ^ ^= ^= << << <<= <<= >> >> >>= >>= ], + "% % %= %= ^ ^ ^= ^= << << <<= <<= >> >> >>= >>="); + + // For these one we must insert spaces between adjacent tokens, again due + // to proc macros. + p!([ +! ?= |> >>@ --> <-- $$ =====> ], "+! ? = | > >> @ - -> <- - $$== == =>"); // FIXME + p!([ ,; ;, ** @@ $+$ >< <> ?? +== ], ", ; ;, * * @ @ $+ $> < < > ? ? += ="); // FIXME + p!([ :#!@|$=&*,+;*~? ], ": #! @ | $= & *, + ; * ~ ?"); // FIXME +} From 0670466e2cb2ed10276d3f6397201f44bc49067b Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Tue, 7 Nov 2023 23:40:22 -0500 Subject: [PATCH 337/435] Update cargo --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index 65e297d1ec0d..7046d992f9f3 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 65e297d1ec0dee1a74800efe600b8dc163bcf5db +Subproject commit 7046d992f9f32ba209a8079f662ebccf9da8de25 From a5738803735db820f0c4e1d45edf706526308cf6 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 2 Nov 2023 14:27:22 +1100 Subject: [PATCH 338/435] coverage: Rename the `run-coverage` test mode to `coverage-run` This makes it more consistent with the `coverage-map` mode and the shared `tests/coverage` test directory. --- src/bootstrap/src/core/build_steps/test.rs | 22 +++++++++---------- src/bootstrap/src/core/builder.rs | 4 ++-- src/tools/compiletest/src/common.rs | 4 ++-- src/tools/compiletest/src/header.rs | 4 ++-- src/tools/compiletest/src/runtest.rs | 14 ++++++------ .../auxiliary/doctest_crate.rs | 0 .../doctest.coverage | 0 .../doctest.rs | 0 tests/coverage/README.md | 6 ++--- 9 files changed, 27 insertions(+), 27 deletions(-) rename tests/{run-coverage-rustdoc => coverage-run-rustdoc}/auxiliary/doctest_crate.rs (100%) rename tests/{run-coverage-rustdoc => coverage-run-rustdoc}/doctest.coverage (100%) rename tests/{run-coverage-rustdoc => coverage-run-rustdoc}/doctest.rs (100%) diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 39667d16b7b6..c034e5c9d69e 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -1434,7 +1434,7 @@ impl Step for Coverage { fn run(self, builder: &Builder<'_>) { self.run_unified_suite(builder, CoverageMap::MODE); - self.run_unified_suite(builder, RunCoverage::MODE); + self.run_unified_suite(builder, CoverageRun::MODE); } } @@ -1444,16 +1444,16 @@ coverage_test_alias!(CoverageMap { default: true, only_hosts: false, }); -coverage_test_alias!(RunCoverage { - alias_and_mode: "run-coverage", +coverage_test_alias!(CoverageRun { + alias_and_mode: "coverage-run", default: true, only_hosts: true, }); -host_test!(RunCoverageRustdoc { - path: "tests/run-coverage-rustdoc", - mode: "run-coverage", - suite: "run-coverage-rustdoc" +host_test!(CoverageRunRustdoc { + path: "tests/coverage-run-rustdoc", + mode: "coverage-run", + suite: "coverage-run-rustdoc" }); // For the mir-opt suite we do not use macros, as we need custom behavior when blessing. @@ -1640,7 +1640,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the || (mode == "ui" && is_rustdoc) || mode == "js-doc-test" || mode == "rustdoc-json" - || suite == "run-coverage-rustdoc" + || suite == "coverage-run-rustdoc" { cmd.arg("--rustdoc-path").arg(builder.rustdoc(compiler)); } @@ -1662,7 +1662,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the cmd.arg("--coverage-dump-path").arg(coverage_dump); } - if mode == "run-coverage" { + if mode == "coverage-run" { // The demangler doesn't need the current compiler, so we can avoid // unnecessary rebuilds by using the bootstrap compiler instead. let rust_demangler = builder @@ -1854,11 +1854,11 @@ note: if you're sure you want to do this, please open an issue as to why. In the } if !builder.config.dry_run() - && (matches!(suite, "run-make" | "run-make-fulldeps") || mode == "run-coverage") + && (matches!(suite, "run-make" | "run-make-fulldeps") || mode == "coverage-run") { // The llvm/bin directory contains many useful cross-platform // tools. Pass the path to run-make tests so they can use them. - // (The run-coverage tests also need these tools to process + // (The coverage-run tests also need these tools to process // coverage reports.) let llvm_bin_path = llvm_config .parent() diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs index 38eb46332738..1b6ba89aadd2 100644 --- a/src/bootstrap/src/core/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -729,7 +729,7 @@ impl<'a> Builder<'a> { test::RunPassValgrind, test::Coverage, test::CoverageMap, - test::RunCoverage, + test::CoverageRun, test::MirOpt, test::Codegen, test::CodegenUnits, @@ -740,7 +740,7 @@ impl<'a> Builder<'a> { test::CodegenCranelift, test::CodegenGCC, test::Rustdoc, - test::RunCoverageRustdoc, + test::CoverageRunRustdoc, test::Pretty, test::Crate, test::CrateLibrustc, diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index a908218fff14..bdf8c35e73b5 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -67,7 +67,7 @@ string_enum! { MirOpt => "mir-opt", Assembly => "assembly", CoverageMap => "coverage-map", - RunCoverage => "run-coverage", + CoverageRun => "coverage-run", } } @@ -91,7 +91,7 @@ impl Mode { // Coverage tests use the same test files for multiple test modes, // so each mode should have a separate output directory. match self { - CoverageMap | RunCoverage => self.to_str(), + CoverageMap | CoverageRun => self.to_str(), _ => "", } } diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 948439d6e79d..d6516cff63fb 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -911,11 +911,11 @@ pub fn make_test_description( let mut should_fail = false; let extra_directives: &[&str] = match config.mode { - // The run-coverage tests are treated as having these extra directives, + // The coverage-run tests are treated as having these extra directives, // without needing to specify them manually in every test file. // (Some of the comments below have been copied over from // `tests/run-make/coverage-reports/Makefile`, which no longer exists.) - Mode::RunCoverage => { + Mode::CoverageRun => { &[ "needs-profiler-support", // FIXME(mati865): MinGW GCC miscompiles compiler-rt profiling library but with Clang it works diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index cbcd3dc2fded..63e8ba7c79f9 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -6,7 +6,7 @@ use crate::common::{Assembly, Incremental, JsDocTest, MirOpt, RunMake, RustdocJs use crate::common::{Codegen, CodegenUnits, DebugInfo, Debugger, Rustdoc}; use crate::common::{CompareMode, FailMode, PassMode}; use crate::common::{Config, TestPaths}; -use crate::common::{CoverageMap, Pretty, RunCoverage, RunPassValgrind}; +use crate::common::{CoverageMap, CoverageRun, Pretty, RunPassValgrind}; use crate::common::{UI_COVERAGE, UI_COVERAGE_MAP, UI_RUN_STDERR, UI_RUN_STDOUT}; use crate::compute_diff::{write_diff, write_filtered_diff}; use crate::errors::{self, Error, ErrorKind}; @@ -257,7 +257,7 @@ impl<'test> TestCx<'test> { Assembly => self.run_assembly_test(), JsDocTest => self.run_js_doc_test(), CoverageMap => self.run_coverage_map_test(), - RunCoverage => self.run_coverage_test(), + CoverageRun => self.run_coverage_run_test(), } } @@ -510,7 +510,7 @@ impl<'test> TestCx<'test> { } } - fn run_coverage_test(&self) { + fn run_coverage_run_test(&self) { let should_run = self.run_if_enabled(); let proc_res = self.compile_test(should_run, Emit::None); @@ -549,7 +549,7 @@ impl<'test> TestCx<'test> { let mut profraw_paths = vec![profraw_path]; let mut bin_paths = vec![self.make_exe_name()]; - if self.config.suite == "run-coverage-rustdoc" { + if self.config.suite == "coverage-run-rustdoc" { self.run_doctests_for_coverage(&mut profraw_paths, &mut bin_paths); } @@ -2193,7 +2193,7 @@ impl<'test> TestCx<'test> { || self.is_vxworks_pure_static() || self.config.target.contains("bpf") || !self.config.target_cfg().dynamic_linking - || matches!(self.config.mode, CoverageMap | RunCoverage) + || matches!(self.config.mode, CoverageMap | CoverageRun) { // We primarily compile all auxiliary libraries as dynamic libraries // to avoid code size bloat and large binaries as much as possible @@ -2395,7 +2395,7 @@ impl<'test> TestCx<'test> { } } DebugInfo => { /* debuginfo tests must be unoptimized */ } - CoverageMap | RunCoverage => { + CoverageMap | CoverageRun => { // Coverage mappings and coverage reports are affected by // optimization level, so they ignore the optimize-tests // setting and set an optimization level in their mode's @@ -2478,7 +2478,7 @@ impl<'test> TestCx<'test> { // by `compile-flags`. rustc.arg("-Copt-level=2"); } - RunCoverage => { + CoverageRun => { rustc.arg("-Cinstrument-coverage"); // Coverage reports are sometimes sensitive to optimizations, // and the current snapshots assume `opt-level=2` unless diff --git a/tests/run-coverage-rustdoc/auxiliary/doctest_crate.rs b/tests/coverage-run-rustdoc/auxiliary/doctest_crate.rs similarity index 100% rename from tests/run-coverage-rustdoc/auxiliary/doctest_crate.rs rename to tests/coverage-run-rustdoc/auxiliary/doctest_crate.rs diff --git a/tests/run-coverage-rustdoc/doctest.coverage b/tests/coverage-run-rustdoc/doctest.coverage similarity index 100% rename from tests/run-coverage-rustdoc/doctest.coverage rename to tests/coverage-run-rustdoc/doctest.coverage diff --git a/tests/run-coverage-rustdoc/doctest.rs b/tests/coverage-run-rustdoc/doctest.rs similarity index 100% rename from tests/run-coverage-rustdoc/doctest.rs rename to tests/coverage-run-rustdoc/doctest.rs diff --git a/tests/coverage/README.md b/tests/coverage/README.md index f1e403c65e35..c72aa69c0ce0 100644 --- a/tests/coverage/README.md +++ b/tests/coverage/README.md @@ -2,8 +2,8 @@ The tests in this directory are shared by two different test modes, and can be run in multiple different ways: - `./x.py test coverage-map` (compiles to LLVM IR and checks coverage mappings) -- `./x.py test run-coverage` (runs a test binary and checks its coverage report) -- `./x.py test coverage` (runs both `coverage-map` and `run-coverage`) +- `./x.py test coverage-run` (runs a test binary and checks its coverage report) +- `./x.py test coverage` (runs both `coverage-map` and `coverage-run`) ## Maintenance note @@ -11,6 +11,6 @@ These tests can be sensitive to small changes in MIR spans or MIR control flow, especially in HIR-to-MIR lowering or MIR optimizations. If you haven't touched the coverage code directly, and the tests still pass in -`run-coverage` mode, then it should usually be OK to just re-bless the mappings +`coverage-run` mode, then it should usually be OK to just re-bless the mappings as necessary with `./x.py test coverage-map --bless`, without worrying too much about the exact changes. From 76aa83e3e13bf23168389699ca69c59d7a79a336 Mon Sep 17 00:00:00 2001 From: David Wood Date: Wed, 8 Nov 2023 14:15:26 +0800 Subject: [PATCH 339/435] target: move base specs to spec/base Signed-off-by: David Wood --- .../src/spec/aarch64_apple_darwin.rs | 2 +- .../src/spec/aarch64_apple_ios.rs | 2 +- .../src/spec/aarch64_apple_ios_macabi.rs | 2 +- .../src/spec/aarch64_apple_ios_sim.rs | 2 +- .../src/spec/aarch64_apple_tvos.rs | 2 +- .../src/spec/aarch64_apple_tvos_sim.rs | 2 +- .../src/spec/aarch64_apple_watchos_sim.rs | 2 +- .../src/spec/aarch64_be_unknown_linux_gnu.rs | 4 +- .../aarch64_be_unknown_linux_gnu_ilp32.rs | 4 +- .../src/spec/aarch64_be_unknown_netbsd.rs | 4 +- .../src/spec/aarch64_kmc_solid_asp3.rs | 4 +- .../src/spec/aarch64_linux_android.rs | 4 +- .../src/spec/aarch64_pc_windows_gnullvm.rs | 4 +- .../src/spec/aarch64_pc_windows_msvc.rs | 4 +- .../src/spec/aarch64_unknown_freebsd.rs | 4 +- .../src/spec/aarch64_unknown_fuchsia.rs | 4 +- .../src/spec/aarch64_unknown_hermit.rs | 4 +- .../src/spec/aarch64_unknown_linux_gnu.rs | 4 +- .../spec/aarch64_unknown_linux_gnu_ilp32.rs | 4 +- .../src/spec/aarch64_unknown_linux_musl.rs | 4 +- .../src/spec/aarch64_unknown_linux_ohos.rs | 4 +- .../src/spec/aarch64_unknown_netbsd.rs | 4 +- .../src/spec/aarch64_unknown_nto_qnx_710.rs | 5 +- .../src/spec/aarch64_unknown_openbsd.rs | 4 +- .../src/spec/aarch64_unknown_redox.rs | 4 +- .../src/spec/aarch64_unknown_teeos.rs | 4 +- .../src/spec/aarch64_unknown_uefi.rs | 5 +- .../src/spec/aarch64_uwp_windows_msvc.rs | 4 +- .../src/spec/aarch64_wrs_vxworks.rs | 4 +- .../src/spec/arm64_32_apple_watchos.rs | 2 +- .../src/spec/arm_linux_androideabi.rs | 4 +- .../src/spec/arm_unknown_linux_gnueabi.rs | 4 +- .../src/spec/arm_unknown_linux_gnueabihf.rs | 4 +- .../src/spec/arm_unknown_linux_musleabi.rs | 4 +- .../src/spec/arm_unknown_linux_musleabihf.rs | 4 +- .../src/spec/armeb_unknown_linux_gnueabi.rs | 4 +- .../src/spec/armv4t_unknown_linux_gnueabi.rs | 4 +- .../src/spec/armv5te_none_eabi.rs | 4 +- .../src/spec/armv5te_unknown_linux_gnueabi.rs | 4 +- .../spec/armv5te_unknown_linux_musleabi.rs | 4 +- .../spec/armv5te_unknown_linux_uclibceabi.rs | 4 +- .../src/spec/armv6_unknown_freebsd.rs | 4 +- .../src/spec/armv6_unknown_netbsd_eabihf.rs | 4 +- .../src/spec/armv7_linux_androideabi.rs | 4 +- .../src/spec/armv7_unknown_freebsd.rs | 4 +- .../src/spec/armv7_unknown_linux_gnueabi.rs | 4 +- .../src/spec/armv7_unknown_linux_gnueabihf.rs | 4 +- .../src/spec/armv7_unknown_linux_musleabi.rs | 4 +- .../spec/armv7_unknown_linux_musleabihf.rs | 4 +- .../src/spec/armv7_unknown_linux_ohos.rs | 4 +- .../spec/armv7_unknown_linux_uclibceabi.rs | 4 +- .../spec/armv7_unknown_linux_uclibceabihf.rs | 4 +- .../src/spec/armv7_unknown_netbsd_eabihf.rs | 4 +- .../src/spec/armv7_wrs_vxworks_eabihf.rs | 4 +- .../src/spec/armv7a_kmc_solid_asp3_eabi.rs | 4 +- .../src/spec/armv7a_kmc_solid_asp3_eabihf.rs | 4 +- .../src/spec/armv7k_apple_watchos.rs | 2 +- .../rustc_target/src/spec/armv7s_apple_ios.rs | 2 +- .../src/spec/avr_unknown_gnu_atmega328.rs | 4 +- .../src/spec/{aix_base.rs => base/aix.rs} | 0 .../spec/{android_base.rs => base/android.rs} | 4 +- .../spec/{apple_base.rs => base/apple/mod.rs} | 6 +-- .../src/spec/{ => base}/apple/tests.rs | 0 .../spec/{avr_gnu_base.rs => base/avr_gnu.rs} | 0 .../src/spec/{bpf_base.rs => base/bpf.rs} | 0 .../{dragonfly_base.rs => base/dragonfly.rs} | 0 .../spec/{freebsd_base.rs => base/freebsd.rs} | 0 .../spec/{fuchsia_base.rs => base/fuchsia.rs} | 0 .../src/spec/{haiku_base.rs => base/haiku.rs} | 0 .../spec/{hermit_base.rs => base/hermit.rs} | 0 .../src/spec/{hurd_base.rs => base/hurd.rs} | 0 .../rustc_target/src/spec/base/hurd_gnu.rs | 5 ++ .../spec/{illumos_base.rs => base/illumos.rs} | 0 .../src/spec/{l4re_base.rs => base/l4re.rs} | 0 .../src/spec/{linux_base.rs => base/linux.rs} | 0 .../rustc_target/src/spec/base/linux_gnu.rs | 5 ++ .../linux_musl.rs} | 4 +- .../linux_ohos.rs} | 4 +- .../src/spec/base/linux_uclibc.rs | 5 ++ compiler/rustc_target/src/spec/base/mod.rs | 37 +++++++++++++++ .../src/spec/{msvc_base.rs => base/msvc.rs} | 0 .../spec/{netbsd_base.rs => base/netbsd.rs} | 0 .../spec/{nto_qnx_base.rs => base/nto_qnx.rs} | 0 .../spec/{openbsd_base.rs => base/openbsd.rs} | 0 .../src/spec/{redox_base.rs => base/redox.rs} | 0 .../spec/{solaris_base.rs => base/solaris.rs} | 0 .../src/spec/{solid_base.rs => base/solid.rs} | 3 +- .../src/spec/{teeos_base.rs => base/teeos.rs} | 5 +- .../src/spec/{thumb_base.rs => base/thumb.rs} | 0 .../{uefi_msvc_base.rs => base/uefi_msvc.rs} | 4 +- .../unikraft_linux_musl.rs} | 0 .../spec/{vxworks_base.rs => base/vxworks.rs} | 0 .../src/spec/{wasm_base.rs => base/wasm.rs} | 8 ++-- .../windows_gnu.rs} | 10 ++-- .../windows_gnullvm.rs} | 0 .../windows_msvc.rs} | 4 +- .../windows_uwp_gnu.rs} | 6 +-- .../windows_uwp_msvc.rs} | 4 +- .../src/spec/bpfeb_unknown_none.rs | 4 +- .../src/spec/bpfel_unknown_none.rs | 4 +- .../src/spec/csky_unknown_linux_gnuabiv2.rs | 4 +- .../src/spec/csky_unknown_linux_gnuabiv2hf.rs | 4 +- .../src/spec/hexagon_unknown_linux_musl.rs | 4 +- .../rustc_target/src/spec/hurd_gnu_base.rs | 5 -- .../rustc_target/src/spec/i386_apple_ios.rs | 2 +- .../src/spec/i586_pc_nto_qnx700.rs | 5 +- .../src/spec/i586_unknown_netbsd.rs | 4 +- .../src/spec/i686_apple_darwin.rs | 2 +- .../src/spec/i686_linux_android.rs | 4 +- .../src/spec/i686_pc_windows_gnu.rs | 4 +- .../src/spec/i686_pc_windows_gnullvm.rs | 4 +- .../src/spec/i686_pc_windows_msvc.rs | 4 +- .../src/spec/i686_unknown_freebsd.rs | 4 +- .../src/spec/i686_unknown_haiku.rs | 4 +- .../src/spec/i686_unknown_hurd_gnu.rs | 4 +- .../src/spec/i686_unknown_linux_gnu.rs | 4 +- .../src/spec/i686_unknown_linux_musl.rs | 4 +- .../src/spec/i686_unknown_netbsd.rs | 4 +- .../src/spec/i686_unknown_openbsd.rs | 4 +- .../src/spec/i686_unknown_uefi.rs | 4 +- .../src/spec/i686_uwp_windows_gnu.rs | 4 +- .../src/spec/i686_uwp_windows_msvc.rs | 4 +- .../rustc_target/src/spec/i686_wrs_vxworks.rs | 4 +- .../rustc_target/src/spec/linux_gnu_base.rs | 5 -- .../src/spec/linux_uclibc_base.rs | 5 -- .../src/spec/loongarch64_unknown_linux_gnu.rs | 4 +- .../src/spec/m68k_unknown_linux_gnu.rs | 4 +- .../src/spec/mips64_openwrt_linux_musl.rs | 4 +- .../src/spec/mips64_unknown_linux_gnuabi64.rs | 4 +- .../spec/mips64_unknown_linux_muslabi64.rs | 4 +- .../spec/mips64el_unknown_linux_gnuabi64.rs | 4 +- .../spec/mips64el_unknown_linux_muslabi64.rs | 4 +- .../src/spec/mips_unknown_linux_gnu.rs | 4 +- .../src/spec/mips_unknown_linux_musl.rs | 4 +- .../src/spec/mips_unknown_linux_uclibc.rs | 4 +- .../src/spec/mipsel_unknown_linux_gnu.rs | 4 +- .../src/spec/mipsel_unknown_linux_musl.rs | 4 +- .../src/spec/mipsel_unknown_linux_uclibc.rs | 4 +- .../src/spec/mipsel_unknown_netbsd.rs | 4 +- .../src/spec/mipsisa32r6_unknown_linux_gnu.rs | 4 +- .../spec/mipsisa32r6el_unknown_linux_gnu.rs | 4 +- .../mipsisa64r6_unknown_linux_gnuabi64.rs | 4 +- .../mipsisa64r6el_unknown_linux_gnuabi64.rs | 4 +- compiler/rustc_target/src/spec/mod.rs | 46 ++----------------- .../src/spec/powerpc64_ibm_aix.rs | 4 +- .../src/spec/powerpc64_unknown_freebsd.rs | 4 +- .../src/spec/powerpc64_unknown_linux_gnu.rs | 4 +- .../src/spec/powerpc64_unknown_linux_musl.rs | 4 +- .../src/spec/powerpc64_unknown_openbsd.rs | 4 +- .../src/spec/powerpc64_wrs_vxworks.rs | 4 +- .../src/spec/powerpc64le_unknown_freebsd.rs | 4 +- .../src/spec/powerpc64le_unknown_linux_gnu.rs | 4 +- .../spec/powerpc64le_unknown_linux_musl.rs | 4 +- .../src/spec/powerpc_unknown_freebsd.rs | 4 +- .../src/spec/powerpc_unknown_linux_gnu.rs | 4 +- .../src/spec/powerpc_unknown_linux_gnuspe.rs | 4 +- .../src/spec/powerpc_unknown_linux_musl.rs | 4 +- .../src/spec/powerpc_unknown_netbsd.rs | 4 +- .../src/spec/powerpc_unknown_openbsd.rs | 4 +- .../src/spec/powerpc_wrs_vxworks.rs | 4 +- .../src/spec/powerpc_wrs_vxworks_spe.rs | 4 +- .../src/spec/riscv32gc_unknown_linux_gnu.rs | 4 +- .../src/spec/riscv32gc_unknown_linux_musl.rs | 4 +- .../src/spec/riscv64_linux_android.rs | 4 +- .../src/spec/riscv64gc_unknown_freebsd.rs | 4 +- .../src/spec/riscv64gc_unknown_fuchsia.rs | 4 +- .../src/spec/riscv64gc_unknown_hermit.rs | 4 +- .../src/spec/riscv64gc_unknown_linux_gnu.rs | 4 +- .../src/spec/riscv64gc_unknown_linux_musl.rs | 4 +- .../src/spec/riscv64gc_unknown_netbsd.rs | 4 +- .../src/spec/riscv64gc_unknown_openbsd.rs | 4 +- .../src/spec/s390x_unknown_linux_gnu.rs | 4 +- .../src/spec/s390x_unknown_linux_musl.rs | 4 +- .../src/spec/sparc64_unknown_linux_gnu.rs | 4 +- .../src/spec/sparc64_unknown_netbsd.rs | 4 +- .../src/spec/sparc64_unknown_openbsd.rs | 4 +- .../src/spec/sparc_unknown_linux_gnu.rs | 4 +- .../src/spec/sparcv9_sun_solaris.rs | 4 +- .../src/spec/thumbv4t_none_eabi.rs | 4 +- .../src/spec/thumbv5te_none_eabi.rs | 4 +- .../src/spec/thumbv6m_none_eabi.rs | 4 +- .../src/spec/thumbv7a_pc_windows_msvc.rs | 4 +- .../src/spec/thumbv7a_uwp_windows_msvc.rs | 4 +- .../src/spec/thumbv7em_none_eabi.rs | 4 +- .../src/spec/thumbv7em_none_eabihf.rs | 4 +- .../src/spec/thumbv7m_none_eabi.rs | 4 +- .../src/spec/thumbv7neon_linux_androideabi.rs | 4 +- .../thumbv7neon_unknown_linux_gnueabihf.rs | 4 +- .../thumbv7neon_unknown_linux_musleabihf.rs | 4 +- .../src/spec/thumbv8m_base_none_eabi.rs | 4 +- .../src/spec/thumbv8m_main_none_eabi.rs | 4 +- .../src/spec/thumbv8m_main_none_eabihf.rs | 4 +- .../src/spec/wasm32_unknown_emscripten.rs | 7 +-- .../src/spec/wasm32_unknown_unknown.rs | 4 +- compiler/rustc_target/src/spec/wasm32_wasi.rs | 8 ++-- .../src/spec/wasm32_wasi_preview1_threads.rs | 5 +- .../src/spec/wasm64_unknown_unknown.rs | 4 +- .../src/spec/x86_64_apple_darwin.rs | 2 +- .../rustc_target/src/spec/x86_64_apple_ios.rs | 2 +- .../src/spec/x86_64_apple_ios_macabi.rs | 2 +- .../src/spec/x86_64_apple_tvos.rs | 2 +- .../src/spec/x86_64_apple_watchos_sim.rs | 2 +- .../src/spec/x86_64_linux_android.rs | 6 ++- .../src/spec/x86_64_pc_nto_qnx710.rs | 5 +- .../src/spec/x86_64_pc_solaris.rs | 4 +- .../src/spec/x86_64_pc_windows_gnu.rs | 4 +- .../src/spec/x86_64_pc_windows_gnullvm.rs | 4 +- .../src/spec/x86_64_pc_windows_msvc.rs | 4 +- .../src/spec/x86_64_sun_solaris.rs | 4 +- .../src/spec/x86_64_unikraft_linux_musl.rs | 4 +- .../src/spec/x86_64_unknown_dragonfly.rs | 4 +- .../src/spec/x86_64_unknown_freebsd.rs | 4 +- .../src/spec/x86_64_unknown_fuchsia.rs | 4 +- .../src/spec/x86_64_unknown_haiku.rs | 4 +- .../src/spec/x86_64_unknown_hermit.rs | 4 +- .../src/spec/x86_64_unknown_illumos.rs | 4 +- .../src/spec/x86_64_unknown_l4re_uclibc.rs | 4 +- .../src/spec/x86_64_unknown_linux_gnu.rs | 4 +- .../src/spec/x86_64_unknown_linux_gnux32.rs | 4 +- .../src/spec/x86_64_unknown_linux_musl.rs | 4 +- .../src/spec/x86_64_unknown_linux_ohos.rs | 4 +- .../src/spec/x86_64_unknown_netbsd.rs | 6 ++- .../src/spec/x86_64_unknown_openbsd.rs | 4 +- .../src/spec/x86_64_unknown_redox.rs | 4 +- .../src/spec/x86_64_unknown_uefi.rs | 7 ++- .../src/spec/x86_64_uwp_windows_gnu.rs | 4 +- .../src/spec/x86_64_uwp_windows_msvc.rs | 4 +- .../src/spec/x86_64_wrs_vxworks.rs | 4 +- .../src/spec/x86_64h_apple_darwin.rs | 2 +- 229 files changed, 453 insertions(+), 449 deletions(-) rename compiler/rustc_target/src/spec/{aix_base.rs => base/aix.rs} (100%) rename compiler/rustc_target/src/spec/{android_base.rs => base/android.rs} (85%) rename compiler/rustc_target/src/spec/{apple_base.rs => base/apple/mod.rs} (98%) rename compiler/rustc_target/src/spec/{ => base}/apple/tests.rs (100%) rename compiler/rustc_target/src/spec/{avr_gnu_base.rs => base/avr_gnu.rs} (100%) rename compiler/rustc_target/src/spec/{bpf_base.rs => base/bpf.rs} (100%) rename compiler/rustc_target/src/spec/{dragonfly_base.rs => base/dragonfly.rs} (100%) rename compiler/rustc_target/src/spec/{freebsd_base.rs => base/freebsd.rs} (100%) rename compiler/rustc_target/src/spec/{fuchsia_base.rs => base/fuchsia.rs} (100%) rename compiler/rustc_target/src/spec/{haiku_base.rs => base/haiku.rs} (100%) rename compiler/rustc_target/src/spec/{hermit_base.rs => base/hermit.rs} (100%) rename compiler/rustc_target/src/spec/{hurd_base.rs => base/hurd.rs} (100%) create mode 100644 compiler/rustc_target/src/spec/base/hurd_gnu.rs rename compiler/rustc_target/src/spec/{illumos_base.rs => base/illumos.rs} (100%) rename compiler/rustc_target/src/spec/{l4re_base.rs => base/l4re.rs} (100%) rename compiler/rustc_target/src/spec/{linux_base.rs => base/linux.rs} (100%) create mode 100644 compiler/rustc_target/src/spec/base/linux_gnu.rs rename compiler/rustc_target/src/spec/{linux_musl_base.rs => base/linux_musl.rs} (80%) rename compiler/rustc_target/src/spec/{linux_ohos_base.rs => base/linux_ohos.rs} (69%) create mode 100644 compiler/rustc_target/src/spec/base/linux_uclibc.rs create mode 100644 compiler/rustc_target/src/spec/base/mod.rs rename compiler/rustc_target/src/spec/{msvc_base.rs => base/msvc.rs} (100%) rename compiler/rustc_target/src/spec/{netbsd_base.rs => base/netbsd.rs} (100%) rename compiler/rustc_target/src/spec/{nto_qnx_base.rs => base/nto_qnx.rs} (100%) rename compiler/rustc_target/src/spec/{openbsd_base.rs => base/openbsd.rs} (100%) rename compiler/rustc_target/src/spec/{redox_base.rs => base/redox.rs} (100%) rename compiler/rustc_target/src/spec/{solaris_base.rs => base/solaris.rs} (100%) rename compiler/rustc_target/src/spec/{solid_base.rs => base/solid.rs} (83%) rename compiler/rustc_target/src/spec/{teeos_base.rs => base/teeos.rs} (84%) rename compiler/rustc_target/src/spec/{thumb_base.rs => base/thumb.rs} (100%) rename compiler/rustc_target/src/spec/{uefi_msvc_base.rs => base/uefi_msvc.rs} (95%) rename compiler/rustc_target/src/spec/{unikraft_linux_musl_base.rs => base/unikraft_linux_musl.rs} (100%) rename compiler/rustc_target/src/spec/{vxworks_base.rs => base/vxworks.rs} (100%) rename compiler/rustc_target/src/spec/{wasm_base.rs => base/wasm.rs} (96%) rename compiler/rustc_target/src/spec/{windows_gnu_base.rs => base/windows_gnu.rs} (95%) rename compiler/rustc_target/src/spec/{windows_gnullvm_base.rs => base/windows_gnullvm.rs} (100%) rename compiler/rustc_target/src/spec/{windows_msvc_base.rs => base/windows_msvc.rs} (93%) rename compiler/rustc_target/src/spec/{windows_uwp_gnu_base.rs => base/windows_uwp_gnu.rs} (80%) rename compiler/rustc_target/src/spec/{windows_uwp_msvc_base.rs => base/windows_uwp_msvc.rs} (65%) delete mode 100644 compiler/rustc_target/src/spec/hurd_gnu_base.rs delete mode 100644 compiler/rustc_target/src/spec/linux_gnu_base.rs delete mode 100644 compiler/rustc_target/src/spec/linux_uclibc_base.rs diff --git a/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs b/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs index 9ac732351411..8e6c00b1255d 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs @@ -1,4 +1,4 @@ -use super::apple_base::{macos_llvm_target, opts, Arch}; +use crate::spec::base::apple::{macos_llvm_target, opts, Arch}; use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions}; pub fn target() -> Target { diff --git a/compiler/rustc_target/src/spec/aarch64_apple_ios.rs b/compiler/rustc_target/src/spec/aarch64_apple_ios.rs index e9edfd2877b8..9fc5b5de466b 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_ios.rs +++ b/compiler/rustc_target/src/spec/aarch64_apple_ios.rs @@ -1,4 +1,4 @@ -use super::apple_base::{ios_llvm_target, opts, Arch}; +use crate::spec::base::apple::{ios_llvm_target, opts, Arch}; use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions}; pub fn target() -> Target { diff --git a/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs index b29ab14e7f28..0172a3a9c2e8 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs +++ b/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs @@ -1,4 +1,4 @@ -use super::apple_base::{opts, Arch}; +use crate::spec::base::apple::{opts, Arch}; use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, SanitizerSet, Target, TargetOptions}; pub fn target() -> Target { diff --git a/compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs b/compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs index 6e2d62b6e085..602a687779e4 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs +++ b/compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs @@ -1,4 +1,4 @@ -use super::apple_base::{ios_sim_llvm_target, opts, Arch}; +use crate::spec::base::apple::{ios_sim_llvm_target, opts, Arch}; use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions}; pub fn target() -> Target { diff --git a/compiler/rustc_target/src/spec/aarch64_apple_tvos.rs b/compiler/rustc_target/src/spec/aarch64_apple_tvos.rs index f7cdfa71c4b6..a1a31935509c 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_tvos.rs +++ b/compiler/rustc_target/src/spec/aarch64_apple_tvos.rs @@ -1,4 +1,4 @@ -use super::apple_base::{opts, tvos_llvm_target, Arch}; +use crate::spec::base::apple::{opts, tvos_llvm_target, Arch}; use crate::spec::{FramePointer, Target, TargetOptions}; pub fn target() -> Target { diff --git a/compiler/rustc_target/src/spec/aarch64_apple_tvos_sim.rs b/compiler/rustc_target/src/spec/aarch64_apple_tvos_sim.rs index 909a52a5097e..7b0bbb28e476 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_tvos_sim.rs +++ b/compiler/rustc_target/src/spec/aarch64_apple_tvos_sim.rs @@ -1,4 +1,4 @@ -use super::apple_base::{opts, tvos_sim_llvm_target, Arch}; +use crate::spec::base::apple::{opts, tvos_sim_llvm_target, Arch}; use crate::spec::{FramePointer, Target, TargetOptions}; pub fn target() -> Target { diff --git a/compiler/rustc_target/src/spec/aarch64_apple_watchos_sim.rs b/compiler/rustc_target/src/spec/aarch64_apple_watchos_sim.rs index e4af4127c222..014560d2278b 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_watchos_sim.rs +++ b/compiler/rustc_target/src/spec/aarch64_apple_watchos_sim.rs @@ -1,4 +1,4 @@ -use super::apple_base::{opts, watchos_sim_llvm_target, Arch}; +use crate::spec::base::apple::{opts, watchos_sim_llvm_target, Arch}; use crate::spec::{FramePointer, Target, TargetOptions}; pub fn target() -> Target { diff --git a/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu.rs index b84783c0a407..bbaa870ec2e8 100644 --- a/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu.rs @@ -1,5 +1,5 @@ use crate::abi::Endian; -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -12,7 +12,7 @@ pub fn target() -> Target { max_atomic_width: Some(128), mcount: "\u{1}_mcount".into(), endian: Endian::Big, - ..super::linux_gnu_base::opts() + ..base::linux_gnu::opts() }, } } diff --git a/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu_ilp32.rs b/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu_ilp32.rs index a24e0119f25e..7536e507b3d7 100644 --- a/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu_ilp32.rs +++ b/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu_ilp32.rs @@ -1,8 +1,8 @@ use crate::abi::Endian; -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::linux_gnu_base::opts(); + let mut base = base::linux_gnu::opts(); base.max_atomic_width = Some(128); Target { diff --git a/compiler/rustc_target/src/spec/aarch64_be_unknown_netbsd.rs b/compiler/rustc_target/src/spec/aarch64_be_unknown_netbsd.rs index 98ae05974aa8..21de8a71a0df 100644 --- a/compiler/rustc_target/src/spec/aarch64_be_unknown_netbsd.rs +++ b/compiler/rustc_target/src/spec/aarch64_be_unknown_netbsd.rs @@ -1,5 +1,5 @@ use crate::abi::Endian; -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -11,7 +11,7 @@ pub fn target() -> Target { mcount: "__mcount".into(), max_atomic_width: Some(128), endian: Endian::Big, - ..super::netbsd_base::opts() + ..base::netbsd::opts() }, } } diff --git a/compiler/rustc_target/src/spec/aarch64_kmc_solid_asp3.rs b/compiler/rustc_target/src/spec/aarch64_kmc_solid_asp3.rs index 437fd6015803..f72a6c1056f2 100644 --- a/compiler/rustc_target/src/spec/aarch64_kmc_solid_asp3.rs +++ b/compiler/rustc_target/src/spec/aarch64_kmc_solid_asp3.rs @@ -1,7 +1,7 @@ -use super::{RelocModel, Target, TargetOptions}; +use super::{base, RelocModel, Target, TargetOptions}; pub fn target() -> Target { - let base = super::solid_base::opts("asp3"); + let base = base::solid::opts("asp3"); Target { llvm_target: "aarch64-unknown-none".into(), pointer_width: 64, diff --git a/compiler/rustc_target/src/spec/aarch64_linux_android.rs b/compiler/rustc_target/src/spec/aarch64_linux_android.rs index 071b727b35c5..7c6fed7ab995 100644 --- a/compiler/rustc_target/src/spec/aarch64_linux_android.rs +++ b/compiler/rustc_target/src/spec/aarch64_linux_android.rs @@ -1,4 +1,4 @@ -use crate::spec::{SanitizerSet, Target, TargetOptions}; +use crate::spec::{base, SanitizerSet, Target, TargetOptions}; // See https://developer.android.com/ndk/guides/abis.html#arm64-v8a // for target ABI requirements. @@ -20,7 +20,7 @@ pub fn target() -> Target { | SanitizerSet::SHADOWCALLSTACK | SanitizerSet::ADDRESS, supports_xray: true, - ..super::android_base::opts() + ..base::android::opts() }, } } diff --git a/compiler/rustc_target/src/spec/aarch64_pc_windows_gnullvm.rs b/compiler/rustc_target/src/spec/aarch64_pc_windows_gnullvm.rs index cf1d7ca1158d..1ea738142825 100644 --- a/compiler/rustc_target/src/spec/aarch64_pc_windows_gnullvm.rs +++ b/compiler/rustc_target/src/spec/aarch64_pc_windows_gnullvm.rs @@ -1,7 +1,7 @@ -use crate::spec::Target; +use crate::spec::{base, Target}; pub fn target() -> Target { - let mut base = super::windows_gnullvm_base::opts(); + let mut base = base::windows_gnullvm::opts(); base.max_atomic_width = Some(128); base.features = "+v8a,+neon,+fp-armv8".into(); base.linker = Some("aarch64-w64-mingw32-clang".into()); diff --git a/compiler/rustc_target/src/spec/aarch64_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/aarch64_pc_windows_msvc.rs index 56b76bc7ada9..cbd1329726a2 100644 --- a/compiler/rustc_target/src/spec/aarch64_pc_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/aarch64_pc_windows_msvc.rs @@ -1,7 +1,7 @@ -use crate::spec::Target; +use crate::spec::{base, Target}; pub fn target() -> Target { - let mut base = super::windows_msvc_base::opts(); + let mut base = base::windows_msvc::opts(); base.max_atomic_width = Some(128); base.features = "+v8a,+neon,+fp-armv8".into(); diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_freebsd.rs b/compiler/rustc_target/src/spec/aarch64_unknown_freebsd.rs index 84fa9814bbea..0f95984a31f5 100644 --- a/compiler/rustc_target/src/spec/aarch64_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/aarch64_unknown_freebsd.rs @@ -1,4 +1,4 @@ -use crate::spec::{SanitizerSet, Target, TargetOptions}; +use crate::spec::{base, SanitizerSet, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -13,7 +13,7 @@ pub fn target() -> Target { | SanitizerSet::CFI | SanitizerSet::MEMORY | SanitizerSet::THREAD, - ..super::freebsd_base::opts() + ..base::freebsd::opts() }, } } diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_fuchsia.rs b/compiler/rustc_target/src/spec/aarch64_unknown_fuchsia.rs index a5683fa7348a..cacc6ea235a3 100644 --- a/compiler/rustc_target/src/spec/aarch64_unknown_fuchsia.rs +++ b/compiler/rustc_target/src/spec/aarch64_unknown_fuchsia.rs @@ -1,4 +1,4 @@ -use crate::spec::{SanitizerSet, Target, TargetOptions}; +use crate::spec::{base, SanitizerSet, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -12,7 +12,7 @@ pub fn target() -> Target { supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::SHADOWCALLSTACK, - ..super::fuchsia_base::opts() + ..base::fuchsia::opts() }, } } diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_hermit.rs b/compiler/rustc_target/src/spec/aarch64_unknown_hermit.rs index 2414867be552..3839e0b9c465 100644 --- a/compiler/rustc_target/src/spec/aarch64_unknown_hermit.rs +++ b/compiler/rustc_target/src/spec/aarch64_unknown_hermit.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -9,7 +9,7 @@ pub fn target() -> Target { options: TargetOptions { features: "+v8a,+strict-align,+neon,+fp-armv8".into(), max_atomic_width: Some(128), - ..super::hermit_base::opts() + ..base::hermit::opts() }, } } diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs index da246089440f..c0b07db38180 100644 --- a/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs @@ -1,4 +1,4 @@ -use crate::spec::{SanitizerSet, Target, TargetOptions}; +use crate::spec::{base, SanitizerSet, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -18,7 +18,7 @@ pub fn target() -> Target { | SanitizerSet::THREAD | SanitizerSet::HWADDRESS, supports_xray: true, - ..super::linux_gnu_base::opts() + ..base::linux_gnu::opts() }, } } diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu_ilp32.rs b/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu_ilp32.rs index ad9df53c2b7f..d4c6271b241f 100644 --- a/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu_ilp32.rs +++ b/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu_ilp32.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -11,7 +11,7 @@ pub fn target() -> Target { features: "+v8a,+outline-atomics".into(), max_atomic_width: Some(128), mcount: "\u{1}_mcount".into(), - ..super::linux_gnu_base::opts() + ..base::linux_gnu::opts() }, } } diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/aarch64_unknown_linux_musl.rs index 523eb6bd2fe2..364df677e44a 100644 --- a/compiler/rustc_target/src/spec/aarch64_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/aarch64_unknown_linux_musl.rs @@ -1,7 +1,7 @@ -use crate::spec::{SanitizerSet, Target, TargetOptions}; +use crate::spec::{base, SanitizerSet, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::linux_musl_base::opts(); + let mut base = base::linux_musl::opts(); base.max_atomic_width = Some(128); base.supports_xray = true; base.features = "+v8a".into(); diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_linux_ohos.rs b/compiler/rustc_target/src/spec/aarch64_unknown_linux_ohos.rs index c8f3db00e01b..3698693a54aa 100644 --- a/compiler/rustc_target/src/spec/aarch64_unknown_linux_ohos.rs +++ b/compiler/rustc_target/src/spec/aarch64_unknown_linux_ohos.rs @@ -1,9 +1,9 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; use super::SanitizerSet; pub fn target() -> Target { - let mut base = super::linux_ohos_base::opts(); + let mut base = base::linux_ohos::opts(); base.max_atomic_width = Some(128); Target { diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_netbsd.rs b/compiler/rustc_target/src/spec/aarch64_unknown_netbsd.rs index a58b64d3d03a..3194d16ff473 100644 --- a/compiler/rustc_target/src/spec/aarch64_unknown_netbsd.rs +++ b/compiler/rustc_target/src/spec/aarch64_unknown_netbsd.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -10,7 +10,7 @@ pub fn target() -> Target { features: "+v8a".into(), mcount: "__mcount".into(), max_atomic_width: Some(128), - ..super::netbsd_base::opts() + ..base::netbsd::opts() }, } } diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_nto_qnx_710.rs b/compiler/rustc_target/src/spec/aarch64_unknown_nto_qnx_710.rs index 630642dcd33a..aeeaab3af323 100644 --- a/compiler/rustc_target/src/spec/aarch64_unknown_nto_qnx_710.rs +++ b/compiler/rustc_target/src/spec/aarch64_unknown_nto_qnx_710.rs @@ -1,5 +1,4 @@ -use super::nto_qnx_base; -use crate::spec::{Cc, LinkerFlavor, Lld, Target, TargetOptions}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -24,7 +23,7 @@ pub fn target() -> Target { &["-Vgcc_ntoaarch64le_cxx"], ), env: "nto71".into(), - ..nto_qnx_base::opts() + ..base::nto_qnx::opts() }, } } diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/aarch64_unknown_openbsd.rs index 224e31af24f7..e3f5aafc7d44 100644 --- a/compiler/rustc_target/src/spec/aarch64_unknown_openbsd.rs +++ b/compiler/rustc_target/src/spec/aarch64_unknown_openbsd.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -9,7 +9,7 @@ pub fn target() -> Target { options: TargetOptions { features: "+v8a".into(), max_atomic_width: Some(128), - ..super::openbsd_base::opts() + ..base::openbsd::opts() }, } } diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_redox.rs b/compiler/rustc_target/src/spec/aarch64_unknown_redox.rs index 5650162cdbc9..de875e29ffdc 100644 --- a/compiler/rustc_target/src/spec/aarch64_unknown_redox.rs +++ b/compiler/rustc_target/src/spec/aarch64_unknown_redox.rs @@ -1,7 +1,7 @@ -use crate::spec::Target; +use crate::spec::{base, Target}; pub fn target() -> Target { - let mut base = super::redox_base::opts(); + let mut base = base::redox::opts(); base.max_atomic_width = Some(128); base.features = "+v8a".into(); diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_teeos.rs b/compiler/rustc_target/src/spec/aarch64_unknown_teeos.rs index 64a7dc681c89..eec2668d4878 100644 --- a/compiler/rustc_target/src/spec/aarch64_unknown_teeos.rs +++ b/compiler/rustc_target/src/spec/aarch64_unknown_teeos.rs @@ -1,7 +1,7 @@ -use crate::spec::Target; +use crate::spec::{base, Target}; pub fn target() -> Target { - let mut base = super::teeos_base::opts(); + let mut base = base::teeos::opts(); base.features = "+strict-align,+neon,+fp-armv8".into(); base.max_atomic_width = Some(128); base.linker = Some("aarch64-linux-gnu-ld".into()); diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_uefi.rs b/compiler/rustc_target/src/spec/aarch64_unknown_uefi.rs index 82fb015569d6..9ed6ed2651f3 100644 --- a/compiler/rustc_target/src/spec/aarch64_unknown_uefi.rs +++ b/compiler/rustc_target/src/spec/aarch64_unknown_uefi.rs @@ -1,11 +1,10 @@ // This defines the aarch64 target for UEFI systems as described in the UEFI specification. See the // uefi-base module for generic UEFI options. -use super::uefi_msvc_base; -use crate::spec::{LinkerFlavor, Lld, Target}; +use crate::spec::{base, LinkerFlavor, Lld, Target}; pub fn target() -> Target { - let mut base = uefi_msvc_base::opts(); + let mut base = base::uefi_msvc::opts(); base.max_atomic_width = Some(128); base.add_pre_link_args(LinkerFlavor::Msvc(Lld::No), &["/machine:arm64"]); diff --git a/compiler/rustc_target/src/spec/aarch64_uwp_windows_msvc.rs b/compiler/rustc_target/src/spec/aarch64_uwp_windows_msvc.rs index d39442d91776..c64b2c7d113f 100644 --- a/compiler/rustc_target/src/spec/aarch64_uwp_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/aarch64_uwp_windows_msvc.rs @@ -1,7 +1,7 @@ -use crate::spec::Target; +use crate::spec::{base, Target}; pub fn target() -> Target { - let mut base = super::windows_uwp_msvc_base::opts(); + let mut base = base::windows_uwp_msvc::opts(); base.max_atomic_width = Some(128); base.features = "+v8a".into(); diff --git a/compiler/rustc_target/src/spec/aarch64_wrs_vxworks.rs b/compiler/rustc_target/src/spec/aarch64_wrs_vxworks.rs index 7e2af4c7a6a4..29f61d857788 100644 --- a/compiler/rustc_target/src/spec/aarch64_wrs_vxworks.rs +++ b/compiler/rustc_target/src/spec/aarch64_wrs_vxworks.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -9,7 +9,7 @@ pub fn target() -> Target { options: TargetOptions { features: "+v8a".into(), max_atomic_width: Some(128), - ..super::vxworks_base::opts() + ..base::vxworks::opts() }, } } diff --git a/compiler/rustc_target/src/spec/arm64_32_apple_watchos.rs b/compiler/rustc_target/src/spec/arm64_32_apple_watchos.rs index c757ed45e472..9931b7b866cb 100644 --- a/compiler/rustc_target/src/spec/arm64_32_apple_watchos.rs +++ b/compiler/rustc_target/src/spec/arm64_32_apple_watchos.rs @@ -1,4 +1,4 @@ -use super::apple_base::{opts, Arch}; +use crate::spec::base::apple::{opts, Arch}; use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { diff --git a/compiler/rustc_target/src/spec/arm_linux_androideabi.rs b/compiler/rustc_target/src/spec/arm_linux_androideabi.rs index bbf1fa315ab4..43b27b414d88 100644 --- a/compiler/rustc_target/src/spec/arm_linux_androideabi.rs +++ b/compiler/rustc_target/src/spec/arm_linux_androideabi.rs @@ -1,4 +1,4 @@ -use crate::spec::{SanitizerSet, Target, TargetOptions}; +use crate::spec::{base, SanitizerSet, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -12,7 +12,7 @@ pub fn target() -> Target { features: "+strict-align,+v5te".into(), supported_sanitizers: SanitizerSet::ADDRESS, max_atomic_width: Some(32), - ..super::android_base::opts() + ..base::android::opts() }, } } diff --git a/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabi.rs index 400030ca0c60..e4fa54c4b754 100644 --- a/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabi.rs +++ b/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabi.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -12,7 +12,7 @@ pub fn target() -> Target { max_atomic_width: Some(64), mcount: "\u{1}__gnu_mcount_nc".into(), llvm_mcount_intrinsic: Some("llvm.arm.gnu.eabi.mcount".into()), - ..super::linux_gnu_base::opts() + ..base::linux_gnu::opts() }, } } diff --git a/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabihf.rs b/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabihf.rs index 6228fb15a83f..f379ea35ecb6 100644 --- a/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabihf.rs +++ b/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabihf.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -12,7 +12,7 @@ pub fn target() -> Target { max_atomic_width: Some(64), mcount: "\u{1}__gnu_mcount_nc".into(), llvm_mcount_intrinsic: Some("llvm.arm.gnu.eabi.mcount".into()), - ..super::linux_gnu_base::opts() + ..base::linux_gnu::opts() }, } } diff --git a/compiler/rustc_target/src/spec/arm_unknown_linux_musleabi.rs b/compiler/rustc_target/src/spec/arm_unknown_linux_musleabi.rs index 3ef441d6a607..f3d5ff892442 100644 --- a/compiler/rustc_target/src/spec/arm_unknown_linux_musleabi.rs +++ b/compiler/rustc_target/src/spec/arm_unknown_linux_musleabi.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -16,7 +16,7 @@ pub fn target() -> Target { features: "+strict-align,+v6".into(), max_atomic_width: Some(64), mcount: "\u{1}mcount".into(), - ..super::linux_musl_base::opts() + ..base::linux_musl::opts() }, } } diff --git a/compiler/rustc_target/src/spec/arm_unknown_linux_musleabihf.rs b/compiler/rustc_target/src/spec/arm_unknown_linux_musleabihf.rs index eb6660d4c289..f3e366d59937 100644 --- a/compiler/rustc_target/src/spec/arm_unknown_linux_musleabihf.rs +++ b/compiler/rustc_target/src/spec/arm_unknown_linux_musleabihf.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -16,7 +16,7 @@ pub fn target() -> Target { features: "+strict-align,+v6,+vfp2,-d32".into(), max_atomic_width: Some(64), mcount: "\u{1}mcount".into(), - ..super::linux_musl_base::opts() + ..base::linux_musl::opts() }, } } diff --git a/compiler/rustc_target/src/spec/armeb_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/armeb_unknown_linux_gnueabi.rs index 1d66515a72e0..07c7e1c58456 100644 --- a/compiler/rustc_target/src/spec/armeb_unknown_linux_gnueabi.rs +++ b/compiler/rustc_target/src/spec/armeb_unknown_linux_gnueabi.rs @@ -1,5 +1,5 @@ use crate::abi::Endian; -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -14,7 +14,7 @@ pub fn target() -> Target { max_atomic_width: Some(64), mcount: "\u{1}__gnu_mcount_nc".into(), llvm_mcount_intrinsic: Some("llvm.arm.gnu.eabi.mcount".into()), - ..super::linux_gnu_base::opts() + ..base::linux_gnu::opts() }, } } diff --git a/compiler/rustc_target/src/spec/armv4t_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/armv4t_unknown_linux_gnueabi.rs index cffebcc9581c..5ab753c3d61b 100644 --- a/compiler/rustc_target/src/spec/armv4t_unknown_linux_gnueabi.rs +++ b/compiler/rustc_target/src/spec/armv4t_unknown_linux_gnueabi.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -14,7 +14,7 @@ pub fn target() -> Target { mcount: "\u{1}__gnu_mcount_nc".into(), llvm_mcount_intrinsic: Some("llvm.arm.gnu.eabi.mcount".into()), has_thumb_interworking: true, - ..super::linux_gnu_base::opts() + ..base::linux_gnu::opts() }, } } diff --git a/compiler/rustc_target/src/spec/armv5te_none_eabi.rs b/compiler/rustc_target/src/spec/armv5te_none_eabi.rs index dfd27b654746..5e23efecdbe1 100644 --- a/compiler/rustc_target/src/spec/armv5te_none_eabi.rs +++ b/compiler/rustc_target/src/spec/armv5te_none_eabi.rs @@ -1,6 +1,6 @@ //! Targets the ARMv5TE, with code as `a32` code by default. -use crate::spec::{cvs, FramePointer, Target, TargetOptions}; +use crate::spec::{base, cvs, FramePointer, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -35,7 +35,7 @@ pub fn target() -> Target { atomic_cas: false, has_thumb_interworking: true, - ..super::thumb_base::opts() + ..base::thumb::opts() }, } } diff --git a/compiler/rustc_target/src/spec/armv5te_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/armv5te_unknown_linux_gnueabi.rs index b940563102b0..7155ab289c0a 100644 --- a/compiler/rustc_target/src/spec/armv5te_unknown_linux_gnueabi.rs +++ b/compiler/rustc_target/src/spec/armv5te_unknown_linux_gnueabi.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -13,7 +13,7 @@ pub fn target() -> Target { max_atomic_width: Some(32), mcount: "\u{1}__gnu_mcount_nc".into(), has_thumb_interworking: true, - ..super::linux_gnu_base::opts() + ..base::linux_gnu::opts() }, } } diff --git a/compiler/rustc_target/src/spec/armv5te_unknown_linux_musleabi.rs b/compiler/rustc_target/src/spec/armv5te_unknown_linux_musleabi.rs index 2530971b5021..3f25ab2bcc19 100644 --- a/compiler/rustc_target/src/spec/armv5te_unknown_linux_musleabi.rs +++ b/compiler/rustc_target/src/spec/armv5te_unknown_linux_musleabi.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -17,7 +17,7 @@ pub fn target() -> Target { max_atomic_width: Some(32), mcount: "\u{1}mcount".into(), has_thumb_interworking: true, - ..super::linux_musl_base::opts() + ..base::linux_musl::opts() }, } } diff --git a/compiler/rustc_target/src/spec/armv5te_unknown_linux_uclibceabi.rs b/compiler/rustc_target/src/spec/armv5te_unknown_linux_uclibceabi.rs index a51be10a3d82..af6e3baa27ae 100644 --- a/compiler/rustc_target/src/spec/armv5te_unknown_linux_uclibceabi.rs +++ b/compiler/rustc_target/src/spec/armv5te_unknown_linux_uclibceabi.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -13,7 +13,7 @@ pub fn target() -> Target { max_atomic_width: Some(32), mcount: "\u{1}__gnu_mcount_nc".into(), has_thumb_interworking: true, - ..super::linux_uclibc_base::opts() + ..base::linux_uclibc::opts() }, } } diff --git a/compiler/rustc_target/src/spec/armv6_unknown_freebsd.rs b/compiler/rustc_target/src/spec/armv6_unknown_freebsd.rs index 4a8aa31576fa..22f6ee810557 100644 --- a/compiler/rustc_target/src/spec/armv6_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/armv6_unknown_freebsd.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -14,7 +14,7 @@ pub fn target() -> Target { max_atomic_width: Some(64), mcount: "\u{1}__gnu_mcount_nc".into(), llvm_mcount_intrinsic: Some("llvm.arm.gnu.eabi.mcount".into()), - ..super::freebsd_base::opts() + ..base::freebsd::opts() }, } } diff --git a/compiler/rustc_target/src/spec/armv6_unknown_netbsd_eabihf.rs b/compiler/rustc_target/src/spec/armv6_unknown_netbsd_eabihf.rs index 6e26f686fcb5..84d9ceac04d4 100644 --- a/compiler/rustc_target/src/spec/armv6_unknown_netbsd_eabihf.rs +++ b/compiler/rustc_target/src/spec/armv6_unknown_netbsd_eabihf.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -13,7 +13,7 @@ pub fn target() -> Target { features: "+v6,+vfp2,-d32".into(), max_atomic_width: Some(64), mcount: "__mcount".into(), - ..super::netbsd_base::opts() + ..base::netbsd::opts() }, } } diff --git a/compiler/rustc_target/src/spec/armv7_linux_androideabi.rs b/compiler/rustc_target/src/spec/armv7_linux_androideabi.rs index 402e0fd92363..bb3e574e32fe 100644 --- a/compiler/rustc_target/src/spec/armv7_linux_androideabi.rs +++ b/compiler/rustc_target/src/spec/armv7_linux_androideabi.rs @@ -1,4 +1,4 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, SanitizerSet, Target, TargetOptions}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, SanitizerSet, Target, TargetOptions}; // This target if is for the baseline of the Android v7a ABI // in thumb mode. It's named armv7-* instead of thumbv7-* @@ -9,7 +9,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, SanitizerSet, Target, TargetOptions}; // for target ABI requirements. pub fn target() -> Target { - let mut base = super::android_base::opts(); + let mut base = base::android::opts(); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-march=armv7-a"]); Target { llvm_target: "armv7-none-linux-android".into(), diff --git a/compiler/rustc_target/src/spec/armv7_unknown_freebsd.rs b/compiler/rustc_target/src/spec/armv7_unknown_freebsd.rs index bc37b62de8e2..9f4a432c6fa5 100644 --- a/compiler/rustc_target/src/spec/armv7_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/armv7_unknown_freebsd.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -13,7 +13,7 @@ pub fn target() -> Target { features: "+v7,+vfp3,-d32,+thumb2,-neon".into(), max_atomic_width: Some(64), mcount: "\u{1}__gnu_mcount_nc".into(), - ..super::freebsd_base::opts() + ..base::freebsd::opts() }, } } diff --git a/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabi.rs index 73ae212a7a6e..ad9fd773b8b8 100644 --- a/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabi.rs +++ b/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabi.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; // This target is for glibc Linux on ARMv7 without thumb-mode, NEON or // hardfloat. @@ -15,7 +15,7 @@ pub fn target() -> Target { max_atomic_width: Some(64), mcount: "\u{1}__gnu_mcount_nc".into(), llvm_mcount_intrinsic: Some("llvm.arm.gnu.eabi.mcount".into()), - ..super::linux_gnu_base::opts() + ..base::linux_gnu::opts() }, } } diff --git a/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabihf.rs b/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabihf.rs index e39ea49a0032..aad7977d504a 100644 --- a/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabihf.rs +++ b/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabihf.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; // This target is for glibc Linux on ARMv7 without NEON or // thumb-mode. See the thumbv7neon variant for enabling both. @@ -15,7 +15,7 @@ pub fn target() -> Target { features: "+v7,+vfp3,-d32,+thumb2,-neon".into(), max_atomic_width: Some(64), mcount: "\u{1}__gnu_mcount_nc".into(), - ..super::linux_gnu_base::opts() + ..base::linux_gnu::opts() }, } } diff --git a/compiler/rustc_target/src/spec/armv7_unknown_linux_musleabi.rs b/compiler/rustc_target/src/spec/armv7_unknown_linux_musleabi.rs index 7dae8577396e..7f30a5ad7d7d 100644 --- a/compiler/rustc_target/src/spec/armv7_unknown_linux_musleabi.rs +++ b/compiler/rustc_target/src/spec/armv7_unknown_linux_musleabi.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; // This target is for musl Linux on ARMv7 without thumb-mode, NEON or // hardfloat. @@ -20,7 +20,7 @@ pub fn target() -> Target { features: "+v7,+thumb2,+soft-float,-neon".into(), max_atomic_width: Some(64), mcount: "\u{1}mcount".into(), - ..super::linux_musl_base::opts() + ..base::linux_musl::opts() }, } } diff --git a/compiler/rustc_target/src/spec/armv7_unknown_linux_musleabihf.rs b/compiler/rustc_target/src/spec/armv7_unknown_linux_musleabihf.rs index ba83964bf585..ec5c6419f639 100644 --- a/compiler/rustc_target/src/spec/armv7_unknown_linux_musleabihf.rs +++ b/compiler/rustc_target/src/spec/armv7_unknown_linux_musleabihf.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; // This target is for musl Linux on ARMv7 without thumb-mode or NEON. @@ -19,7 +19,7 @@ pub fn target() -> Target { features: "+v7,+vfp3,-d32,+thumb2,-neon".into(), max_atomic_width: Some(64), mcount: "\u{1}mcount".into(), - ..super::linux_musl_base::opts() + ..base::linux_musl::opts() }, } } diff --git a/compiler/rustc_target/src/spec/armv7_unknown_linux_ohos.rs b/compiler/rustc_target/src/spec/armv7_unknown_linux_ohos.rs index e9b0bda68ef1..9f2ac541ddc9 100644 --- a/compiler/rustc_target/src/spec/armv7_unknown_linux_ohos.rs +++ b/compiler/rustc_target/src/spec/armv7_unknown_linux_ohos.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; // This target is for OpenHarmony on ARMv7 Linux with thumb-mode, but no NEON or // hardfloat. @@ -18,7 +18,7 @@ pub fn target() -> Target { features: "+v7,+thumb2,+soft-float,-neon".into(), max_atomic_width: Some(64), mcount: "\u{1}mcount".into(), - ..super::linux_ohos_base::opts() + ..base::linux_ohos::opts() }, } } diff --git a/compiler/rustc_target/src/spec/armv7_unknown_linux_uclibceabi.rs b/compiler/rustc_target/src/spec/armv7_unknown_linux_uclibceabi.rs index 171f67070d54..212c80718f03 100644 --- a/compiler/rustc_target/src/spec/armv7_unknown_linux_uclibceabi.rs +++ b/compiler/rustc_target/src/spec/armv7_unknown_linux_uclibceabi.rs @@ -1,10 +1,10 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; // This target is for uclibc Linux on ARMv7 without NEON, // thumb-mode or hardfloat. pub fn target() -> Target { - let base = super::linux_uclibc_base::opts(); + let base = base::linux_uclibc::opts(); Target { llvm_target: "armv7-unknown-linux-gnueabi".into(), pointer_width: 32, diff --git a/compiler/rustc_target/src/spec/armv7_unknown_linux_uclibceabihf.rs b/compiler/rustc_target/src/spec/armv7_unknown_linux_uclibceabihf.rs index d3e95a6573d8..f760ad9e79c2 100644 --- a/compiler/rustc_target/src/spec/armv7_unknown_linux_uclibceabihf.rs +++ b/compiler/rustc_target/src/spec/armv7_unknown_linux_uclibceabihf.rs @@ -1,10 +1,10 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; // This target is for uclibc Linux on ARMv7 without NEON or // thumb-mode. See the thumbv7neon variant for enabling both. pub fn target() -> Target { - let base = super::linux_uclibc_base::opts(); + let base = base::linux_uclibc::opts(); Target { llvm_target: "armv7-unknown-linux-gnueabihf".into(), pointer_width: 32, diff --git a/compiler/rustc_target/src/spec/armv7_unknown_netbsd_eabihf.rs b/compiler/rustc_target/src/spec/armv7_unknown_netbsd_eabihf.rs index c89ae2483988..e5518c6daecf 100644 --- a/compiler/rustc_target/src/spec/armv7_unknown_netbsd_eabihf.rs +++ b/compiler/rustc_target/src/spec/armv7_unknown_netbsd_eabihf.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -13,7 +13,7 @@ pub fn target() -> Target { features: "+v7,+vfp3,-d32,+thumb2,-neon".into(), max_atomic_width: Some(64), mcount: "__mcount".into(), - ..super::netbsd_base::opts() + ..base::netbsd::opts() }, } } diff --git a/compiler/rustc_target/src/spec/armv7_wrs_vxworks_eabihf.rs b/compiler/rustc_target/src/spec/armv7_wrs_vxworks_eabihf.rs index c1ab90172e27..0b4e64307d28 100644 --- a/compiler/rustc_target/src/spec/armv7_wrs_vxworks_eabihf.rs +++ b/compiler/rustc_target/src/spec/armv7_wrs_vxworks_eabihf.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -11,7 +11,7 @@ pub fn target() -> Target { // Info about features at https://wiki.debian.org/ArmHardFloatPort features: "+v7,+vfp3,-d32,+thumb2,-neon".into(), max_atomic_width: Some(64), - ..super::vxworks_base::opts() + ..base::vxworks::opts() }, } } diff --git a/compiler/rustc_target/src/spec/armv7a_kmc_solid_asp3_eabi.rs b/compiler/rustc_target/src/spec/armv7a_kmc_solid_asp3_eabi.rs index b49dc650bd00..68c6aa9efc67 100644 --- a/compiler/rustc_target/src/spec/armv7a_kmc_solid_asp3_eabi.rs +++ b/compiler/rustc_target/src/spec/armv7a_kmc_solid_asp3_eabi.rs @@ -1,7 +1,7 @@ -use super::{RelocModel, Target, TargetOptions}; +use super::{base, RelocModel, Target, TargetOptions}; pub fn target() -> Target { - let base = super::solid_base::opts("asp3"); + let base = base::solid::opts("asp3"); Target { llvm_target: "armv7a-none-eabi".into(), pointer_width: 32, diff --git a/compiler/rustc_target/src/spec/armv7a_kmc_solid_asp3_eabihf.rs b/compiler/rustc_target/src/spec/armv7a_kmc_solid_asp3_eabihf.rs index 7d30238e8ab2..04e45699cfc4 100644 --- a/compiler/rustc_target/src/spec/armv7a_kmc_solid_asp3_eabihf.rs +++ b/compiler/rustc_target/src/spec/armv7a_kmc_solid_asp3_eabihf.rs @@ -1,7 +1,7 @@ -use super::{RelocModel, Target, TargetOptions}; +use super::{base, RelocModel, Target, TargetOptions}; pub fn target() -> Target { - let base = super::solid_base::opts("asp3"); + let base = base::solid::opts("asp3"); Target { llvm_target: "armv7a-none-eabihf".into(), pointer_width: 32, diff --git a/compiler/rustc_target/src/spec/armv7k_apple_watchos.rs b/compiler/rustc_target/src/spec/armv7k_apple_watchos.rs index 6e1d00d1f6ca..751fdcb20f19 100644 --- a/compiler/rustc_target/src/spec/armv7k_apple_watchos.rs +++ b/compiler/rustc_target/src/spec/armv7k_apple_watchos.rs @@ -1,4 +1,4 @@ -use super::apple_base::{opts, Arch}; +use crate::spec::base::apple::{opts, Arch}; use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { diff --git a/compiler/rustc_target/src/spec/armv7s_apple_ios.rs b/compiler/rustc_target/src/spec/armv7s_apple_ios.rs index be7f8542c9e5..44c624c4ebde 100644 --- a/compiler/rustc_target/src/spec/armv7s_apple_ios.rs +++ b/compiler/rustc_target/src/spec/armv7s_apple_ios.rs @@ -1,4 +1,4 @@ -use super::apple_base::{ios_llvm_target, opts, Arch}; +use crate::spec::base::apple::{ios_llvm_target, opts, Arch}; use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { diff --git a/compiler/rustc_target/src/spec/avr_unknown_gnu_atmega328.rs b/compiler/rustc_target/src/spec/avr_unknown_gnu_atmega328.rs index 6c16b03cc283..bf01413a80ad 100644 --- a/compiler/rustc_target/src/spec/avr_unknown_gnu_atmega328.rs +++ b/compiler/rustc_target/src/spec/avr_unknown_gnu_atmega328.rs @@ -1,5 +1,5 @@ -use crate::spec::Target; +use crate::spec::{base, Target}; pub fn target() -> Target { - super::avr_gnu_base::target("atmega328", "-mmcu=atmega328") + base::avr_gnu::target("atmega328", "-mmcu=atmega328") } diff --git a/compiler/rustc_target/src/spec/aix_base.rs b/compiler/rustc_target/src/spec/base/aix.rs similarity index 100% rename from compiler/rustc_target/src/spec/aix_base.rs rename to compiler/rustc_target/src/spec/base/aix.rs diff --git a/compiler/rustc_target/src/spec/android_base.rs b/compiler/rustc_target/src/spec/base/android.rs similarity index 85% rename from compiler/rustc_target/src/spec/android_base.rs rename to compiler/rustc_target/src/spec/base/android.rs index 9c1df1a06778..af15c16a5a9a 100644 --- a/compiler/rustc_target/src/spec/android_base.rs +++ b/compiler/rustc_target/src/spec/base/android.rs @@ -1,7 +1,7 @@ -use crate::spec::{SanitizerSet, TargetOptions}; +use crate::spec::{base, SanitizerSet, TargetOptions}; pub fn opts() -> TargetOptions { - let mut base = super::linux_base::opts(); + let mut base = base::linux::opts(); base.os = "android".into(); base.is_like_android = true; base.default_dwarf_version = 2; diff --git a/compiler/rustc_target/src/spec/apple_base.rs b/compiler/rustc_target/src/spec/base/apple/mod.rs similarity index 98% rename from compiler/rustc_target/src/spec/apple_base.rs rename to compiler/rustc_target/src/spec/base/apple/mod.rs index 7a666eea437d..99e64503e257 100644 --- a/compiler/rustc_target/src/spec/apple_base.rs +++ b/compiler/rustc_target/src/spec/base/apple/mod.rs @@ -1,10 +1,10 @@ use std::{borrow::Cow, env}; +use crate::spec::{add_link_args, add_link_args_iter}; use crate::spec::{cvs, Cc, DebuginfoKind, FramePointer, LinkArgs}; use crate::spec::{LinkerFlavor, Lld, SplitDebuginfo, StaticCow, Target, TargetOptions}; #[cfg(test)] -#[path = "apple/tests.rs"] mod tests; use Arch::*; @@ -102,13 +102,13 @@ fn pre_link_args(os: &'static str, arch: Arch, abi: &'static str) -> LinkArgs { LinkerFlavor::Darwin(Cc::No, Lld::No), &["-arch", arch, "-platform_version"], ); - super::add_link_args_iter( + add_link_args_iter( &mut args, LinkerFlavor::Darwin(Cc::No, Lld::No), [platform_name, platform_version.clone(), platform_version].into_iter(), ); if abi != "macabi" { - super::add_link_args(&mut args, LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-arch", arch]); + add_link_args(&mut args, LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-arch", arch]); } args diff --git a/compiler/rustc_target/src/spec/apple/tests.rs b/compiler/rustc_target/src/spec/base/apple/tests.rs similarity index 100% rename from compiler/rustc_target/src/spec/apple/tests.rs rename to compiler/rustc_target/src/spec/base/apple/tests.rs diff --git a/compiler/rustc_target/src/spec/avr_gnu_base.rs b/compiler/rustc_target/src/spec/base/avr_gnu.rs similarity index 100% rename from compiler/rustc_target/src/spec/avr_gnu_base.rs rename to compiler/rustc_target/src/spec/base/avr_gnu.rs diff --git a/compiler/rustc_target/src/spec/bpf_base.rs b/compiler/rustc_target/src/spec/base/bpf.rs similarity index 100% rename from compiler/rustc_target/src/spec/bpf_base.rs rename to compiler/rustc_target/src/spec/base/bpf.rs diff --git a/compiler/rustc_target/src/spec/dragonfly_base.rs b/compiler/rustc_target/src/spec/base/dragonfly.rs similarity index 100% rename from compiler/rustc_target/src/spec/dragonfly_base.rs rename to compiler/rustc_target/src/spec/base/dragonfly.rs diff --git a/compiler/rustc_target/src/spec/freebsd_base.rs b/compiler/rustc_target/src/spec/base/freebsd.rs similarity index 100% rename from compiler/rustc_target/src/spec/freebsd_base.rs rename to compiler/rustc_target/src/spec/base/freebsd.rs diff --git a/compiler/rustc_target/src/spec/fuchsia_base.rs b/compiler/rustc_target/src/spec/base/fuchsia.rs similarity index 100% rename from compiler/rustc_target/src/spec/fuchsia_base.rs rename to compiler/rustc_target/src/spec/base/fuchsia.rs diff --git a/compiler/rustc_target/src/spec/haiku_base.rs b/compiler/rustc_target/src/spec/base/haiku.rs similarity index 100% rename from compiler/rustc_target/src/spec/haiku_base.rs rename to compiler/rustc_target/src/spec/base/haiku.rs diff --git a/compiler/rustc_target/src/spec/hermit_base.rs b/compiler/rustc_target/src/spec/base/hermit.rs similarity index 100% rename from compiler/rustc_target/src/spec/hermit_base.rs rename to compiler/rustc_target/src/spec/base/hermit.rs diff --git a/compiler/rustc_target/src/spec/hurd_base.rs b/compiler/rustc_target/src/spec/base/hurd.rs similarity index 100% rename from compiler/rustc_target/src/spec/hurd_base.rs rename to compiler/rustc_target/src/spec/base/hurd.rs diff --git a/compiler/rustc_target/src/spec/base/hurd_gnu.rs b/compiler/rustc_target/src/spec/base/hurd_gnu.rs new file mode 100644 index 000000000000..3501dbdea1b5 --- /dev/null +++ b/compiler/rustc_target/src/spec/base/hurd_gnu.rs @@ -0,0 +1,5 @@ +use crate::spec::{base, TargetOptions}; + +pub fn opts() -> TargetOptions { + TargetOptions { env: "gnu".into(), ..base::hurd::opts() } +} diff --git a/compiler/rustc_target/src/spec/illumos_base.rs b/compiler/rustc_target/src/spec/base/illumos.rs similarity index 100% rename from compiler/rustc_target/src/spec/illumos_base.rs rename to compiler/rustc_target/src/spec/base/illumos.rs diff --git a/compiler/rustc_target/src/spec/l4re_base.rs b/compiler/rustc_target/src/spec/base/l4re.rs similarity index 100% rename from compiler/rustc_target/src/spec/l4re_base.rs rename to compiler/rustc_target/src/spec/base/l4re.rs diff --git a/compiler/rustc_target/src/spec/linux_base.rs b/compiler/rustc_target/src/spec/base/linux.rs similarity index 100% rename from compiler/rustc_target/src/spec/linux_base.rs rename to compiler/rustc_target/src/spec/base/linux.rs diff --git a/compiler/rustc_target/src/spec/base/linux_gnu.rs b/compiler/rustc_target/src/spec/base/linux_gnu.rs new file mode 100644 index 000000000000..3491277c4407 --- /dev/null +++ b/compiler/rustc_target/src/spec/base/linux_gnu.rs @@ -0,0 +1,5 @@ +use crate::spec::{base, TargetOptions}; + +pub fn opts() -> TargetOptions { + TargetOptions { env: "gnu".into(), ..base::linux::opts() } +} diff --git a/compiler/rustc_target/src/spec/linux_musl_base.rs b/compiler/rustc_target/src/spec/base/linux_musl.rs similarity index 80% rename from compiler/rustc_target/src/spec/linux_musl_base.rs rename to compiler/rustc_target/src/spec/base/linux_musl.rs index b698bcbcef69..5117cadbee0e 100644 --- a/compiler/rustc_target/src/spec/linux_musl_base.rs +++ b/compiler/rustc_target/src/spec/base/linux_musl.rs @@ -1,8 +1,8 @@ use crate::spec::crt_objects; -use crate::spec::{LinkSelfContainedDefault, TargetOptions}; +use crate::spec::{base, LinkSelfContainedDefault, TargetOptions}; pub fn opts() -> TargetOptions { - let mut base = super::linux_base::opts(); + let mut base = base::linux::opts(); base.env = "musl".into(); base.pre_link_objects_self_contained = crt_objects::pre_musl_self_contained(); diff --git a/compiler/rustc_target/src/spec/linux_ohos_base.rs b/compiler/rustc_target/src/spec/base/linux_ohos.rs similarity index 69% rename from compiler/rustc_target/src/spec/linux_ohos_base.rs rename to compiler/rustc_target/src/spec/base/linux_ohos.rs index 4ad4c837336f..273e6a98dd4d 100644 --- a/compiler/rustc_target/src/spec/linux_ohos_base.rs +++ b/compiler/rustc_target/src/spec/base/linux_ohos.rs @@ -1,7 +1,7 @@ -use crate::spec::TargetOptions; +use crate::spec::{base, TargetOptions}; pub fn opts() -> TargetOptions { - let mut base = super::linux_base::opts(); + let mut base = base::linux::opts(); base.env = "ohos".into(); base.crt_static_default = false; diff --git a/compiler/rustc_target/src/spec/base/linux_uclibc.rs b/compiler/rustc_target/src/spec/base/linux_uclibc.rs new file mode 100644 index 000000000000..540344e9e94d --- /dev/null +++ b/compiler/rustc_target/src/spec/base/linux_uclibc.rs @@ -0,0 +1,5 @@ +use crate::spec::{base, TargetOptions}; + +pub fn opts() -> TargetOptions { + TargetOptions { env: "uclibc".into(), ..base::linux::opts() } +} diff --git a/compiler/rustc_target/src/spec/base/mod.rs b/compiler/rustc_target/src/spec/base/mod.rs new file mode 100644 index 000000000000..d137aaa53585 --- /dev/null +++ b/compiler/rustc_target/src/spec/base/mod.rs @@ -0,0 +1,37 @@ +pub(crate) mod aix; +pub(crate) mod android; +pub(crate) mod apple; +pub(crate) mod avr_gnu; +pub(crate) mod bpf; +pub(crate) mod dragonfly; +pub(crate) mod freebsd; +pub(crate) mod fuchsia; +pub(crate) mod haiku; +pub(crate) mod hermit; +pub(crate) mod hurd; +pub(crate) mod hurd_gnu; +pub(crate) mod illumos; +pub(crate) mod l4re; +pub(crate) mod linux; +pub(crate) mod linux_gnu; +pub(crate) mod linux_musl; +pub(crate) mod linux_ohos; +pub(crate) mod linux_uclibc; +pub(crate) mod msvc; +pub(crate) mod netbsd; +pub(crate) mod nto_qnx; +pub(crate) mod openbsd; +pub(crate) mod redox; +pub(crate) mod solaris; +pub(crate) mod solid; +pub(crate) mod teeos; +pub(crate) mod thumb; +pub(crate) mod uefi_msvc; +pub(crate) mod unikraft_linux_musl; +pub(crate) mod vxworks; +pub(crate) mod wasm; +pub(crate) mod windows_gnu; +pub(crate) mod windows_gnullvm; +pub(crate) mod windows_msvc; +pub(crate) mod windows_uwp_gnu; +pub(crate) mod windows_uwp_msvc; diff --git a/compiler/rustc_target/src/spec/msvc_base.rs b/compiler/rustc_target/src/spec/base/msvc.rs similarity index 100% rename from compiler/rustc_target/src/spec/msvc_base.rs rename to compiler/rustc_target/src/spec/base/msvc.rs diff --git a/compiler/rustc_target/src/spec/netbsd_base.rs b/compiler/rustc_target/src/spec/base/netbsd.rs similarity index 100% rename from compiler/rustc_target/src/spec/netbsd_base.rs rename to compiler/rustc_target/src/spec/base/netbsd.rs diff --git a/compiler/rustc_target/src/spec/nto_qnx_base.rs b/compiler/rustc_target/src/spec/base/nto_qnx.rs similarity index 100% rename from compiler/rustc_target/src/spec/nto_qnx_base.rs rename to compiler/rustc_target/src/spec/base/nto_qnx.rs diff --git a/compiler/rustc_target/src/spec/openbsd_base.rs b/compiler/rustc_target/src/spec/base/openbsd.rs similarity index 100% rename from compiler/rustc_target/src/spec/openbsd_base.rs rename to compiler/rustc_target/src/spec/base/openbsd.rs diff --git a/compiler/rustc_target/src/spec/redox_base.rs b/compiler/rustc_target/src/spec/base/redox.rs similarity index 100% rename from compiler/rustc_target/src/spec/redox_base.rs rename to compiler/rustc_target/src/spec/base/redox.rs diff --git a/compiler/rustc_target/src/spec/solaris_base.rs b/compiler/rustc_target/src/spec/base/solaris.rs similarity index 100% rename from compiler/rustc_target/src/spec/solaris_base.rs rename to compiler/rustc_target/src/spec/base/solaris.rs diff --git a/compiler/rustc_target/src/spec/solid_base.rs b/compiler/rustc_target/src/spec/base/solid.rs similarity index 83% rename from compiler/rustc_target/src/spec/solid_base.rs rename to compiler/rustc_target/src/spec/base/solid.rs index eaf72b7616c7..ce4a8869001b 100644 --- a/compiler/rustc_target/src/spec/solid_base.rs +++ b/compiler/rustc_target/src/spec/base/solid.rs @@ -1,5 +1,4 @@ -use super::FramePointer; -use crate::spec::TargetOptions; +use crate::spec::{FramePointer, TargetOptions}; pub fn opts(kernel: &str) -> TargetOptions { TargetOptions { diff --git a/compiler/rustc_target/src/spec/teeos_base.rs b/compiler/rustc_target/src/spec/base/teeos.rs similarity index 84% rename from compiler/rustc_target/src/spec/teeos_base.rs rename to compiler/rustc_target/src/spec/base/teeos.rs index 1bc71bab0160..38d0a6d73140 100644 --- a/compiler/rustc_target/src/spec/teeos_base.rs +++ b/compiler/rustc_target/src/spec/base/teeos.rs @@ -1,12 +1,11 @@ -use super::{Cc, LinkerFlavor, Lld, PanicStrategy}; -use crate::spec::{RelroLevel, TargetOptions}; +use crate::spec::{add_link_args, Cc, LinkerFlavor, Lld, PanicStrategy, RelroLevel, TargetOptions}; pub fn opts() -> TargetOptions { let lld_args = &["-zmax-page-size=4096", "-znow", "-ztext", "--execute-only"]; let cc_args = &["-Wl,-zmax-page-size=4096", "-Wl,-znow", "-Wl,-ztext", "-mexecute-only"]; let mut pre_link_args = TargetOptions::link_args(LinkerFlavor::Gnu(Cc::No, Lld::No), lld_args); - super::add_link_args(&mut pre_link_args, LinkerFlavor::Gnu(Cc::Yes, Lld::No), cc_args); + add_link_args(&mut pre_link_args, LinkerFlavor::Gnu(Cc::Yes, Lld::No), cc_args); TargetOptions { os: "teeos".into(), diff --git a/compiler/rustc_target/src/spec/thumb_base.rs b/compiler/rustc_target/src/spec/base/thumb.rs similarity index 100% rename from compiler/rustc_target/src/spec/thumb_base.rs rename to compiler/rustc_target/src/spec/base/thumb.rs diff --git a/compiler/rustc_target/src/spec/uefi_msvc_base.rs b/compiler/rustc_target/src/spec/base/uefi_msvc.rs similarity index 95% rename from compiler/rustc_target/src/spec/uefi_msvc_base.rs rename to compiler/rustc_target/src/spec/base/uefi_msvc.rs index a50a55ad7e02..e8acd6078e2a 100644 --- a/compiler/rustc_target/src/spec/uefi_msvc_base.rs +++ b/compiler/rustc_target/src/spec/base/uefi_msvc.rs @@ -9,10 +9,10 @@ // the timer-interrupt. Device-drivers are required to use polling-based models. Furthermore, all // code runs in the same environment, no process separation is supported. -use crate::spec::{LinkerFlavor, Lld, PanicStrategy, StackProbeType, TargetOptions}; +use crate::spec::{base, LinkerFlavor, Lld, PanicStrategy, StackProbeType, TargetOptions}; pub fn opts() -> TargetOptions { - let mut base = super::msvc_base::opts(); + let mut base = base::msvc::opts(); base.add_pre_link_args( LinkerFlavor::Msvc(Lld::No), diff --git a/compiler/rustc_target/src/spec/unikraft_linux_musl_base.rs b/compiler/rustc_target/src/spec/base/unikraft_linux_musl.rs similarity index 100% rename from compiler/rustc_target/src/spec/unikraft_linux_musl_base.rs rename to compiler/rustc_target/src/spec/base/unikraft_linux_musl.rs diff --git a/compiler/rustc_target/src/spec/vxworks_base.rs b/compiler/rustc_target/src/spec/base/vxworks.rs similarity index 100% rename from compiler/rustc_target/src/spec/vxworks_base.rs rename to compiler/rustc_target/src/spec/base/vxworks.rs diff --git a/compiler/rustc_target/src/spec/wasm_base.rs b/compiler/rustc_target/src/spec/base/wasm.rs similarity index 96% rename from compiler/rustc_target/src/spec/wasm_base.rs rename to compiler/rustc_target/src/spec/base/wasm.rs index 82a3afeae31e..87ade9e58cf4 100644 --- a/compiler/rustc_target/src/spec/wasm_base.rs +++ b/compiler/rustc_target/src/spec/base/wasm.rs @@ -1,5 +1,7 @@ -use super::LinkSelfContainedDefault; -use super::{cvs, Cc, LinkerFlavor, PanicStrategy, RelocModel, TargetOptions, TlsModel}; +use crate::spec::{ + add_link_args, cvs, Cc, LinkSelfContainedDefault, LinkerFlavor, PanicStrategy, RelocModel, + TargetOptions, TlsModel, +}; pub fn options() -> TargetOptions { macro_rules! args { @@ -50,7 +52,7 @@ pub fn options() -> TargetOptions { } let mut pre_link_args = TargetOptions::link_args(LinkerFlavor::WasmLld(Cc::No), args!("")); - super::add_link_args(&mut pre_link_args, LinkerFlavor::WasmLld(Cc::Yes), args!("-Wl,")); + add_link_args(&mut pre_link_args, LinkerFlavor::WasmLld(Cc::Yes), args!("-Wl,")); TargetOptions { is_like_wasm: true, diff --git a/compiler/rustc_target/src/spec/windows_gnu_base.rs b/compiler/rustc_target/src/spec/base/windows_gnu.rs similarity index 95% rename from compiler/rustc_target/src/spec/windows_gnu_base.rs rename to compiler/rustc_target/src/spec/base/windows_gnu.rs index b84e0fc07830..25f02dc14519 100644 --- a/compiler/rustc_target/src/spec/windows_gnu_base.rs +++ b/compiler/rustc_target/src/spec/base/windows_gnu.rs @@ -1,5 +1,5 @@ -use crate::spec::crt_objects; use crate::spec::LinkSelfContainedDefault; +use crate::spec::{add_link_args, crt_objects}; use crate::spec::{cvs, Cc, DebuginfoKind, LinkerFlavor, Lld, SplitDebuginfo, TargetOptions}; use std::borrow::Cow; @@ -13,7 +13,7 @@ pub fn opts() -> TargetOptions { "--disable-auto-image-base", ], ); - super::add_link_args( + add_link_args( &mut pre_link_args, LinkerFlavor::Gnu(Cc::Yes, Lld::No), &[ @@ -45,14 +45,14 @@ pub fn opts() -> TargetOptions { ]; let mut late_link_args = TargetOptions::link_args(LinkerFlavor::Gnu(Cc::No, Lld::No), mingw_libs); - super::add_link_args(&mut late_link_args, LinkerFlavor::Gnu(Cc::Yes, Lld::No), mingw_libs); + add_link_args(&mut late_link_args, LinkerFlavor::Gnu(Cc::Yes, Lld::No), mingw_libs); // If any of our crates are dynamically linked then we need to use // the shared libgcc_s-dw2-1.dll. This is required to support // unwinding across DLL boundaries. let dynamic_unwind_libs = &["-lgcc_s"]; let mut late_link_args_dynamic = TargetOptions::link_args(LinkerFlavor::Gnu(Cc::No, Lld::No), dynamic_unwind_libs); - super::add_link_args( + add_link_args( &mut late_link_args_dynamic, LinkerFlavor::Gnu(Cc::Yes, Lld::No), dynamic_unwind_libs, @@ -65,7 +65,7 @@ pub fn opts() -> TargetOptions { let static_unwind_libs = &["-lgcc_eh", "-l:libpthread.a"]; let mut late_link_args_static = TargetOptions::link_args(LinkerFlavor::Gnu(Cc::No, Lld::No), static_unwind_libs); - super::add_link_args( + add_link_args( &mut late_link_args_static, LinkerFlavor::Gnu(Cc::Yes, Lld::No), static_unwind_libs, diff --git a/compiler/rustc_target/src/spec/windows_gnullvm_base.rs b/compiler/rustc_target/src/spec/base/windows_gnullvm.rs similarity index 100% rename from compiler/rustc_target/src/spec/windows_gnullvm_base.rs rename to compiler/rustc_target/src/spec/base/windows_gnullvm.rs diff --git a/compiler/rustc_target/src/spec/windows_msvc_base.rs b/compiler/rustc_target/src/spec/base/windows_msvc.rs similarity index 93% rename from compiler/rustc_target/src/spec/windows_msvc_base.rs rename to compiler/rustc_target/src/spec/base/windows_msvc.rs index 21062c337d82..e3cf9757219e 100644 --- a/compiler/rustc_target/src/spec/windows_msvc_base.rs +++ b/compiler/rustc_target/src/spec/base/windows_msvc.rs @@ -1,7 +1,7 @@ -use crate::spec::{cvs, TargetOptions}; +use crate::spec::{base, cvs, TargetOptions}; pub fn opts() -> TargetOptions { - let base = super::msvc_base::opts(); + let base = base::msvc::opts(); TargetOptions { os: "windows".into(), diff --git a/compiler/rustc_target/src/spec/windows_uwp_gnu_base.rs b/compiler/rustc_target/src/spec/base/windows_uwp_gnu.rs similarity index 80% rename from compiler/rustc_target/src/spec/windows_uwp_gnu_base.rs rename to compiler/rustc_target/src/spec/base/windows_uwp_gnu.rs index f30c33d997e3..17256e18e24e 100644 --- a/compiler/rustc_target/src/spec/windows_uwp_gnu_base.rs +++ b/compiler/rustc_target/src/spec/base/windows_uwp_gnu.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, LinkArgs, LinkerFlavor, Lld, TargetOptions}; +use crate::spec::{add_link_args, base, Cc, LinkArgs, LinkerFlavor, Lld, TargetOptions}; pub fn opts() -> TargetOptions { - let base = super::windows_gnu_base::opts(); + let base = base::windows_gnu::opts(); // FIXME: This should be updated for the exception machinery changes from #67502 // and inherit from `windows_gnu_base`, at least partially. @@ -17,7 +17,7 @@ pub fn opts() -> TargetOptions { ]; let mut late_link_args = TargetOptions::link_args(LinkerFlavor::Gnu(Cc::No, Lld::No), mingw_libs); - super::add_link_args(&mut late_link_args, LinkerFlavor::Gnu(Cc::Yes, Lld::No), mingw_libs); + add_link_args(&mut late_link_args, LinkerFlavor::Gnu(Cc::Yes, Lld::No), mingw_libs); // Reset the flags back to empty until the FIXME above is addressed. let late_link_args_dynamic = LinkArgs::new(); let late_link_args_static = LinkArgs::new(); diff --git a/compiler/rustc_target/src/spec/windows_uwp_msvc_base.rs b/compiler/rustc_target/src/spec/base/windows_uwp_msvc.rs similarity index 65% rename from compiler/rustc_target/src/spec/windows_uwp_msvc_base.rs rename to compiler/rustc_target/src/spec/base/windows_uwp_msvc.rs index 8c942c59dd03..59a761671254 100644 --- a/compiler/rustc_target/src/spec/windows_uwp_msvc_base.rs +++ b/compiler/rustc_target/src/spec/base/windows_uwp_msvc.rs @@ -1,7 +1,7 @@ -use crate::spec::{LinkerFlavor, Lld, TargetOptions}; +use crate::spec::{base, LinkerFlavor, Lld, TargetOptions}; pub fn opts() -> TargetOptions { - let mut opts = super::windows_msvc_base::opts(); + let mut opts = base::windows_msvc::opts(); opts.abi = "uwp".into(); opts.vendor = "uwp".into(); diff --git a/compiler/rustc_target/src/spec/bpfeb_unknown_none.rs b/compiler/rustc_target/src/spec/bpfeb_unknown_none.rs index 174ddfa50bfc..91e091e237af 100644 --- a/compiler/rustc_target/src/spec/bpfeb_unknown_none.rs +++ b/compiler/rustc_target/src/spec/bpfeb_unknown_none.rs @@ -1,5 +1,5 @@ use crate::spec::Target; -use crate::{abi::Endian, spec::bpf_base}; +use crate::{abi::Endian, spec::base}; pub fn target() -> Target { Target { @@ -7,6 +7,6 @@ pub fn target() -> Target { data_layout: "E-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(), pointer_width: 64, arch: "bpf".into(), - options: bpf_base::opts(Endian::Big), + options: base::bpf::opts(Endian::Big), } } diff --git a/compiler/rustc_target/src/spec/bpfel_unknown_none.rs b/compiler/rustc_target/src/spec/bpfel_unknown_none.rs index 7625e7b0e48e..45ab750ead6f 100644 --- a/compiler/rustc_target/src/spec/bpfel_unknown_none.rs +++ b/compiler/rustc_target/src/spec/bpfel_unknown_none.rs @@ -1,5 +1,5 @@ use crate::spec::Target; -use crate::{abi::Endian, spec::bpf_base}; +use crate::{abi::Endian, spec::base}; pub fn target() -> Target { Target { @@ -7,6 +7,6 @@ pub fn target() -> Target { data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(), pointer_width: 64, arch: "bpf".into(), - options: bpf_base::opts(Endian::Little), + options: base::bpf::opts(Endian::Little), } } diff --git a/compiler/rustc_target/src/spec/csky_unknown_linux_gnuabiv2.rs b/compiler/rustc_target/src/spec/csky_unknown_linux_gnuabiv2.rs index 93becd708693..14cd33a260a7 100644 --- a/compiler/rustc_target/src/spec/csky_unknown_linux_gnuabiv2.rs +++ b/compiler/rustc_target/src/spec/csky_unknown_linux_gnuabiv2.rs @@ -1,4 +1,4 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, Target, TargetOptions}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, Target, TargetOptions}; // This target is for glibc Linux on Csky @@ -14,7 +14,7 @@ pub fn target() -> Target { features: "+2e3,+3e7,+7e10,+cache,+dsp1e2,+dspe60,+e1,+e2,+edsp,+elrw,+hard-tp,+high-registers,+hwdiv,+mp,+mp1e2,+nvic,+trust".into(), late_link_args: TargetOptions::link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-l:libatomic.a"]), max_atomic_width: Some(32), - ..super::linux_gnu_base::opts() + ..base::linux_gnu::opts() }, } } diff --git a/compiler/rustc_target/src/spec/csky_unknown_linux_gnuabiv2hf.rs b/compiler/rustc_target/src/spec/csky_unknown_linux_gnuabiv2hf.rs index 745188341603..0ce271c601ce 100644 --- a/compiler/rustc_target/src/spec/csky_unknown_linux_gnuabiv2hf.rs +++ b/compiler/rustc_target/src/spec/csky_unknown_linux_gnuabiv2hf.rs @@ -1,4 +1,4 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, Target, TargetOptions}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, Target, TargetOptions}; // This target is for glibc Linux on Csky @@ -15,7 +15,7 @@ pub fn target() -> Target { features: "+hard-float,+hard-float-abi,+2e3,+3e7,+7e10,+cache,+dsp1e2,+dspe60,+e1,+e2,+edsp,+elrw,+hard-tp,+high-registers,+hwdiv,+mp,+mp1e2,+nvic,+trust".into(), late_link_args: TargetOptions::link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-l:libatomic.a", "-mhard-float"]), max_atomic_width: Some(32), - ..super::linux_gnu_base::opts() + ..base::linux_gnu::opts() }, } } diff --git a/compiler/rustc_target/src/spec/hexagon_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/hexagon_unknown_linux_musl.rs index 4c6ab5f5ae45..98a5e7abd09d 100644 --- a/compiler/rustc_target/src/spec/hexagon_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/hexagon_unknown_linux_musl.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, LinkerFlavor, Target}; +use crate::spec::{base, Cc, LinkerFlavor, Target}; pub fn target() -> Target { - let mut base = super::linux_musl_base::opts(); + let mut base = base::linux_musl::opts(); base.cpu = "hexagonv60".into(); base.max_atomic_width = Some(32); // FIXME: HVX length defaults are per-CPU diff --git a/compiler/rustc_target/src/spec/hurd_gnu_base.rs b/compiler/rustc_target/src/spec/hurd_gnu_base.rs deleted file mode 100644 index b9cf26d9380b..000000000000 --- a/compiler/rustc_target/src/spec/hurd_gnu_base.rs +++ /dev/null @@ -1,5 +0,0 @@ -use crate::spec::TargetOptions; - -pub fn opts() -> TargetOptions { - TargetOptions { env: "gnu".into(), ..super::hurd_base::opts() } -} diff --git a/compiler/rustc_target/src/spec/i386_apple_ios.rs b/compiler/rustc_target/src/spec/i386_apple_ios.rs index 5819981612e8..ed2c990ffa64 100644 --- a/compiler/rustc_target/src/spec/i386_apple_ios.rs +++ b/compiler/rustc_target/src/spec/i386_apple_ios.rs @@ -1,4 +1,4 @@ -use super::apple_base::{ios_sim_llvm_target, opts, Arch}; +use crate::spec::base::apple::{ios_sim_llvm_target, opts, Arch}; use crate::spec::{StackProbeType, Target, TargetOptions}; pub fn target() -> Target { diff --git a/compiler/rustc_target/src/spec/i586_pc_nto_qnx700.rs b/compiler/rustc_target/src/spec/i586_pc_nto_qnx700.rs index 68afa7fe4012..06089391623b 100644 --- a/compiler/rustc_target/src/spec/i586_pc_nto_qnx700.rs +++ b/compiler/rustc_target/src/spec/i586_pc_nto_qnx700.rs @@ -1,5 +1,4 @@ -use super::nto_qnx_base; -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -18,7 +17,7 @@ pub fn target() -> Target { ), env: "nto70".into(), stack_probes: StackProbeType::X86, - ..nto_qnx_base::opts() + ..base::nto_qnx::opts() }, } } diff --git a/compiler/rustc_target/src/spec/i586_unknown_netbsd.rs b/compiler/rustc_target/src/spec/i586_unknown_netbsd.rs index 0d8bdc3f89f7..8375fa4c0c0f 100644 --- a/compiler/rustc_target/src/spec/i586_unknown_netbsd.rs +++ b/compiler/rustc_target/src/spec/i586_unknown_netbsd.rs @@ -1,7 +1,7 @@ -use crate::spec::{StackProbeType, Target, TargetOptions}; +use crate::spec::{base, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::netbsd_base::opts(); + let mut base = base::netbsd::opts(); base.cpu = "pentium".into(); base.max_atomic_width = Some(64); base.stack_probes = StackProbeType::Call; diff --git a/compiler/rustc_target/src/spec/i686_apple_darwin.rs b/compiler/rustc_target/src/spec/i686_apple_darwin.rs index b5103d15db69..242fe5ed98a9 100644 --- a/compiler/rustc_target/src/spec/i686_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/i686_apple_darwin.rs @@ -1,4 +1,4 @@ -use super::apple_base::{macos_llvm_target, opts, Arch}; +use crate::spec::base::apple::{macos_llvm_target, opts, Arch}; use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { diff --git a/compiler/rustc_target/src/spec/i686_linux_android.rs b/compiler/rustc_target/src/spec/i686_linux_android.rs index c7c30c23901d..987265598ebc 100644 --- a/compiler/rustc_target/src/spec/i686_linux_android.rs +++ b/compiler/rustc_target/src/spec/i686_linux_android.rs @@ -1,10 +1,10 @@ -use crate::spec::{SanitizerSet, StackProbeType, Target, TargetOptions}; +use crate::spec::{base, SanitizerSet, StackProbeType, Target, TargetOptions}; // See https://developer.android.com/ndk/guides/abis.html#x86 // for target ABI requirements. pub fn target() -> Target { - let mut base = super::android_base::opts(); + let mut base = base::android::opts(); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/i686_pc_windows_gnu.rs b/compiler/rustc_target/src/spec/i686_pc_windows_gnu.rs index 7a11138754fa..8d4a39b58114 100644 --- a/compiler/rustc_target/src/spec/i686_pc_windows_gnu.rs +++ b/compiler/rustc_target/src/spec/i686_pc_windows_gnu.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, Target}; +use crate::spec::{base, Cc, FramePointer, LinkerFlavor, Lld, Target}; pub fn target() -> Target { - let mut base = super::windows_gnu_base::opts(); + let mut base = base::windows_gnu::opts(); base.cpu = "pentium4".into(); base.max_atomic_width = Some(64); base.frame_pointer = FramePointer::Always; // Required for backtraces diff --git a/compiler/rustc_target/src/spec/i686_pc_windows_gnullvm.rs b/compiler/rustc_target/src/spec/i686_pc_windows_gnullvm.rs index 3154b512a520..bb410cd8caf2 100644 --- a/compiler/rustc_target/src/spec/i686_pc_windows_gnullvm.rs +++ b/compiler/rustc_target/src/spec/i686_pc_windows_gnullvm.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, Target}; +use crate::spec::{base, Cc, FramePointer, LinkerFlavor, Lld, Target}; pub fn target() -> Target { - let mut base = super::windows_gnullvm_base::opts(); + let mut base = base::windows_gnullvm::opts(); base.cpu = "pentium4".into(); base.max_atomic_width = Some(64); base.frame_pointer = FramePointer::Always; // Required for backtraces diff --git a/compiler/rustc_target/src/spec/i686_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/i686_pc_windows_msvc.rs index db4c00dc697d..ba80c23196e1 100644 --- a/compiler/rustc_target/src/spec/i686_pc_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/i686_pc_windows_msvc.rs @@ -1,7 +1,7 @@ -use crate::spec::{LinkerFlavor, Lld, Target}; +use crate::spec::{base, LinkerFlavor, Lld, Target}; pub fn target() -> Target { - let mut base = super::windows_msvc_base::opts(); + let mut base = base::windows_msvc::opts(); base.cpu = "pentium4".into(); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/i686_unknown_freebsd.rs b/compiler/rustc_target/src/spec/i686_unknown_freebsd.rs index 35ca78034f17..70aa0b47962e 100644 --- a/compiler/rustc_target/src/spec/i686_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/i686_unknown_freebsd.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target}; pub fn target() -> Target { - let mut base = super::freebsd_base::opts(); + let mut base = base::freebsd::opts(); base.cpu = "pentium4".into(); base.max_atomic_width = Some(64); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32", "-Wl,-znotext"]); diff --git a/compiler/rustc_target/src/spec/i686_unknown_haiku.rs b/compiler/rustc_target/src/spec/i686_unknown_haiku.rs index e6b72336c5cf..9715f6c21d90 100644 --- a/compiler/rustc_target/src/spec/i686_unknown_haiku.rs +++ b/compiler/rustc_target/src/spec/i686_unknown_haiku.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target}; pub fn target() -> Target { - let mut base = super::haiku_base::opts(); + let mut base = base::haiku::opts(); base.cpu = "pentium4".into(); base.max_atomic_width = Some(64); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32"]); diff --git a/compiler/rustc_target/src/spec/i686_unknown_hurd_gnu.rs b/compiler/rustc_target/src/spec/i686_unknown_hurd_gnu.rs index 29f803601381..9102673ef779 100644 --- a/compiler/rustc_target/src/spec/i686_unknown_hurd_gnu.rs +++ b/compiler/rustc_target/src/spec/i686_unknown_hurd_gnu.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target}; pub fn target() -> Target { - let mut base = super::hurd_gnu_base::opts(); + let mut base = base::hurd_gnu::opts(); base.cpu = "pentiumpro".into(); base.max_atomic_width = Some(64); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32"]); diff --git a/compiler/rustc_target/src/spec/i686_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/i686_unknown_linux_gnu.rs index 73e536a7e4d9..0ca058b2fd2a 100644 --- a/compiler/rustc_target/src/spec/i686_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/i686_unknown_linux_gnu.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target}; pub fn target() -> Target { - let mut base = super::linux_gnu_base::opts(); + let mut base = base::linux_gnu::opts(); base.cpu = "pentium4".into(); base.max_atomic_width = Some(64); base.supported_sanitizers = SanitizerSet::ADDRESS; diff --git a/compiler/rustc_target/src/spec/i686_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/i686_unknown_linux_musl.rs index 3825082ba25e..ce0df3a72344 100644 --- a/compiler/rustc_target/src/spec/i686_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/i686_unknown_linux_musl.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, StackProbeType, Target}; +use crate::spec::{base, Cc, FramePointer, LinkerFlavor, Lld, StackProbeType, Target}; pub fn target() -> Target { - let mut base = super::linux_musl_base::opts(); + let mut base = base::linux_musl::opts(); base.cpu = "pentium4".into(); base.max_atomic_width = Some(64); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32", "-Wl,-melf_i386"]); diff --git a/compiler/rustc_target/src/spec/i686_unknown_netbsd.rs b/compiler/rustc_target/src/spec/i686_unknown_netbsd.rs index b191996c7de0..2a3ac5932d35 100644 --- a/compiler/rustc_target/src/spec/i686_unknown_netbsd.rs +++ b/compiler/rustc_target/src/spec/i686_unknown_netbsd.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::netbsd_base::opts(); + let mut base = base::netbsd::opts(); base.cpu = "pentium4".into(); base.max_atomic_width = Some(64); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32"]); diff --git a/compiler/rustc_target/src/spec/i686_unknown_openbsd.rs b/compiler/rustc_target/src/spec/i686_unknown_openbsd.rs index 8babe5597128..45883542bead 100644 --- a/compiler/rustc_target/src/spec/i686_unknown_openbsd.rs +++ b/compiler/rustc_target/src/spec/i686_unknown_openbsd.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target}; pub fn target() -> Target { - let mut base = super::openbsd_base::opts(); + let mut base = base::openbsd::opts(); base.cpu = "pentium4".into(); base.max_atomic_width = Some(64); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32", "-fuse-ld=lld"]); diff --git a/compiler/rustc_target/src/spec/i686_unknown_uefi.rs b/compiler/rustc_target/src/spec/i686_unknown_uefi.rs index a2e42c5e61d5..25315e19cddb 100644 --- a/compiler/rustc_target/src/spec/i686_unknown_uefi.rs +++ b/compiler/rustc_target/src/spec/i686_unknown_uefi.rs @@ -5,10 +5,10 @@ // The cdecl ABI is used. It differs from the stdcall or fastcall ABI. // "i686-unknown-windows" is used to get the minimal subset of windows-specific features. -use crate::spec::Target; +use crate::spec::{base, Target}; pub fn target() -> Target { - let mut base = super::uefi_msvc_base::opts(); + let mut base = base::uefi_msvc::opts(); base.cpu = "pentium4".into(); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/i686_uwp_windows_gnu.rs b/compiler/rustc_target/src/spec/i686_uwp_windows_gnu.rs index a3e32569827f..ec211a710eb0 100644 --- a/compiler/rustc_target/src/spec/i686_uwp_windows_gnu.rs +++ b/compiler/rustc_target/src/spec/i686_uwp_windows_gnu.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, Target}; +use crate::spec::{base, Cc, FramePointer, LinkerFlavor, Lld, Target}; pub fn target() -> Target { - let mut base = super::windows_uwp_gnu_base::opts(); + let mut base = base::windows_uwp_gnu::opts(); base.cpu = "pentium4".into(); base.max_atomic_width = Some(64); base.frame_pointer = FramePointer::Always; // Required for backtraces diff --git a/compiler/rustc_target/src/spec/i686_uwp_windows_msvc.rs b/compiler/rustc_target/src/spec/i686_uwp_windows_msvc.rs index 4c657fe908ac..7cca2fc6b9f7 100644 --- a/compiler/rustc_target/src/spec/i686_uwp_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/i686_uwp_windows_msvc.rs @@ -1,7 +1,7 @@ -use crate::spec::Target; +use crate::spec::{base, Target}; pub fn target() -> Target { - let mut base = super::windows_uwp_msvc_base::opts(); + let mut base = base::windows_uwp_msvc::opts(); base.cpu = "pentium4".into(); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/i686_wrs_vxworks.rs b/compiler/rustc_target/src/spec/i686_wrs_vxworks.rs index b5cfdfcebea9..965a895972c6 100644 --- a/compiler/rustc_target/src/spec/i686_wrs_vxworks.rs +++ b/compiler/rustc_target/src/spec/i686_wrs_vxworks.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target}; pub fn target() -> Target { - let mut base = super::vxworks_base::opts(); + let mut base = base::vxworks::opts(); base.cpu = "pentium4".into(); base.max_atomic_width = Some(64); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32"]); diff --git a/compiler/rustc_target/src/spec/linux_gnu_base.rs b/compiler/rustc_target/src/spec/linux_gnu_base.rs deleted file mode 100644 index 8d6b3f185122..000000000000 --- a/compiler/rustc_target/src/spec/linux_gnu_base.rs +++ /dev/null @@ -1,5 +0,0 @@ -use crate::spec::TargetOptions; - -pub fn opts() -> TargetOptions { - TargetOptions { env: "gnu".into(), ..super::linux_base::opts() } -} diff --git a/compiler/rustc_target/src/spec/linux_uclibc_base.rs b/compiler/rustc_target/src/spec/linux_uclibc_base.rs deleted file mode 100644 index 4ba480ffecff..000000000000 --- a/compiler/rustc_target/src/spec/linux_uclibc_base.rs +++ /dev/null @@ -1,5 +0,0 @@ -use crate::spec::TargetOptions; - -pub fn opts() -> TargetOptions { - TargetOptions { env: "uclibc".into(), ..super::linux_base::opts() } -} diff --git a/compiler/rustc_target/src/spec/loongarch64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/loongarch64_unknown_linux_gnu.rs index db8b9c70e670..0f05e7c475a8 100644 --- a/compiler/rustc_target/src/spec/loongarch64_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/loongarch64_unknown_linux_gnu.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -11,7 +11,7 @@ pub fn target() -> Target { features: "+f,+d".into(), llvm_abiname: "lp64d".into(), max_atomic_width: Some(64), - ..super::linux_gnu_base::opts() + ..base::linux_gnu::opts() }, } } diff --git a/compiler/rustc_target/src/spec/m68k_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/m68k_unknown_linux_gnu.rs index 9bcd56bed002..b54f5d753cc3 100644 --- a/compiler/rustc_target/src/spec/m68k_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/m68k_unknown_linux_gnu.rs @@ -1,8 +1,8 @@ use crate::abi::Endian; -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::linux_gnu_base::opts(); + let mut base = base::linux_gnu::opts(); base.cpu = "M68020".into(); base.max_atomic_width = Some(32); diff --git a/compiler/rustc_target/src/spec/mips64_openwrt_linux_musl.rs b/compiler/rustc_target/src/spec/mips64_openwrt_linux_musl.rs index 3c6ef52c6cd7..6191a6dfd415 100644 --- a/compiler/rustc_target/src/spec/mips64_openwrt_linux_musl.rs +++ b/compiler/rustc_target/src/spec/mips64_openwrt_linux_musl.rs @@ -1,10 +1,10 @@ /// A target tuple for OpenWrt MIPS64 targets /// use crate::abi::Endian; -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::linux_musl_base::opts(); + let mut base = base::linux_musl::opts(); base.cpu = "mips64r2".into(); base.features = "+mips64r2,+soft-float".into(); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/mips64_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/mips64_unknown_linux_gnuabi64.rs index b9df0046b12b..e1131f07f264 100644 --- a/compiler/rustc_target/src/spec/mips64_unknown_linux_gnuabi64.rs +++ b/compiler/rustc_target/src/spec/mips64_unknown_linux_gnuabi64.rs @@ -1,5 +1,5 @@ use crate::abi::Endian; -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -16,7 +16,7 @@ pub fn target() -> Target { max_atomic_width: Some(64), mcount: "_mcount".into(), - ..super::linux_gnu_base::opts() + ..base::linux_gnu::opts() }, } } diff --git a/compiler/rustc_target/src/spec/mips64_unknown_linux_muslabi64.rs b/compiler/rustc_target/src/spec/mips64_unknown_linux_muslabi64.rs index 465e97a026c5..147c1c224761 100644 --- a/compiler/rustc_target/src/spec/mips64_unknown_linux_muslabi64.rs +++ b/compiler/rustc_target/src/spec/mips64_unknown_linux_muslabi64.rs @@ -1,8 +1,8 @@ use crate::abi::Endian; -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::linux_musl_base::opts(); + let mut base = base::linux_musl::opts(); base.cpu = "mips64r2".into(); base.features = "+mips64r2".into(); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/mips64el_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/mips64el_unknown_linux_gnuabi64.rs index 57ad8c47399b..4c612554d204 100644 --- a/compiler/rustc_target/src/spec/mips64el_unknown_linux_gnuabi64.rs +++ b/compiler/rustc_target/src/spec/mips64el_unknown_linux_gnuabi64.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -14,7 +14,7 @@ pub fn target() -> Target { max_atomic_width: Some(64), mcount: "_mcount".into(), - ..super::linux_gnu_base::opts() + ..base::linux_gnu::opts() }, } } diff --git a/compiler/rustc_target/src/spec/mips64el_unknown_linux_muslabi64.rs b/compiler/rustc_target/src/spec/mips64el_unknown_linux_muslabi64.rs index 75575eb7eebd..d60404f0ce53 100644 --- a/compiler/rustc_target/src/spec/mips64el_unknown_linux_muslabi64.rs +++ b/compiler/rustc_target/src/spec/mips64el_unknown_linux_muslabi64.rs @@ -1,7 +1,7 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::linux_musl_base::opts(); + let mut base = base::linux_musl::opts(); base.cpu = "mips64r2".into(); base.features = "+mips64r2".into(); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/mips_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/mips_unknown_linux_gnu.rs index 8df8b0b4c2c7..c49b89bbd465 100644 --- a/compiler/rustc_target/src/spec/mips_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/mips_unknown_linux_gnu.rs @@ -1,5 +1,5 @@ use crate::abi::Endian; -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -14,7 +14,7 @@ pub fn target() -> Target { max_atomic_width: Some(32), mcount: "_mcount".into(), - ..super::linux_gnu_base::opts() + ..base::linux_gnu::opts() }, } } diff --git a/compiler/rustc_target/src/spec/mips_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/mips_unknown_linux_musl.rs index c2846313a9eb..92d2d9d84c1d 100644 --- a/compiler/rustc_target/src/spec/mips_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/mips_unknown_linux_musl.rs @@ -1,8 +1,8 @@ use crate::abi::Endian; -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::linux_musl_base::opts(); + let mut base = base::linux_musl::opts(); base.cpu = "mips32r2".into(); base.features = "+mips32r2,+soft-float".into(); base.max_atomic_width = Some(32); diff --git a/compiler/rustc_target/src/spec/mips_unknown_linux_uclibc.rs b/compiler/rustc_target/src/spec/mips_unknown_linux_uclibc.rs index c59bb5fdd223..51df0a974cb1 100644 --- a/compiler/rustc_target/src/spec/mips_unknown_linux_uclibc.rs +++ b/compiler/rustc_target/src/spec/mips_unknown_linux_uclibc.rs @@ -1,5 +1,5 @@ use crate::abi::Endian; -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -14,7 +14,7 @@ pub fn target() -> Target { max_atomic_width: Some(32), mcount: "_mcount".into(), - ..super::linux_uclibc_base::opts() + ..base::linux_uclibc::opts() }, } } diff --git a/compiler/rustc_target/src/spec/mipsel_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/mipsel_unknown_linux_gnu.rs index 01346e71a92f..c2e482148cd7 100644 --- a/compiler/rustc_target/src/spec/mipsel_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/mipsel_unknown_linux_gnu.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -13,7 +13,7 @@ pub fn target() -> Target { max_atomic_width: Some(32), mcount: "_mcount".into(), - ..super::linux_gnu_base::opts() + ..base::linux_gnu::opts() }, } } diff --git a/compiler/rustc_target/src/spec/mipsel_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/mipsel_unknown_linux_musl.rs index 0e8f1a2c8e0e..5eed050453d1 100644 --- a/compiler/rustc_target/src/spec/mipsel_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/mipsel_unknown_linux_musl.rs @@ -1,7 +1,7 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::linux_musl_base::opts(); + let mut base = base::linux_musl::opts(); base.cpu = "mips32r2".into(); base.features = "+mips32r2,+soft-float".into(); base.max_atomic_width = Some(32); diff --git a/compiler/rustc_target/src/spec/mipsel_unknown_linux_uclibc.rs b/compiler/rustc_target/src/spec/mipsel_unknown_linux_uclibc.rs index 8342074586bc..77e69119d167 100644 --- a/compiler/rustc_target/src/spec/mipsel_unknown_linux_uclibc.rs +++ b/compiler/rustc_target/src/spec/mipsel_unknown_linux_uclibc.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -13,7 +13,7 @@ pub fn target() -> Target { max_atomic_width: Some(32), mcount: "_mcount".into(), - ..super::linux_uclibc_base::opts() + ..base::linux_uclibc::opts() }, } } diff --git a/compiler/rustc_target/src/spec/mipsel_unknown_netbsd.rs b/compiler/rustc_target/src/spec/mipsel_unknown_netbsd.rs index 651358d6422c..706a1af3e154 100644 --- a/compiler/rustc_target/src/spec/mipsel_unknown_netbsd.rs +++ b/compiler/rustc_target/src/spec/mipsel_unknown_netbsd.rs @@ -1,8 +1,8 @@ use crate::abi::Endian; -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::netbsd_base::opts(); + let mut base = base::netbsd::opts(); base.max_atomic_width = Some(32); base.cpu = "mips32".into(); diff --git a/compiler/rustc_target/src/spec/mipsisa32r6_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/mipsisa32r6_unknown_linux_gnu.rs index 983a449b006a..59783882e186 100644 --- a/compiler/rustc_target/src/spec/mipsisa32r6_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/mipsisa32r6_unknown_linux_gnu.rs @@ -1,5 +1,5 @@ use crate::abi::Endian; -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -14,7 +14,7 @@ pub fn target() -> Target { max_atomic_width: Some(32), mcount: "_mcount".into(), - ..super::linux_gnu_base::opts() + ..base::linux_gnu::opts() }, } } diff --git a/compiler/rustc_target/src/spec/mipsisa32r6el_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/mipsisa32r6el_unknown_linux_gnu.rs index ec0facdfb7bf..c3d79412e1c8 100644 --- a/compiler/rustc_target/src/spec/mipsisa32r6el_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/mipsisa32r6el_unknown_linux_gnu.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -13,7 +13,7 @@ pub fn target() -> Target { max_atomic_width: Some(32), mcount: "_mcount".into(), - ..super::linux_gnu_base::opts() + ..base::linux_gnu::opts() }, } } diff --git a/compiler/rustc_target/src/spec/mipsisa64r6_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/mipsisa64r6_unknown_linux_gnuabi64.rs index 16dd1c416f4f..2ae6e7521f94 100644 --- a/compiler/rustc_target/src/spec/mipsisa64r6_unknown_linux_gnuabi64.rs +++ b/compiler/rustc_target/src/spec/mipsisa64r6_unknown_linux_gnuabi64.rs @@ -1,5 +1,5 @@ use crate::abi::Endian; -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -16,7 +16,7 @@ pub fn target() -> Target { max_atomic_width: Some(64), mcount: "_mcount".into(), - ..super::linux_gnu_base::opts() + ..base::linux_gnu::opts() }, } } diff --git a/compiler/rustc_target/src/spec/mipsisa64r6el_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/mipsisa64r6el_unknown_linux_gnuabi64.rs index 8d0a6aa8f514..31637e9f6d02 100644 --- a/compiler/rustc_target/src/spec/mipsisa64r6el_unknown_linux_gnuabi64.rs +++ b/compiler/rustc_target/src/spec/mipsisa64r6el_unknown_linux_gnuabi64.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -14,7 +14,7 @@ pub fn target() -> Target { max_atomic_width: Some(64), mcount: "_mcount".into(), - ..super::linux_gnu_base::opts() + ..base::linux_gnu::opts() }, } } diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 48ca5fcf3ad0..f569584c20b6 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -57,47 +57,11 @@ use rustc_macros::HashStable_Generic; pub mod abi; pub mod crt_objects; -mod aix_base; -mod android_base; -mod apple_base; -pub use apple_base::deployment_target as current_apple_deployment_target; -pub use apple_base::platform as current_apple_platform; -pub use apple_base::sdk_version as current_apple_sdk_version; -mod avr_gnu_base; -pub use avr_gnu_base::ef_avr_arch; -mod bpf_base; -mod dragonfly_base; -mod freebsd_base; -mod fuchsia_base; -mod haiku_base; -mod hermit_base; -mod hurd_base; -mod hurd_gnu_base; -mod illumos_base; -mod l4re_base; -mod linux_base; -mod linux_gnu_base; -mod linux_musl_base; -mod linux_ohos_base; -mod linux_uclibc_base; -mod msvc_base; -mod netbsd_base; -mod nto_qnx_base; -mod openbsd_base; -mod redox_base; -mod solaris_base; -mod solid_base; -mod teeos_base; -mod thumb_base; -mod uefi_msvc_base; -mod unikraft_linux_musl_base; -mod vxworks_base; -mod wasm_base; -mod windows_gnu_base; -mod windows_gnullvm_base; -mod windows_msvc_base; -mod windows_uwp_gnu_base; -mod windows_uwp_msvc_base; +mod base; +pub use base::apple::deployment_target as current_apple_deployment_target; +pub use base::apple::platform as current_apple_platform; +pub use base::apple::sdk_version as current_apple_sdk_version; +pub use base::avr_gnu::ef_avr_arch; /// Linker is called through a C/C++ compiler. #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)] diff --git a/compiler/rustc_target/src/spec/powerpc64_ibm_aix.rs b/compiler/rustc_target/src/spec/powerpc64_ibm_aix.rs index 4e105a03e287..c512e4c7c489 100644 --- a/compiler/rustc_target/src/spec/powerpc64_ibm_aix.rs +++ b/compiler/rustc_target/src/spec/powerpc64_ibm_aix.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, LinkerFlavor, Target}; +use crate::spec::{base, Cc, LinkerFlavor, Target}; pub fn target() -> Target { - let mut base = super::aix_base::opts(); + let mut base = base::aix::opts(); base.max_atomic_width = Some(64); base.add_pre_link_args( LinkerFlavor::Unix(Cc::No), diff --git a/compiler/rustc_target/src/spec/powerpc64_unknown_freebsd.rs b/compiler/rustc_target/src/spec/powerpc64_unknown_freebsd.rs index e8fe55a00db0..e470ec05eff5 100644 --- a/compiler/rustc_target/src/spec/powerpc64_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/powerpc64_unknown_freebsd.rs @@ -1,8 +1,8 @@ use crate::abi::Endian; -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::freebsd_base::opts(); + let mut base = base::freebsd::opts(); base.cpu = "ppc64".into(); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs index 7a0cc539f1a8..34e3184d348e 100644 --- a/compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs @@ -1,8 +1,8 @@ use crate::abi::Endian; -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::linux_gnu_base::opts(); + let mut base = base::linux_gnu::opts(); base.cpu = "ppc64".into(); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs index f80b22828c1d..e2e707f4a1ac 100644 --- a/compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs @@ -1,8 +1,8 @@ use crate::abi::Endian; -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::linux_musl_base::opts(); + let mut base = base::linux_musl::opts(); base.cpu = "ppc64".into(); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/powerpc64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/powerpc64_unknown_openbsd.rs index 3643f7b0c374..ebaeb04be315 100644 --- a/compiler/rustc_target/src/spec/powerpc64_unknown_openbsd.rs +++ b/compiler/rustc_target/src/spec/powerpc64_unknown_openbsd.rs @@ -1,8 +1,8 @@ use crate::abi::Endian; -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::openbsd_base::opts(); + let mut base = base::openbsd::opts(); base.cpu = "ppc64".into(); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs b/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs index b0472e64e134..e2085ba7ce3e 100644 --- a/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs +++ b/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs @@ -1,8 +1,8 @@ use crate::abi::Endian; -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::vxworks_base::opts(); + let mut base = base::vxworks::opts(); base.cpu = "ppc64".into(); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/powerpc64le_unknown_freebsd.rs b/compiler/rustc_target/src/spec/powerpc64le_unknown_freebsd.rs index 342b1cf4f4ca..b399d36d8b24 100644 --- a/compiler/rustc_target/src/spec/powerpc64le_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/powerpc64le_unknown_freebsd.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::freebsd_base::opts(); + let mut base = base::freebsd::opts(); base.cpu = "ppc64le".into(); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_gnu.rs index 815e3d2781ca..194c3170e683 100644 --- a/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_gnu.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::linux_gnu_base::opts(); + let mut base = base::linux_gnu::opts(); base.cpu = "ppc64le".into(); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_musl.rs index 0b9b78bcec89..1f53e6895983 100644 --- a/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_musl.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::linux_musl_base::opts(); + let mut base = base::linux_musl::opts(); base.cpu = "ppc64le".into(); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_freebsd.rs b/compiler/rustc_target/src/spec/powerpc_unknown_freebsd.rs index e036f5bdbada..6d094f9a3676 100644 --- a/compiler/rustc_target/src/spec/powerpc_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/powerpc_unknown_freebsd.rs @@ -1,8 +1,8 @@ use crate::abi::Endian; -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::freebsd_base::opts(); + let mut base = base::freebsd::opts(); // Extra hint to linker that we are generating secure-PLT code. base.add_pre_link_args( LinkerFlavor::Gnu(Cc::Yes, Lld::No), diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnu.rs index c8d6f8b9c676..1600698da44a 100644 --- a/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnu.rs @@ -1,8 +1,8 @@ use crate::abi::Endian; -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::linux_gnu_base::opts(); + let mut base = base::linux_gnu::opts(); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32"]); base.max_atomic_width = Some(32); base.stack_probes = StackProbeType::Inline; diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs b/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs index fdaa9d366d92..af0fbfebef22 100644 --- a/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs +++ b/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs @@ -1,8 +1,8 @@ use crate::abi::Endian; -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::linux_gnu_base::opts(); + let mut base = base::linux_gnu::opts(); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-mspe"]); base.max_atomic_width = Some(32); base.stack_probes = StackProbeType::Inline; diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/powerpc_unknown_linux_musl.rs index 7fe708cf5304..9b0ac4a0fc9b 100644 --- a/compiler/rustc_target/src/spec/powerpc_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/powerpc_unknown_linux_musl.rs @@ -1,8 +1,8 @@ use crate::abi::Endian; -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::linux_musl_base::opts(); + let mut base = base::linux_musl::opts(); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32"]); base.max_atomic_width = Some(32); base.stack_probes = StackProbeType::Inline; diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_netbsd.rs b/compiler/rustc_target/src/spec/powerpc_unknown_netbsd.rs index 6f8875ba7b40..bc2e239d9a52 100644 --- a/compiler/rustc_target/src/spec/powerpc_unknown_netbsd.rs +++ b/compiler/rustc_target/src/spec/powerpc_unknown_netbsd.rs @@ -1,8 +1,8 @@ use crate::abi::Endian; -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::netbsd_base::opts(); + let mut base = base::netbsd::opts(); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32"]); base.max_atomic_width = Some(32); base.stack_probes = StackProbeType::Inline; diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_openbsd.rs b/compiler/rustc_target/src/spec/powerpc_unknown_openbsd.rs index 280d36698b48..081aaaea2499 100644 --- a/compiler/rustc_target/src/spec/powerpc_unknown_openbsd.rs +++ b/compiler/rustc_target/src/spec/powerpc_unknown_openbsd.rs @@ -1,8 +1,8 @@ use crate::abi::Endian; -use crate::spec::{StackProbeType, Target}; +use crate::spec::{base, StackProbeType, Target}; pub fn target() -> Target { - let mut base = super::openbsd_base::opts(); + let mut base = base::openbsd::opts(); base.endian = Endian::Big; base.max_atomic_width = Some(32); base.stack_probes = StackProbeType::Inline; diff --git a/compiler/rustc_target/src/spec/powerpc_wrs_vxworks.rs b/compiler/rustc_target/src/spec/powerpc_wrs_vxworks.rs index 6f245e6ab62a..e8bccc153850 100644 --- a/compiler/rustc_target/src/spec/powerpc_wrs_vxworks.rs +++ b/compiler/rustc_target/src/spec/powerpc_wrs_vxworks.rs @@ -1,8 +1,8 @@ use crate::abi::Endian; -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::vxworks_base::opts(); + let mut base = base::vxworks::opts(); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32", "--secure-plt"]); base.max_atomic_width = Some(32); base.stack_probes = StackProbeType::Inline; diff --git a/compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs b/compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs index 1d5a5e5c6ac6..fa4ef098e038 100644 --- a/compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs +++ b/compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs @@ -1,8 +1,8 @@ use crate::abi::Endian; -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::vxworks_base::opts(); + let mut base = base::vxworks::opts(); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-mspe", "--secure-plt"]); base.max_atomic_width = Some(32); base.stack_probes = StackProbeType::Inline; diff --git a/compiler/rustc_target/src/spec/riscv32gc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/riscv32gc_unknown_linux_gnu.rs index bffd377bc4a1..06e8f1837637 100644 --- a/compiler/rustc_target/src/spec/riscv32gc_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/riscv32gc_unknown_linux_gnu.rs @@ -1,4 +1,4 @@ -use crate::spec::{CodeModel, Target, TargetOptions}; +use crate::spec::{base, CodeModel, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -12,7 +12,7 @@ pub fn target() -> Target { features: "+m,+a,+f,+d,+c".into(), llvm_abiname: "ilp32d".into(), max_atomic_width: Some(32), - ..super::linux_gnu_base::opts() + ..base::linux_gnu::opts() }, } } diff --git a/compiler/rustc_target/src/spec/riscv32gc_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/riscv32gc_unknown_linux_musl.rs index c9f3acffb77b..722703d2384f 100644 --- a/compiler/rustc_target/src/spec/riscv32gc_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/riscv32gc_unknown_linux_musl.rs @@ -1,4 +1,4 @@ -use crate::spec::{CodeModel, Target, TargetOptions}; +use crate::spec::{base, CodeModel, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -12,7 +12,7 @@ pub fn target() -> Target { features: "+m,+a,+f,+d,+c".into(), llvm_abiname: "ilp32d".into(), max_atomic_width: Some(32), - ..super::linux_musl_base::opts() + ..base::linux_musl::opts() }, } } diff --git a/compiler/rustc_target/src/spec/riscv64_linux_android.rs b/compiler/rustc_target/src/spec/riscv64_linux_android.rs index 121237f6ba43..40e447dbb836 100644 --- a/compiler/rustc_target/src/spec/riscv64_linux_android.rs +++ b/compiler/rustc_target/src/spec/riscv64_linux_android.rs @@ -1,4 +1,4 @@ -use crate::spec::{CodeModel, SanitizerSet, Target, TargetOptions}; +use crate::spec::{base, CodeModel, SanitizerSet, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -13,7 +13,7 @@ pub fn target() -> Target { llvm_abiname: "lp64d".into(), supported_sanitizers: SanitizerSet::ADDRESS, max_atomic_width: Some(64), - ..super::android_base::opts() + ..base::android::opts() }, } } diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_freebsd.rs b/compiler/rustc_target/src/spec/riscv64gc_unknown_freebsd.rs index 8281bac10f88..2c7878de8120 100644 --- a/compiler/rustc_target/src/spec/riscv64gc_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/riscv64gc_unknown_freebsd.rs @@ -1,4 +1,4 @@ -use crate::spec::{CodeModel, Target, TargetOptions}; +use crate::spec::{base, CodeModel, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -12,7 +12,7 @@ pub fn target() -> Target { features: "+m,+a,+f,+d,+c".into(), llvm_abiname: "lp64d".into(), max_atomic_width: Some(64), - ..super::freebsd_base::opts() + ..base::freebsd::opts() }, } } diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_fuchsia.rs b/compiler/rustc_target/src/spec/riscv64gc_unknown_fuchsia.rs index 0585ed76fe81..a29470c24fbd 100644 --- a/compiler/rustc_target/src/spec/riscv64gc_unknown_fuchsia.rs +++ b/compiler/rustc_target/src/spec/riscv64gc_unknown_fuchsia.rs @@ -1,4 +1,4 @@ -use crate::spec::{CodeModel, SanitizerSet, Target, TargetOptions}; +use crate::spec::{base, CodeModel, SanitizerSet, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -13,7 +13,7 @@ pub fn target() -> Target { llvm_abiname: "lp64d".into(), max_atomic_width: Some(64), supported_sanitizers: SanitizerSet::SHADOWCALLSTACK, - ..super::fuchsia_base::opts() + ..base::fuchsia::opts() }, } } diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_hermit.rs b/compiler/rustc_target/src/spec/riscv64gc_unknown_hermit.rs index 1f6a34c0cacc..b7e29d2da3dc 100644 --- a/compiler/rustc_target/src/spec/riscv64gc_unknown_hermit.rs +++ b/compiler/rustc_target/src/spec/riscv64gc_unknown_hermit.rs @@ -1,4 +1,4 @@ -use crate::spec::{CodeModel, RelocModel, Target, TargetOptions, TlsModel}; +use crate::spec::{base, CodeModel, RelocModel, Target, TargetOptions, TlsModel}; pub fn target() -> Target { Target { @@ -14,7 +14,7 @@ pub fn target() -> Target { tls_model: TlsModel::LocalExec, max_atomic_width: Some(64), llvm_abiname: "lp64d".into(), - ..super::hermit_base::opts() + ..base::hermit::opts() }, } } diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_gnu.rs index 90dccb28063d..c0969d4e11eb 100644 --- a/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_gnu.rs @@ -1,4 +1,4 @@ -use crate::spec::{CodeModel, Target, TargetOptions}; +use crate::spec::{base, CodeModel, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -12,7 +12,7 @@ pub fn target() -> Target { features: "+m,+a,+f,+d,+c".into(), llvm_abiname: "lp64d".into(), max_atomic_width: Some(64), - ..super::linux_gnu_base::opts() + ..base::linux_gnu::opts() }, } } diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_musl.rs index 1a56c78e6852..656e260d094d 100644 --- a/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_musl.rs @@ -1,4 +1,4 @@ -use crate::spec::{CodeModel, Target, TargetOptions}; +use crate::spec::{base, CodeModel, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -12,7 +12,7 @@ pub fn target() -> Target { features: "+m,+a,+f,+d,+c".into(), llvm_abiname: "lp64d".into(), max_atomic_width: Some(64), - ..super::linux_musl_base::opts() + ..base::linux_musl::opts() }, } } diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_netbsd.rs b/compiler/rustc_target/src/spec/riscv64gc_unknown_netbsd.rs index a89bd363a47e..43a313a94080 100644 --- a/compiler/rustc_target/src/spec/riscv64gc_unknown_netbsd.rs +++ b/compiler/rustc_target/src/spec/riscv64gc_unknown_netbsd.rs @@ -1,4 +1,4 @@ -use crate::spec::{CodeModel, Target, TargetOptions}; +use crate::spec::{base, CodeModel, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -13,7 +13,7 @@ pub fn target() -> Target { llvm_abiname: "lp64d".into(), max_atomic_width: Some(64), mcount: "__mcount".into(), - ..super::netbsd_base::opts() + ..base::netbsd::opts() }, } } diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_openbsd.rs b/compiler/rustc_target/src/spec/riscv64gc_unknown_openbsd.rs index ade9d77624bd..1f1da7d5a29e 100644 --- a/compiler/rustc_target/src/spec/riscv64gc_unknown_openbsd.rs +++ b/compiler/rustc_target/src/spec/riscv64gc_unknown_openbsd.rs @@ -1,4 +1,4 @@ -use crate::spec::{CodeModel, Target, TargetOptions}; +use crate::spec::{base, CodeModel, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -12,7 +12,7 @@ pub fn target() -> Target { features: "+m,+a,+f,+d,+c".into(), llvm_abiname: "lp64d".into(), max_atomic_width: Some(64), - ..super::openbsd_base::opts() + ..base::openbsd::opts() }, } } diff --git a/compiler/rustc_target/src/spec/s390x_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/s390x_unknown_linux_gnu.rs index f2c722b9a89d..6fc410eb2235 100644 --- a/compiler/rustc_target/src/spec/s390x_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/s390x_unknown_linux_gnu.rs @@ -1,8 +1,8 @@ use crate::abi::Endian; -use crate::spec::{SanitizerSet, StackProbeType, Target}; +use crate::spec::{base, SanitizerSet, StackProbeType, Target}; pub fn target() -> Target { - let mut base = super::linux_gnu_base::opts(); + let mut base = base::linux_gnu::opts(); base.endian = Endian::Big; // z10 is the oldest CPU supported by LLVM base.cpu = "z10".into(); diff --git a/compiler/rustc_target/src/spec/s390x_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/s390x_unknown_linux_musl.rs index 8fe9d023c527..03772aab372a 100644 --- a/compiler/rustc_target/src/spec/s390x_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/s390x_unknown_linux_musl.rs @@ -1,8 +1,8 @@ use crate::abi::Endian; -use crate::spec::{SanitizerSet, StackProbeType, Target}; +use crate::spec::{base, SanitizerSet, StackProbeType, Target}; pub fn target() -> Target { - let mut base = super::linux_musl_base::opts(); + let mut base = base::linux_musl::opts(); base.endian = Endian::Big; // z10 is the oldest CPU supported by LLVM base.cpu = "z10".into(); diff --git a/compiler/rustc_target/src/spec/sparc64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/sparc64_unknown_linux_gnu.rs index 39efd8f305cd..20ec9a84e8b8 100644 --- a/compiler/rustc_target/src/spec/sparc64_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/sparc64_unknown_linux_gnu.rs @@ -1,8 +1,8 @@ use crate::abi::Endian; -use crate::spec::Target; +use crate::spec::{base, Target}; pub fn target() -> Target { - let mut base = super::linux_gnu_base::opts(); + let mut base = base::linux_gnu::opts(); base.endian = Endian::Big; base.cpu = "v9".into(); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/sparc64_unknown_netbsd.rs b/compiler/rustc_target/src/spec/sparc64_unknown_netbsd.rs index 38ab066b0879..c8c0fd2e134c 100644 --- a/compiler/rustc_target/src/spec/sparc64_unknown_netbsd.rs +++ b/compiler/rustc_target/src/spec/sparc64_unknown_netbsd.rs @@ -1,8 +1,8 @@ use crate::abi::Endian; -use crate::spec::{Cc, LinkerFlavor, Lld, Target, TargetOptions}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::netbsd_base::opts(); + let mut base = base::netbsd::opts(); base.cpu = "v9".into(); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/sparc64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/sparc64_unknown_openbsd.rs index 06a5f782a6df..82ce610066a2 100644 --- a/compiler/rustc_target/src/spec/sparc64_unknown_openbsd.rs +++ b/compiler/rustc_target/src/spec/sparc64_unknown_openbsd.rs @@ -1,8 +1,8 @@ use crate::abi::Endian; -use crate::spec::{Cc, LinkerFlavor, Lld, Target}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, Target}; pub fn target() -> Target { - let mut base = super::openbsd_base::opts(); + let mut base = base::openbsd::opts(); base.endian = Endian::Big; base.cpu = "v9".into(); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); diff --git a/compiler/rustc_target/src/spec/sparc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/sparc_unknown_linux_gnu.rs index b10e6264b73c..548fbb9ed52d 100644 --- a/compiler/rustc_target/src/spec/sparc_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/sparc_unknown_linux_gnu.rs @@ -1,8 +1,8 @@ use crate::abi::Endian; -use crate::spec::{Cc, LinkerFlavor, Lld, Target}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, Target}; pub fn target() -> Target { - let mut base = super::linux_gnu_base::opts(); + let mut base = base::linux_gnu::opts(); base.endian = Endian::Big; base.cpu = "v9".into(); base.max_atomic_width = Some(32); diff --git a/compiler/rustc_target/src/spec/sparcv9_sun_solaris.rs b/compiler/rustc_target/src/spec/sparcv9_sun_solaris.rs index 4d2bc98ab783..16cd991dd286 100644 --- a/compiler/rustc_target/src/spec/sparcv9_sun_solaris.rs +++ b/compiler/rustc_target/src/spec/sparcv9_sun_solaris.rs @@ -1,8 +1,8 @@ use crate::abi::Endian; -use crate::spec::{Cc, LinkerFlavor, Target}; +use crate::spec::{base, Cc, LinkerFlavor, Target}; pub fn target() -> Target { - let mut base = super::solaris_base::opts(); + let mut base = base::solaris::opts(); base.endian = Endian::Big; base.add_pre_link_args(LinkerFlavor::Unix(Cc::Yes), &["-m64"]); // llvm calls this "v9" diff --git a/compiler/rustc_target/src/spec/thumbv4t_none_eabi.rs b/compiler/rustc_target/src/spec/thumbv4t_none_eabi.rs index 88a76f49acd6..7b5c019b1bb5 100644 --- a/compiler/rustc_target/src/spec/thumbv4t_none_eabi.rs +++ b/compiler/rustc_target/src/spec/thumbv4t_none_eabi.rs @@ -9,8 +9,8 @@ //! The default link script is very likely wrong, so you should use //! `-Clink-arg=-Tmy_script.ld` to override that with a correct linker script. +use crate::spec::{base, PanicStrategy, RelocModel, Target, TargetOptions}; use crate::spec::{cvs, FramePointer}; -use crate::spec::{PanicStrategy, RelocModel, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -53,7 +53,7 @@ pub fn target() -> Target { atomic_cas: false, has_thumb_interworking: true, - ..super::thumb_base::opts() + ..base::thumb::opts() }, } } diff --git a/compiler/rustc_target/src/spec/thumbv5te_none_eabi.rs b/compiler/rustc_target/src/spec/thumbv5te_none_eabi.rs index 021b0e0eb622..d9212afb084c 100644 --- a/compiler/rustc_target/src/spec/thumbv5te_none_eabi.rs +++ b/compiler/rustc_target/src/spec/thumbv5te_none_eabi.rs @@ -1,6 +1,6 @@ //! Targets the ARMv5TE, with code as `t32` code by default. -use crate::spec::{cvs, FramePointer, Target, TargetOptions}; +use crate::spec::{base, cvs, FramePointer, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -35,7 +35,7 @@ pub fn target() -> Target { atomic_cas: false, has_thumb_interworking: true, - ..super::thumb_base::opts() + ..base::thumb::opts() }, } } diff --git a/compiler/rustc_target/src/spec/thumbv6m_none_eabi.rs b/compiler/rustc_target/src/spec/thumbv6m_none_eabi.rs index c9bb0112f0e3..ac076fb8864e 100644 --- a/compiler/rustc_target/src/spec/thumbv6m_none_eabi.rs +++ b/compiler/rustc_target/src/spec/thumbv6m_none_eabi.rs @@ -1,6 +1,6 @@ // Targets the Cortex-M0, Cortex-M0+ and Cortex-M1 processors (ARMv6-M architecture) -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -19,7 +19,7 @@ pub fn target() -> Target { // There are no atomic CAS instructions available in the instruction set of the ARMv6-M // architecture atomic_cas: false, - ..super::thumb_base::opts() + ..base::thumb::opts() }, } } diff --git a/compiler/rustc_target/src/spec/thumbv7a_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/thumbv7a_pc_windows_msvc.rs index f1be274f067c..128ac1dd1792 100644 --- a/compiler/rustc_target/src/spec/thumbv7a_pc_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/thumbv7a_pc_windows_msvc.rs @@ -1,7 +1,7 @@ -use crate::spec::{LinkerFlavor, Lld, PanicStrategy, Target, TargetOptions}; +use crate::spec::{base, LinkerFlavor, Lld, PanicStrategy, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::windows_msvc_base::opts(); + let mut base = base::windows_msvc::opts(); // Prevent error LNK2013: BRANCH24(T) fixup overflow // The LBR optimization tries to eliminate branch islands, // but if the displacement is larger than can fit diff --git a/compiler/rustc_target/src/spec/thumbv7a_uwp_windows_msvc.rs b/compiler/rustc_target/src/spec/thumbv7a_uwp_windows_msvc.rs index 65c2f5a704b7..810ed6a24044 100644 --- a/compiler/rustc_target/src/spec/thumbv7a_uwp_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/thumbv7a_uwp_windows_msvc.rs @@ -1,4 +1,4 @@ -use crate::spec::{PanicStrategy, Target, TargetOptions}; +use crate::spec::{base, PanicStrategy, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -12,7 +12,7 @@ pub fn target() -> Target { // FIXME(jordanrh): use PanicStrategy::Unwind when SEH is // implemented for windows/arm in LLVM panic_strategy: PanicStrategy::Abort, - ..super::windows_uwp_msvc_base::opts() + ..base::windows_uwp_msvc::opts() }, } } diff --git a/compiler/rustc_target/src/spec/thumbv7em_none_eabi.rs b/compiler/rustc_target/src/spec/thumbv7em_none_eabi.rs index 000e5f2d3c6b..1752f1d9aacf 100644 --- a/compiler/rustc_target/src/spec/thumbv7em_none_eabi.rs +++ b/compiler/rustc_target/src/spec/thumbv7em_none_eabi.rs @@ -9,7 +9,7 @@ // To opt-in to hardware accelerated floating point operations, you can use, for example, // `-C target-feature=+vfp4` or `-C target-cpu=cortex-m4`. -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -21,7 +21,7 @@ pub fn target() -> Target { options: TargetOptions { abi: "eabi".into(), max_atomic_width: Some(32), - ..super::thumb_base::opts() + ..base::thumb::opts() }, } } diff --git a/compiler/rustc_target/src/spec/thumbv7em_none_eabihf.rs b/compiler/rustc_target/src/spec/thumbv7em_none_eabihf.rs index 39a72564e49a..c113c62fc1d8 100644 --- a/compiler/rustc_target/src/spec/thumbv7em_none_eabihf.rs +++ b/compiler/rustc_target/src/spec/thumbv7em_none_eabihf.rs @@ -8,7 +8,7 @@ // // To opt into double precision hardware support, use the `-C target-feature=+fp64` flag. -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -30,7 +30,7 @@ pub fn target() -> Target { // ARMv7-M Architecture Reference Manual - A2.5 The optional floating-point extension features: "+vfp4,-d32,-fp64".into(), max_atomic_width: Some(32), - ..super::thumb_base::opts() + ..base::thumb::opts() }, } } diff --git a/compiler/rustc_target/src/spec/thumbv7m_none_eabi.rs b/compiler/rustc_target/src/spec/thumbv7m_none_eabi.rs index ab25cde66c7c..f9ab3ce1ad08 100644 --- a/compiler/rustc_target/src/spec/thumbv7m_none_eabi.rs +++ b/compiler/rustc_target/src/spec/thumbv7m_none_eabi.rs @@ -1,6 +1,6 @@ // Targets the Cortex-M3 processor (ARMv7-M) -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -12,7 +12,7 @@ pub fn target() -> Target { options: TargetOptions { abi: "eabi".into(), max_atomic_width: Some(32), - ..super::thumb_base::opts() + ..base::thumb::opts() }, } } diff --git a/compiler/rustc_target/src/spec/thumbv7neon_linux_androideabi.rs b/compiler/rustc_target/src/spec/thumbv7neon_linux_androideabi.rs index 624837a22d60..c07aa944d7e3 100644 --- a/compiler/rustc_target/src/spec/thumbv7neon_linux_androideabi.rs +++ b/compiler/rustc_target/src/spec/thumbv7neon_linux_androideabi.rs @@ -1,4 +1,4 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, Target, TargetOptions}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, Target, TargetOptions}; // This target if is for the Android v7a ABI in thumb mode with // NEON unconditionally enabled and, therefore, with 32 FPU registers @@ -9,7 +9,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, Target, TargetOptions}; // for target ABI requirements. pub fn target() -> Target { - let mut base = super::android_base::opts(); + let mut base = base::android::opts(); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-march=armv7-a"]); Target { llvm_target: "armv7-none-linux-android".into(), diff --git a/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_gnueabihf.rs b/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_gnueabihf.rs index b500c50de985..b4045037c6ab 100644 --- a/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_gnueabihf.rs +++ b/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_gnueabihf.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; // This target is for glibc Linux on ARMv7 with thumb mode enabled // (for consistency with Android and Debian-based distributions) @@ -17,7 +17,7 @@ pub fn target() -> Target { // Info about features at https://wiki.debian.org/ArmHardFloatPort features: "+v7,+thumb-mode,+thumb2,+vfp3,+neon".into(), max_atomic_width: Some(64), - ..super::linux_gnu_base::opts() + ..base::linux_gnu::opts() }, } } diff --git a/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_musleabihf.rs b/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_musleabihf.rs index dce0cbcef026..6ef30f10fe44 100644 --- a/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_musleabihf.rs +++ b/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_musleabihf.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; // This target is for musl Linux on ARMv7 with thumb mode enabled // (for consistency with Android and Debian-based distributions) @@ -23,7 +23,7 @@ pub fn target() -> Target { features: "+v7,+thumb-mode,+thumb2,+vfp3,+neon".into(), max_atomic_width: Some(64), mcount: "\u{1}mcount".into(), - ..super::linux_musl_base::opts() + ..base::linux_musl::opts() }, } } diff --git a/compiler/rustc_target/src/spec/thumbv8m_base_none_eabi.rs b/compiler/rustc_target/src/spec/thumbv8m_base_none_eabi.rs index 756b1834c827..bf62574867a6 100644 --- a/compiler/rustc_target/src/spec/thumbv8m_base_none_eabi.rs +++ b/compiler/rustc_target/src/spec/thumbv8m_base_none_eabi.rs @@ -1,6 +1,6 @@ // Targets the Cortex-M23 processor (Baseline ARMv8-M) -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -15,7 +15,7 @@ pub fn target() -> Target { // with +strict-align. features: "+strict-align".into(), max_atomic_width: Some(32), - ..super::thumb_base::opts() + ..base::thumb::opts() }, } } diff --git a/compiler/rustc_target/src/spec/thumbv8m_main_none_eabi.rs b/compiler/rustc_target/src/spec/thumbv8m_main_none_eabi.rs index 4b6268546549..07fc7feade59 100644 --- a/compiler/rustc_target/src/spec/thumbv8m_main_none_eabi.rs +++ b/compiler/rustc_target/src/spec/thumbv8m_main_none_eabi.rs @@ -1,7 +1,7 @@ // Targets the Cortex-M33 processor (Armv8-M Mainline architecture profile), // without the Floating Point extension. -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -13,7 +13,7 @@ pub fn target() -> Target { options: TargetOptions { abi: "eabi".into(), max_atomic_width: Some(32), - ..super::thumb_base::opts() + ..base::thumb::opts() }, } } diff --git a/compiler/rustc_target/src/spec/thumbv8m_main_none_eabihf.rs b/compiler/rustc_target/src/spec/thumbv8m_main_none_eabihf.rs index 86c25f9e4b99..61d4e8fc802e 100644 --- a/compiler/rustc_target/src/spec/thumbv8m_main_none_eabihf.rs +++ b/compiler/rustc_target/src/spec/thumbv8m_main_none_eabihf.rs @@ -1,7 +1,7 @@ // Targets the Cortex-M33 processor (Armv8-M Mainline architecture profile), // with the Floating Point extension. -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -19,7 +19,7 @@ pub fn target() -> Target { // These parameters map to the following LLVM features. features: "+fp-armv8,-fp64,-d32".into(), max_atomic_width: Some(32), - ..super::thumb_base::opts() + ..base::thumb::opts() }, } } diff --git a/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs b/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs index 6f77ef98c015..394f02ecac49 100644 --- a/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs +++ b/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs @@ -1,5 +1,6 @@ -use super::{cvs, wasm_base}; -use super::{LinkArgs, LinkerFlavor, PanicStrategy, RelocModel, Target, TargetOptions}; +use crate::spec::{ + base, cvs, LinkArgs, LinkerFlavor, PanicStrategy, RelocModel, Target, TargetOptions, +}; pub fn target() -> Target { // Reset flags for non-Em flavors back to empty to satisfy sanity checking tests. @@ -22,7 +23,7 @@ pub fn target() -> Target { panic_strategy: PanicStrategy::Unwind, no_default_libraries: false, families: cvs!["unix", "wasm"], - ..wasm_base::options() + ..base::wasm::options() }; Target { llvm_target: "wasm32-unknown-emscripten".into(), diff --git a/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs b/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs index 06529c2e4039..2a40d9c66370 100644 --- a/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs +++ b/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs @@ -10,11 +10,11 @@ //! This target is more or less managed by the Rust and WebAssembly Working //! Group nowadays at . -use super::{wasm_base, Cc, LinkerFlavor, Target}; use crate::spec::abi::Abi; +use crate::spec::{base, Cc, LinkerFlavor, Target}; pub fn target() -> Target { - let mut options = wasm_base::options(); + let mut options = base::wasm::options(); options.os = "unknown".into(); // This is a default for backwards-compatibility with the original diff --git a/compiler/rustc_target/src/spec/wasm32_wasi.rs b/compiler/rustc_target/src/spec/wasm32_wasi.rs index 23fabcdc90de..6dbcb01ea436 100644 --- a/compiler/rustc_target/src/spec/wasm32_wasi.rs +++ b/compiler/rustc_target/src/spec/wasm32_wasi.rs @@ -72,12 +72,12 @@ //! best we can with this target. Don't start relying on too much here unless //! you know what you're getting in to! -use super::crt_objects; -use super::LinkSelfContainedDefault; -use super::{wasm_base, Cc, LinkerFlavor, Target}; +use crate::spec::crt_objects; +use crate::spec::LinkSelfContainedDefault; +use crate::spec::{base, Cc, LinkerFlavor, Target}; pub fn target() -> Target { - let mut options = wasm_base::options(); + let mut options = base::wasm::options(); options.os = "wasi".into(); options.add_pre_link_args(LinkerFlavor::WasmLld(Cc::Yes), &["--target=wasm32-wasi"]); diff --git a/compiler/rustc_target/src/spec/wasm32_wasi_preview1_threads.rs b/compiler/rustc_target/src/spec/wasm32_wasi_preview1_threads.rs index ba9a99ae380e..28ea4cc9ece3 100644 --- a/compiler/rustc_target/src/spec/wasm32_wasi_preview1_threads.rs +++ b/compiler/rustc_target/src/spec/wasm32_wasi_preview1_threads.rs @@ -72,11 +72,10 @@ //! best we can with this target. Don't start relying on too much here unless //! you know what you're getting in to! -use super::{crt_objects, wasm_base}; -use super::{Cc, LinkSelfContainedDefault, LinkerFlavor, Target}; +use crate::spec::{base, crt_objects, Cc, LinkSelfContainedDefault, LinkerFlavor, Target}; pub fn target() -> Target { - let mut options = wasm_base::options(); + let mut options = base::wasm::options(); options.os = "wasi".into(); diff --git a/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs b/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs index 3fda398d24c8..54c5ae8e2030 100644 --- a/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs +++ b/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs @@ -7,10 +7,10 @@ //! the standard library is available, most of it returns an error immediately //! (e.g. trying to create a TCP stream or something like that). -use super::{wasm_base, Cc, LinkerFlavor, Target}; +use crate::spec::{base, Cc, LinkerFlavor, Target}; pub fn target() -> Target { - let mut options = wasm_base::options(); + let mut options = base::wasm::options(); options.os = "unknown".into(); options.add_pre_link_args( diff --git a/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs b/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs index e3f5d7321d13..9170a10d254b 100644 --- a/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs @@ -1,4 +1,4 @@ -use super::apple_base::{macos_llvm_target, opts, Arch}; +use crate::spec::base::apple::{macos_llvm_target, opts, Arch}; use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, SanitizerSet}; use crate::spec::{StackProbeType, Target, TargetOptions}; diff --git a/compiler/rustc_target/src/spec/x86_64_apple_ios.rs b/compiler/rustc_target/src/spec/x86_64_apple_ios.rs index 061b6a96fc88..d9f3f7de655c 100644 --- a/compiler/rustc_target/src/spec/x86_64_apple_ios.rs +++ b/compiler/rustc_target/src/spec/x86_64_apple_ios.rs @@ -1,4 +1,4 @@ -use super::apple_base::{ios_sim_llvm_target, opts, Arch}; +use crate::spec::base::apple::{ios_sim_llvm_target, opts, Arch}; use crate::spec::{SanitizerSet, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { diff --git a/compiler/rustc_target/src/spec/x86_64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/x86_64_apple_ios_macabi.rs index fd1926f29456..5e6fbac34d71 100644 --- a/compiler/rustc_target/src/spec/x86_64_apple_ios_macabi.rs +++ b/compiler/rustc_target/src/spec/x86_64_apple_ios_macabi.rs @@ -1,4 +1,4 @@ -use super::apple_base::{opts, Arch}; +use crate::spec::base::apple::{opts, Arch}; use crate::spec::{Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { diff --git a/compiler/rustc_target/src/spec/x86_64_apple_tvos.rs b/compiler/rustc_target/src/spec/x86_64_apple_tvos.rs index 2ec4d9569e3e..1c4d9196c185 100644 --- a/compiler/rustc_target/src/spec/x86_64_apple_tvos.rs +++ b/compiler/rustc_target/src/spec/x86_64_apple_tvos.rs @@ -1,4 +1,4 @@ -use super::apple_base::{opts, tvos_sim_llvm_target, Arch}; +use crate::spec::base::apple::{opts, tvos_sim_llvm_target, Arch}; use crate::spec::{StackProbeType, Target, TargetOptions}; pub fn target() -> Target { diff --git a/compiler/rustc_target/src/spec/x86_64_apple_watchos_sim.rs b/compiler/rustc_target/src/spec/x86_64_apple_watchos_sim.rs index 5fcc00a86ff9..258148677fb8 100644 --- a/compiler/rustc_target/src/spec/x86_64_apple_watchos_sim.rs +++ b/compiler/rustc_target/src/spec/x86_64_apple_watchos_sim.rs @@ -1,4 +1,4 @@ -use super::apple_base::{opts, watchos_sim_llvm_target, Arch}; +use crate::spec::base::apple::{opts, watchos_sim_llvm_target, Arch}; use crate::spec::{StackProbeType, Target, TargetOptions}; pub fn target() -> Target { diff --git a/compiler/rustc_target/src/spec/x86_64_linux_android.rs b/compiler/rustc_target/src/spec/x86_64_linux_android.rs index c110674fd870..6cffda44fa9e 100644 --- a/compiler/rustc_target/src/spec/x86_64_linux_android.rs +++ b/compiler/rustc_target/src/spec/x86_64_linux_android.rs @@ -1,7 +1,9 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target, TargetOptions}; +use crate::spec::{ + base, Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target, TargetOptions, +}; pub fn target() -> Target { - let mut base = super::android_base::opts(); + let mut base = base::android::opts(); base.cpu = "x86-64".into(); base.plt_by_default = false; // https://developer.android.com/ndk/guides/abis.html#86-64 diff --git a/compiler/rustc_target/src/spec/x86_64_pc_nto_qnx710.rs b/compiler/rustc_target/src/spec/x86_64_pc_nto_qnx710.rs index 8424757df076..93aec4c425a2 100644 --- a/compiler/rustc_target/src/spec/x86_64_pc_nto_qnx710.rs +++ b/compiler/rustc_target/src/spec/x86_64_pc_nto_qnx710.rs @@ -1,5 +1,4 @@ -use super::nto_qnx_base; -use crate::spec::{Cc, LinkerFlavor, Lld, Target, TargetOptions}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -17,7 +16,7 @@ pub fn target() -> Target { &["-Vgcc_ntox86_64_cxx"], ), env: "nto71".into(), - ..nto_qnx_base::opts() + ..base::nto_qnx::opts() }, } } diff --git a/compiler/rustc_target/src/spec/x86_64_pc_solaris.rs b/compiler/rustc_target/src/spec/x86_64_pc_solaris.rs index e2c59d2938e6..ca6a6dc500b8 100644 --- a/compiler/rustc_target/src/spec/x86_64_pc_solaris.rs +++ b/compiler/rustc_target/src/spec/x86_64_pc_solaris.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, LinkerFlavor, SanitizerSet, StackProbeType, Target}; +use crate::spec::{base, Cc, LinkerFlavor, SanitizerSet, StackProbeType, Target}; pub fn target() -> Target { - let mut base = super::solaris_base::opts(); + let mut base = base::solaris::opts(); base.add_pre_link_args(LinkerFlavor::Unix(Cc::Yes), &["-m64"]); base.cpu = "x86-64".into(); base.plt_by_default = false; diff --git a/compiler/rustc_target/src/spec/x86_64_pc_windows_gnu.rs b/compiler/rustc_target/src/spec/x86_64_pc_windows_gnu.rs index 1b8885c34da7..6d3e07270517 100644 --- a/compiler/rustc_target/src/spec/x86_64_pc_windows_gnu.rs +++ b/compiler/rustc_target/src/spec/x86_64_pc_windows_gnu.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, Target}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, Target}; pub fn target() -> Target { - let mut base = super::windows_gnu_base::opts(); + let mut base = base::windows_gnu::opts(); base.cpu = "x86-64".into(); base.plt_by_default = false; // Use high-entropy 64 bit address space for ASLR diff --git a/compiler/rustc_target/src/spec/x86_64_pc_windows_gnullvm.rs b/compiler/rustc_target/src/spec/x86_64_pc_windows_gnullvm.rs index 8f5e398a0be9..a56ebfa585e2 100644 --- a/compiler/rustc_target/src/spec/x86_64_pc_windows_gnullvm.rs +++ b/compiler/rustc_target/src/spec/x86_64_pc_windows_gnullvm.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, Target}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, Target}; pub fn target() -> Target { - let mut base = super::windows_gnullvm_base::opts(); + let mut base = base::windows_gnullvm::opts(); base.cpu = "x86-64".into(); base.plt_by_default = false; base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); diff --git a/compiler/rustc_target/src/spec/x86_64_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/x86_64_pc_windows_msvc.rs index 6b897ca7070e..7d6276a0c2d5 100644 --- a/compiler/rustc_target/src/spec/x86_64_pc_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/x86_64_pc_windows_msvc.rs @@ -1,7 +1,7 @@ -use crate::spec::Target; +use crate::spec::{base, Target}; pub fn target() -> Target { - let mut base = super::windows_msvc_base::opts(); + let mut base = base::windows_msvc::opts(); base.cpu = "x86-64".into(); base.plt_by_default = false; base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/x86_64_sun_solaris.rs b/compiler/rustc_target/src/spec/x86_64_sun_solaris.rs index 650065f6330a..cca099d3bbf6 100644 --- a/compiler/rustc_target/src/spec/x86_64_sun_solaris.rs +++ b/compiler/rustc_target/src/spec/x86_64_sun_solaris.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, LinkerFlavor, StackProbeType, Target}; +use crate::spec::{base, Cc, LinkerFlavor, StackProbeType, Target}; pub fn target() -> Target { - let mut base = super::solaris_base::opts(); + let mut base = base::solaris::opts(); base.add_pre_link_args(LinkerFlavor::Unix(Cc::Yes), &["-m64"]); base.cpu = "x86-64".into(); base.plt_by_default = false; diff --git a/compiler/rustc_target/src/spec/x86_64_unikraft_linux_musl.rs b/compiler/rustc_target/src/spec/x86_64_unikraft_linux_musl.rs index 2aa093b131f5..c12cb1ab00e0 100644 --- a/compiler/rustc_target/src/spec/x86_64_unikraft_linux_musl.rs +++ b/compiler/rustc_target/src/spec/x86_64_unikraft_linux_musl.rs @@ -1,4 +1,4 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -13,7 +13,7 @@ pub fn target() -> Target { pre_link_args: TargetOptions::link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]), max_atomic_width: Some(64), stack_probes: StackProbeType::X86, - ..super::unikraft_linux_musl_base::opts() + ..base::unikraft_linux_musl::opts() }, } } diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_dragonfly.rs b/compiler/rustc_target/src/spec/x86_64_unknown_dragonfly.rs index 3b8e75977b5a..68d1a755b792 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_dragonfly.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_dragonfly.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target}; pub fn target() -> Target { - let mut base = super::dragonfly_base::opts(); + let mut base = base::dragonfly::opts(); base.cpu = "x86-64".into(); base.plt_by_default = false; base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_freebsd.rs b/compiler/rustc_target/src/spec/x86_64_unknown_freebsd.rs index b2d91d09996f..e3f29fa5afaf 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_freebsd.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target}; pub fn target() -> Target { - let mut base = super::freebsd_base::opts(); + let mut base = base::freebsd::opts(); base.cpu = "x86-64".into(); base.plt_by_default = false; base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_fuchsia.rs b/compiler/rustc_target/src/spec/x86_64_unknown_fuchsia.rs index bee935419602..c8850d703e35 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_fuchsia.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_fuchsia.rs @@ -1,7 +1,7 @@ -use crate::spec::{SanitizerSet, StackProbeType, Target}; +use crate::spec::{base, SanitizerSet, StackProbeType, Target}; pub fn target() -> Target { - let mut base = super::fuchsia_base::opts(); + let mut base = base::fuchsia::opts(); base.cpu = "x86-64".into(); base.plt_by_default = false; base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_haiku.rs b/compiler/rustc_target/src/spec/x86_64_unknown_haiku.rs index 16ed3150e6e2..ca55e6514ddd 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_haiku.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_haiku.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target}; pub fn target() -> Target { - let mut base = super::haiku_base::opts(); + let mut base = base::haiku::opts(); base.cpu = "x86-64".into(); base.plt_by_default = false; base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_hermit.rs b/compiler/rustc_target/src/spec/x86_64_unknown_hermit.rs index 1eb069301117..3cc50d40dda6 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_hermit.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_hermit.rs @@ -1,4 +1,4 @@ -use crate::spec::{StackProbeType, Target, TargetOptions}; +use crate::spec::{base, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -13,7 +13,7 @@ pub fn target() -> Target { plt_by_default: false, max_atomic_width: Some(64), stack_probes: StackProbeType::X86, - ..super::hermit_base::opts() + ..base::hermit::opts() }, } } diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_illumos.rs b/compiler/rustc_target/src/spec/x86_64_unknown_illumos.rs index 9259cfe5f0ed..eb2b13cb5c26 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_illumos.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_illumos.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, LinkerFlavor, SanitizerSet, Target}; +use crate::spec::{base, Cc, LinkerFlavor, SanitizerSet, Target}; pub fn target() -> Target { - let mut base = super::illumos_base::opts(); + let mut base = base::illumos::opts(); base.add_pre_link_args(LinkerFlavor::Unix(Cc::Yes), &["-m64", "-std=c99"]); base.cpu = "x86-64".into(); base.plt_by_default = false; diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_l4re_uclibc.rs b/compiler/rustc_target/src/spec/x86_64_unknown_l4re_uclibc.rs index 912d289c47f9..7b86fe738b1e 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_l4re_uclibc.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_l4re_uclibc.rs @@ -1,7 +1,7 @@ -use crate::spec::{PanicStrategy, Target}; +use crate::spec::{base, PanicStrategy, Target}; pub fn target() -> Target { - let mut base = super::l4re_base::opts(); + let mut base = base::l4re::opts(); base.cpu = "x86-64".into(); base.plt_by_default = false; base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs index 2f970f87cc64..80e267c163fa 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target}; pub fn target() -> Target { - let mut base = super::linux_gnu_base::opts(); + let mut base = base::linux_gnu::opts(); base.cpu = "x86-64".into(); base.plt_by_default = false; base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnux32.rs b/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnux32.rs index 5469d02c5923..622bfe8bbe8e 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnux32.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnux32.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target}; pub fn target() -> Target { - let mut base = super::linux_gnu_base::opts(); + let mut base = base::linux_gnu::opts(); base.cpu = "x86-64".into(); base.abi = "x32".into(); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/x86_64_unknown_linux_musl.rs index 7154f5fa3068..d74ff466a015 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_linux_musl.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target}; pub fn target() -> Target { - let mut base = super::linux_musl_base::opts(); + let mut base = base::linux_musl::opts(); base.cpu = "x86-64".into(); base.plt_by_default = false; base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_linux_ohos.rs b/compiler/rustc_target/src/spec/x86_64_unknown_linux_ohos.rs index a96be8cd5546..87b004df0018 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_linux_ohos.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_linux_ohos.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target}; pub fn target() -> Target { - let mut base = super::linux_ohos_base::opts(); + let mut base = base::linux_ohos::opts(); base.cpu = "x86-64".into(); base.max_atomic_width = Some(64); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_netbsd.rs b/compiler/rustc_target/src/spec/x86_64_unknown_netbsd.rs index 2e7bf34f7d2f..04060513abc8 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_netbsd.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_netbsd.rs @@ -1,7 +1,9 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target, TargetOptions}; +use crate::spec::{ + base, Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target, TargetOptions, +}; pub fn target() -> Target { - let mut base = super::netbsd_base::opts(); + let mut base = base::netbsd::opts(); base.cpu = "x86-64".into(); base.plt_by_default = false; base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/x86_64_unknown_openbsd.rs index 86fa9bf7ed2a..5e6e7efb2de8 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_openbsd.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_openbsd.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target}; pub fn target() -> Target { - let mut base = super::openbsd_base::opts(); + let mut base = base::openbsd::opts(); base.cpu = "x86-64".into(); base.plt_by_default = false; base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_redox.rs b/compiler/rustc_target/src/spec/x86_64_unknown_redox.rs index decc97367822..382ff71f019c 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_redox.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_redox.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target}; pub fn target() -> Target { - let mut base = super::redox_base::opts(); + let mut base = base::redox::opts(); base.cpu = "x86-64".into(); base.plt_by_default = false; base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_uefi.rs b/compiler/rustc_target/src/spec/x86_64_unknown_uefi.rs index 41ba768068a3..5abfb8162f70 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_uefi.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_uefi.rs @@ -5,10 +5,13 @@ // The win64 ABI is used. It differs from the sysv64 ABI, so we must use a windows target with // LLVM. "x86_64-unknown-windows" is used to get the minimal subset of windows-specific features. -use crate::{abi::call::Conv, spec::Target}; +use crate::{ + abi::call::Conv, + spec::{base, Target}, +}; pub fn target() -> Target { - let mut base = super::uefi_msvc_base::opts(); + let mut base = base::uefi_msvc::opts(); base.cpu = "x86-64".into(); base.plt_by_default = false; base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/x86_64_uwp_windows_gnu.rs b/compiler/rustc_target/src/spec/x86_64_uwp_windows_gnu.rs index 1a9d2a57182d..a46d3a0e27bc 100644 --- a/compiler/rustc_target/src/spec/x86_64_uwp_windows_gnu.rs +++ b/compiler/rustc_target/src/spec/x86_64_uwp_windows_gnu.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, Target}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, Target}; pub fn target() -> Target { - let mut base = super::windows_uwp_gnu_base::opts(); + let mut base = base::windows_uwp_gnu::opts(); base.cpu = "x86-64".into(); base.plt_by_default = false; // Use high-entropy 64 bit address space for ASLR diff --git a/compiler/rustc_target/src/spec/x86_64_uwp_windows_msvc.rs b/compiler/rustc_target/src/spec/x86_64_uwp_windows_msvc.rs index 1ae403fa83f3..a3bc27aa0650 100644 --- a/compiler/rustc_target/src/spec/x86_64_uwp_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/x86_64_uwp_windows_msvc.rs @@ -1,7 +1,7 @@ -use crate::spec::Target; +use crate::spec::{base, Target}; pub fn target() -> Target { - let mut base = super::windows_uwp_msvc_base::opts(); + let mut base = base::windows_uwp_msvc::opts(); base.cpu = "x86-64".into(); base.plt_by_default = false; base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/x86_64_wrs_vxworks.rs b/compiler/rustc_target/src/spec/x86_64_wrs_vxworks.rs index a7c4aaecf910..4b221fe6959f 100644 --- a/compiler/rustc_target/src/spec/x86_64_wrs_vxworks.rs +++ b/compiler/rustc_target/src/spec/x86_64_wrs_vxworks.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target}; pub fn target() -> Target { - let mut base = super::vxworks_base::opts(); + let mut base = base::vxworks::opts(); base.cpu = "x86-64".into(); base.plt_by_default = false; base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/x86_64h_apple_darwin.rs b/compiler/rustc_target/src/spec/x86_64h_apple_darwin.rs index 54f7490b2c05..a30e9d17cef8 100644 --- a/compiler/rustc_target/src/spec/x86_64h_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/x86_64h_apple_darwin.rs @@ -1,4 +1,4 @@ -use super::apple_base::{macos_llvm_target, opts, Arch}; +use crate::spec::base::apple::{macos_llvm_target, opts, Arch}; use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, SanitizerSet}; use crate::spec::{StackProbeType, Target, TargetOptions}; From 1af256fe8aea69909e1bf068506a29ebbf82eccf Mon Sep 17 00:00:00 2001 From: David Wood Date: Wed, 8 Nov 2023 14:25:34 +0800 Subject: [PATCH 340/435] targets: move target specs to spec/targets Signed-off-by: David Wood --- compiler/rustc_target/src/spec/aarch64_fuchsia.rs | 1 - compiler/rustc_target/src/spec/base/apple/tests.rs | 2 +- compiler/rustc_target/src/spec/mod.rs | 8 +++++--- .../src/spec/{ => targets}/aarch64_apple_darwin.rs | 0 .../src/spec/{ => targets}/aarch64_apple_ios.rs | 0 .../src/spec/{ => targets}/aarch64_apple_ios_macabi.rs | 0 .../src/spec/{ => targets}/aarch64_apple_ios_sim.rs | 0 .../src/spec/{ => targets}/aarch64_apple_tvos.rs | 0 .../src/spec/{ => targets}/aarch64_apple_tvos_sim.rs | 0 .../src/spec/{ => targets}/aarch64_apple_watchos_sim.rs | 0 .../spec/{ => targets}/aarch64_be_unknown_linux_gnu.rs | 0 .../{ => targets}/aarch64_be_unknown_linux_gnu_ilp32.rs | 0 .../src/spec/{ => targets}/aarch64_be_unknown_netbsd.rs | 0 compiler/rustc_target/src/spec/targets/aarch64_fuchsia.rs | 1 + .../src/spec/{ => targets}/aarch64_kmc_solid_asp3.rs | 2 +- .../src/spec/{ => targets}/aarch64_linux_android.rs | 0 .../{ => targets}/aarch64_nintendo_switch_freestanding.rs | 2 +- .../aarch64_nintendo_switch_freestanding_linker_script.ld | 0 .../src/spec/{ => targets}/aarch64_pc_windows_gnullvm.rs | 0 .../src/spec/{ => targets}/aarch64_pc_windows_msvc.rs | 0 .../src/spec/{ => targets}/aarch64_unknown_freebsd.rs | 0 .../src/spec/{ => targets}/aarch64_unknown_fuchsia.rs | 0 .../src/spec/{ => targets}/aarch64_unknown_hermit.rs | 0 .../src/spec/{ => targets}/aarch64_unknown_linux_gnu.rs | 0 .../spec/{ => targets}/aarch64_unknown_linux_gnu_ilp32.rs | 0 .../src/spec/{ => targets}/aarch64_unknown_linux_musl.rs | 0 .../src/spec/{ => targets}/aarch64_unknown_linux_ohos.rs | 3 +-- .../src/spec/{ => targets}/aarch64_unknown_netbsd.rs | 0 .../src/spec/{ => targets}/aarch64_unknown_none.rs | 2 +- .../spec/{ => targets}/aarch64_unknown_none_softfloat.rs | 2 +- .../src/spec/{ => targets}/aarch64_unknown_nto_qnx_710.rs | 0 .../src/spec/{ => targets}/aarch64_unknown_openbsd.rs | 0 .../src/spec/{ => targets}/aarch64_unknown_redox.rs | 0 .../src/spec/{ => targets}/aarch64_unknown_teeos.rs | 0 .../src/spec/{ => targets}/aarch64_unknown_uefi.rs | 0 .../src/spec/{ => targets}/aarch64_uwp_windows_msvc.rs | 0 .../src/spec/{ => targets}/aarch64_wrs_vxworks.rs | 0 .../src/spec/{ => targets}/arm64_32_apple_watchos.rs | 0 .../src/spec/{ => targets}/arm_linux_androideabi.rs | 0 .../src/spec/{ => targets}/arm_unknown_linux_gnueabi.rs | 0 .../src/spec/{ => targets}/arm_unknown_linux_gnueabihf.rs | 0 .../src/spec/{ => targets}/arm_unknown_linux_musleabi.rs | 0 .../spec/{ => targets}/arm_unknown_linux_musleabihf.rs | 0 .../src/spec/{ => targets}/armeb_unknown_linux_gnueabi.rs | 0 .../src/spec/{ => targets}/armebv7r_none_eabi.rs | 0 .../src/spec/{ => targets}/armebv7r_none_eabihf.rs | 0 .../src/spec/{ => targets}/armv4t_none_eabi.rs | 0 .../spec/{ => targets}/armv4t_unknown_linux_gnueabi.rs | 0 .../src/spec/{ => targets}/armv5te_none_eabi.rs | 0 .../spec/{ => targets}/armv5te_unknown_linux_gnueabi.rs | 0 .../spec/{ => targets}/armv5te_unknown_linux_musleabi.rs | 0 .../{ => targets}/armv5te_unknown_linux_uclibceabi.rs | 0 .../src/spec/{ => targets}/armv6_unknown_freebsd.rs | 0 .../src/spec/{ => targets}/armv6_unknown_netbsd_eabihf.rs | 0 .../src/spec/{ => targets}/armv6k_nintendo_3ds.rs | 0 .../src/spec/{ => targets}/armv7_linux_androideabi.rs | 0 .../spec/{ => targets}/armv7_sony_vita_newlibeabihf.rs | 0 .../src/spec/{ => targets}/armv7_unknown_freebsd.rs | 0 .../src/spec/{ => targets}/armv7_unknown_linux_gnueabi.rs | 0 .../spec/{ => targets}/armv7_unknown_linux_gnueabihf.rs | 0 .../spec/{ => targets}/armv7_unknown_linux_musleabi.rs | 0 .../spec/{ => targets}/armv7_unknown_linux_musleabihf.rs | 0 .../src/spec/{ => targets}/armv7_unknown_linux_ohos.rs | 0 .../spec/{ => targets}/armv7_unknown_linux_uclibceabi.rs | 0 .../{ => targets}/armv7_unknown_linux_uclibceabihf.rs | 0 .../src/spec/{ => targets}/armv7_unknown_netbsd_eabihf.rs | 0 .../src/spec/{ => targets}/armv7_wrs_vxworks_eabihf.rs | 0 .../src/spec/{ => targets}/armv7a_kmc_solid_asp3_eabi.rs | 2 +- .../spec/{ => targets}/armv7a_kmc_solid_asp3_eabihf.rs | 2 +- .../src/spec/{ => targets}/armv7a_none_eabi.rs | 2 +- .../src/spec/{ => targets}/armv7a_none_eabihf.rs | 2 +- .../src/spec/{ => targets}/armv7k_apple_watchos.rs | 0 .../src/spec/{ => targets}/armv7r_none_eabi.rs | 0 .../src/spec/{ => targets}/armv7r_none_eabihf.rs | 0 .../src/spec/{ => targets}/armv7s_apple_ios.rs | 0 .../src/spec/{ => targets}/asmjs_unknown_emscripten.rs | 2 +- .../src/spec/{ => targets}/avr_unknown_gnu_atmega328.rs | 0 .../src/spec/{ => targets}/bpfeb_unknown_none.rs | 0 .../src/spec/{ => targets}/bpfel_unknown_none.rs | 0 .../src/spec/{ => targets}/csky_unknown_linux_gnuabiv2.rs | 0 .../spec/{ => targets}/csky_unknown_linux_gnuabiv2hf.rs | 0 .../src/spec/{ => targets}/hexagon_unknown_linux_musl.rs | 0 .../rustc_target/src/spec/{ => targets}/i386_apple_ios.rs | 0 .../src/spec/{ => targets}/i386_unknown_linux_gnu.rs | 0 .../src/spec/{ => targets}/i486_unknown_linux_gnu.rs | 0 .../src/spec/{ => targets}/i586_pc_nto_qnx700.rs | 0 .../src/spec/{ => targets}/i586_pc_windows_msvc.rs | 0 .../src/spec/{ => targets}/i586_unknown_linux_gnu.rs | 0 .../src/spec/{ => targets}/i586_unknown_linux_musl.rs | 0 .../src/spec/{ => targets}/i586_unknown_netbsd.rs | 0 .../src/spec/{ => targets}/i686_apple_darwin.rs | 0 .../src/spec/{ => targets}/i686_linux_android.rs | 0 .../src/spec/{ => targets}/i686_pc_windows_gnu.rs | 0 .../src/spec/{ => targets}/i686_pc_windows_gnullvm.rs | 0 .../src/spec/{ => targets}/i686_pc_windows_msvc.rs | 0 .../src/spec/{ => targets}/i686_unknown_freebsd.rs | 0 .../src/spec/{ => targets}/i686_unknown_haiku.rs | 0 .../src/spec/{ => targets}/i686_unknown_hurd_gnu.rs | 0 .../src/spec/{ => targets}/i686_unknown_linux_gnu.rs | 0 .../src/spec/{ => targets}/i686_unknown_linux_musl.rs | 0 .../src/spec/{ => targets}/i686_unknown_netbsd.rs | 0 .../src/spec/{ => targets}/i686_unknown_openbsd.rs | 0 .../src/spec/{ => targets}/i686_unknown_uefi.rs | 0 .../src/spec/{ => targets}/i686_uwp_windows_gnu.rs | 0 .../src/spec/{ => targets}/i686_uwp_windows_msvc.rs | 0 .../src/spec/{ => targets}/i686_wrs_vxworks.rs | 0 .../spec/{ => targets}/loongarch64_unknown_linux_gnu.rs | 0 .../src/spec/{ => targets}/loongarch64_unknown_none.rs | 4 ++-- .../{ => targets}/loongarch64_unknown_none_softfloat.rs | 4 ++-- .../src/spec/{ => targets}/m68k_unknown_linux_gnu.rs | 0 .../src/spec/{ => targets}/mips64_openwrt_linux_musl.rs | 0 .../spec/{ => targets}/mips64_unknown_linux_gnuabi64.rs | 0 .../spec/{ => targets}/mips64_unknown_linux_muslabi64.rs | 0 .../spec/{ => targets}/mips64el_unknown_linux_gnuabi64.rs | 0 .../{ => targets}/mips64el_unknown_linux_muslabi64.rs | 0 .../src/spec/{ => targets}/mips_unknown_linux_gnu.rs | 0 .../src/spec/{ => targets}/mips_unknown_linux_musl.rs | 0 .../src/spec/{ => targets}/mips_unknown_linux_uclibc.rs | 0 .../src/spec/{ => targets}/mipsel_sony_psp.rs | 0 .../spec/{ => targets}/mipsel_sony_psp_linker_script.ld | 0 .../src/spec/{ => targets}/mipsel_sony_psx.rs | 0 .../src/spec/{ => targets}/mipsel_unknown_linux_gnu.rs | 0 .../src/spec/{ => targets}/mipsel_unknown_linux_musl.rs | 0 .../src/spec/{ => targets}/mipsel_unknown_linux_uclibc.rs | 0 .../src/spec/{ => targets}/mipsel_unknown_netbsd.rs | 0 .../src/spec/{ => targets}/mipsel_unknown_none.rs | 0 .../spec/{ => targets}/mipsisa32r6_unknown_linux_gnu.rs | 0 .../spec/{ => targets}/mipsisa32r6el_unknown_linux_gnu.rs | 0 .../{ => targets}/mipsisa64r6_unknown_linux_gnuabi64.rs | 0 .../{ => targets}/mipsisa64r6el_unknown_linux_gnuabi64.rs | 0 .../src/spec/{ => targets}/msp430_none_elf.rs | 0 .../src/spec/{ => targets}/nvptx64_nvidia_cuda.rs | 0 .../src/spec/{ => targets}/powerpc64_ibm_aix.rs | 0 .../src/spec/{ => targets}/powerpc64_unknown_freebsd.rs | 0 .../src/spec/{ => targets}/powerpc64_unknown_linux_gnu.rs | 0 .../spec/{ => targets}/powerpc64_unknown_linux_musl.rs | 0 .../src/spec/{ => targets}/powerpc64_unknown_openbsd.rs | 0 .../src/spec/{ => targets}/powerpc64_wrs_vxworks.rs | 0 .../src/spec/{ => targets}/powerpc64le_unknown_freebsd.rs | 0 .../spec/{ => targets}/powerpc64le_unknown_linux_gnu.rs | 0 .../spec/{ => targets}/powerpc64le_unknown_linux_musl.rs | 0 .../src/spec/{ => targets}/powerpc_unknown_freebsd.rs | 0 .../src/spec/{ => targets}/powerpc_unknown_linux_gnu.rs | 0 .../spec/{ => targets}/powerpc_unknown_linux_gnuspe.rs | 0 .../src/spec/{ => targets}/powerpc_unknown_linux_musl.rs | 0 .../src/spec/{ => targets}/powerpc_unknown_netbsd.rs | 0 .../src/spec/{ => targets}/powerpc_unknown_openbsd.rs | 0 .../src/spec/{ => targets}/powerpc_wrs_vxworks.rs | 0 .../src/spec/{ => targets}/powerpc_wrs_vxworks_spe.rs | 0 .../src/spec/{ => targets}/riscv32gc_unknown_linux_gnu.rs | 0 .../spec/{ => targets}/riscv32gc_unknown_linux_musl.rs | 0 .../src/spec/{ => targets}/riscv32i_unknown_none_elf.rs | 0 .../src/spec/{ => targets}/riscv32im_unknown_none_elf.rs | 0 .../src/spec/{ => targets}/riscv32imac_esp_espidf.rs | 0 .../spec/{ => targets}/riscv32imac_unknown_none_elf.rs | 0 .../spec/{ => targets}/riscv32imac_unknown_xous_elf.rs | 0 .../src/spec/{ => targets}/riscv32imc_esp_espidf.rs | 0 .../src/spec/{ => targets}/riscv32imc_unknown_none_elf.rs | 0 .../src/spec/{ => targets}/riscv64_linux_android.rs | 0 .../src/spec/{ => targets}/riscv64gc_unknown_freebsd.rs | 0 .../src/spec/{ => targets}/riscv64gc_unknown_fuchsia.rs | 0 .../src/spec/{ => targets}/riscv64gc_unknown_hermit.rs | 0 .../src/spec/{ => targets}/riscv64gc_unknown_linux_gnu.rs | 0 .../spec/{ => targets}/riscv64gc_unknown_linux_musl.rs | 0 .../src/spec/{ => targets}/riscv64gc_unknown_netbsd.rs | 0 .../src/spec/{ => targets}/riscv64gc_unknown_none_elf.rs | 3 +-- .../src/spec/{ => targets}/riscv64gc_unknown_openbsd.rs | 0 .../spec/{ => targets}/riscv64imac_unknown_none_elf.rs | 0 .../src/spec/{ => targets}/s390x_unknown_linux_gnu.rs | 0 .../src/spec/{ => targets}/s390x_unknown_linux_musl.rs | 0 .../src/spec/{ => targets}/sparc64_unknown_linux_gnu.rs | 0 .../src/spec/{ => targets}/sparc64_unknown_netbsd.rs | 0 .../src/spec/{ => targets}/sparc64_unknown_openbsd.rs | 0 .../src/spec/{ => targets}/sparc_unknown_linux_gnu.rs | 0 .../src/spec/{ => targets}/sparc_unknown_none_elf.rs | 0 .../src/spec/{ => targets}/sparcv9_sun_solaris.rs | 0 .../src/spec/{ => targets}/thumbv4t_none_eabi.rs | 0 .../src/spec/{ => targets}/thumbv5te_none_eabi.rs | 0 .../src/spec/{ => targets}/thumbv6m_none_eabi.rs | 0 .../src/spec/{ => targets}/thumbv7a_pc_windows_msvc.rs | 0 .../src/spec/{ => targets}/thumbv7a_uwp_windows_msvc.rs | 0 .../src/spec/{ => targets}/thumbv7em_none_eabi.rs | 0 .../src/spec/{ => targets}/thumbv7em_none_eabihf.rs | 0 .../src/spec/{ => targets}/thumbv7m_none_eabi.rs | 0 .../spec/{ => targets}/thumbv7neon_linux_androideabi.rs | 0 .../{ => targets}/thumbv7neon_unknown_linux_gnueabihf.rs | 0 .../{ => targets}/thumbv7neon_unknown_linux_musleabihf.rs | 0 .../src/spec/{ => targets}/thumbv8m_base_none_eabi.rs | 0 .../src/spec/{ => targets}/thumbv8m_main_none_eabi.rs | 0 .../src/spec/{ => targets}/thumbv8m_main_none_eabihf.rs | 0 .../src/spec/{ => targets}/wasm32_unknown_emscripten.rs | 0 .../src/spec/{ => targets}/wasm32_unknown_unknown.rs | 0 .../rustc_target/src/spec/{ => targets}/wasm32_wasi.rs | 0 .../spec/{ => targets}/wasm32_wasi_preview1_threads.rs | 0 .../src/spec/{ => targets}/wasm64_unknown_unknown.rs | 0 .../src/spec/{ => targets}/x86_64_apple_darwin.rs | 0 .../src/spec/{ => targets}/x86_64_apple_ios.rs | 0 .../src/spec/{ => targets}/x86_64_apple_ios_macabi.rs | 0 .../src/spec/{ => targets}/x86_64_apple_tvos.rs | 0 .../src/spec/{ => targets}/x86_64_apple_watchos_sim.rs | 0 .../src/spec/{ => targets}/x86_64_fortanix_unknown_sgx.rs | 2 +- compiler/rustc_target/src/spec/targets/x86_64_fuchsia.rs | 1 + .../src/spec/{ => targets}/x86_64_linux_android.rs | 0 .../src/spec/{ => targets}/x86_64_pc_nto_qnx710.rs | 0 .../src/spec/{ => targets}/x86_64_pc_solaris.rs | 0 .../src/spec/{ => targets}/x86_64_pc_windows_gnu.rs | 0 .../src/spec/{ => targets}/x86_64_pc_windows_gnullvm.rs | 0 .../src/spec/{ => targets}/x86_64_pc_windows_msvc.rs | 0 .../src/spec/{ => targets}/x86_64_sun_solaris.rs | 0 .../src/spec/{ => targets}/x86_64_unikraft_linux_musl.rs | 0 .../src/spec/{ => targets}/x86_64_unknown_dragonfly.rs | 0 .../src/spec/{ => targets}/x86_64_unknown_freebsd.rs | 0 .../src/spec/{ => targets}/x86_64_unknown_fuchsia.rs | 0 .../src/spec/{ => targets}/x86_64_unknown_haiku.rs | 0 .../src/spec/{ => targets}/x86_64_unknown_hermit.rs | 0 .../src/spec/{ => targets}/x86_64_unknown_illumos.rs | 0 .../src/spec/{ => targets}/x86_64_unknown_l4re_uclibc.rs | 0 .../src/spec/{ => targets}/x86_64_unknown_linux_gnu.rs | 0 .../src/spec/{ => targets}/x86_64_unknown_linux_gnux32.rs | 0 .../src/spec/{ => targets}/x86_64_unknown_linux_musl.rs | 0 .../src/spec/{ => targets}/x86_64_unknown_linux_ohos.rs | 0 .../src/spec/{ => targets}/x86_64_unknown_netbsd.rs | 0 .../src/spec/{ => targets}/x86_64_unknown_none.rs | 4 ++-- .../src/spec/{ => targets}/x86_64_unknown_openbsd.rs | 0 .../src/spec/{ => targets}/x86_64_unknown_redox.rs | 0 .../src/spec/{ => targets}/x86_64_unknown_uefi.rs | 0 .../src/spec/{ => targets}/x86_64_uwp_windows_gnu.rs | 0 .../src/spec/{ => targets}/x86_64_uwp_windows_msvc.rs | 0 .../src/spec/{ => targets}/x86_64_wrs_vxworks.rs | 0 .../src/spec/{ => targets}/x86_64h_apple_darwin.rs | 0 compiler/rustc_target/src/spec/x86_64_fuchsia.rs | 1 - 231 files changed, 26 insertions(+), 26 deletions(-) delete mode 100644 compiler/rustc_target/src/spec/aarch64_fuchsia.rs rename compiler/rustc_target/src/spec/{ => targets}/aarch64_apple_darwin.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/aarch64_apple_ios.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/aarch64_apple_ios_macabi.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/aarch64_apple_ios_sim.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/aarch64_apple_tvos.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/aarch64_apple_tvos_sim.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/aarch64_apple_watchos_sim.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/aarch64_be_unknown_linux_gnu.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/aarch64_be_unknown_linux_gnu_ilp32.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/aarch64_be_unknown_netbsd.rs (100%) create mode 100644 compiler/rustc_target/src/spec/targets/aarch64_fuchsia.rs rename compiler/rustc_target/src/spec/{ => targets}/aarch64_kmc_solid_asp3.rs (90%) rename compiler/rustc_target/src/spec/{ => targets}/aarch64_linux_android.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/aarch64_nintendo_switch_freestanding.rs (91%) rename compiler/rustc_target/src/spec/{ => targets}/aarch64_nintendo_switch_freestanding_linker_script.ld (100%) rename compiler/rustc_target/src/spec/{ => targets}/aarch64_pc_windows_gnullvm.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/aarch64_pc_windows_msvc.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/aarch64_unknown_freebsd.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/aarch64_unknown_fuchsia.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/aarch64_unknown_hermit.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/aarch64_unknown_linux_gnu.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/aarch64_unknown_linux_gnu_ilp32.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/aarch64_unknown_linux_musl.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/aarch64_unknown_linux_ohos.rs (96%) rename compiler/rustc_target/src/spec/{ => targets}/aarch64_unknown_netbsd.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/aarch64_unknown_none.rs (98%) rename compiler/rustc_target/src/spec/{ => targets}/aarch64_unknown_none_softfloat.rs (91%) rename compiler/rustc_target/src/spec/{ => targets}/aarch64_unknown_nto_qnx_710.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/aarch64_unknown_openbsd.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/aarch64_unknown_redox.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/aarch64_unknown_teeos.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/aarch64_unknown_uefi.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/aarch64_uwp_windows_msvc.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/aarch64_wrs_vxworks.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/arm64_32_apple_watchos.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/arm_linux_androideabi.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/arm_unknown_linux_gnueabi.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/arm_unknown_linux_gnueabihf.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/arm_unknown_linux_musleabi.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/arm_unknown_linux_musleabihf.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/armeb_unknown_linux_gnueabi.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/armebv7r_none_eabi.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/armebv7r_none_eabihf.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/armv4t_none_eabi.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/armv4t_unknown_linux_gnueabi.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/armv5te_none_eabi.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/armv5te_unknown_linux_gnueabi.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/armv5te_unknown_linux_musleabi.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/armv5te_unknown_linux_uclibceabi.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/armv6_unknown_freebsd.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/armv6_unknown_netbsd_eabihf.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/armv6k_nintendo_3ds.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/armv7_linux_androideabi.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/armv7_sony_vita_newlibeabihf.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/armv7_unknown_freebsd.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/armv7_unknown_linux_gnueabi.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/armv7_unknown_linux_gnueabihf.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/armv7_unknown_linux_musleabi.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/armv7_unknown_linux_musleabihf.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/armv7_unknown_linux_ohos.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/armv7_unknown_linux_uclibceabi.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/armv7_unknown_linux_uclibceabihf.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/armv7_unknown_netbsd_eabihf.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/armv7_wrs_vxworks_eabihf.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/armv7a_kmc_solid_asp3_eabi.rs (90%) rename compiler/rustc_target/src/spec/{ => targets}/armv7a_kmc_solid_asp3_eabihf.rs (90%) rename compiler/rustc_target/src/spec/{ => targets}/armv7a_none_eabi.rs (94%) rename compiler/rustc_target/src/spec/{ => targets}/armv7a_none_eabihf.rs (92%) rename compiler/rustc_target/src/spec/{ => targets}/armv7k_apple_watchos.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/armv7r_none_eabi.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/armv7r_none_eabihf.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/armv7s_apple_ios.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/asmjs_unknown_emscripten.rs (71%) rename compiler/rustc_target/src/spec/{ => targets}/avr_unknown_gnu_atmega328.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/bpfeb_unknown_none.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/bpfel_unknown_none.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/csky_unknown_linux_gnuabiv2.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/csky_unknown_linux_gnuabiv2hf.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/hexagon_unknown_linux_musl.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/i386_apple_ios.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/i386_unknown_linux_gnu.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/i486_unknown_linux_gnu.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/i586_pc_nto_qnx700.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/i586_pc_windows_msvc.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/i586_unknown_linux_gnu.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/i586_unknown_linux_musl.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/i586_unknown_netbsd.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/i686_apple_darwin.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/i686_linux_android.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/i686_pc_windows_gnu.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/i686_pc_windows_gnullvm.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/i686_pc_windows_msvc.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/i686_unknown_freebsd.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/i686_unknown_haiku.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/i686_unknown_hurd_gnu.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/i686_unknown_linux_gnu.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/i686_unknown_linux_musl.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/i686_unknown_netbsd.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/i686_unknown_openbsd.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/i686_unknown_uefi.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/i686_uwp_windows_gnu.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/i686_uwp_windows_msvc.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/i686_wrs_vxworks.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/loongarch64_unknown_linux_gnu.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/loongarch64_unknown_none.rs (85%) rename compiler/rustc_target/src/spec/{ => targets}/loongarch64_unknown_none_softfloat.rs (86%) rename compiler/rustc_target/src/spec/{ => targets}/m68k_unknown_linux_gnu.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/mips64_openwrt_linux_musl.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/mips64_unknown_linux_gnuabi64.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/mips64_unknown_linux_muslabi64.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/mips64el_unknown_linux_gnuabi64.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/mips64el_unknown_linux_muslabi64.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/mips_unknown_linux_gnu.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/mips_unknown_linux_musl.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/mips_unknown_linux_uclibc.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/mipsel_sony_psp.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/mipsel_sony_psp_linker_script.ld (100%) rename compiler/rustc_target/src/spec/{ => targets}/mipsel_sony_psx.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/mipsel_unknown_linux_gnu.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/mipsel_unknown_linux_musl.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/mipsel_unknown_linux_uclibc.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/mipsel_unknown_netbsd.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/mipsel_unknown_none.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/mipsisa32r6_unknown_linux_gnu.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/mipsisa32r6el_unknown_linux_gnu.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/mipsisa64r6_unknown_linux_gnuabi64.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/mipsisa64r6el_unknown_linux_gnuabi64.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/msp430_none_elf.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/nvptx64_nvidia_cuda.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/powerpc64_ibm_aix.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/powerpc64_unknown_freebsd.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/powerpc64_unknown_linux_gnu.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/powerpc64_unknown_linux_musl.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/powerpc64_unknown_openbsd.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/powerpc64_wrs_vxworks.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/powerpc64le_unknown_freebsd.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/powerpc64le_unknown_linux_gnu.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/powerpc64le_unknown_linux_musl.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/powerpc_unknown_freebsd.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/powerpc_unknown_linux_gnu.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/powerpc_unknown_linux_gnuspe.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/powerpc_unknown_linux_musl.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/powerpc_unknown_netbsd.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/powerpc_unknown_openbsd.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/powerpc_wrs_vxworks.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/powerpc_wrs_vxworks_spe.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/riscv32gc_unknown_linux_gnu.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/riscv32gc_unknown_linux_musl.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/riscv32i_unknown_none_elf.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/riscv32im_unknown_none_elf.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/riscv32imac_esp_espidf.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/riscv32imac_unknown_none_elf.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/riscv32imac_unknown_xous_elf.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/riscv32imc_esp_espidf.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/riscv32imc_unknown_none_elf.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/riscv64_linux_android.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/riscv64gc_unknown_freebsd.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/riscv64gc_unknown_fuchsia.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/riscv64gc_unknown_hermit.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/riscv64gc_unknown_linux_gnu.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/riscv64gc_unknown_linux_musl.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/riscv64gc_unknown_netbsd.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/riscv64gc_unknown_none_elf.rs (96%) rename compiler/rustc_target/src/spec/{ => targets}/riscv64gc_unknown_openbsd.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/riscv64imac_unknown_none_elf.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/s390x_unknown_linux_gnu.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/s390x_unknown_linux_musl.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/sparc64_unknown_linux_gnu.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/sparc64_unknown_netbsd.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/sparc64_unknown_openbsd.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/sparc_unknown_linux_gnu.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/sparc_unknown_none_elf.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/sparcv9_sun_solaris.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/thumbv4t_none_eabi.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/thumbv5te_none_eabi.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/thumbv6m_none_eabi.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/thumbv7a_pc_windows_msvc.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/thumbv7a_uwp_windows_msvc.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/thumbv7em_none_eabi.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/thumbv7em_none_eabihf.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/thumbv7m_none_eabi.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/thumbv7neon_linux_androideabi.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/thumbv7neon_unknown_linux_gnueabihf.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/thumbv7neon_unknown_linux_musleabihf.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/thumbv8m_base_none_eabi.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/thumbv8m_main_none_eabi.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/thumbv8m_main_none_eabihf.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/wasm32_unknown_emscripten.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/wasm32_unknown_unknown.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/wasm32_wasi.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/wasm32_wasi_preview1_threads.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/wasm64_unknown_unknown.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/x86_64_apple_darwin.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/x86_64_apple_ios.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/x86_64_apple_ios_macabi.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/x86_64_apple_tvos.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/x86_64_apple_watchos_sim.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/x86_64_fortanix_unknown_sgx.rs (97%) create mode 100644 compiler/rustc_target/src/spec/targets/x86_64_fuchsia.rs rename compiler/rustc_target/src/spec/{ => targets}/x86_64_linux_android.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/x86_64_pc_nto_qnx710.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/x86_64_pc_solaris.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/x86_64_pc_windows_gnu.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/x86_64_pc_windows_gnullvm.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/x86_64_pc_windows_msvc.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/x86_64_sun_solaris.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/x86_64_unikraft_linux_musl.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/x86_64_unknown_dragonfly.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/x86_64_unknown_freebsd.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/x86_64_unknown_fuchsia.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/x86_64_unknown_haiku.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/x86_64_unknown_hermit.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/x86_64_unknown_illumos.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/x86_64_unknown_l4re_uclibc.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/x86_64_unknown_linux_gnu.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/x86_64_unknown_linux_gnux32.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/x86_64_unknown_linux_musl.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/x86_64_unknown_linux_ohos.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/x86_64_unknown_netbsd.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/x86_64_unknown_none.rs (89%) rename compiler/rustc_target/src/spec/{ => targets}/x86_64_unknown_openbsd.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/x86_64_unknown_redox.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/x86_64_unknown_uefi.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/x86_64_uwp_windows_gnu.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/x86_64_uwp_windows_msvc.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/x86_64_wrs_vxworks.rs (100%) rename compiler/rustc_target/src/spec/{ => targets}/x86_64h_apple_darwin.rs (100%) delete mode 100644 compiler/rustc_target/src/spec/x86_64_fuchsia.rs diff --git a/compiler/rustc_target/src/spec/aarch64_fuchsia.rs b/compiler/rustc_target/src/spec/aarch64_fuchsia.rs deleted file mode 100644 index ddecbb1a8c4a..000000000000 --- a/compiler/rustc_target/src/spec/aarch64_fuchsia.rs +++ /dev/null @@ -1 +0,0 @@ -pub use crate::spec::aarch64_unknown_fuchsia::target; diff --git a/compiler/rustc_target/src/spec/base/apple/tests.rs b/compiler/rustc_target/src/spec/base/apple/tests.rs index 3b23ddadcc47..f13058ebc82a 100644 --- a/compiler/rustc_target/src/spec/base/apple/tests.rs +++ b/compiler/rustc_target/src/spec/base/apple/tests.rs @@ -1,4 +1,4 @@ -use crate::spec::{ +use crate::spec::targets::{ aarch64_apple_darwin, aarch64_apple_ios_sim, aarch64_apple_watchos_sim, i686_apple_darwin, x86_64_apple_darwin, x86_64_apple_ios, x86_64_apple_tvos, x86_64_apple_watchos_sim, }; diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index f569584c20b6..f04799482c83 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1408,14 +1408,16 @@ impl fmt::Display for StackProtector { macro_rules! supported_targets { ( $(($triple:literal, $module:ident),)+ ) => { - $(mod $module;)+ + mod targets { + $(pub(crate) mod $module;)+ + } /// List of supported targets pub const TARGETS: &[&str] = &[$($triple),+]; fn load_builtin(target: &str) -> Option { let mut t = match target { - $( $triple => $module::target(), )+ + $( $triple => targets::$module::target(), )+ _ => return None, }; t.is_builtin = true; @@ -1431,7 +1433,7 @@ macro_rules! supported_targets { $( #[test] // `#[test]` fn $module() { - tests_impl::test_target(super::$module::target()); + tests_impl::test_target(crate::spec::targets::$module::target()); } )+ } diff --git a/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs similarity index 100% rename from compiler/rustc_target/src/spec/aarch64_apple_darwin.rs rename to compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs diff --git a/compiler/rustc_target/src/spec/aarch64_apple_ios.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs similarity index 100% rename from compiler/rustc_target/src/spec/aarch64_apple_ios.rs rename to compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs diff --git a/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs similarity index 100% rename from compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs rename to compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs diff --git a/compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs similarity index 100% rename from compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs rename to compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs diff --git a/compiler/rustc_target/src/spec/aarch64_apple_tvos.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs similarity index 100% rename from compiler/rustc_target/src/spec/aarch64_apple_tvos.rs rename to compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs diff --git a/compiler/rustc_target/src/spec/aarch64_apple_tvos_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs similarity index 100% rename from compiler/rustc_target/src/spec/aarch64_apple_tvos_sim.rs rename to compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs diff --git a/compiler/rustc_target/src/spec/aarch64_apple_watchos_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs similarity index 100% rename from compiler/rustc_target/src/spec/aarch64_apple_watchos_sim.rs rename to compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs diff --git a/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu.rs similarity index 100% rename from compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu.rs rename to compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu.rs diff --git a/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu_ilp32.rs b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu_ilp32.rs similarity index 100% rename from compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu_ilp32.rs rename to compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu_ilp32.rs diff --git a/compiler/rustc_target/src/spec/aarch64_be_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_netbsd.rs similarity index 100% rename from compiler/rustc_target/src/spec/aarch64_be_unknown_netbsd.rs rename to compiler/rustc_target/src/spec/targets/aarch64_be_unknown_netbsd.rs diff --git a/compiler/rustc_target/src/spec/targets/aarch64_fuchsia.rs b/compiler/rustc_target/src/spec/targets/aarch64_fuchsia.rs new file mode 100644 index 000000000000..3668db912bb8 --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/aarch64_fuchsia.rs @@ -0,0 +1 @@ +pub use crate::spec::targets::aarch64_unknown_fuchsia::target; diff --git a/compiler/rustc_target/src/spec/aarch64_kmc_solid_asp3.rs b/compiler/rustc_target/src/spec/targets/aarch64_kmc_solid_asp3.rs similarity index 90% rename from compiler/rustc_target/src/spec/aarch64_kmc_solid_asp3.rs rename to compiler/rustc_target/src/spec/targets/aarch64_kmc_solid_asp3.rs index f72a6c1056f2..e5e22fd1ee28 100644 --- a/compiler/rustc_target/src/spec/aarch64_kmc_solid_asp3.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_kmc_solid_asp3.rs @@ -1,4 +1,4 @@ -use super::{base, RelocModel, Target, TargetOptions}; +use crate::spec::{base, RelocModel, Target, TargetOptions}; pub fn target() -> Target { let base = base::solid::opts("asp3"); diff --git a/compiler/rustc_target/src/spec/aarch64_linux_android.rs b/compiler/rustc_target/src/spec/targets/aarch64_linux_android.rs similarity index 100% rename from compiler/rustc_target/src/spec/aarch64_linux_android.rs rename to compiler/rustc_target/src/spec/targets/aarch64_linux_android.rs diff --git a/compiler/rustc_target/src/spec/aarch64_nintendo_switch_freestanding.rs b/compiler/rustc_target/src/spec/targets/aarch64_nintendo_switch_freestanding.rs similarity index 91% rename from compiler/rustc_target/src/spec/aarch64_nintendo_switch_freestanding.rs rename to compiler/rustc_target/src/spec/targets/aarch64_nintendo_switch_freestanding.rs index e271bdc8a015..02fcc2bb43e9 100644 --- a/compiler/rustc_target/src/spec/aarch64_nintendo_switch_freestanding.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_nintendo_switch_freestanding.rs @@ -1,4 +1,4 @@ -use super::{Cc, LinkerFlavor, Lld, PanicStrategy, RelroLevel, Target, TargetOptions}; +use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelroLevel, Target, TargetOptions}; const LINKER_SCRIPT: &str = include_str!("./aarch64_nintendo_switch_freestanding_linker_script.ld"); diff --git a/compiler/rustc_target/src/spec/aarch64_nintendo_switch_freestanding_linker_script.ld b/compiler/rustc_target/src/spec/targets/aarch64_nintendo_switch_freestanding_linker_script.ld similarity index 100% rename from compiler/rustc_target/src/spec/aarch64_nintendo_switch_freestanding_linker_script.ld rename to compiler/rustc_target/src/spec/targets/aarch64_nintendo_switch_freestanding_linker_script.ld diff --git a/compiler/rustc_target/src/spec/aarch64_pc_windows_gnullvm.rs b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_gnullvm.rs similarity index 100% rename from compiler/rustc_target/src/spec/aarch64_pc_windows_gnullvm.rs rename to compiler/rustc_target/src/spec/targets/aarch64_pc_windows_gnullvm.rs diff --git a/compiler/rustc_target/src/spec/aarch64_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs similarity index 100% rename from compiler/rustc_target/src/spec/aarch64_pc_windows_msvc.rs rename to compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_freebsd.rs similarity index 100% rename from compiler/rustc_target/src/spec/aarch64_unknown_freebsd.rs rename to compiler/rustc_target/src/spec/targets/aarch64_unknown_freebsd.rs diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_fuchsia.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_fuchsia.rs similarity index 100% rename from compiler/rustc_target/src/spec/aarch64_unknown_fuchsia.rs rename to compiler/rustc_target/src/spec/targets/aarch64_unknown_fuchsia.rs diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_hermit.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_hermit.rs similarity index 100% rename from compiler/rustc_target/src/spec/aarch64_unknown_hermit.rs rename to compiler/rustc_target/src/spec/targets/aarch64_unknown_hermit.rs diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu.rs similarity index 100% rename from compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs rename to compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu.rs diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu_ilp32.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu_ilp32.rs similarity index 100% rename from compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu_ilp32.rs rename to compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu_ilp32.rs diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_musl.rs similarity index 100% rename from compiler/rustc_target/src/spec/aarch64_unknown_linux_musl.rs rename to compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_musl.rs diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_linux_ohos.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_ohos.rs similarity index 96% rename from compiler/rustc_target/src/spec/aarch64_unknown_linux_ohos.rs rename to compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_ohos.rs index 3698693a54aa..5f3bef63aa65 100644 --- a/compiler/rustc_target/src/spec/aarch64_unknown_linux_ohos.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_ohos.rs @@ -1,7 +1,6 @@ +use crate::spec::SanitizerSet; use crate::spec::{base, Target, TargetOptions}; -use super::SanitizerSet; - pub fn target() -> Target { let mut base = base::linux_ohos::opts(); base.max_atomic_width = Some(128); diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_netbsd.rs similarity index 100% rename from compiler/rustc_target/src/spec/aarch64_unknown_netbsd.rs rename to compiler/rustc_target/src/spec/targets/aarch64_unknown_netbsd.rs diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_none.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_none.rs similarity index 98% rename from compiler/rustc_target/src/spec/aarch64_unknown_none.rs rename to compiler/rustc_target/src/spec/targets/aarch64_unknown_none.rs index be27302f7f52..88fa6d5a762f 100644 --- a/compiler/rustc_target/src/spec/aarch64_unknown_none.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_none.rs @@ -6,7 +6,7 @@ // // For example, `-C target-cpu=cortex-a53`. -use super::{ +use crate::spec::{ Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, SanitizerSet, Target, TargetOptions, }; diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_none_softfloat.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_none_softfloat.rs similarity index 91% rename from compiler/rustc_target/src/spec/aarch64_unknown_none_softfloat.rs rename to compiler/rustc_target/src/spec/targets/aarch64_unknown_none_softfloat.rs index 9dfa1f268ac5..48b79b0b9bac 100644 --- a/compiler/rustc_target/src/spec/aarch64_unknown_none_softfloat.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_none_softfloat.rs @@ -6,7 +6,7 @@ // // For example, `-C target-cpu=cortex-a53`. -use super::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions}; +use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions}; pub fn target() -> Target { let opts = TargetOptions { diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_nto_qnx_710.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx_710.rs similarity index 100% rename from compiler/rustc_target/src/spec/aarch64_unknown_nto_qnx_710.rs rename to compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx_710.rs diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_openbsd.rs similarity index 100% rename from compiler/rustc_target/src/spec/aarch64_unknown_openbsd.rs rename to compiler/rustc_target/src/spec/targets/aarch64_unknown_openbsd.rs diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_redox.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_redox.rs similarity index 100% rename from compiler/rustc_target/src/spec/aarch64_unknown_redox.rs rename to compiler/rustc_target/src/spec/targets/aarch64_unknown_redox.rs diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_teeos.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_teeos.rs similarity index 100% rename from compiler/rustc_target/src/spec/aarch64_unknown_teeos.rs rename to compiler/rustc_target/src/spec/targets/aarch64_unknown_teeos.rs diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_uefi.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_uefi.rs similarity index 100% rename from compiler/rustc_target/src/spec/aarch64_unknown_uefi.rs rename to compiler/rustc_target/src/spec/targets/aarch64_unknown_uefi.rs diff --git a/compiler/rustc_target/src/spec/aarch64_uwp_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/aarch64_uwp_windows_msvc.rs similarity index 100% rename from compiler/rustc_target/src/spec/aarch64_uwp_windows_msvc.rs rename to compiler/rustc_target/src/spec/targets/aarch64_uwp_windows_msvc.rs diff --git a/compiler/rustc_target/src/spec/aarch64_wrs_vxworks.rs b/compiler/rustc_target/src/spec/targets/aarch64_wrs_vxworks.rs similarity index 100% rename from compiler/rustc_target/src/spec/aarch64_wrs_vxworks.rs rename to compiler/rustc_target/src/spec/targets/aarch64_wrs_vxworks.rs diff --git a/compiler/rustc_target/src/spec/arm64_32_apple_watchos.rs b/compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs similarity index 100% rename from compiler/rustc_target/src/spec/arm64_32_apple_watchos.rs rename to compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs diff --git a/compiler/rustc_target/src/spec/arm_linux_androideabi.rs b/compiler/rustc_target/src/spec/targets/arm_linux_androideabi.rs similarity index 100% rename from compiler/rustc_target/src/spec/arm_linux_androideabi.rs rename to compiler/rustc_target/src/spec/targets/arm_linux_androideabi.rs diff --git a/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/targets/arm_unknown_linux_gnueabi.rs similarity index 100% rename from compiler/rustc_target/src/spec/arm_unknown_linux_gnueabi.rs rename to compiler/rustc_target/src/spec/targets/arm_unknown_linux_gnueabi.rs diff --git a/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabihf.rs b/compiler/rustc_target/src/spec/targets/arm_unknown_linux_gnueabihf.rs similarity index 100% rename from compiler/rustc_target/src/spec/arm_unknown_linux_gnueabihf.rs rename to compiler/rustc_target/src/spec/targets/arm_unknown_linux_gnueabihf.rs diff --git a/compiler/rustc_target/src/spec/arm_unknown_linux_musleabi.rs b/compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabi.rs similarity index 100% rename from compiler/rustc_target/src/spec/arm_unknown_linux_musleabi.rs rename to compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabi.rs diff --git a/compiler/rustc_target/src/spec/arm_unknown_linux_musleabihf.rs b/compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabihf.rs similarity index 100% rename from compiler/rustc_target/src/spec/arm_unknown_linux_musleabihf.rs rename to compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabihf.rs diff --git a/compiler/rustc_target/src/spec/armeb_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/targets/armeb_unknown_linux_gnueabi.rs similarity index 100% rename from compiler/rustc_target/src/spec/armeb_unknown_linux_gnueabi.rs rename to compiler/rustc_target/src/spec/targets/armeb_unknown_linux_gnueabi.rs diff --git a/compiler/rustc_target/src/spec/armebv7r_none_eabi.rs b/compiler/rustc_target/src/spec/targets/armebv7r_none_eabi.rs similarity index 100% rename from compiler/rustc_target/src/spec/armebv7r_none_eabi.rs rename to compiler/rustc_target/src/spec/targets/armebv7r_none_eabi.rs diff --git a/compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs b/compiler/rustc_target/src/spec/targets/armebv7r_none_eabihf.rs similarity index 100% rename from compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs rename to compiler/rustc_target/src/spec/targets/armebv7r_none_eabihf.rs diff --git a/compiler/rustc_target/src/spec/armv4t_none_eabi.rs b/compiler/rustc_target/src/spec/targets/armv4t_none_eabi.rs similarity index 100% rename from compiler/rustc_target/src/spec/armv4t_none_eabi.rs rename to compiler/rustc_target/src/spec/targets/armv4t_none_eabi.rs diff --git a/compiler/rustc_target/src/spec/armv4t_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/targets/armv4t_unknown_linux_gnueabi.rs similarity index 100% rename from compiler/rustc_target/src/spec/armv4t_unknown_linux_gnueabi.rs rename to compiler/rustc_target/src/spec/targets/armv4t_unknown_linux_gnueabi.rs diff --git a/compiler/rustc_target/src/spec/armv5te_none_eabi.rs b/compiler/rustc_target/src/spec/targets/armv5te_none_eabi.rs similarity index 100% rename from compiler/rustc_target/src/spec/armv5te_none_eabi.rs rename to compiler/rustc_target/src/spec/targets/armv5te_none_eabi.rs diff --git a/compiler/rustc_target/src/spec/armv5te_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_gnueabi.rs similarity index 100% rename from compiler/rustc_target/src/spec/armv5te_unknown_linux_gnueabi.rs rename to compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_gnueabi.rs diff --git a/compiler/rustc_target/src/spec/armv5te_unknown_linux_musleabi.rs b/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_musleabi.rs similarity index 100% rename from compiler/rustc_target/src/spec/armv5te_unknown_linux_musleabi.rs rename to compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_musleabi.rs diff --git a/compiler/rustc_target/src/spec/armv5te_unknown_linux_uclibceabi.rs b/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_uclibceabi.rs similarity index 100% rename from compiler/rustc_target/src/spec/armv5te_unknown_linux_uclibceabi.rs rename to compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_uclibceabi.rs diff --git a/compiler/rustc_target/src/spec/armv6_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/armv6_unknown_freebsd.rs similarity index 100% rename from compiler/rustc_target/src/spec/armv6_unknown_freebsd.rs rename to compiler/rustc_target/src/spec/targets/armv6_unknown_freebsd.rs diff --git a/compiler/rustc_target/src/spec/armv6_unknown_netbsd_eabihf.rs b/compiler/rustc_target/src/spec/targets/armv6_unknown_netbsd_eabihf.rs similarity index 100% rename from compiler/rustc_target/src/spec/armv6_unknown_netbsd_eabihf.rs rename to compiler/rustc_target/src/spec/targets/armv6_unknown_netbsd_eabihf.rs diff --git a/compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs b/compiler/rustc_target/src/spec/targets/armv6k_nintendo_3ds.rs similarity index 100% rename from compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs rename to compiler/rustc_target/src/spec/targets/armv6k_nintendo_3ds.rs diff --git a/compiler/rustc_target/src/spec/armv7_linux_androideabi.rs b/compiler/rustc_target/src/spec/targets/armv7_linux_androideabi.rs similarity index 100% rename from compiler/rustc_target/src/spec/armv7_linux_androideabi.rs rename to compiler/rustc_target/src/spec/targets/armv7_linux_androideabi.rs diff --git a/compiler/rustc_target/src/spec/armv7_sony_vita_newlibeabihf.rs b/compiler/rustc_target/src/spec/targets/armv7_sony_vita_newlibeabihf.rs similarity index 100% rename from compiler/rustc_target/src/spec/armv7_sony_vita_newlibeabihf.rs rename to compiler/rustc_target/src/spec/targets/armv7_sony_vita_newlibeabihf.rs diff --git a/compiler/rustc_target/src/spec/armv7_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_freebsd.rs similarity index 100% rename from compiler/rustc_target/src/spec/armv7_unknown_freebsd.rs rename to compiler/rustc_target/src/spec/targets/armv7_unknown_freebsd.rs diff --git a/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_gnueabi.rs similarity index 100% rename from compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabi.rs rename to compiler/rustc_target/src/spec/targets/armv7_unknown_linux_gnueabi.rs diff --git a/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabihf.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_gnueabihf.rs similarity index 100% rename from compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabihf.rs rename to compiler/rustc_target/src/spec/targets/armv7_unknown_linux_gnueabihf.rs diff --git a/compiler/rustc_target/src/spec/armv7_unknown_linux_musleabi.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabi.rs similarity index 100% rename from compiler/rustc_target/src/spec/armv7_unknown_linux_musleabi.rs rename to compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabi.rs diff --git a/compiler/rustc_target/src/spec/armv7_unknown_linux_musleabihf.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabihf.rs similarity index 100% rename from compiler/rustc_target/src/spec/armv7_unknown_linux_musleabihf.rs rename to compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabihf.rs diff --git a/compiler/rustc_target/src/spec/armv7_unknown_linux_ohos.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_ohos.rs similarity index 100% rename from compiler/rustc_target/src/spec/armv7_unknown_linux_ohos.rs rename to compiler/rustc_target/src/spec/targets/armv7_unknown_linux_ohos.rs diff --git a/compiler/rustc_target/src/spec/armv7_unknown_linux_uclibceabi.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_uclibceabi.rs similarity index 100% rename from compiler/rustc_target/src/spec/armv7_unknown_linux_uclibceabi.rs rename to compiler/rustc_target/src/spec/targets/armv7_unknown_linux_uclibceabi.rs diff --git a/compiler/rustc_target/src/spec/armv7_unknown_linux_uclibceabihf.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_uclibceabihf.rs similarity index 100% rename from compiler/rustc_target/src/spec/armv7_unknown_linux_uclibceabihf.rs rename to compiler/rustc_target/src/spec/targets/armv7_unknown_linux_uclibceabihf.rs diff --git a/compiler/rustc_target/src/spec/armv7_unknown_netbsd_eabihf.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_netbsd_eabihf.rs similarity index 100% rename from compiler/rustc_target/src/spec/armv7_unknown_netbsd_eabihf.rs rename to compiler/rustc_target/src/spec/targets/armv7_unknown_netbsd_eabihf.rs diff --git a/compiler/rustc_target/src/spec/armv7_wrs_vxworks_eabihf.rs b/compiler/rustc_target/src/spec/targets/armv7_wrs_vxworks_eabihf.rs similarity index 100% rename from compiler/rustc_target/src/spec/armv7_wrs_vxworks_eabihf.rs rename to compiler/rustc_target/src/spec/targets/armv7_wrs_vxworks_eabihf.rs diff --git a/compiler/rustc_target/src/spec/armv7a_kmc_solid_asp3_eabi.rs b/compiler/rustc_target/src/spec/targets/armv7a_kmc_solid_asp3_eabi.rs similarity index 90% rename from compiler/rustc_target/src/spec/armv7a_kmc_solid_asp3_eabi.rs rename to compiler/rustc_target/src/spec/targets/armv7a_kmc_solid_asp3_eabi.rs index 68c6aa9efc67..57d40d54c449 100644 --- a/compiler/rustc_target/src/spec/armv7a_kmc_solid_asp3_eabi.rs +++ b/compiler/rustc_target/src/spec/targets/armv7a_kmc_solid_asp3_eabi.rs @@ -1,4 +1,4 @@ -use super::{base, RelocModel, Target, TargetOptions}; +use crate::spec::{base, RelocModel, Target, TargetOptions}; pub fn target() -> Target { let base = base::solid::opts("asp3"); diff --git a/compiler/rustc_target/src/spec/armv7a_kmc_solid_asp3_eabihf.rs b/compiler/rustc_target/src/spec/targets/armv7a_kmc_solid_asp3_eabihf.rs similarity index 90% rename from compiler/rustc_target/src/spec/armv7a_kmc_solid_asp3_eabihf.rs rename to compiler/rustc_target/src/spec/targets/armv7a_kmc_solid_asp3_eabihf.rs index 04e45699cfc4..3d21213c5ff8 100644 --- a/compiler/rustc_target/src/spec/armv7a_kmc_solid_asp3_eabihf.rs +++ b/compiler/rustc_target/src/spec/targets/armv7a_kmc_solid_asp3_eabihf.rs @@ -1,4 +1,4 @@ -use super::{base, RelocModel, Target, TargetOptions}; +use crate::spec::{base, RelocModel, Target, TargetOptions}; pub fn target() -> Target { let base = base::solid::opts("asp3"); diff --git a/compiler/rustc_target/src/spec/armv7a_none_eabi.rs b/compiler/rustc_target/src/spec/targets/armv7a_none_eabi.rs similarity index 94% rename from compiler/rustc_target/src/spec/armv7a_none_eabi.rs rename to compiler/rustc_target/src/spec/targets/armv7a_none_eabi.rs index d59de86a2301..c5b61427e698 100644 --- a/compiler/rustc_target/src/spec/armv7a_none_eabi.rs +++ b/compiler/rustc_target/src/spec/targets/armv7a_none_eabi.rs @@ -14,7 +14,7 @@ // - `relocation-model` set to `static`; also no PIE, no relro and no dynamic // linking. rationale: matches `thumb` targets -use super::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions}; +use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions}; pub fn target() -> Target { let opts = TargetOptions { diff --git a/compiler/rustc_target/src/spec/armv7a_none_eabihf.rs b/compiler/rustc_target/src/spec/targets/armv7a_none_eabihf.rs similarity index 92% rename from compiler/rustc_target/src/spec/armv7a_none_eabihf.rs rename to compiler/rustc_target/src/spec/targets/armv7a_none_eabihf.rs index c134f3e09078..ba3caad6a972 100644 --- a/compiler/rustc_target/src/spec/armv7a_none_eabihf.rs +++ b/compiler/rustc_target/src/spec/targets/armv7a_none_eabihf.rs @@ -5,7 +5,7 @@ // changes (list in `armv7a_none_eabi.rs`) to bring it closer to the bare-metal // `thumb` & `aarch64` targets. -use super::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions}; +use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions}; pub fn target() -> Target { let opts = TargetOptions { diff --git a/compiler/rustc_target/src/spec/armv7k_apple_watchos.rs b/compiler/rustc_target/src/spec/targets/armv7k_apple_watchos.rs similarity index 100% rename from compiler/rustc_target/src/spec/armv7k_apple_watchos.rs rename to compiler/rustc_target/src/spec/targets/armv7k_apple_watchos.rs diff --git a/compiler/rustc_target/src/spec/armv7r_none_eabi.rs b/compiler/rustc_target/src/spec/targets/armv7r_none_eabi.rs similarity index 100% rename from compiler/rustc_target/src/spec/armv7r_none_eabi.rs rename to compiler/rustc_target/src/spec/targets/armv7r_none_eabi.rs diff --git a/compiler/rustc_target/src/spec/armv7r_none_eabihf.rs b/compiler/rustc_target/src/spec/targets/armv7r_none_eabihf.rs similarity index 100% rename from compiler/rustc_target/src/spec/armv7r_none_eabihf.rs rename to compiler/rustc_target/src/spec/targets/armv7r_none_eabihf.rs diff --git a/compiler/rustc_target/src/spec/armv7s_apple_ios.rs b/compiler/rustc_target/src/spec/targets/armv7s_apple_ios.rs similarity index 100% rename from compiler/rustc_target/src/spec/armv7s_apple_ios.rs rename to compiler/rustc_target/src/spec/targets/armv7s_apple_ios.rs diff --git a/compiler/rustc_target/src/spec/asmjs_unknown_emscripten.rs b/compiler/rustc_target/src/spec/targets/asmjs_unknown_emscripten.rs similarity index 71% rename from compiler/rustc_target/src/spec/asmjs_unknown_emscripten.rs rename to compiler/rustc_target/src/spec/targets/asmjs_unknown_emscripten.rs index f492c3451a41..e4768c67af55 100644 --- a/compiler/rustc_target/src/spec/asmjs_unknown_emscripten.rs +++ b/compiler/rustc_target/src/spec/targets/asmjs_unknown_emscripten.rs @@ -1,4 +1,4 @@ -use super::{wasm32_unknown_emscripten, LinkerFlavor, Target}; +use crate::spec::{targets::wasm32_unknown_emscripten, LinkerFlavor, Target}; pub fn target() -> Target { let mut target = wasm32_unknown_emscripten::target(); diff --git a/compiler/rustc_target/src/spec/avr_unknown_gnu_atmega328.rs b/compiler/rustc_target/src/spec/targets/avr_unknown_gnu_atmega328.rs similarity index 100% rename from compiler/rustc_target/src/spec/avr_unknown_gnu_atmega328.rs rename to compiler/rustc_target/src/spec/targets/avr_unknown_gnu_atmega328.rs diff --git a/compiler/rustc_target/src/spec/bpfeb_unknown_none.rs b/compiler/rustc_target/src/spec/targets/bpfeb_unknown_none.rs similarity index 100% rename from compiler/rustc_target/src/spec/bpfeb_unknown_none.rs rename to compiler/rustc_target/src/spec/targets/bpfeb_unknown_none.rs diff --git a/compiler/rustc_target/src/spec/bpfel_unknown_none.rs b/compiler/rustc_target/src/spec/targets/bpfel_unknown_none.rs similarity index 100% rename from compiler/rustc_target/src/spec/bpfel_unknown_none.rs rename to compiler/rustc_target/src/spec/targets/bpfel_unknown_none.rs diff --git a/compiler/rustc_target/src/spec/csky_unknown_linux_gnuabiv2.rs b/compiler/rustc_target/src/spec/targets/csky_unknown_linux_gnuabiv2.rs similarity index 100% rename from compiler/rustc_target/src/spec/csky_unknown_linux_gnuabiv2.rs rename to compiler/rustc_target/src/spec/targets/csky_unknown_linux_gnuabiv2.rs diff --git a/compiler/rustc_target/src/spec/csky_unknown_linux_gnuabiv2hf.rs b/compiler/rustc_target/src/spec/targets/csky_unknown_linux_gnuabiv2hf.rs similarity index 100% rename from compiler/rustc_target/src/spec/csky_unknown_linux_gnuabiv2hf.rs rename to compiler/rustc_target/src/spec/targets/csky_unknown_linux_gnuabiv2hf.rs diff --git a/compiler/rustc_target/src/spec/hexagon_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/hexagon_unknown_linux_musl.rs similarity index 100% rename from compiler/rustc_target/src/spec/hexagon_unknown_linux_musl.rs rename to compiler/rustc_target/src/spec/targets/hexagon_unknown_linux_musl.rs diff --git a/compiler/rustc_target/src/spec/i386_apple_ios.rs b/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs similarity index 100% rename from compiler/rustc_target/src/spec/i386_apple_ios.rs rename to compiler/rustc_target/src/spec/targets/i386_apple_ios.rs diff --git a/compiler/rustc_target/src/spec/i386_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/i386_unknown_linux_gnu.rs similarity index 100% rename from compiler/rustc_target/src/spec/i386_unknown_linux_gnu.rs rename to compiler/rustc_target/src/spec/targets/i386_unknown_linux_gnu.rs diff --git a/compiler/rustc_target/src/spec/i486_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/i486_unknown_linux_gnu.rs similarity index 100% rename from compiler/rustc_target/src/spec/i486_unknown_linux_gnu.rs rename to compiler/rustc_target/src/spec/targets/i486_unknown_linux_gnu.rs diff --git a/compiler/rustc_target/src/spec/i586_pc_nto_qnx700.rs b/compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs similarity index 100% rename from compiler/rustc_target/src/spec/i586_pc_nto_qnx700.rs rename to compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs diff --git a/compiler/rustc_target/src/spec/i586_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/i586_pc_windows_msvc.rs similarity index 100% rename from compiler/rustc_target/src/spec/i586_pc_windows_msvc.rs rename to compiler/rustc_target/src/spec/targets/i586_pc_windows_msvc.rs diff --git a/compiler/rustc_target/src/spec/i586_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/i586_unknown_linux_gnu.rs similarity index 100% rename from compiler/rustc_target/src/spec/i586_unknown_linux_gnu.rs rename to compiler/rustc_target/src/spec/targets/i586_unknown_linux_gnu.rs diff --git a/compiler/rustc_target/src/spec/i586_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/i586_unknown_linux_musl.rs similarity index 100% rename from compiler/rustc_target/src/spec/i586_unknown_linux_musl.rs rename to compiler/rustc_target/src/spec/targets/i586_unknown_linux_musl.rs diff --git a/compiler/rustc_target/src/spec/i586_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/i586_unknown_netbsd.rs similarity index 100% rename from compiler/rustc_target/src/spec/i586_unknown_netbsd.rs rename to compiler/rustc_target/src/spec/targets/i586_unknown_netbsd.rs diff --git a/compiler/rustc_target/src/spec/i686_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs similarity index 100% rename from compiler/rustc_target/src/spec/i686_apple_darwin.rs rename to compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs diff --git a/compiler/rustc_target/src/spec/i686_linux_android.rs b/compiler/rustc_target/src/spec/targets/i686_linux_android.rs similarity index 100% rename from compiler/rustc_target/src/spec/i686_linux_android.rs rename to compiler/rustc_target/src/spec/targets/i686_linux_android.rs diff --git a/compiler/rustc_target/src/spec/i686_pc_windows_gnu.rs b/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnu.rs similarity index 100% rename from compiler/rustc_target/src/spec/i686_pc_windows_gnu.rs rename to compiler/rustc_target/src/spec/targets/i686_pc_windows_gnu.rs diff --git a/compiler/rustc_target/src/spec/i686_pc_windows_gnullvm.rs b/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnullvm.rs similarity index 100% rename from compiler/rustc_target/src/spec/i686_pc_windows_gnullvm.rs rename to compiler/rustc_target/src/spec/targets/i686_pc_windows_gnullvm.rs diff --git a/compiler/rustc_target/src/spec/i686_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs similarity index 100% rename from compiler/rustc_target/src/spec/i686_pc_windows_msvc.rs rename to compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs diff --git a/compiler/rustc_target/src/spec/i686_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_freebsd.rs similarity index 100% rename from compiler/rustc_target/src/spec/i686_unknown_freebsd.rs rename to compiler/rustc_target/src/spec/targets/i686_unknown_freebsd.rs diff --git a/compiler/rustc_target/src/spec/i686_unknown_haiku.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_haiku.rs similarity index 100% rename from compiler/rustc_target/src/spec/i686_unknown_haiku.rs rename to compiler/rustc_target/src/spec/targets/i686_unknown_haiku.rs diff --git a/compiler/rustc_target/src/spec/i686_unknown_hurd_gnu.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_hurd_gnu.rs similarity index 100% rename from compiler/rustc_target/src/spec/i686_unknown_hurd_gnu.rs rename to compiler/rustc_target/src/spec/targets/i686_unknown_hurd_gnu.rs diff --git a/compiler/rustc_target/src/spec/i686_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_linux_gnu.rs similarity index 100% rename from compiler/rustc_target/src/spec/i686_unknown_linux_gnu.rs rename to compiler/rustc_target/src/spec/targets/i686_unknown_linux_gnu.rs diff --git a/compiler/rustc_target/src/spec/i686_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_linux_musl.rs similarity index 100% rename from compiler/rustc_target/src/spec/i686_unknown_linux_musl.rs rename to compiler/rustc_target/src/spec/targets/i686_unknown_linux_musl.rs diff --git a/compiler/rustc_target/src/spec/i686_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_netbsd.rs similarity index 100% rename from compiler/rustc_target/src/spec/i686_unknown_netbsd.rs rename to compiler/rustc_target/src/spec/targets/i686_unknown_netbsd.rs diff --git a/compiler/rustc_target/src/spec/i686_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_openbsd.rs similarity index 100% rename from compiler/rustc_target/src/spec/i686_unknown_openbsd.rs rename to compiler/rustc_target/src/spec/targets/i686_unknown_openbsd.rs diff --git a/compiler/rustc_target/src/spec/i686_unknown_uefi.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_uefi.rs similarity index 100% rename from compiler/rustc_target/src/spec/i686_unknown_uefi.rs rename to compiler/rustc_target/src/spec/targets/i686_unknown_uefi.rs diff --git a/compiler/rustc_target/src/spec/i686_uwp_windows_gnu.rs b/compiler/rustc_target/src/spec/targets/i686_uwp_windows_gnu.rs similarity index 100% rename from compiler/rustc_target/src/spec/i686_uwp_windows_gnu.rs rename to compiler/rustc_target/src/spec/targets/i686_uwp_windows_gnu.rs diff --git a/compiler/rustc_target/src/spec/i686_uwp_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/i686_uwp_windows_msvc.rs similarity index 100% rename from compiler/rustc_target/src/spec/i686_uwp_windows_msvc.rs rename to compiler/rustc_target/src/spec/targets/i686_uwp_windows_msvc.rs diff --git a/compiler/rustc_target/src/spec/i686_wrs_vxworks.rs b/compiler/rustc_target/src/spec/targets/i686_wrs_vxworks.rs similarity index 100% rename from compiler/rustc_target/src/spec/i686_wrs_vxworks.rs rename to compiler/rustc_target/src/spec/targets/i686_wrs_vxworks.rs diff --git a/compiler/rustc_target/src/spec/loongarch64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_gnu.rs similarity index 100% rename from compiler/rustc_target/src/spec/loongarch64_unknown_linux_gnu.rs rename to compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_gnu.rs diff --git a/compiler/rustc_target/src/spec/loongarch64_unknown_none.rs b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none.rs similarity index 85% rename from compiler/rustc_target/src/spec/loongarch64_unknown_none.rs rename to compiler/rustc_target/src/spec/targets/loongarch64_unknown_none.rs index dbc96d68eae1..3b1ea8e206f1 100644 --- a/compiler/rustc_target/src/spec/loongarch64_unknown_none.rs +++ b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none.rs @@ -1,5 +1,5 @@ -use super::{Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy, RelocModel}; -use super::{Target, TargetOptions}; +use crate::spec::{Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy, RelocModel}; +use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { Target { diff --git a/compiler/rustc_target/src/spec/loongarch64_unknown_none_softfloat.rs b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none_softfloat.rs similarity index 86% rename from compiler/rustc_target/src/spec/loongarch64_unknown_none_softfloat.rs rename to compiler/rustc_target/src/spec/targets/loongarch64_unknown_none_softfloat.rs index c4d5c7bc44cc..ab9300ef9c72 100644 --- a/compiler/rustc_target/src/spec/loongarch64_unknown_none_softfloat.rs +++ b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none_softfloat.rs @@ -1,5 +1,5 @@ -use super::{Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy, RelocModel}; -use super::{Target, TargetOptions}; +use crate::spec::{Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy, RelocModel}; +use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { Target { diff --git a/compiler/rustc_target/src/spec/m68k_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/m68k_unknown_linux_gnu.rs similarity index 100% rename from compiler/rustc_target/src/spec/m68k_unknown_linux_gnu.rs rename to compiler/rustc_target/src/spec/targets/m68k_unknown_linux_gnu.rs diff --git a/compiler/rustc_target/src/spec/mips64_openwrt_linux_musl.rs b/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs similarity index 100% rename from compiler/rustc_target/src/spec/mips64_openwrt_linux_musl.rs rename to compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs diff --git a/compiler/rustc_target/src/spec/mips64_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_gnuabi64.rs similarity index 100% rename from compiler/rustc_target/src/spec/mips64_unknown_linux_gnuabi64.rs rename to compiler/rustc_target/src/spec/targets/mips64_unknown_linux_gnuabi64.rs diff --git a/compiler/rustc_target/src/spec/mips64_unknown_linux_muslabi64.rs b/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_muslabi64.rs similarity index 100% rename from compiler/rustc_target/src/spec/mips64_unknown_linux_muslabi64.rs rename to compiler/rustc_target/src/spec/targets/mips64_unknown_linux_muslabi64.rs diff --git a/compiler/rustc_target/src/spec/mips64el_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_gnuabi64.rs similarity index 100% rename from compiler/rustc_target/src/spec/mips64el_unknown_linux_gnuabi64.rs rename to compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_gnuabi64.rs diff --git a/compiler/rustc_target/src/spec/mips64el_unknown_linux_muslabi64.rs b/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_muslabi64.rs similarity index 100% rename from compiler/rustc_target/src/spec/mips64el_unknown_linux_muslabi64.rs rename to compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_muslabi64.rs diff --git a/compiler/rustc_target/src/spec/mips_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/mips_unknown_linux_gnu.rs similarity index 100% rename from compiler/rustc_target/src/spec/mips_unknown_linux_gnu.rs rename to compiler/rustc_target/src/spec/targets/mips_unknown_linux_gnu.rs diff --git a/compiler/rustc_target/src/spec/mips_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/mips_unknown_linux_musl.rs similarity index 100% rename from compiler/rustc_target/src/spec/mips_unknown_linux_musl.rs rename to compiler/rustc_target/src/spec/targets/mips_unknown_linux_musl.rs diff --git a/compiler/rustc_target/src/spec/mips_unknown_linux_uclibc.rs b/compiler/rustc_target/src/spec/targets/mips_unknown_linux_uclibc.rs similarity index 100% rename from compiler/rustc_target/src/spec/mips_unknown_linux_uclibc.rs rename to compiler/rustc_target/src/spec/targets/mips_unknown_linux_uclibc.rs diff --git a/compiler/rustc_target/src/spec/mipsel_sony_psp.rs b/compiler/rustc_target/src/spec/targets/mipsel_sony_psp.rs similarity index 100% rename from compiler/rustc_target/src/spec/mipsel_sony_psp.rs rename to compiler/rustc_target/src/spec/targets/mipsel_sony_psp.rs diff --git a/compiler/rustc_target/src/spec/mipsel_sony_psp_linker_script.ld b/compiler/rustc_target/src/spec/targets/mipsel_sony_psp_linker_script.ld similarity index 100% rename from compiler/rustc_target/src/spec/mipsel_sony_psp_linker_script.ld rename to compiler/rustc_target/src/spec/targets/mipsel_sony_psp_linker_script.ld diff --git a/compiler/rustc_target/src/spec/mipsel_sony_psx.rs b/compiler/rustc_target/src/spec/targets/mipsel_sony_psx.rs similarity index 100% rename from compiler/rustc_target/src/spec/mipsel_sony_psx.rs rename to compiler/rustc_target/src/spec/targets/mipsel_sony_psx.rs diff --git a/compiler/rustc_target/src/spec/mipsel_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_gnu.rs similarity index 100% rename from compiler/rustc_target/src/spec/mipsel_unknown_linux_gnu.rs rename to compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_gnu.rs diff --git a/compiler/rustc_target/src/spec/mipsel_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_musl.rs similarity index 100% rename from compiler/rustc_target/src/spec/mipsel_unknown_linux_musl.rs rename to compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_musl.rs diff --git a/compiler/rustc_target/src/spec/mipsel_unknown_linux_uclibc.rs b/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_uclibc.rs similarity index 100% rename from compiler/rustc_target/src/spec/mipsel_unknown_linux_uclibc.rs rename to compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_uclibc.rs diff --git a/compiler/rustc_target/src/spec/mipsel_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/mipsel_unknown_netbsd.rs similarity index 100% rename from compiler/rustc_target/src/spec/mipsel_unknown_netbsd.rs rename to compiler/rustc_target/src/spec/targets/mipsel_unknown_netbsd.rs diff --git a/compiler/rustc_target/src/spec/mipsel_unknown_none.rs b/compiler/rustc_target/src/spec/targets/mipsel_unknown_none.rs similarity index 100% rename from compiler/rustc_target/src/spec/mipsel_unknown_none.rs rename to compiler/rustc_target/src/spec/targets/mipsel_unknown_none.rs diff --git a/compiler/rustc_target/src/spec/mipsisa32r6_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/mipsisa32r6_unknown_linux_gnu.rs similarity index 100% rename from compiler/rustc_target/src/spec/mipsisa32r6_unknown_linux_gnu.rs rename to compiler/rustc_target/src/spec/targets/mipsisa32r6_unknown_linux_gnu.rs diff --git a/compiler/rustc_target/src/spec/mipsisa32r6el_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/mipsisa32r6el_unknown_linux_gnu.rs similarity index 100% rename from compiler/rustc_target/src/spec/mipsisa32r6el_unknown_linux_gnu.rs rename to compiler/rustc_target/src/spec/targets/mipsisa32r6el_unknown_linux_gnu.rs diff --git a/compiler/rustc_target/src/spec/mipsisa64r6_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/targets/mipsisa64r6_unknown_linux_gnuabi64.rs similarity index 100% rename from compiler/rustc_target/src/spec/mipsisa64r6_unknown_linux_gnuabi64.rs rename to compiler/rustc_target/src/spec/targets/mipsisa64r6_unknown_linux_gnuabi64.rs diff --git a/compiler/rustc_target/src/spec/mipsisa64r6el_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/targets/mipsisa64r6el_unknown_linux_gnuabi64.rs similarity index 100% rename from compiler/rustc_target/src/spec/mipsisa64r6el_unknown_linux_gnuabi64.rs rename to compiler/rustc_target/src/spec/targets/mipsisa64r6el_unknown_linux_gnuabi64.rs diff --git a/compiler/rustc_target/src/spec/msp430_none_elf.rs b/compiler/rustc_target/src/spec/targets/msp430_none_elf.rs similarity index 100% rename from compiler/rustc_target/src/spec/msp430_none_elf.rs rename to compiler/rustc_target/src/spec/targets/msp430_none_elf.rs diff --git a/compiler/rustc_target/src/spec/nvptx64_nvidia_cuda.rs b/compiler/rustc_target/src/spec/targets/nvptx64_nvidia_cuda.rs similarity index 100% rename from compiler/rustc_target/src/spec/nvptx64_nvidia_cuda.rs rename to compiler/rustc_target/src/spec/targets/nvptx64_nvidia_cuda.rs diff --git a/compiler/rustc_target/src/spec/powerpc64_ibm_aix.rs b/compiler/rustc_target/src/spec/targets/powerpc64_ibm_aix.rs similarity index 100% rename from compiler/rustc_target/src/spec/powerpc64_ibm_aix.rs rename to compiler/rustc_target/src/spec/targets/powerpc64_ibm_aix.rs diff --git a/compiler/rustc_target/src/spec/powerpc64_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_freebsd.rs similarity index 100% rename from compiler/rustc_target/src/spec/powerpc64_unknown_freebsd.rs rename to compiler/rustc_target/src/spec/targets/powerpc64_unknown_freebsd.rs diff --git a/compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_gnu.rs similarity index 100% rename from compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs rename to compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_gnu.rs diff --git a/compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_musl.rs similarity index 100% rename from compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs rename to compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_musl.rs diff --git a/compiler/rustc_target/src/spec/powerpc64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_openbsd.rs similarity index 100% rename from compiler/rustc_target/src/spec/powerpc64_unknown_openbsd.rs rename to compiler/rustc_target/src/spec/targets/powerpc64_unknown_openbsd.rs diff --git a/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs b/compiler/rustc_target/src/spec/targets/powerpc64_wrs_vxworks.rs similarity index 100% rename from compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs rename to compiler/rustc_target/src/spec/targets/powerpc64_wrs_vxworks.rs diff --git a/compiler/rustc_target/src/spec/powerpc64le_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_freebsd.rs similarity index 100% rename from compiler/rustc_target/src/spec/powerpc64le_unknown_freebsd.rs rename to compiler/rustc_target/src/spec/targets/powerpc64le_unknown_freebsd.rs diff --git a/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_gnu.rs similarity index 100% rename from compiler/rustc_target/src/spec/powerpc64le_unknown_linux_gnu.rs rename to compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_gnu.rs diff --git a/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_musl.rs similarity index 100% rename from compiler/rustc_target/src/spec/powerpc64le_unknown_linux_musl.rs rename to compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_musl.rs diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/powerpc_unknown_freebsd.rs similarity index 100% rename from compiler/rustc_target/src/spec/powerpc_unknown_freebsd.rs rename to compiler/rustc_target/src/spec/targets/powerpc_unknown_freebsd.rs diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnu.rs similarity index 100% rename from compiler/rustc_target/src/spec/powerpc_unknown_linux_gnu.rs rename to compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnu.rs diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnuspe.rs similarity index 100% rename from compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs rename to compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnuspe.rs diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_musl.rs similarity index 100% rename from compiler/rustc_target/src/spec/powerpc_unknown_linux_musl.rs rename to compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_musl.rs diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/powerpc_unknown_netbsd.rs similarity index 100% rename from compiler/rustc_target/src/spec/powerpc_unknown_netbsd.rs rename to compiler/rustc_target/src/spec/targets/powerpc_unknown_netbsd.rs diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/powerpc_unknown_openbsd.rs similarity index 100% rename from compiler/rustc_target/src/spec/powerpc_unknown_openbsd.rs rename to compiler/rustc_target/src/spec/targets/powerpc_unknown_openbsd.rs diff --git a/compiler/rustc_target/src/spec/powerpc_wrs_vxworks.rs b/compiler/rustc_target/src/spec/targets/powerpc_wrs_vxworks.rs similarity index 100% rename from compiler/rustc_target/src/spec/powerpc_wrs_vxworks.rs rename to compiler/rustc_target/src/spec/targets/powerpc_wrs_vxworks.rs diff --git a/compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs b/compiler/rustc_target/src/spec/targets/powerpc_wrs_vxworks_spe.rs similarity index 100% rename from compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs rename to compiler/rustc_target/src/spec/targets/powerpc_wrs_vxworks_spe.rs diff --git a/compiler/rustc_target/src/spec/riscv32gc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_gnu.rs similarity index 100% rename from compiler/rustc_target/src/spec/riscv32gc_unknown_linux_gnu.rs rename to compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_gnu.rs diff --git a/compiler/rustc_target/src/spec/riscv32gc_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_musl.rs similarity index 100% rename from compiler/rustc_target/src/spec/riscv32gc_unknown_linux_musl.rs rename to compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_musl.rs diff --git a/compiler/rustc_target/src/spec/riscv32i_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32i_unknown_none_elf.rs similarity index 100% rename from compiler/rustc_target/src/spec/riscv32i_unknown_none_elf.rs rename to compiler/rustc_target/src/spec/targets/riscv32i_unknown_none_elf.rs diff --git a/compiler/rustc_target/src/spec/riscv32im_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32im_unknown_none_elf.rs similarity index 100% rename from compiler/rustc_target/src/spec/riscv32im_unknown_none_elf.rs rename to compiler/rustc_target/src/spec/targets/riscv32im_unknown_none_elf.rs diff --git a/compiler/rustc_target/src/spec/riscv32imac_esp_espidf.rs b/compiler/rustc_target/src/spec/targets/riscv32imac_esp_espidf.rs similarity index 100% rename from compiler/rustc_target/src/spec/riscv32imac_esp_espidf.rs rename to compiler/rustc_target/src/spec/targets/riscv32imac_esp_espidf.rs diff --git a/compiler/rustc_target/src/spec/riscv32imac_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_none_elf.rs similarity index 100% rename from compiler/rustc_target/src/spec/riscv32imac_unknown_none_elf.rs rename to compiler/rustc_target/src/spec/targets/riscv32imac_unknown_none_elf.rs diff --git a/compiler/rustc_target/src/spec/riscv32imac_unknown_xous_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_xous_elf.rs similarity index 100% rename from compiler/rustc_target/src/spec/riscv32imac_unknown_xous_elf.rs rename to compiler/rustc_target/src/spec/targets/riscv32imac_unknown_xous_elf.rs diff --git a/compiler/rustc_target/src/spec/riscv32imc_esp_espidf.rs b/compiler/rustc_target/src/spec/targets/riscv32imc_esp_espidf.rs similarity index 100% rename from compiler/rustc_target/src/spec/riscv32imc_esp_espidf.rs rename to compiler/rustc_target/src/spec/targets/riscv32imc_esp_espidf.rs diff --git a/compiler/rustc_target/src/spec/riscv32imc_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32imc_unknown_none_elf.rs similarity index 100% rename from compiler/rustc_target/src/spec/riscv32imc_unknown_none_elf.rs rename to compiler/rustc_target/src/spec/targets/riscv32imc_unknown_none_elf.rs diff --git a/compiler/rustc_target/src/spec/riscv64_linux_android.rs b/compiler/rustc_target/src/spec/targets/riscv64_linux_android.rs similarity index 100% rename from compiler/rustc_target/src/spec/riscv64_linux_android.rs rename to compiler/rustc_target/src/spec/targets/riscv64_linux_android.rs diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_freebsd.rs similarity index 100% rename from compiler/rustc_target/src/spec/riscv64gc_unknown_freebsd.rs rename to compiler/rustc_target/src/spec/targets/riscv64gc_unknown_freebsd.rs diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_fuchsia.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_fuchsia.rs similarity index 100% rename from compiler/rustc_target/src/spec/riscv64gc_unknown_fuchsia.rs rename to compiler/rustc_target/src/spec/targets/riscv64gc_unknown_fuchsia.rs diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_hermit.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_hermit.rs similarity index 100% rename from compiler/rustc_target/src/spec/riscv64gc_unknown_hermit.rs rename to compiler/rustc_target/src/spec/targets/riscv64gc_unknown_hermit.rs diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_gnu.rs similarity index 100% rename from compiler/rustc_target/src/spec/riscv64gc_unknown_linux_gnu.rs rename to compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_gnu.rs diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_musl.rs similarity index 100% rename from compiler/rustc_target/src/spec/riscv64gc_unknown_linux_musl.rs rename to compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_musl.rs diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_netbsd.rs similarity index 100% rename from compiler/rustc_target/src/spec/riscv64gc_unknown_netbsd.rs rename to compiler/rustc_target/src/spec/targets/riscv64gc_unknown_netbsd.rs diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_none_elf.rs similarity index 96% rename from compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs rename to compiler/rustc_target/src/spec/targets/riscv64gc_unknown_none_elf.rs index ab3c14e3fe73..f29e224244ef 100644 --- a/compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs +++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_none_elf.rs @@ -1,8 +1,7 @@ +use crate::spec::SanitizerSet; use crate::spec::{Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy}; use crate::spec::{RelocModel, Target, TargetOptions}; -use super::SanitizerSet; - pub fn target() -> Target { Target { data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(), diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_openbsd.rs similarity index 100% rename from compiler/rustc_target/src/spec/riscv64gc_unknown_openbsd.rs rename to compiler/rustc_target/src/spec/targets/riscv64gc_unknown_openbsd.rs diff --git a/compiler/rustc_target/src/spec/riscv64imac_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv64imac_unknown_none_elf.rs similarity index 100% rename from compiler/rustc_target/src/spec/riscv64imac_unknown_none_elf.rs rename to compiler/rustc_target/src/spec/targets/riscv64imac_unknown_none_elf.rs diff --git a/compiler/rustc_target/src/spec/s390x_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_gnu.rs similarity index 100% rename from compiler/rustc_target/src/spec/s390x_unknown_linux_gnu.rs rename to compiler/rustc_target/src/spec/targets/s390x_unknown_linux_gnu.rs diff --git a/compiler/rustc_target/src/spec/s390x_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_musl.rs similarity index 100% rename from compiler/rustc_target/src/spec/s390x_unknown_linux_musl.rs rename to compiler/rustc_target/src/spec/targets/s390x_unknown_linux_musl.rs diff --git a/compiler/rustc_target/src/spec/sparc64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/sparc64_unknown_linux_gnu.rs similarity index 100% rename from compiler/rustc_target/src/spec/sparc64_unknown_linux_gnu.rs rename to compiler/rustc_target/src/spec/targets/sparc64_unknown_linux_gnu.rs diff --git a/compiler/rustc_target/src/spec/sparc64_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/sparc64_unknown_netbsd.rs similarity index 100% rename from compiler/rustc_target/src/spec/sparc64_unknown_netbsd.rs rename to compiler/rustc_target/src/spec/targets/sparc64_unknown_netbsd.rs diff --git a/compiler/rustc_target/src/spec/sparc64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/sparc64_unknown_openbsd.rs similarity index 100% rename from compiler/rustc_target/src/spec/sparc64_unknown_openbsd.rs rename to compiler/rustc_target/src/spec/targets/sparc64_unknown_openbsd.rs diff --git a/compiler/rustc_target/src/spec/sparc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/sparc_unknown_linux_gnu.rs similarity index 100% rename from compiler/rustc_target/src/spec/sparc_unknown_linux_gnu.rs rename to compiler/rustc_target/src/spec/targets/sparc_unknown_linux_gnu.rs diff --git a/compiler/rustc_target/src/spec/sparc_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/sparc_unknown_none_elf.rs similarity index 100% rename from compiler/rustc_target/src/spec/sparc_unknown_none_elf.rs rename to compiler/rustc_target/src/spec/targets/sparc_unknown_none_elf.rs diff --git a/compiler/rustc_target/src/spec/sparcv9_sun_solaris.rs b/compiler/rustc_target/src/spec/targets/sparcv9_sun_solaris.rs similarity index 100% rename from compiler/rustc_target/src/spec/sparcv9_sun_solaris.rs rename to compiler/rustc_target/src/spec/targets/sparcv9_sun_solaris.rs diff --git a/compiler/rustc_target/src/spec/thumbv4t_none_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv4t_none_eabi.rs similarity index 100% rename from compiler/rustc_target/src/spec/thumbv4t_none_eabi.rs rename to compiler/rustc_target/src/spec/targets/thumbv4t_none_eabi.rs diff --git a/compiler/rustc_target/src/spec/thumbv5te_none_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv5te_none_eabi.rs similarity index 100% rename from compiler/rustc_target/src/spec/thumbv5te_none_eabi.rs rename to compiler/rustc_target/src/spec/targets/thumbv5te_none_eabi.rs diff --git a/compiler/rustc_target/src/spec/thumbv6m_none_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv6m_none_eabi.rs similarity index 100% rename from compiler/rustc_target/src/spec/thumbv6m_none_eabi.rs rename to compiler/rustc_target/src/spec/targets/thumbv6m_none_eabi.rs diff --git a/compiler/rustc_target/src/spec/thumbv7a_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/thumbv7a_pc_windows_msvc.rs similarity index 100% rename from compiler/rustc_target/src/spec/thumbv7a_pc_windows_msvc.rs rename to compiler/rustc_target/src/spec/targets/thumbv7a_pc_windows_msvc.rs diff --git a/compiler/rustc_target/src/spec/thumbv7a_uwp_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/thumbv7a_uwp_windows_msvc.rs similarity index 100% rename from compiler/rustc_target/src/spec/thumbv7a_uwp_windows_msvc.rs rename to compiler/rustc_target/src/spec/targets/thumbv7a_uwp_windows_msvc.rs diff --git a/compiler/rustc_target/src/spec/thumbv7em_none_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv7em_none_eabi.rs similarity index 100% rename from compiler/rustc_target/src/spec/thumbv7em_none_eabi.rs rename to compiler/rustc_target/src/spec/targets/thumbv7em_none_eabi.rs diff --git a/compiler/rustc_target/src/spec/thumbv7em_none_eabihf.rs b/compiler/rustc_target/src/spec/targets/thumbv7em_none_eabihf.rs similarity index 100% rename from compiler/rustc_target/src/spec/thumbv7em_none_eabihf.rs rename to compiler/rustc_target/src/spec/targets/thumbv7em_none_eabihf.rs diff --git a/compiler/rustc_target/src/spec/thumbv7m_none_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv7m_none_eabi.rs similarity index 100% rename from compiler/rustc_target/src/spec/thumbv7m_none_eabi.rs rename to compiler/rustc_target/src/spec/targets/thumbv7m_none_eabi.rs diff --git a/compiler/rustc_target/src/spec/thumbv7neon_linux_androideabi.rs b/compiler/rustc_target/src/spec/targets/thumbv7neon_linux_androideabi.rs similarity index 100% rename from compiler/rustc_target/src/spec/thumbv7neon_linux_androideabi.rs rename to compiler/rustc_target/src/spec/targets/thumbv7neon_linux_androideabi.rs diff --git a/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_gnueabihf.rs b/compiler/rustc_target/src/spec/targets/thumbv7neon_unknown_linux_gnueabihf.rs similarity index 100% rename from compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_gnueabihf.rs rename to compiler/rustc_target/src/spec/targets/thumbv7neon_unknown_linux_gnueabihf.rs diff --git a/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_musleabihf.rs b/compiler/rustc_target/src/spec/targets/thumbv7neon_unknown_linux_musleabihf.rs similarity index 100% rename from compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_musleabihf.rs rename to compiler/rustc_target/src/spec/targets/thumbv7neon_unknown_linux_musleabihf.rs diff --git a/compiler/rustc_target/src/spec/thumbv8m_base_none_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv8m_base_none_eabi.rs similarity index 100% rename from compiler/rustc_target/src/spec/thumbv8m_base_none_eabi.rs rename to compiler/rustc_target/src/spec/targets/thumbv8m_base_none_eabi.rs diff --git a/compiler/rustc_target/src/spec/thumbv8m_main_none_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv8m_main_none_eabi.rs similarity index 100% rename from compiler/rustc_target/src/spec/thumbv8m_main_none_eabi.rs rename to compiler/rustc_target/src/spec/targets/thumbv8m_main_none_eabi.rs diff --git a/compiler/rustc_target/src/spec/thumbv8m_main_none_eabihf.rs b/compiler/rustc_target/src/spec/targets/thumbv8m_main_none_eabihf.rs similarity index 100% rename from compiler/rustc_target/src/spec/thumbv8m_main_none_eabihf.rs rename to compiler/rustc_target/src/spec/targets/thumbv8m_main_none_eabihf.rs diff --git a/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs b/compiler/rustc_target/src/spec/targets/wasm32_unknown_emscripten.rs similarity index 100% rename from compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs rename to compiler/rustc_target/src/spec/targets/wasm32_unknown_emscripten.rs diff --git a/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs b/compiler/rustc_target/src/spec/targets/wasm32_unknown_unknown.rs similarity index 100% rename from compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs rename to compiler/rustc_target/src/spec/targets/wasm32_unknown_unknown.rs diff --git a/compiler/rustc_target/src/spec/wasm32_wasi.rs b/compiler/rustc_target/src/spec/targets/wasm32_wasi.rs similarity index 100% rename from compiler/rustc_target/src/spec/wasm32_wasi.rs rename to compiler/rustc_target/src/spec/targets/wasm32_wasi.rs diff --git a/compiler/rustc_target/src/spec/wasm32_wasi_preview1_threads.rs b/compiler/rustc_target/src/spec/targets/wasm32_wasi_preview1_threads.rs similarity index 100% rename from compiler/rustc_target/src/spec/wasm32_wasi_preview1_threads.rs rename to compiler/rustc_target/src/spec/targets/wasm32_wasi_preview1_threads.rs diff --git a/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs b/compiler/rustc_target/src/spec/targets/wasm64_unknown_unknown.rs similarity index 100% rename from compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs rename to compiler/rustc_target/src/spec/targets/wasm64_unknown_unknown.rs diff --git a/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs similarity index 100% rename from compiler/rustc_target/src/spec/x86_64_apple_darwin.rs rename to compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs diff --git a/compiler/rustc_target/src/spec/x86_64_apple_ios.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs similarity index 100% rename from compiler/rustc_target/src/spec/x86_64_apple_ios.rs rename to compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs diff --git a/compiler/rustc_target/src/spec/x86_64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs similarity index 100% rename from compiler/rustc_target/src/spec/x86_64_apple_ios_macabi.rs rename to compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs diff --git a/compiler/rustc_target/src/spec/x86_64_apple_tvos.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs similarity index 100% rename from compiler/rustc_target/src/spec/x86_64_apple_tvos.rs rename to compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs diff --git a/compiler/rustc_target/src/spec/x86_64_apple_watchos_sim.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs similarity index 100% rename from compiler/rustc_target/src/spec/x86_64_apple_watchos_sim.rs rename to compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs diff --git a/compiler/rustc_target/src/spec/x86_64_fortanix_unknown_sgx.rs b/compiler/rustc_target/src/spec/targets/x86_64_fortanix_unknown_sgx.rs similarity index 97% rename from compiler/rustc_target/src/spec/x86_64_fortanix_unknown_sgx.rs rename to compiler/rustc_target/src/spec/targets/x86_64_fortanix_unknown_sgx.rs index a7ed74f47212..f4117edc3ff5 100644 --- a/compiler/rustc_target/src/spec/x86_64_fortanix_unknown_sgx.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_fortanix_unknown_sgx.rs @@ -1,6 +1,6 @@ use std::borrow::Cow; -use super::{cvs, Cc, LinkerFlavor, Lld, Target, TargetOptions}; +use crate::spec::{cvs, Cc, LinkerFlavor, Lld, Target, TargetOptions}; pub fn target() -> Target { let pre_link_args = TargetOptions::link_args( diff --git a/compiler/rustc_target/src/spec/targets/x86_64_fuchsia.rs b/compiler/rustc_target/src/spec/targets/x86_64_fuchsia.rs new file mode 100644 index 000000000000..46df00e9c02b --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/x86_64_fuchsia.rs @@ -0,0 +1 @@ +pub use crate::spec::targets::x86_64_unknown_fuchsia::target; diff --git a/compiler/rustc_target/src/spec/x86_64_linux_android.rs b/compiler/rustc_target/src/spec/targets/x86_64_linux_android.rs similarity index 100% rename from compiler/rustc_target/src/spec/x86_64_linux_android.rs rename to compiler/rustc_target/src/spec/targets/x86_64_linux_android.rs diff --git a/compiler/rustc_target/src/spec/x86_64_pc_nto_qnx710.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_nto_qnx710.rs similarity index 100% rename from compiler/rustc_target/src/spec/x86_64_pc_nto_qnx710.rs rename to compiler/rustc_target/src/spec/targets/x86_64_pc_nto_qnx710.rs diff --git a/compiler/rustc_target/src/spec/x86_64_pc_solaris.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_solaris.rs similarity index 100% rename from compiler/rustc_target/src/spec/x86_64_pc_solaris.rs rename to compiler/rustc_target/src/spec/targets/x86_64_pc_solaris.rs diff --git a/compiler/rustc_target/src/spec/x86_64_pc_windows_gnu.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnu.rs similarity index 100% rename from compiler/rustc_target/src/spec/x86_64_pc_windows_gnu.rs rename to compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnu.rs diff --git a/compiler/rustc_target/src/spec/x86_64_pc_windows_gnullvm.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnullvm.rs similarity index 100% rename from compiler/rustc_target/src/spec/x86_64_pc_windows_gnullvm.rs rename to compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnullvm.rs diff --git a/compiler/rustc_target/src/spec/x86_64_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs similarity index 100% rename from compiler/rustc_target/src/spec/x86_64_pc_windows_msvc.rs rename to compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs diff --git a/compiler/rustc_target/src/spec/x86_64_sun_solaris.rs b/compiler/rustc_target/src/spec/targets/x86_64_sun_solaris.rs similarity index 100% rename from compiler/rustc_target/src/spec/x86_64_sun_solaris.rs rename to compiler/rustc_target/src/spec/targets/x86_64_sun_solaris.rs diff --git a/compiler/rustc_target/src/spec/x86_64_unikraft_linux_musl.rs b/compiler/rustc_target/src/spec/targets/x86_64_unikraft_linux_musl.rs similarity index 100% rename from compiler/rustc_target/src/spec/x86_64_unikraft_linux_musl.rs rename to compiler/rustc_target/src/spec/targets/x86_64_unikraft_linux_musl.rs diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_dragonfly.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_dragonfly.rs similarity index 100% rename from compiler/rustc_target/src/spec/x86_64_unknown_dragonfly.rs rename to compiler/rustc_target/src/spec/targets/x86_64_unknown_dragonfly.rs diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_freebsd.rs similarity index 100% rename from compiler/rustc_target/src/spec/x86_64_unknown_freebsd.rs rename to compiler/rustc_target/src/spec/targets/x86_64_unknown_freebsd.rs diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_fuchsia.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_fuchsia.rs similarity index 100% rename from compiler/rustc_target/src/spec/x86_64_unknown_fuchsia.rs rename to compiler/rustc_target/src/spec/targets/x86_64_unknown_fuchsia.rs diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_haiku.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_haiku.rs similarity index 100% rename from compiler/rustc_target/src/spec/x86_64_unknown_haiku.rs rename to compiler/rustc_target/src/spec/targets/x86_64_unknown_haiku.rs diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_hermit.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_hermit.rs similarity index 100% rename from compiler/rustc_target/src/spec/x86_64_unknown_hermit.rs rename to compiler/rustc_target/src/spec/targets/x86_64_unknown_hermit.rs diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_illumos.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_illumos.rs similarity index 100% rename from compiler/rustc_target/src/spec/x86_64_unknown_illumos.rs rename to compiler/rustc_target/src/spec/targets/x86_64_unknown_illumos.rs diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_l4re_uclibc.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_l4re_uclibc.rs similarity index 100% rename from compiler/rustc_target/src/spec/x86_64_unknown_l4re_uclibc.rs rename to compiler/rustc_target/src/spec/targets/x86_64_unknown_l4re_uclibc.rs diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs similarity index 100% rename from compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs rename to compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnux32.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnux32.rs similarity index 100% rename from compiler/rustc_target/src/spec/x86_64_unknown_linux_gnux32.rs rename to compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnux32.rs diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_musl.rs similarity index 100% rename from compiler/rustc_target/src/spec/x86_64_unknown_linux_musl.rs rename to compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_musl.rs diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_linux_ohos.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_ohos.rs similarity index 100% rename from compiler/rustc_target/src/spec/x86_64_unknown_linux_ohos.rs rename to compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_ohos.rs diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_netbsd.rs similarity index 100% rename from compiler/rustc_target/src/spec/x86_64_unknown_netbsd.rs rename to compiler/rustc_target/src/spec/targets/x86_64_unknown_netbsd.rs diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_none.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs similarity index 89% rename from compiler/rustc_target/src/spec/x86_64_unknown_none.rs rename to compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs index fe3b24f2d4af..9aa95a35f8e5 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_none.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs @@ -4,8 +4,8 @@ // `target-cpu` compiler flags to opt-in more hardware-specific // features. -use super::{Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy}; -use super::{RelroLevel, SanitizerSet, StackProbeType, Target, TargetOptions}; +use crate::spec::{Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy}; +use crate::spec::{RelroLevel, SanitizerSet, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { let opts = TargetOptions { diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_openbsd.rs similarity index 100% rename from compiler/rustc_target/src/spec/x86_64_unknown_openbsd.rs rename to compiler/rustc_target/src/spec/targets/x86_64_unknown_openbsd.rs diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_redox.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_redox.rs similarity index 100% rename from compiler/rustc_target/src/spec/x86_64_unknown_redox.rs rename to compiler/rustc_target/src/spec/targets/x86_64_unknown_redox.rs diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_uefi.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_uefi.rs similarity index 100% rename from compiler/rustc_target/src/spec/x86_64_unknown_uefi.rs rename to compiler/rustc_target/src/spec/targets/x86_64_unknown_uefi.rs diff --git a/compiler/rustc_target/src/spec/x86_64_uwp_windows_gnu.rs b/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_gnu.rs similarity index 100% rename from compiler/rustc_target/src/spec/x86_64_uwp_windows_gnu.rs rename to compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_gnu.rs diff --git a/compiler/rustc_target/src/spec/x86_64_uwp_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_msvc.rs similarity index 100% rename from compiler/rustc_target/src/spec/x86_64_uwp_windows_msvc.rs rename to compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_msvc.rs diff --git a/compiler/rustc_target/src/spec/x86_64_wrs_vxworks.rs b/compiler/rustc_target/src/spec/targets/x86_64_wrs_vxworks.rs similarity index 100% rename from compiler/rustc_target/src/spec/x86_64_wrs_vxworks.rs rename to compiler/rustc_target/src/spec/targets/x86_64_wrs_vxworks.rs diff --git a/compiler/rustc_target/src/spec/x86_64h_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs similarity index 100% rename from compiler/rustc_target/src/spec/x86_64h_apple_darwin.rs rename to compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs diff --git a/compiler/rustc_target/src/spec/x86_64_fuchsia.rs b/compiler/rustc_target/src/spec/x86_64_fuchsia.rs deleted file mode 100644 index 96fed0975666..000000000000 --- a/compiler/rustc_target/src/spec/x86_64_fuchsia.rs +++ /dev/null @@ -1 +0,0 @@ -pub use crate::spec::x86_64_unknown_fuchsia::target; From ef7ebaa788112e68cabe1a99d624cf71cbf89390 Mon Sep 17 00:00:00 2001 From: David Wood Date: Wed, 8 Nov 2023 14:37:54 +0800 Subject: [PATCH 341/435] rustc_target: move file for uniformity Signed-off-by: David Wood --- compiler/rustc_target/src/spec/{abi.rs => abi/mod.rs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename compiler/rustc_target/src/spec/{abi.rs => abi/mod.rs} (100%) diff --git a/compiler/rustc_target/src/spec/abi.rs b/compiler/rustc_target/src/spec/abi/mod.rs similarity index 100% rename from compiler/rustc_target/src/spec/abi.rs rename to compiler/rustc_target/src/spec/abi/mod.rs From b9b7982f720c5ce828a74395864357edf76243f8 Mon Sep 17 00:00:00 2001 From: Qiu Chaofan Date: Tue, 1 Aug 2023 11:37:23 +0800 Subject: [PATCH 342/435] Add AIX platform-support doc --- src/doc/rustc/src/SUMMARY.md | 1 + src/doc/rustc/src/platform-support.md | 2 +- src/doc/rustc/src/platform-support/aix.md | 26 +++++++++++++++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 src/doc/rustc/src/platform-support/aix.md diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index 8b4d673d831c..1b27b77b3e6b 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -41,6 +41,7 @@ - [mipsel-sony-psx](platform-support/mipsel-sony-psx.md) - [mipsisa\*r6\*-unknown-linux-gnu\*](platform-support/mips-release-6.md) - [nvptx64-nvidia-cuda](platform-support/nvptx64-nvidia-cuda.md) + - [powerpc64-ibm-aix](platform-support/aix.md) - [riscv32imac-unknown-xous-elf](platform-support/riscv32imac-unknown-xous-elf.md) - [sparc-unknown-none-elf](./platform-support/sparc-unknown-none-elf.md) - [*-pc-windows-gnullvm](platform-support/pc-windows-gnullvm.md) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 6a979869a59a..907e9c59f316 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -310,7 +310,7 @@ target | std | host | notes `powerpc64-wrs-vxworks` | ? | | `powerpc64le-unknown-linux-musl` | ? | | [`powerpc64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/powerpc64 -`powerpc64-ibm-aix` | ? | | 64-bit AIX (7.2 and newer) +[`powerpc64-ibm-aix`](platform-support/aix.md) | ? | | 64-bit AIX (7.2 and newer) `riscv32gc-unknown-linux-gnu` | | | RISC-V Linux (kernel 5.4, glibc 2.33) `riscv32gc-unknown-linux-musl` | | | RISC-V Linux (kernel 5.4, musl + RISCV32 support patches) `riscv32im-unknown-none-elf` | * | | Bare RISC-V (RV32IM ISA) diff --git a/src/doc/rustc/src/platform-support/aix.md b/src/doc/rustc/src/platform-support/aix.md new file mode 100644 index 000000000000..c3ce71a18356 --- /dev/null +++ b/src/doc/rustc/src/platform-support/aix.md @@ -0,0 +1,26 @@ +# `powerpc64-ibm-aix` + +**Tier: 3** + +Rust for AIX operating system, currently only 64-bit PowerPC is supported. + +## Target maintainers + +- QIU Chaofan `qiucofan@cn.ibm.com`, https://github.com/ecnelises +- Kai LUO, `lkail@cn.ibm.com`, https://github.com/bzEq + +## Requirements + +This target supports host tools, std and alloc. This target cannot be cross-compiled as for now, mainly because of the unavailability of system linker on other platforms. + +Binary built for this target is expected to run on Power7 or newer CPU, and AIX 7.2 or newer version. + +Binary format of this platform is [XCOFF](https://www.ibm.com/docs/en/aix/7.2?topic=formats-xcoff-object-file-format). Archive file format is ['AIX big format'](https://www.ibm.com/docs/en/aix/7.2?topic=formats-ar-file-format-big). + +## Testing + +This target supports running test suites natively, but it's not available to cross-compile and execute in emulator. + +## Interoperability with C code + +This target supports C code. C code compiled by XL, Open XL and Clang are compatible with Rust. Typical triple of AIX on 64-bit PowerPC of these compilers are also `powerpc64-ibm-aix`. From 769ad29c3ec2c1925a85652254b0368c1fd3f0c5 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Wed, 8 Nov 2023 11:21:44 +0200 Subject: [PATCH 343/435] triagebot.toml: use inclusive language --- triagebot.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/triagebot.toml b/triagebot.toml index 69bbbdb03bf4..b51a91c7452d 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -579,7 +579,7 @@ Otherwise, you can ignore this comment. message = "`src/tools/x` was changed. Bump version of Cargo.toml in `src/tools/x` so tidy will suggest installing the new version." [mentions."src/tools/tidy/src/deps.rs"] -message = "Third-party dependency whitelist may have been modified! You must ensure that any new dependencies have compatible licenses before merging." +message = "Third-party dependency allowlist may have been modified! You must ensure that any new dependencies have compatible licenses before merging." cc = ["@davidtwco", "@wesleywiser"] [mentions."src/bootstrap/src/core/config"] From 03435e6fdd42a6b810e9a0fcbafd89f8935b72fc Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Wed, 8 Nov 2023 12:19:32 +0200 Subject: [PATCH 344/435] accept review suggestion Co-authored-by: joboet --- triagebot.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/triagebot.toml b/triagebot.toml index b51a91c7452d..4c8c1c59beba 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -579,7 +579,7 @@ Otherwise, you can ignore this comment. message = "`src/tools/x` was changed. Bump version of Cargo.toml in `src/tools/x` so tidy will suggest installing the new version." [mentions."src/tools/tidy/src/deps.rs"] -message = "Third-party dependency allowlist may have been modified! You must ensure that any new dependencies have compatible licenses before merging." +message = "The list of allowed third-party dependencies may have been modified! You must ensure that any new dependencies have compatible licenses before merging." cc = ["@davidtwco", "@wesleywiser"] [mentions."src/bootstrap/src/core/config"] From ae4d18b2da7a1d044481948bb84f40ba4eec24c5 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Fri, 27 Oct 2023 06:51:12 +0300 Subject: [PATCH 345/435] handle the case when the change-id isn't found When we switch back and forth between the old and recent branches, if there was a breaking change in the bootstrap configuration in between, we have to update the change-id in the build configuration with each checkout, which can be exhausting. This change fixes that. Signed-off-by: onur-ozkan --- src/bootstrap/src/bin/main.rs | 20 ++++++++++++-------- src/bootstrap/src/lib.rs | 17 +++++++++++++---- 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/src/bootstrap/src/bin/main.rs b/src/bootstrap/src/bin/main.rs index d87fb6a9cef0..e0caecca5c07 100644 --- a/src/bootstrap/src/bin/main.rs +++ b/src/bootstrap/src/bin/main.rs @@ -109,31 +109,35 @@ fn check_version(config: &Config) -> Option { } let latest_config_id = CONFIG_CHANGE_HISTORY.last().unwrap(); - let suggestion = if let Some(id) = config.change_id { + if let Some(id) = config.change_id { if &id != latest_config_id { - msg.push_str("WARNING: there have been changes to x.py since you last updated.\n"); let change_links: Vec = find_recent_config_change_ids(id) .iter() .map(|id| format!("https://github.com/rust-lang/rust/pull/{id}")) .collect(); if !change_links.is_empty() { + msg.push_str("WARNING: there have been changes to x.py since you last updated.\n"); msg.push_str("To see more detail about these changes, visit the following PRs:\n"); + for link in change_links { msg.push_str(&format!(" - {link}\n")); } + + msg.push_str("WARNING: there have been changes to x.py since you last updated.\n"); + + msg.push_str("note: to silence this warning, "); + msg.push_str(&format!( + "update `config.toml` to use `change-id = {latest_config_id}` instead" + )); } - msg.push_str("WARNING: there have been changes to x.py since you last updated.\n"); - format!("update `config.toml` to use `change-id = {latest_config_id}` instead") } else { return None; } } else { msg.push_str("WARNING: The `change-id` is missing in the `config.toml`. This means that you will not be able to track the major changes made to the bootstrap configurations.\n"); - format!("add `change-id = {latest_config_id}` at the top of `config.toml`") + msg.push_str("note: to silence this warning, "); + msg.push_str(&format!("add `change-id = {latest_config_id}` at the top of `config.toml`")); }; - msg.push_str("note: to silence this warning, "); - msg.push_str(&suggestion); - Some(msg) } diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index fc3413a3c817..d7c05da6864a 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -1849,10 +1849,19 @@ fn envify(s: &str) -> String { } pub fn find_recent_config_change_ids(current_id: usize) -> Vec { - let index = CONFIG_CHANGE_HISTORY - .iter() - .position(|&id| id == current_id) - .expect(&format!("Value `{}` was not found in `CONFIG_CHANGE_HISTORY`.", current_id)); + if !CONFIG_CHANGE_HISTORY.contains(¤t_id) { + // If the current change-id is greater than the most recent one, + // return an empty list; otherwise, return the full list. + if let Some(max_id) = CONFIG_CHANGE_HISTORY.iter().max() { + if ¤t_id > max_id { + return Vec::new(); + } + } + + return CONFIG_CHANGE_HISTORY.to_vec(); + } + + let index = CONFIG_CHANGE_HISTORY.iter().position(|&id| id == current_id).unwrap(); CONFIG_CHANGE_HISTORY .iter() From e8781003862a316c81c58ef8bc69b8c6e099c01b Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Fri, 27 Oct 2023 07:03:48 +0300 Subject: [PATCH 346/435] bootstrap: improve `fn check_version` Signed-off-by: onur-ozkan --- src/bootstrap/src/bin/main.rs | 42 +++++++++++++++++------------------ 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/bootstrap/src/bin/main.rs b/src/bootstrap/src/bin/main.rs index e0caecca5c07..6c0d8c8c5501 100644 --- a/src/bootstrap/src/bin/main.rs +++ b/src/bootstrap/src/bin/main.rs @@ -110,29 +110,29 @@ fn check_version(config: &Config) -> Option { let latest_config_id = CONFIG_CHANGE_HISTORY.last().unwrap(); if let Some(id) = config.change_id { - if &id != latest_config_id { - let change_links: Vec = find_recent_config_change_ids(id) - .iter() - .map(|id| format!("https://github.com/rust-lang/rust/pull/{id}")) - .collect(); - if !change_links.is_empty() { - msg.push_str("WARNING: there have been changes to x.py since you last updated.\n"); - msg.push_str("To see more detail about these changes, visit the following PRs:\n"); - - for link in change_links { - msg.push_str(&format!(" - {link}\n")); - } - - msg.push_str("WARNING: there have been changes to x.py since you last updated.\n"); - - msg.push_str("note: to silence this warning, "); - msg.push_str(&format!( - "update `config.toml` to use `change-id = {latest_config_id}` instead" - )); - } - } else { + if &id == latest_config_id { return None; } + + let change_links: Vec = find_recent_config_change_ids(id) + .iter() + .map(|id| format!("https://github.com/rust-lang/rust/pull/{id}")) + .collect(); + if !change_links.is_empty() { + msg.push_str("WARNING: there have been changes to x.py since you last updated.\n"); + msg.push_str("To see more detail about these changes, visit the following PRs:\n"); + + for link in change_links { + msg.push_str(&format!(" - {link}\n")); + } + + msg.push_str("WARNING: there have been changes to x.py since you last updated.\n"); + + msg.push_str("note: to silence this warning, "); + msg.push_str(&format!( + "update `config.toml` to use `change-id = {latest_config_id}` instead" + )); + } } else { msg.push_str("WARNING: The `change-id` is missing in the `config.toml`. This means that you will not be able to track the major changes made to the bootstrap configurations.\n"); msg.push_str("note: to silence this warning, "); From e0cb1cc29609e8f24f1feaa29295a757523ed4dc Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Tue, 7 Nov 2023 09:29:19 +0300 Subject: [PATCH 347/435] bootstrap: add more detail on change-id comments Signed-off-by: onur-ozkan --- src/bootstrap/src/lib.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index d7c05da6864a..9ec192861f46 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -75,8 +75,9 @@ const LLD_FILE_NAMES: &[&str] = &["ld.lld", "ld64.lld", "lld-link", "wasm-ld"]; /// You can visit `https://github.com/rust-lang/rust/pull/{any-id-from-the-list}` to /// check for more details regarding each change. /// -/// If you make any major changes (such as adding new values or changing default values), please -/// ensure that the associated PR ID is added to the end of this list. +/// If you make any major changes (such as adding new values or changing default values), +/// please ensure that the associated PR ID is added to the end of this list. +/// This is necessary because the list must be sorted by the merge date. pub const CONFIG_CHANGE_HISTORY: &[usize] = &[115898, 116998, 117435, 116881]; /// Extra --check-cfg to add when building @@ -1850,8 +1851,10 @@ fn envify(s: &str) -> String { pub fn find_recent_config_change_ids(current_id: usize) -> Vec { if !CONFIG_CHANGE_HISTORY.contains(¤t_id) { - // If the current change-id is greater than the most recent one, - // return an empty list; otherwise, return the full list. + // If the current change-id is greater than the most recent one, return + // an empty list (it may be due to switching from a recent branch to an + // older one); otherwise, return the full list (assuming the user provided + // the incorrect change-id by accident). if let Some(max_id) = CONFIG_CHANGE_HISTORY.iter().max() { if ¤t_id > max_id { return Vec::new(); From bf360d407eb36ebb0cf508f6d6df9a41adf27229 Mon Sep 17 00:00:00 2001 From: lcnr Date: Wed, 8 Nov 2023 12:24:19 +0100 Subject: [PATCH 348/435] instrument constituent types computation --- .../src/solve/assembly/structural_traits.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs index d655a4106b86..839968b25a1b 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs @@ -14,6 +14,7 @@ use crate::solve::EvalCtxt; // // For types with an "existential" binder, i.e. coroutine witnesses, we also // instantiate the binder with placeholders eagerly. +#[instrument(level = "debug", skip(ecx), ret)] pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<'tcx>( ecx: &EvalCtxt<'_, 'tcx>, ty: Ty<'tcx>, @@ -107,6 +108,7 @@ pub(in crate::solve) fn replace_erased_lifetimes_with_bound_vars<'tcx>( ty::Binder::bind_with_vars(ty, bound_vars) } +#[instrument(level = "debug", skip(ecx), ret)] pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait<'tcx>( ecx: &EvalCtxt<'_, 'tcx>, ty: Ty<'tcx>, @@ -152,6 +154,7 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait<'tcx>( } } +#[instrument(level = "debug", skip(ecx), ret)] pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>( ecx: &EvalCtxt<'_, 'tcx>, ty: Ty<'tcx>, From 469d34b39b5d5be623850a3500c1e3a226180b41 Mon Sep 17 00:00:00 2001 From: Jake Goulding Date: Tue, 31 Oct 2023 15:47:59 -0400 Subject: [PATCH 349/435] Mark Rustdoc test as Linux-only Due to incorrect CI configuration, this test was not being run on macOS. aarch64-apple-darwin will start running it, so we correct the configuration. --- tests/rustdoc-ui/issues/issue-107918.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/rustdoc-ui/issues/issue-107918.rs b/tests/rustdoc-ui/issues/issue-107918.rs index 13788df0fc99..0ddb3dc92150 100644 --- a/tests/rustdoc-ui/issues/issue-107918.rs +++ b/tests/rustdoc-ui/issues/issue-107918.rs @@ -1,7 +1,7 @@ // aux-build:panic-handler.rs // compile-flags: --document-private-items // build-pass -// ignore-windows +// only-linux #![no_std] #![no_main] From 64090536d4d700c6383532177b0993157957f5c8 Mon Sep 17 00:00:00 2001 From: Jake Goulding Date: Tue, 31 Oct 2023 16:32:37 -0400 Subject: [PATCH 350/435] Install tidy for aarch64-apple-darwin The GitHub Actions image has this preinstalled for x86_64 but not M1. --- .github/workflows/ci.yml | 9 +++++++++ src/ci/github-actions/ci.yml | 4 ++++ src/ci/scripts/install-tidy.sh | 24 ++++++++++++++++++++++++ 3 files changed, 37 insertions(+) create mode 100755 src/ci/scripts/install-tidy.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8cc26d2995e7..475521071961 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -106,6 +106,9 @@ jobs: - name: install clang run: src/ci/scripts/install-clang.sh if: success() && !env.SKIP_JOB + - name: install tidy + run: src/ci/scripts/install-tidy.sh + if: success() && !env.SKIP_JOB - name: install WIX run: src/ci/scripts/install-wix.sh if: success() && !env.SKIP_JOB @@ -483,6 +486,9 @@ jobs: - name: install clang run: src/ci/scripts/install-clang.sh if: success() && !env.SKIP_JOB + - name: install tidy + run: src/ci/scripts/install-tidy.sh + if: success() && !env.SKIP_JOB - name: install WIX run: src/ci/scripts/install-wix.sh if: success() && !env.SKIP_JOB @@ -607,6 +613,9 @@ jobs: - name: install clang run: src/ci/scripts/install-clang.sh if: success() && !env.SKIP_JOB + - name: install tidy + run: src/ci/scripts/install-tidy.sh + if: success() && !env.SKIP_JOB - name: install WIX run: src/ci/scripts/install-wix.sh if: success() && !env.SKIP_JOB diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml index b415eb5961bb..6518a88732f6 100644 --- a/src/ci/github-actions/ci.yml +++ b/src/ci/github-actions/ci.yml @@ -173,6 +173,10 @@ x--expand-yaml-anchors--remove: run: src/ci/scripts/install-clang.sh <<: *step + - name: install tidy + run: src/ci/scripts/install-tidy.sh + <<: *step + - name: install WIX run: src/ci/scripts/install-wix.sh <<: *step diff --git a/src/ci/scripts/install-tidy.sh b/src/ci/scripts/install-tidy.sh new file mode 100755 index 000000000000..fab126453fdc --- /dev/null +++ b/src/ci/scripts/install-tidy.sh @@ -0,0 +1,24 @@ +#!/bin/bash +# This script downloads and installs the tidy binary from Homebrew. + +set -euo pipefail +IFS=$'\n\t' + +source "$(cd "$(dirname "$0")" && pwd)/../shared.sh" + +# Only the macOS arm64/aarch64 GitHub Actions runner needs to have tidy +# installed; other platforms have it preinstalled. + +if isMacOS; then + platform=$(uname -m) + case $platform in + x86_64) + ;; + arm64) + brew install tidy-html5 + ;; + *) + echo "unsupported architecture: ${platform}" + exit 1 + esac +fi From 6909992501b400c8cd7d75e8d61365b2c20015f9 Mon Sep 17 00:00:00 2001 From: Jake Goulding Date: Tue, 31 Oct 2023 11:05:56 -0400 Subject: [PATCH 351/435] Run tests in CI for aarch64-apple-darwin --- .github/workflows/ci.yml | 13 +++++++++++++ src/ci/github-actions/ci.yml | 19 +++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 475521071961..5f659a1c3060 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -373,6 +373,19 @@ jobs: NO_OVERFLOW_CHECKS: 1 DIST_REQUIRE_ALL_TOOLS: 1 os: macos-13-xlarge + - name: aarch64-apple + env: + SCRIPT: "./x.py --stage 2 test --host=aarch64-apple-darwin --target=aarch64-apple-darwin" + RUST_CONFIGURE_ARGS: "--enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false" + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + SELECT_XCODE: /Applications/Xcode_13.4.1.app + USE_XCODE_CLANG: 1 + MACOSX_DEPLOYMENT_TARGET: 11.0 + MACOSX_STD_DEPLOYMENT_TARGET: 11.0 + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + NO_OVERFLOW_CHECKS: 1 + os: macos-13-xlarge - name: x86_64-msvc env: RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --enable-profiler" diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml index 6518a88732f6..da29ffb8e5f9 100644 --- a/src/ci/github-actions/ci.yml +++ b/src/ci/github-actions/ci.yml @@ -569,6 +569,25 @@ jobs: DIST_REQUIRE_ALL_TOOLS: 1 <<: *job-macos-m1 + # This target only needs to support 11.0 and up as nothing else supports the hardware + - name: aarch64-apple + env: + SCRIPT: ./x.py --stage 2 test --host=aarch64-apple-darwin --target=aarch64-apple-darwin + RUST_CONFIGURE_ARGS: >- + --enable-sanitizers + --enable-profiler + --set rust.jemalloc + --set llvm.ninja=false + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + SELECT_XCODE: /Applications/Xcode_13.4.1.app + USE_XCODE_CLANG: 1 + MACOSX_DEPLOYMENT_TARGET: 11.0 + MACOSX_STD_DEPLOYMENT_TARGET: 11.0 + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + NO_OVERFLOW_CHECKS: 1 + <<: *job-macos-m1 + ###################### # Windows Builders # ###################### From 1854776fa947e6f12dda66ec7858d9c00a11ac95 Mon Sep 17 00:00:00 2001 From: Max Tilley <1138504+3tilley@users.noreply.github.com> Date: Wed, 8 Nov 2023 00:26:55 +0000 Subject: [PATCH 352/435] Reorder type mismatch suggestions Suggestions are reordered to to make sure potential missing expect on Option/Result runs before the suggestion to remove the last method call --- compiler/rustc_hir_typeck/src/demand.rs | 4 ++-- tests/ui/suggestions/issue-117669.rs | 4 ++++ tests/ui/suggestions/issue-117669.stderr | 18 ++++++++++++++++++ 3 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 tests/ui/suggestions/issue-117669.rs create mode 100644 tests/ui/suggestions/issue-117669.stderr diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index abb832280301..dbbfddc1556c 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -43,6 +43,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Use `||` to give these suggestions a precedence let suggested = self.suggest_missing_parentheses(err, expr) + || self.suggest_missing_unwrap_expect(err, expr, expected, expr_ty) || self.suggest_remove_last_method_call(err, expr, expected) || self.suggest_associated_const(err, expr, expected) || self.suggest_deref_ref_or_into(err, expr, expected, expr_ty, expected_ty_expr) @@ -58,8 +59,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { || self.suggest_into(err, expr, expr_ty, expected) || self.suggest_floating_point_literal(err, expr, expected) || self.suggest_null_ptr_for_literal_zero_given_to_ptr_arg(err, expr, expected) - || self.suggest_coercing_result_via_try_operator(err, expr, expected, expr_ty) - || self.suggest_missing_unwrap_expect(err, expr, expected, expr_ty); + || self.suggest_coercing_result_via_try_operator(err, expr, expected, expr_ty); if !suggested { self.note_source_of_type_mismatch_constraint( diff --git a/tests/ui/suggestions/issue-117669.rs b/tests/ui/suggestions/issue-117669.rs new file mode 100644 index 000000000000..09b4f2bd47ca --- /dev/null +++ b/tests/ui/suggestions/issue-117669.rs @@ -0,0 +1,4 @@ +fn main() { + let abs: i32 = 3i32.checked_abs(); + //~^ ERROR mismatched types +} diff --git a/tests/ui/suggestions/issue-117669.stderr b/tests/ui/suggestions/issue-117669.stderr new file mode 100644 index 000000000000..f09675fcc5c9 --- /dev/null +++ b/tests/ui/suggestions/issue-117669.stderr @@ -0,0 +1,18 @@ +error[E0308]: mismatched types + --> $DIR/issue-117669.rs:2:20 + | +LL | let abs: i32 = 3i32.checked_abs(); + | --- ^^^^^^^^^^^^^^^^^^ expected `i32`, found `Option` + | | + | expected due to this + | + = note: expected type `i32` + found enum `Option` +help: consider using `Option::expect` to unwrap the `Option` value, panicking if the value is an `Option::None` + | +LL | let abs: i32 = 3i32.checked_abs().expect("REASON"); + | +++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. From 33edea60f018f889ce1a9f29c0d7617e859efa76 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 8 Nov 2023 15:44:29 +0100 Subject: [PATCH 353/435] Add test for reexported hidden item with `--document-hidden-items` --- tests/rustdoc-json/reexport/reexport_of_hidden.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 tests/rustdoc-json/reexport/reexport_of_hidden.rs diff --git a/tests/rustdoc-json/reexport/reexport_of_hidden.rs b/tests/rustdoc-json/reexport/reexport_of_hidden.rs new file mode 100644 index 000000000000..1b6ff5fadca1 --- /dev/null +++ b/tests/rustdoc-json/reexport/reexport_of_hidden.rs @@ -0,0 +1,10 @@ +// compile-flags: --document-hidden-items + +// @has "$.index[*].inner[?(@.import.name=='UsedHidden')]" +// @has "$.index[*][?(@.name=='Hidden')]" +pub mod submodule { + #[doc(hidden)] + pub struct Hidden {} +} + +pub use submodule::Hidden as UsedHidden; From 7c385f5a03c08df98aca71fbe4ef57dff66ffa56 Mon Sep 17 00:00:00 2001 From: Ramon de C Valle Date: Fri, 28 Jul 2023 16:22:04 -0700 Subject: [PATCH 354/435] Update exploit mitigations documentation Updates the rustc book with most up to date information about exploit mitigations supported by the Rust compiler. --- src/doc/rustc/src/exploit-mitigations.md | 130 ++++++++++++----------- src/doc/rustc/src/images/image1.png | Bin 15293 -> 164896 bytes src/doc/rustc/src/images/image2.png | Bin 28772 -> 155307 bytes src/doc/rustc/src/images/image3.png | Bin 19069 -> 19936 bytes 4 files changed, 66 insertions(+), 64 deletions(-) diff --git a/src/doc/rustc/src/exploit-mitigations.md b/src/doc/rustc/src/exploit-mitigations.md index f02a4dcf963a..d4e2fc52e973 100644 --- a/src/doc/rustc/src/exploit-mitigations.md +++ b/src/doc/rustc/src/exploit-mitigations.md @@ -43,7 +43,8 @@ understood within a given context. This section documents the exploit mitigations applicable to the Rust compiler when building programs for the Linux operating system on the AMD64 architecture and equivalent.1 +class="footnote">1 All examples in this section were built using +nightly builds of the Rust compiler on Debian testing. The Rust Programming Language currently has no specification. The Rust compiler (i.e., rustc) is the language reference implementation. All references to “the @@ -102,7 +103,10 @@ and unsigned integer computations that cannot be represented in their type, resulting in an overflow or wraparound. The Rust compiler supports integer overflow checks, and enables it when debug -assertions are enabled since version 1.1.0 (2015-06-25)[14]–[20]. +assertions are enabled since version 1.0.0 (2015-05-15)[14]–[17], but support +for it was not completed until version 1.1.0 (2015-06-25)[16]. An option to +control integer overflow checks was later stabilized in version 1.17.0 +(2017-04-27)[18]–[20]. ```compile_fail fn main() { @@ -120,7 +124,7 @@ $ cargo run thread 'main' panicked at 'attempt to add with overflow', src/main.rs:3:23 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace. ``` -Fig. 3. Build and execution of hello-rust-integer with debug assertions +Fig. 3. Build and execution of hello-rust-integer with debug assertions enabled. ```text @@ -130,7 +134,7 @@ $ cargo run --release Running `target/release/hello-rust-integer` u: 0 ``` -Fig. 4. Build and execution of hello-rust-integer with debug assertions +Fig. 4. Build and execution of hello-rust-integer with debug assertions disabled. Integer overflow checks are enabled when debug assertions are enabled (see Fig. @@ -156,7 +160,7 @@ Non-executable memory regions increase the difficulty of exploitation by limiting the memory regions that can be used to execute arbitrary code. Most modern processors provide support for the operating system to mark memory regions as non executable, but it was previously emulated by software, such as -in grsecurity/PaX's [PAGEEXEC](https://pax.grsecurity.net/docs/pageexec.txt) +in grsecurity/PaX’s [PAGEEXEC](https://pax.grsecurity.net/docs/pageexec.txt) and [SEGMEXEC](https://pax.grsecurity.net/docs/segmexec.txt), on processors that did not provide support for it. This is also known as “No Execute (NX) Bit”, “Execute Disable (XD) Bit”, “Execute Never (XN) Bit”, and others. @@ -171,7 +175,7 @@ $ readelf -l target/release/hello-rust | grep -A 1 GNU_STACK GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 RW 0x10 ``` -Fig. 5. Checking if non-executable memory regions are enabled for a given +Fig. 5. Checking if non-executable memory regions are enabled for a given binary. The presence of an element of type `PT_GNU_STACK` in the program header table @@ -199,30 +203,33 @@ when attempting to read from the guard page/region. This is also referred to as The Rust compiler supports stack clashing protection via stack probing, and enables it by default since version 1.20.0 (2017-08-31)[26]–[29]. -![Screenshot of IDA Pro listing cross references to __rust_probestack in hello-rust.](images/image1.png "Cross references to __rust_probestack in hello-rust.") -Fig. 6. IDA Pro listing cross references to `__rust_probestack` in hello-rust. - ```rust -fn hello() { - println!("Hello, world!"); -} - fn main() { - let _: [u64; 1024] = [0; 1024]; - hello(); + let v: [u8; 16384] = [1; 16384]; + let first = &v[0]; + println!("The first element is: {first}"); } ``` -Fig 7. Modified hello-rust. +Fig. 6. hello-rust-stack-probe-1 program. -![Screenshot of IDA Pro listing cross references to __rust_probestack in modified hello-rust.](images/image2.png "Cross references to __rust_probestack in modified hello-rust.") -Fig. 8. IDA Pro listing cross references to `__rust_probestack` in modified -hello-rust. +![Screenshot of IDA Pro listing the "unrolled loop" stack probe variant in modified hello-rust.](images/image1.png "The \"unrolled loop\" stack probe variant in modified hello-rust.") +Fig. 7. The "unrolled loop" stack probe variant in modified hello-rust. -To check if stack clashing protection is enabled for a given binary, search for -cross references to `__rust_probestack`. The `__rust_probestack` is called in -the prologue of functions whose stack size is larger than a page size (see Fig. -6), and can be forced for illustration purposes by modifying the hello-rust -example as seen in Fig. 7 and Fig. 8. +```rust +fn main() { + let v: [u8; 65536] = [1; 65536]; + let first = &v[0]; + println!("The first element is: {first}"); +} +``` +Fig. 8. hello-rust-stack-probe-2 program. + +![Screenshot of IDA Pro listing the "standard loop" stack probe variant in modified hello-rust.](images/image2.png "The \"standard loop\" stack probe variant in modified hello-rust.") +Fig. 9. The "standard loop" stack probe variant in modified hello-rust. + +To check if stack clashing protection is enabled for a given binary, look for +any of the two stack probe variants in the prologue of functions whose stack +size is larger than a page size (see Figs. 6–9). ### Read-only relocations and immediate binding @@ -272,7 +279,7 @@ section indicates immediate binding is not enabled for a given binary. The presence of both an element of type `PT_GNU_RELRO` in the program header table and of an element with the `DT_BIND_NOW` tag and the `DF_BIND_NOW` flag in the dynamic section indicates full RELRO is enabled for a given binary (see -Fig. 9 and Fig. 10). +Figs. 9–10). 4\. And the `DF_1_NOW` flag for some link editors. @@ -321,7 +328,7 @@ $ cargo run free(): invalid next size (normal) Aborted ``` -Fig. 12. Build and execution of hello-rust-heap with debug assertions enabled. +Fig. 12. Build and execution of hello-rust-heap with debug assertions enabled. ```text $ cargo run --release @@ -331,10 +338,10 @@ $ cargo run --release free(): invalid next size (normal) Aborted ``` -Fig. 13. Build and execution of hello-rust-heap with debug assertions disabled. +Fig. 13. Build and execution of hello-rust-heap with debug assertions disabled. -Heap corruption checks are being performed when using the default allocator -(i.e., the GNU Allocator) as seen in Fig. 12 and Fig. 13. +Heap corruption checks are performed when using the default allocator (i.e., +the GNU Allocator) (see Figs. 12–13). 5\. Linux's standard C library default allocator is the GNU Allocator, which is derived from ptmalloc (pthreads malloc) by Wolfram Gloger, @@ -350,15 +357,13 @@ instruction pointer, and checking if this value has changed when returning from a function. This is also known as “Stack Protector” or “Stack Smashing Protector (SSP)”. -The Rust compiler supports stack smashing protection on nightly builds[42]. +The Rust compiler supports stack smashing protection on nightly builds[40]. ![Screenshot of IDA Pro listing cross references to __stack_chk_fail in hello-rust.](images/image3.png "Cross references to __stack_chk_fail in hello-rust.") Fig. 14. IDA Pro listing cross references to `__stack_chk_fail` in hello-rust. To check if stack smashing protection is enabled for a given binary, search for -cross references to `__stack_chk_fail`. The presence of these cross-references -in Rust-compiled code (e.g., `hello_rust::main`) indicates that the stack -smashing protection is enabled (see Fig. 14). +cross references to `__stack_chk_fail` (see Fig. 14). ### Forward-edge control flow protection @@ -380,17 +385,14 @@ commercially available [grsecurity/PaX Reuse Attack Protector (RAP)](https://grsecurity.net/rap_faq). The Rust compiler supports forward-edge control flow protection on nightly -builds[40]-[41] 6. ```text -$ readelf -s -W target/debug/rust-cfi | grep "\.cfi" - 12: 0000000000005170 46 FUNC LOCAL DEFAULT 14 _RNvCsjaOHoaNjor6_8rust_cfi7add_one.cfi - 15: 00000000000051a0 16 FUNC LOCAL DEFAULT 14 _RNvCsjaOHoaNjor6_8rust_cfi7add_two.cfi - 17: 0000000000005270 396 FUNC LOCAL DEFAULT 14 _RNvCsjaOHoaNjor6_8rust_cfi4main.cfi -... +$ readelf -s -W target/release/hello-rust | grep "\.cfi" + 5: 0000000000006480 657 FUNC LOCAL DEFAULT 15 _ZN10hello_rust4main17h4e359f1dcd627c83E.cfi ``` -Fig. 15. Checking if LLVM CFI is enabled for a given binary[41]. +Fig. 15. Checking if LLVM CFI is enabled for a given binary. The presence of symbols suffixed with ".cfi" or the `__cfi_init` symbol (and references to `__cfi_check`) indicates that LLVM CFI (i.e., forward-edge @@ -429,21 +431,21 @@ Newer processors provide hardware assistance for backward-edge control flow protection, such as ARM Pointer Authentication, and Intel Shadow Stack as part of Intel CET. -The Rust compiler supports shadow stack for aarch64 only 7 on nightly Rust -compilers [43]-[44]. Safe stack is available on nightly Rust compilers -[45]-[46]. +The Rust compiler supports shadow stack for the AArch64 architecture7on +nightly builds[43]-[44], and also supports safe stack on nightly +builds[45]-[46]. ```text $ readelf -s target/release/hello-rust | grep __safestack_init - 1177: 00000000000057b0 444 FUNC GLOBAL DEFAULT 9 __safestack_init + 678: 0000000000008c80 426 FUNC GLOBAL DEFAULT 15 __safestack_init ``` Fig. 16. Checking if LLVM SafeStack is enabled for a given binary. The presence of the `__safestack_init` symbol indicates that LLVM SafeStack is -enabled for a given binary (see Fig. 16). Conversely, the absence of the -`__safestack_init` symbol indicates that LLVM SafeStack is not enabled for a -given binary. +enabled for a given binary. Conversely, the absence of the `__safestack_init` +symbol indicates that LLVM SafeStack is not enabled for a given binary (see +Fig. 16). 7\. The shadow stack implementation for the AMD64 architecture and equivalent in LLVM was removed due to performance and security issues. . -26. “Replace stack overflow checking with stack probes #16012.” GitHub. +26. Zoxc. “Replace stack overflow checking with stack probes #16012.” GitHub. . -27. B. Striegel. “Extend stack probe support to non-tier-1 platforms, and - clarify policy for mitigating LLVM-dependent unsafety #43241.” GitHub. - . - -28. A. Crichton. “rustc: Implement stack probes for x86 #42816.” GitHub. +27. A. Crichton. “rustc: Implement stack probes for x86 #42816.” GitHub. . -29. A. Crichton. “Add \_\_rust\_probestack intrinsic #175.” GitHub. +28. A. Crichton. “Add \_\_rust\_probestack intrinsic #175.” GitHub. . +29. S. Guelton, S. Ledru, J. Stone. “Bringing Stack Clash Protection to Clang / + X86 — the Open Source Way.” The LLVM Project Blog. + . + 30. B. Anderson. “Consider applying -Wl,-z,relro or -Wl,-z,relro,-z,now by default #29877.” GitHub. . @@ -605,16 +607,16 @@ to `READ_IMPLIES_EXEC`). 39. A. Crichton. “Remove the alloc\_jemalloc crate #55238.” GitHub. . -40. R. de C Valle. “Tracking Issue for LLVM Control Flow Integrity (CFI) Support - for Rust #89653.” GitHub. . - -41. “ControlFlowIntegrity.” The Rust Unstable Book. - [https://doc.rust-lang.org/unstable-book/compiler-flags/sanitizer.html#controlflowintegrity](../unstable-book/compiler-flags/sanitizer.html#controlflowintegrity). - -42. bbjornse. “add codegen option for using LLVM stack smash protection #84197.” +40. bbjornse. “Add codegen option for using LLVM stack smash protection #84197.” GitHub. -43. ivanloz. “Add support for LLVM ShadowCallStack. #98208.” GitHub. +41. R. de C. Valle. “Tracking Issue for LLVM Control Flow Integrity (CFI) Support + for Rust #89653.” GitHub. . + +42. “ControlFlowIntegrity.” The Rust Unstable Book. + [https://doc.rust-lang.org/unstable-book/compiler-flags/sanitizer.html#controlflowintegrity](../unstable-book/compiler-flags/sanitizer.html#controlflowintegrity). + +43. I. Lozano. “Add support for LLVM ShadowCallStack #98208.” GitHub. . 44. “ShadowCallStack.” The Rust Unstable Book. diff --git a/src/doc/rustc/src/images/image1.png b/src/doc/rustc/src/images/image1.png index ee2d3fd4f43c6727b5042114519e12917242c3c6..0da45e56620dab85ac83e44482acc71ae18e486c 100644 GIT binary patch literal 164896 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 literal 15293 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
      N)1e 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 M>FVdQ&MBb@02w^=qyPW_ From 30588657b753b9ae500b3514d58da18a4a155b08 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 8 Nov 2023 20:37:08 +0100 Subject: [PATCH 355/435] avoid unnecessary nested conditionals --- .../src/thir/pattern/const_to_pat.rs | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index a5e7cae69349..48a590f5d37f 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -228,17 +228,15 @@ impl<'tcx> ConstToPat<'tcx> { } } } - } else if !self.saw_const_match_lint.get() { - if !have_valtree { - // The only way valtree construction can fail without the structural match - // checker finding a violation is if there is a pointer somewhere. - self.tcx().emit_spanned_lint( - lint::builtin::POINTER_STRUCTURAL_MATCH, - self.id, - self.span, - PointerPattern, - ); - } + } else if !have_valtree && !self.saw_const_match_lint.get() { + // The only way valtree construction can fail without the structural match + // checker finding a violation is if there is a pointer somewhere. + self.tcx().emit_spanned_lint( + lint::builtin::POINTER_STRUCTURAL_MATCH, + self.id, + self.span, + PointerPattern, + ); } // Always check for `PartialEq`, even if we emitted other lints. (But not if there were From de0458af970adfd768b18bac7cb5a377f837378c Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Wed, 8 Nov 2023 23:45:31 +0300 Subject: [PATCH 356/435] speed up `x clean` Since `x clean` runs with bootstrap, we can speed up this process by avoiding the cleaning of bootstrap artifacts, as they are not necessarily needed to be cleaned. Signed-off-by: onur-ozkan --- src/bootstrap/src/core/build_steps/clean.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/bootstrap/src/core/build_steps/clean.rs b/src/bootstrap/src/core/build_steps/clean.rs index 679770ce0ec7..1f0ca2ac5c88 100644 --- a/src/bootstrap/src/core/build_steps/clean.rs +++ b/src/bootstrap/src/core/build_steps/clean.rs @@ -139,7 +139,6 @@ fn clean_specific_stage(build: &Build, stage: u32) { fn clean_default(build: &Build) { rm_rf(&build.out.join("tmp")); rm_rf(&build.out.join("dist")); - rm_rf(&build.out.join("bootstrap")); rm_rf(&build.out.join("rustfmt.stamp")); for host in &build.hosts { From 622be2d138e2849e0b9ea9afb2a83f31ba030be1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Wed, 8 Nov 2023 22:17:27 +0100 Subject: [PATCH 357/435] Restore rustc shim error message --- src/bootstrap/src/bin/rustc.rs | 3 +++ src/bootstrap/src/utils/bin_helpers.rs | 1 - 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/src/bin/rustc.rs b/src/bootstrap/src/bin/rustc.rs index 3041fd37ac80..e3c010eb49c5 100644 --- a/src/bootstrap/src/bin/rustc.rs +++ b/src/bootstrap/src/bin/rustc.rs @@ -32,6 +32,9 @@ fn main() { let args = env::args_os().skip(1).collect::>(); let arg = |name| args.windows(2).find(|args| args[0] == name).and_then(|args| args[1].to_str()); + // We don't use the stage in this shim, but let's parse it to make sure that we're invoked + // by bootstrap, or that we provide a helpful error message if not. + bin_helpers::parse_rustc_stage(); let verbose = bin_helpers::parse_rustc_verbose(); // Detect whether or not we're a build script depending on whether --target diff --git a/src/bootstrap/src/utils/bin_helpers.rs b/src/bootstrap/src/utils/bin_helpers.rs index b9177c490ac2..ab41a6b96002 100644 --- a/src/bootstrap/src/utils/bin_helpers.rs +++ b/src/bootstrap/src/utils/bin_helpers.rs @@ -18,7 +18,6 @@ pub(crate) fn parse_rustc_verbose() -> usize { /// Parses the value of the "RUSTC_STAGE" environment variable and returns it as a `String`. /// /// If "RUSTC_STAGE" was not set, the program will be terminated with 101. -#[allow(unused)] pub(crate) fn parse_rustc_stage() -> String { std::env::var("RUSTC_STAGE").unwrap_or_else(|_| { // Don't panic here; it's reasonable to try and run these shims directly. Give a helpful error instead. From a42eca42df821a1d6e74a931195a00258f94bd6a Mon Sep 17 00:00:00 2001 From: lcnr Date: Wed, 8 Nov 2023 13:55:21 +0100 Subject: [PATCH 358/435] generator layout: ignore fake borrows --- .../src/impls/borrowed_locals.rs | 9 +++-- .../src/cleanup_post_borrowck.rs | 2 +- .../ui/coroutine/witness-ignore-fake-reads.rs | 34 +++++++++++++++++++ 3 files changed, 42 insertions(+), 3 deletions(-) create mode 100644 tests/ui/coroutine/witness-ignore-fake-reads.rs diff --git a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs index 1e8e09ac333b..48cc33fafb5b 100644 --- a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs +++ b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs @@ -5,7 +5,8 @@ use rustc_middle::mir::*; use crate::{AnalysisDomain, GenKill, GenKillAnalysis}; /// A dataflow analysis that tracks whether a pointer or reference could possibly exist that points -/// to a given local. +/// to a given local. This analysis ignores fake borrows, so it should not be used by +/// borrowck. /// /// At present, this is used as a very limited form of alias analysis. For example, /// `MaybeBorrowedLocals` is used to compute which locals are live during a yield expression for @@ -91,13 +92,17 @@ where self.super_rvalue(rvalue, location); match rvalue { - Rvalue::AddressOf(_, borrowed_place) | Rvalue::Ref(_, _, borrowed_place) => { + // We ignore fake borrows as these get removed after analysis and shouldn't effect + // the layout of generators. + Rvalue::AddressOf(_, borrowed_place) + | Rvalue::Ref(_, BorrowKind::Mut { .. } | BorrowKind::Shared, borrowed_place) => { if !borrowed_place.is_indirect() { self.trans.gen(borrowed_place.local); } } Rvalue::Cast(..) + | Rvalue::Ref(_, BorrowKind::Shallow, _) | Rvalue::ShallowInitBox(..) | Rvalue::Use(..) | Rvalue::ThreadLocalRef(..) diff --git a/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs b/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs index d435d3ee69b7..1164dcf29da8 100644 --- a/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs +++ b/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs @@ -4,7 +4,7 @@ //! //! - [`AscribeUserType`] //! - [`FakeRead`] -//! - [`Assign`] statements with a [`Shallow`] borrow +//! - [`Assign`] statements with a [`Fake`] borrow //! //! [`AscribeUserType`]: rustc_middle::mir::StatementKind::AscribeUserType //! [`Assign`]: rustc_middle::mir::StatementKind::Assign diff --git a/tests/ui/coroutine/witness-ignore-fake-reads.rs b/tests/ui/coroutine/witness-ignore-fake-reads.rs new file mode 100644 index 000000000000..ccf9ce8b49e1 --- /dev/null +++ b/tests/ui/coroutine/witness-ignore-fake-reads.rs @@ -0,0 +1,34 @@ +// check-pass +// edition: 2021 + +// regression test for #117059 +struct SendNotSync(*const ()); +unsafe impl Send for SendNotSync {} +// impl !Sync for SendNotSync {} // automatically disabled + +struct Inner { + stream: SendNotSync, + state: bool, +} + +struct SendSync; +impl std::ops::Deref for SendSync { + type Target = Inner; + fn deref(&self) -> &Self::Target { + todo!(); + } +} + +async fn next() { + let inner = SendSync; + match inner.state { + true if false => {} + false => async {}.await, + _ => {} + } +} + +fn is_send(_: T) {} +fn main() { + is_send(next()) +} From 992d93f687c75f8f5ee69e0fb43bff509c7c9cb8 Mon Sep 17 00:00:00 2001 From: lcnr Date: Wed, 8 Nov 2023 13:42:30 +0100 Subject: [PATCH 359/435] rename `BorrowKind::Shallow` to `Fake` also adds some comments --- compiler/rustc_borrowck/src/borrow_set.rs | 2 +- compiler/rustc_borrowck/src/def_use.rs | 2 +- .../src/diagnostics/conflict_errors.rs | 13 +++++----- .../rustc_borrowck/src/diagnostics/mod.rs | 2 +- compiler/rustc_borrowck/src/invalidation.rs | 10 ++++---- compiler/rustc_borrowck/src/lib.rs | 24 +++++++++---------- .../rustc_borrowck/src/places_conflict.rs | 6 ++--- compiler/rustc_borrowck/src/type_check/mod.rs | 2 +- compiler/rustc_codegen_ssa/src/mir/analyze.rs | 2 +- .../src/transform/check_consts/check.rs | 6 ++--- .../src/transform/check_consts/resolver.rs | 2 +- .../src/transform/promote_consts.rs | 2 +- .../src/transform/validate.rs | 4 ++-- compiler/rustc_middle/src/mir/pretty.rs | 2 +- compiler/rustc_middle/src/mir/statement.rs | 4 ++-- compiler/rustc_middle/src/mir/syntax.rs | 4 ++-- compiler/rustc_middle/src/mir/tcx.rs | 2 +- compiler/rustc_middle/src/mir/visit.rs | 10 ++++---- .../src/build/expr/as_place.rs | 2 +- .../rustc_mir_build/src/build/matches/mod.rs | 2 +- .../rustc_mir_build/src/check_unsafety.rs | 6 ++--- .../src/impls/borrowed_locals.rs | 2 +- .../rustc_mir_dataflow/src/impls/liveness.rs | 2 +- .../src/cleanup_post_borrowck.rs | 4 ++-- .../rustc_mir_transform/src/const_prop.rs | 2 +- compiler/rustc_mir_transform/src/copy_prop.rs | 2 +- compiler/rustc_mir_transform/src/coroutine.rs | 13 +++++++--- compiler/rustc_mir_transform/src/ssa.rs | 2 +- compiler/rustc_smir/src/rustc_smir/mod.rs | 2 +- compiler/stable_mir/src/mir/body.rs | 5 ++-- 30 files changed, 75 insertions(+), 68 deletions(-) diff --git a/compiler/rustc_borrowck/src/borrow_set.rs b/compiler/rustc_borrowck/src/borrow_set.rs index 0b44beeb004c..5248a649c349 100644 --- a/compiler/rustc_borrowck/src/borrow_set.rs +++ b/compiler/rustc_borrowck/src/borrow_set.rs @@ -71,7 +71,7 @@ impl<'tcx> fmt::Display for BorrowData<'tcx> { fn fmt(&self, w: &mut fmt::Formatter<'_>) -> fmt::Result { let kind = match self.kind { mir::BorrowKind::Shared => "", - mir::BorrowKind::Shallow => "shallow ", + mir::BorrowKind::Fake => "fake ", mir::BorrowKind::Mut { kind: mir::MutBorrowKind::ClosureCapture } => "uniq ", // FIXME: differentiate `TwoPhaseBorrow` mir::BorrowKind::Mut { diff --git a/compiler/rustc_borrowck/src/def_use.rs b/compiler/rustc_borrowck/src/def_use.rs index 201f0df12387..d0cf339e7ba4 100644 --- a/compiler/rustc_borrowck/src/def_use.rs +++ b/compiler/rustc_borrowck/src/def_use.rs @@ -49,7 +49,7 @@ pub fn categorize(context: PlaceContext) -> Option { // cross suspension points so this behavior is unproblematic. PlaceContext::MutatingUse(MutatingUseContext::Borrow) | PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow) | - PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow) | + PlaceContext::NonMutatingUse(NonMutatingUseContext::FakeBorrow) | // `PlaceMention` and `AscribeUserType` both evaluate the place, which must not // contain dangling references. diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 247200dcd269..9a8f1c97edf4 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -1022,7 +1022,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { self.cannot_uniquely_borrow_by_two_closures(span, &desc_place, issued_span, None) } - (BorrowKind::Mut { .. }, BorrowKind::Shallow) => { + (BorrowKind::Mut { .. }, BorrowKind::Fake) => { if let Some(immutable_section_description) = self.classify_immutable_section(issued_borrow.assigned_place) { @@ -1114,11 +1114,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ) } - (BorrowKind::Shared, BorrowKind::Shared | BorrowKind::Shallow) - | ( - BorrowKind::Shallow, - BorrowKind::Mut { .. } | BorrowKind::Shared | BorrowKind::Shallow, - ) => unreachable!(), + (BorrowKind::Shared, BorrowKind::Shared | BorrowKind::Fake) + | (BorrowKind::Fake, BorrowKind::Mut { .. } | BorrowKind::Shared | BorrowKind::Fake) => { + unreachable!() + } }; if issued_spans == borrow_spans { @@ -2806,7 +2805,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let loan_span = loan_spans.args_or_use(); let descr_place = self.describe_any_place(place.as_ref()); - if loan.kind == BorrowKind::Shallow { + if loan.kind == BorrowKind::Fake { if let Some(section) = self.classify_immutable_section(loan.assigned_place) { let mut err = self.cannot_mutate_in_immutable_section( span, diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 4b95b4783eb4..c4323fef9355 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -634,7 +634,7 @@ impl UseSpans<'_> { err.subdiagnostic(match kind { Some(kd) => match kd { rustc_middle::mir::BorrowKind::Shared - | rustc_middle::mir::BorrowKind::Shallow => { + | rustc_middle::mir::BorrowKind::Fake => { CaptureVarKind::Immut { kind_span: capture_kind_span } } diff --git a/compiler/rustc_borrowck/src/invalidation.rs b/compiler/rustc_borrowck/src/invalidation.rs index 7b5b52e39b12..ec6d7b74e61a 100644 --- a/compiler/rustc_borrowck/src/invalidation.rs +++ b/compiler/rustc_borrowck/src/invalidation.rs @@ -253,8 +253,8 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> { match rvalue { &Rvalue::Ref(_ /*rgn*/, bk, place) => { let access_kind = match bk { - BorrowKind::Shallow => { - (Shallow(Some(ArtificialField::ShallowBorrow)), Read(ReadKind::Borrow(bk))) + BorrowKind::Fake => { + (Shallow(Some(ArtificialField::FakeBorrow)), Read(ReadKind::Borrow(bk))) } BorrowKind::Shared => (Deep, Read(ReadKind::Borrow(bk))), BorrowKind::Mut { .. } => { @@ -376,8 +376,8 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> { // have already taken the reservation } - (Read(_), BorrowKind::Shallow | BorrowKind::Shared) - | (Read(ReadKind::Borrow(BorrowKind::Shallow)), BorrowKind::Mut { .. }) => { + (Read(_), BorrowKind::Fake | BorrowKind::Shared) + | (Read(ReadKind::Borrow(BorrowKind::Fake)), BorrowKind::Mut { .. }) => { // Reads don't invalidate shared or shallow borrows } @@ -422,7 +422,7 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> { // only mutable borrows should be 2-phase assert!(match borrow.kind { - BorrowKind::Shared | BorrowKind::Shallow => false, + BorrowKind::Shared | BorrowKind::Fake => false, BorrowKind::Mut { .. } => true, }); diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 1a74582389d1..5787ea13e793 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -846,7 +846,7 @@ use self::ReadOrWrite::{Activation, Read, Reservation, Write}; #[derive(Copy, Clone, PartialEq, Eq, Debug)] enum ArtificialField { ArrayLength, - ShallowBorrow, + FakeBorrow, } #[derive(Copy, Clone, PartialEq, Eq, Debug)] @@ -1085,18 +1085,18 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { Control::Continue } - (Read(_), BorrowKind::Shared | BorrowKind::Shallow) - | (Read(ReadKind::Borrow(BorrowKind::Shallow)), BorrowKind::Mut { .. }) => { + (Read(_), BorrowKind::Shared | BorrowKind::Fake) + | (Read(ReadKind::Borrow(BorrowKind::Fake)), BorrowKind::Mut { .. }) => { Control::Continue } - (Reservation(_), BorrowKind::Shallow | BorrowKind::Shared) => { + (Reservation(_), BorrowKind::Fake | BorrowKind::Shared) => { // This used to be a future compatibility warning (to be // disallowed on NLL). See rust-lang/rust#56254 Control::Continue } - (Write(WriteKind::Move), BorrowKind::Shallow) => { + (Write(WriteKind::Move), BorrowKind::Fake) => { // Handled by initialization checks. Control::Continue } @@ -1204,8 +1204,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { match rvalue { &Rvalue::Ref(_ /*rgn*/, bk, place) => { let access_kind = match bk { - BorrowKind::Shallow => { - (Shallow(Some(ArtificialField::ShallowBorrow)), Read(ReadKind::Borrow(bk))) + BorrowKind::Fake => { + (Shallow(Some(ArtificialField::FakeBorrow)), Read(ReadKind::Borrow(bk))) } BorrowKind::Shared => (Deep, Read(ReadKind::Borrow(bk))), BorrowKind::Mut { .. } => { @@ -1226,7 +1226,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { flow_state, ); - let action = if bk == BorrowKind::Shallow { + let action = if bk == BorrowKind::Fake { InitializationRequiringAction::MatchOn } else { InitializationRequiringAction::Borrow @@ -1583,7 +1583,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // only mutable borrows should be 2-phase assert!(match borrow.kind { - BorrowKind::Shared | BorrowKind::Shallow => false, + BorrowKind::Shared | BorrowKind::Fake => false, BorrowKind::Mut { .. } => true, }); @@ -2142,14 +2142,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { | WriteKind::Replace | WriteKind::StorageDeadOrDrop | WriteKind::MutableBorrow(BorrowKind::Shared) - | WriteKind::MutableBorrow(BorrowKind::Shallow), + | WriteKind::MutableBorrow(BorrowKind::Fake), ) | Write( WriteKind::Move | WriteKind::Replace | WriteKind::StorageDeadOrDrop | WriteKind::MutableBorrow(BorrowKind::Shared) - | WriteKind::MutableBorrow(BorrowKind::Shallow), + | WriteKind::MutableBorrow(BorrowKind::Fake), ) => { if self.is_mutable(place.as_ref(), is_local_mutation_allowed).is_err() && !self.has_buffered_errors() @@ -2173,7 +2173,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { return false; } Read( - ReadKind::Borrow(BorrowKind::Mut { .. } | BorrowKind::Shared | BorrowKind::Shallow) + ReadKind::Borrow(BorrowKind::Mut { .. } | BorrowKind::Shared | BorrowKind::Fake) | ReadKind::Copy, ) => { // Access authorized diff --git a/compiler/rustc_borrowck/src/places_conflict.rs b/compiler/rustc_borrowck/src/places_conflict.rs index 539d0837659c..777ebf0d438d 100644 --- a/compiler/rustc_borrowck/src/places_conflict.rs +++ b/compiler/rustc_borrowck/src/places_conflict.rs @@ -204,7 +204,7 @@ fn place_components_conflict<'tcx>( match (elem, &base_ty.kind(), access) { (_, _, Shallow(Some(ArtificialField::ArrayLength))) - | (_, _, Shallow(Some(ArtificialField::ShallowBorrow))) => { + | (_, _, Shallow(Some(ArtificialField::FakeBorrow))) => { // The array length is like additional fields on the // type; it does not overlap any existing data there. // Furthermore, if cannot actually be a prefix of any @@ -273,10 +273,10 @@ fn place_components_conflict<'tcx>( // If the second example, where we did, then we still know // that the borrow can access a *part* of our place that // our access cares about, so we still have a conflict. - if borrow_kind == BorrowKind::Shallow + if borrow_kind == BorrowKind::Fake && borrow_place.projection.len() < access_place.projection.len() { - debug!("borrow_conflicts_with_place: shallow borrow"); + debug!("borrow_conflicts_with_place: fake borrow"); false } else { debug!("borrow_conflicts_with_place: full borrow, CONFLICT"); diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 9f30d9d8ba12..608d010394f6 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -751,7 +751,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { PlaceContext::MutatingUse(_) => ty::Invariant, PlaceContext::NonUse(StorageDead | StorageLive | VarDebugInfo) => ty::Invariant, PlaceContext::NonMutatingUse( - Inspect | Copy | Move | PlaceMention | SharedBorrow | ShallowBorrow | AddressOf + Inspect | Copy | Move | PlaceMention | SharedBorrow | FakeBorrow | AddressOf | Projection, ) => ty::Covariant, PlaceContext::NonUse(AscribeUserTy(variance)) => variance, diff --git a/compiler/rustc_codegen_ssa/src/mir/analyze.rs b/compiler/rustc_codegen_ssa/src/mir/analyze.rs index 53cc063e55a5..2285e7f4e01e 100644 --- a/compiler/rustc_codegen_ssa/src/mir/analyze.rs +++ b/compiler/rustc_codegen_ssa/src/mir/analyze.rs @@ -219,7 +219,7 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx> | PlaceContext::NonMutatingUse( NonMutatingUseContext::Inspect | NonMutatingUseContext::SharedBorrow - | NonMutatingUseContext::ShallowBorrow + | NonMutatingUseContext::FakeBorrow | NonMutatingUseContext::AddressOf | NonMutatingUseContext::Projection, ) => { diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index 135c99fefbc8..76116e339859 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -423,8 +423,8 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { BorrowKind::Shared => { PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow) } - BorrowKind::Shallow => { - PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow) + BorrowKind::Fake => { + PlaceContext::NonMutatingUse(NonMutatingUseContext::FakeBorrow) } BorrowKind::Mut { .. } => { PlaceContext::MutatingUse(MutatingUseContext::Borrow) @@ -500,7 +500,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { self.check_mut_borrow(place.local, hir::BorrowKind::Raw) } - Rvalue::Ref(_, BorrowKind::Shared | BorrowKind::Shallow, place) + Rvalue::Ref(_, BorrowKind::Shared | BorrowKind::Fake, place) | Rvalue::AddressOf(Mutability::Not, place) => { let borrowed_place_has_mut_interior = qualifs::in_place::( &self.ccx, diff --git a/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs b/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs index a137f84b7382..a23922c778ff 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs @@ -105,7 +105,7 @@ where fn ref_allows_mutation(&self, kind: mir::BorrowKind, place: mir::Place<'tcx>) -> bool { match kind { mir::BorrowKind::Mut { .. } => true, - mir::BorrowKind::Shared | mir::BorrowKind::Shallow => { + mir::BorrowKind::Shared | mir::BorrowKind::Fake => { self.shared_borrow_allows_mutation(place) } } diff --git a/compiler/rustc_const_eval/src/transform/promote_consts.rs b/compiler/rustc_const_eval/src/transform/promote_consts.rs index 059029766387..32af537e271d 100644 --- a/compiler/rustc_const_eval/src/transform/promote_consts.rs +++ b/compiler/rustc_const_eval/src/transform/promote_consts.rs @@ -456,7 +456,7 @@ impl<'tcx> Validator<'_, 'tcx> { match kind { // Reject these borrow types just to be safe. // FIXME(RalfJung): could we allow them? Should we? No point in it until we have a usecase. - BorrowKind::Shallow | BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture } => { + BorrowKind::Fake | BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture } => { return Err(Unpromotable); } diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index 4d71f7636676..5922922d47b6 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -848,11 +848,11 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { } match rvalue { Rvalue::Use(_) | Rvalue::CopyForDeref(_) | Rvalue::Aggregate(..) => {} - Rvalue::Ref(_, BorrowKind::Shallow, _) => { + Rvalue::Ref(_, BorrowKind::Fake, _) => { if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) { self.fail( location, - "`Assign` statement with a `Shallow` borrow should have been removed in runtime MIR", + "`Assign` statement with a `Fake` borrow should have been removed in runtime MIR", ); } } diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index debd85dad2e0..a1324858416a 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -942,7 +942,7 @@ impl<'tcx> Debug for Rvalue<'tcx> { Ref(region, borrow_kind, ref place) => { let kind_str = match borrow_kind { BorrowKind::Shared => "", - BorrowKind::Shallow => "shallow ", + BorrowKind::Fake => "fake ", BorrowKind::Mut { .. } => "mut ", }; diff --git a/compiler/rustc_middle/src/mir/statement.rs b/compiler/rustc_middle/src/mir/statement.rs index 5864acaed7b2..3471d620ee69 100644 --- a/compiler/rustc_middle/src/mir/statement.rs +++ b/compiler/rustc_middle/src/mir/statement.rs @@ -446,7 +446,7 @@ impl<'tcx> Rvalue<'tcx> { impl BorrowKind { pub fn mutability(&self) -> Mutability { match *self { - BorrowKind::Shared | BorrowKind::Shallow => Mutability::Not, + BorrowKind::Shared | BorrowKind::Fake => Mutability::Not, BorrowKind::Mut { .. } => Mutability::Mut, } } @@ -454,7 +454,7 @@ impl BorrowKind { pub fn allows_two_phase_borrow(&self) -> bool { match *self { BorrowKind::Shared - | BorrowKind::Shallow + | BorrowKind::Fake | BorrowKind::Mut { kind: MutBorrowKind::Default | MutBorrowKind::ClosureCapture } => { false } diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index b6543affc6db..7b0f27f9b348 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -123,7 +123,7 @@ pub enum AnalysisPhase { /// * [`TerminatorKind::FalseEdge`] /// * [`StatementKind::FakeRead`] /// * [`StatementKind::AscribeUserType`] - /// * [`Rvalue::Ref`] with `BorrowKind::Shallow` + /// * [`Rvalue::Ref`] with `BorrowKind::Fake` /// /// Furthermore, `Deref` projections must be the first projection within any place (if they /// appear at all) @@ -182,7 +182,7 @@ pub enum BorrowKind { /// should not prevent `if let None = x { ... }`, for example, because the /// mutating `(*x as Some).0` can't affect the discriminant of `x`. /// We can also report errors with this kind of borrow differently. - Shallow, + Fake, /// Data is mutable and not aliasable. Mut { kind: MutBorrowKind }, diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs index 931ee7fd05ef..6ab2da23a8ad 100644 --- a/compiler/rustc_middle/src/mir/tcx.rs +++ b/compiler/rustc_middle/src/mir/tcx.rs @@ -278,7 +278,7 @@ impl BorrowKind { // We have no type corresponding to a shallow borrow, so use // `&` as an approximation. - BorrowKind::Shallow => hir::Mutability::Not, + BorrowKind::Fake => hir::Mutability::Not, } } } diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 0f0ca3a1420e..d47cfd5712f8 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -649,8 +649,8 @@ macro_rules! make_mir_visitor { BorrowKind::Shared => PlaceContext::NonMutatingUse( NonMutatingUseContext::SharedBorrow ), - BorrowKind::Shallow => PlaceContext::NonMutatingUse( - NonMutatingUseContext::ShallowBorrow + BorrowKind::Fake => PlaceContext::NonMutatingUse( + NonMutatingUseContext::FakeBorrow ), BorrowKind::Mut { .. } => PlaceContext::MutatingUse(MutatingUseContext::Borrow), @@ -1261,8 +1261,8 @@ pub enum NonMutatingUseContext { Move, /// Shared borrow. SharedBorrow, - /// Shallow borrow. - ShallowBorrow, + /// A fake borrow. + FakeBorrow, /// AddressOf for *const pointer. AddressOf, /// PlaceMention statement. @@ -1341,7 +1341,7 @@ impl PlaceContext { matches!( self, PlaceContext::NonMutatingUse( - NonMutatingUseContext::SharedBorrow | NonMutatingUseContext::ShallowBorrow + NonMutatingUseContext::SharedBorrow | NonMutatingUseContext::FakeBorrow ) | PlaceContext::MutatingUse(MutatingUseContext::Borrow) ) } diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs index c6a09f6568a5..7e9191a37d32 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs @@ -690,7 +690,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { fake_borrow_temp.into(), Rvalue::Ref( tcx.lifetimes.re_erased, - BorrowKind::Shallow, + BorrowKind::Fake, Place { local: base_place.local, projection }, ), ); diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index a43aae6f4494..304870274ac6 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -2021,7 +2021,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let re_erased = tcx.lifetimes.re_erased; let scrutinee_source_info = self.source_info(scrutinee_span); for &(place, temp) in fake_borrows { - let borrow = Rvalue::Ref(re_erased, BorrowKind::Shallow, place); + let borrow = Rvalue::Ref(re_erased, BorrowKind::Fake, place); self.cfg.push_assign(block, scrutinee_source_info, Place::from(temp), borrow); } diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 3d895c131a85..fcb563607828 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -288,7 +288,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { ); }; match borrow_kind { - BorrowKind::Shallow | BorrowKind::Shared => { + BorrowKind::Fake | BorrowKind::Shared => { if !ty.is_freeze(self.tcx, self.param_env) { self.requires_unsafe(pat.span, BorrowOfLayoutConstrainedField); } @@ -483,7 +483,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { visit::walk_expr(&mut visitor, expr); if visitor.found { match borrow_kind { - BorrowKind::Shallow | BorrowKind::Shared + BorrowKind::Fake | BorrowKind::Shared if !self.thir[arg].ty.is_freeze(self.tcx, self.param_env) => { self.requires_unsafe(expr.span, BorrowOfLayoutConstrainedField) @@ -491,7 +491,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { BorrowKind::Mut { .. } => { self.requires_unsafe(expr.span, MutationOfLayoutConstrainedField) } - BorrowKind::Shallow | BorrowKind::Shared => {} + BorrowKind::Fake | BorrowKind::Shared => {} } } } diff --git a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs index 48cc33fafb5b..01acc380fa39 100644 --- a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs +++ b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs @@ -102,7 +102,7 @@ where } Rvalue::Cast(..) - | Rvalue::Ref(_, BorrowKind::Shallow, _) + | Rvalue::Ref(_, BorrowKind::Fake, _) | Rvalue::ShallowInitBox(..) | Rvalue::Use(..) | Rvalue::ThreadLocalRef(..) diff --git a/compiler/rustc_mir_dataflow/src/impls/liveness.rs b/compiler/rustc_mir_dataflow/src/impls/liveness.rs index c1152e88cd0f..bdfb6a6ff6b1 100644 --- a/compiler/rustc_mir_dataflow/src/impls/liveness.rs +++ b/compiler/rustc_mir_dataflow/src/impls/liveness.rs @@ -201,7 +201,7 @@ impl DefUse { | NonMutatingUseContext::Inspect | NonMutatingUseContext::Move | NonMutatingUseContext::PlaceMention - | NonMutatingUseContext::ShallowBorrow + | NonMutatingUseContext::FakeBorrow | NonMutatingUseContext::SharedBorrow, ) => Some(DefUse::Use), diff --git a/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs b/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs index 1164dcf29da8..5b4bc4fa1342 100644 --- a/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs +++ b/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs @@ -10,7 +10,7 @@ //! [`Assign`]: rustc_middle::mir::StatementKind::Assign //! [`FakeRead`]: rustc_middle::mir::StatementKind::FakeRead //! [`Nop`]: rustc_middle::mir::StatementKind::Nop -//! [`Shallow`]: rustc_middle::mir::BorrowKind::Shallow +//! [`Fake`]: rustc_middle::mir::BorrowKind::Fake use crate::MirPass; use rustc_middle::mir::{Body, BorrowKind, Rvalue, StatementKind, TerminatorKind}; @@ -24,7 +24,7 @@ impl<'tcx> MirPass<'tcx> for CleanupPostBorrowck { for statement in basic_block.statements.iter_mut() { match statement.kind { StatementKind::AscribeUserType(..) - | StatementKind::Assign(box (_, Rvalue::Ref(_, BorrowKind::Shallow, _))) + | StatementKind::Assign(box (_, Rvalue::Ref(_, BorrowKind::Fake, _))) | StatementKind::FakeRead(..) => statement.make_nop(), _ => (), } diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs index 53c0d0dea292..0adbb078105a 100644 --- a/compiler/rustc_mir_transform/src/const_prop.rs +++ b/compiler/rustc_mir_transform/src/const_prop.rs @@ -668,7 +668,7 @@ impl<'tcx> Visitor<'tcx> for CanConstProp { // These can't ever be propagated under any scheme, as we can't reason about indirect // mutation. | NonMutatingUse(NonMutatingUseContext::SharedBorrow) - | NonMutatingUse(NonMutatingUseContext::ShallowBorrow) + | NonMutatingUse(NonMutatingUseContext::FakeBorrow) | NonMutatingUse(NonMutatingUseContext::AddressOf) | MutatingUse(MutatingUseContext::Borrow) | MutatingUse(MutatingUseContext::AddressOf) => { diff --git a/compiler/rustc_mir_transform/src/copy_prop.rs b/compiler/rustc_mir_transform/src/copy_prop.rs index be4af3b76f1e..f5db7ce97eba 100644 --- a/compiler/rustc_mir_transform/src/copy_prop.rs +++ b/compiler/rustc_mir_transform/src/copy_prop.rs @@ -131,7 +131,7 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'_, 'tcx> { let observes_address = match ctxt { PlaceContext::NonMutatingUse( NonMutatingUseContext::SharedBorrow - | NonMutatingUseContext::ShallowBorrow + | NonMutatingUseContext::FakeBorrow | NonMutatingUseContext::AddressOf, ) => true, // For debuginfo, merging locals is ok. diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index fc30a718cbb5..dfafd8598306 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -637,6 +637,14 @@ struct LivenessInfo { storage_liveness: IndexVec>>, } +/// Computes which locals have to be stored in the state-machine for the +/// given coroutine. +/// +/// The basic idea is as follows: +/// - a local is live until we encounter a `StorageDead` statement. In +/// case none exist, the local is considered to be always live. +/// - a local has to be stored if it is either directly used after the +/// the suspend point, or if it is live and has been previously borrowed. fn locals_live_across_suspend_points<'tcx>( tcx: TyCtxt<'tcx>, body: &Body<'tcx>, @@ -1449,16 +1457,15 @@ pub(crate) fn mir_coroutine_witnesses<'tcx>( // The first argument is the coroutine type passed by value let coroutine_ty = body.local_decls[ty::CAPTURE_STRUCT_LOCAL].ty; - // Get the interior types and args which typeck computed let movable = match *coroutine_ty.kind() { ty::Coroutine(_, _, movability) => movability == hir::Movability::Movable, ty::Error(_) => return None, _ => span_bug!(body.span, "unexpected coroutine type {}", coroutine_ty), }; - // When first entering the coroutine, move the resume argument into its new local. - let always_live_locals = always_storage_live_locals(&body); + // The witness simply contains all locals live across suspend points. + let always_live_locals = always_storage_live_locals(&body); let liveness_info = locals_live_across_suspend_points(tcx, body, &always_live_locals, movable); // Extract locals which are live across suspension point into `layout` diff --git a/compiler/rustc_mir_transform/src/ssa.rs b/compiler/rustc_mir_transform/src/ssa.rs index 8dc7b60c4e53..1f59c790b4eb 100644 --- a/compiler/rustc_mir_transform/src/ssa.rs +++ b/compiler/rustc_mir_transform/src/ssa.rs @@ -234,7 +234,7 @@ impl<'tcx> Visitor<'tcx> for SsaVisitor<'_> { // so we have to remove them too. PlaceContext::NonMutatingUse( NonMutatingUseContext::SharedBorrow - | NonMutatingUseContext::ShallowBorrow + | NonMutatingUseContext::FakeBorrow | NonMutatingUseContext::AddressOf, ) | PlaceContext::MutatingUse(_) => { diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index 25bd82bf1ef5..27596c08f1c1 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -455,7 +455,7 @@ impl<'tcx> Stable<'tcx> for mir::BorrowKind { use mir::BorrowKind::*; match *self { Shared => stable_mir::mir::BorrowKind::Shared, - Shallow => stable_mir::mir::BorrowKind::Shallow, + Fake => stable_mir::mir::BorrowKind::Fake, Mut { kind } => stable_mir::mir::BorrowKind::Mut { kind: kind.stable(tables) }, } } diff --git a/compiler/stable_mir/src/mir/body.rs b/compiler/stable_mir/src/mir/body.rs index 4818bceadeff..069337836853 100644 --- a/compiler/stable_mir/src/mir/body.rs +++ b/compiler/stable_mir/src/mir/body.rs @@ -437,9 +437,10 @@ pub enum BorrowKind { Shared, /// The immediately borrowed place must be immutable, but projections from - /// it don't need to be. For example, a shallow borrow of `a.b` doesn't + /// it don't need to be. This is used to prevent match guards from replacing + /// the scrutinee. For example, a fake borrow of `a.b` doesn't /// conflict with a mutable borrow of `a.b.c`. - Shallow, + Fake, /// Data is mutable and not aliasable. Mut { From 92267c9794accc7fb990598f23de4ec4b3831c6d Mon Sep 17 00:00:00 2001 From: lcnr Date: Wed, 8 Nov 2023 18:38:30 +0100 Subject: [PATCH 360/435] update mir-opt tests --- .../match_false_edges.full_tested_match.built.after.mir | 2 +- .../match_false_edges.full_tested_match2.built.after.mir | 2 +- .../building/match_false_edges.main.built.after.mir | 4 ++-- ...rt.SimplifyCfg-initial.after-ElaborateDrops.after.diff | 8 ++++---- ...nd.SimplifyCfg-initial.after-ElaborateDrops.after.diff | 8 ++++---- .../mir-opt/match_test.main.SimplifyCfg-initial.after.mir | 2 +- ...rrows.match_guard.CleanupPostBorrowck.panic-abort.diff | 8 ++++---- ...rows.match_guard.CleanupPostBorrowck.panic-unwind.diff | 8 ++++---- 8 files changed, 21 insertions(+), 21 deletions(-) diff --git a/tests/mir-opt/building/match_false_edges.full_tested_match.built.after.mir b/tests/mir-opt/building/match_false_edges.full_tested_match.built.after.mir index 1946c70e4764..b99b0b99559a 100644 --- a/tests/mir-opt/building/match_false_edges.full_tested_match.built.after.mir +++ b/tests/mir-opt/building/match_false_edges.full_tested_match.built.after.mir @@ -52,7 +52,7 @@ fn full_tested_match() -> () { bb5: { StorageLive(_6); _6 = &((_2 as Some).0: i32); - _4 = &shallow _2; + _4 = &fake _2; StorageLive(_7); _7 = guard() -> [return: bb6, unwind: bb12]; } diff --git a/tests/mir-opt/building/match_false_edges.full_tested_match2.built.after.mir b/tests/mir-opt/building/match_false_edges.full_tested_match2.built.after.mir index b6175b051568..d1d86b55d686 100644 --- a/tests/mir-opt/building/match_false_edges.full_tested_match2.built.after.mir +++ b/tests/mir-opt/building/match_false_edges.full_tested_match2.built.after.mir @@ -58,7 +58,7 @@ fn full_tested_match2() -> () { bb5: { StorageLive(_6); _6 = &((_2 as Some).0: i32); - _4 = &shallow _2; + _4 = &fake _2; StorageLive(_7); _7 = guard() -> [return: bb6, unwind: bb12]; } diff --git a/tests/mir-opt/building/match_false_edges.main.built.after.mir b/tests/mir-opt/building/match_false_edges.main.built.after.mir index 0b57d1b97e15..1d4fe67f350c 100644 --- a/tests/mir-opt/building/match_false_edges.main.built.after.mir +++ b/tests/mir-opt/building/match_false_edges.main.built.after.mir @@ -78,7 +78,7 @@ fn main() -> () { bb8: { StorageLive(_7); _7 = &((_2 as Some).0: i32); - _5 = &shallow _2; + _5 = &fake _2; StorageLive(_8); _8 = guard() -> [return: bb9, unwind: bb20]; } @@ -120,7 +120,7 @@ fn main() -> () { bb14: { StorageLive(_11); _11 = &((_2 as Some).0: i32); - _5 = &shallow _2; + _5 = &fake _2; StorageLive(_12); StorageLive(_13); _13 = (*_11); diff --git a/tests/mir-opt/match_arm_scopes.complicated_match.panic-abort.SimplifyCfg-initial.after-ElaborateDrops.after.diff b/tests/mir-opt/match_arm_scopes.complicated_match.panic-abort.SimplifyCfg-initial.after-ElaborateDrops.after.diff index 2989582d0382..b4bd45ba597f 100644 --- a/tests/mir-opt/match_arm_scopes.complicated_match.panic-abort.SimplifyCfg-initial.after-ElaborateDrops.after.diff +++ b/tests/mir-opt/match_arm_scopes.complicated_match.panic-abort.SimplifyCfg-initial.after-ElaborateDrops.after.diff @@ -80,8 +80,8 @@ _6 = &(_2.1: bool); StorageLive(_8); _8 = &(_2.2: std::string::String); -- _3 = &shallow (_2.0: bool); -- _4 = &shallow (_2.1: bool); +- _3 = &fake (_2.0: bool); +- _4 = &fake (_2.1: bool); StorageLive(_9); StorageLive(_10); _10 = _1; @@ -137,8 +137,8 @@ _6 = &(_2.0: bool); StorageLive(_8); _8 = &(_2.2: std::string::String); -- _3 = &shallow (_2.0: bool); -- _4 = &shallow (_2.1: bool); +- _3 = &fake (_2.0: bool); +- _4 = &fake (_2.1: bool); StorageLive(_12); StorageLive(_13); _13 = _1; diff --git a/tests/mir-opt/match_arm_scopes.complicated_match.panic-unwind.SimplifyCfg-initial.after-ElaborateDrops.after.diff b/tests/mir-opt/match_arm_scopes.complicated_match.panic-unwind.SimplifyCfg-initial.after-ElaborateDrops.after.diff index 2989582d0382..b4bd45ba597f 100644 --- a/tests/mir-opt/match_arm_scopes.complicated_match.panic-unwind.SimplifyCfg-initial.after-ElaborateDrops.after.diff +++ b/tests/mir-opt/match_arm_scopes.complicated_match.panic-unwind.SimplifyCfg-initial.after-ElaborateDrops.after.diff @@ -80,8 +80,8 @@ _6 = &(_2.1: bool); StorageLive(_8); _8 = &(_2.2: std::string::String); -- _3 = &shallow (_2.0: bool); -- _4 = &shallow (_2.1: bool); +- _3 = &fake (_2.0: bool); +- _4 = &fake (_2.1: bool); StorageLive(_9); StorageLive(_10); _10 = _1; @@ -137,8 +137,8 @@ _6 = &(_2.0: bool); StorageLive(_8); _8 = &(_2.2: std::string::String); -- _3 = &shallow (_2.0: bool); -- _4 = &shallow (_2.1: bool); +- _3 = &fake (_2.0: bool); +- _4 = &fake (_2.1: bool); StorageLive(_12); StorageLive(_13); _13 = _1; diff --git a/tests/mir-opt/match_test.main.SimplifyCfg-initial.after.mir b/tests/mir-opt/match_test.main.SimplifyCfg-initial.after.mir index 90ec3ab49ad0..ebb2f70a4758 100644 --- a/tests/mir-opt/match_test.main.SimplifyCfg-initial.after.mir +++ b/tests/mir-opt/match_test.main.SimplifyCfg-initial.after.mir @@ -68,7 +68,7 @@ fn main() -> () { } bb9: { - _8 = &shallow _1; + _8 = &fake _1; StorageLive(_9); _9 = _2; switchInt(move _9) -> [0: bb11, otherwise: bb10]; diff --git a/tests/mir-opt/remove_fake_borrows.match_guard.CleanupPostBorrowck.panic-abort.diff b/tests/mir-opt/remove_fake_borrows.match_guard.CleanupPostBorrowck.panic-abort.diff index 61329bb75d13..54da6ee659f9 100644 --- a/tests/mir-opt/remove_fake_borrows.match_guard.CleanupPostBorrowck.panic-abort.diff +++ b/tests/mir-opt/remove_fake_borrows.match_guard.CleanupPostBorrowck.panic-abort.diff @@ -33,10 +33,10 @@ } bb4: { -- _4 = &shallow _1; -- _5 = &shallow (*((_1 as Some).0: &&i32)); -- _6 = &shallow ((_1 as Some).0: &&i32); -- _7 = &shallow (*(*((_1 as Some).0: &&i32))); +- _4 = &fake _1; +- _5 = &fake (*((_1 as Some).0: &&i32)); +- _6 = &fake ((_1 as Some).0: &&i32); +- _7 = &fake (*(*((_1 as Some).0: &&i32))); + nop; + nop; + nop; diff --git a/tests/mir-opt/remove_fake_borrows.match_guard.CleanupPostBorrowck.panic-unwind.diff b/tests/mir-opt/remove_fake_borrows.match_guard.CleanupPostBorrowck.panic-unwind.diff index 61329bb75d13..54da6ee659f9 100644 --- a/tests/mir-opt/remove_fake_borrows.match_guard.CleanupPostBorrowck.panic-unwind.diff +++ b/tests/mir-opt/remove_fake_borrows.match_guard.CleanupPostBorrowck.panic-unwind.diff @@ -33,10 +33,10 @@ } bb4: { -- _4 = &shallow _1; -- _5 = &shallow (*((_1 as Some).0: &&i32)); -- _6 = &shallow ((_1 as Some).0: &&i32); -- _7 = &shallow (*(*((_1 as Some).0: &&i32))); +- _4 = &fake _1; +- _5 = &fake (*((_1 as Some).0: &&i32)); +- _6 = &fake ((_1 as Some).0: &&i32); +- _7 = &fake (*(*((_1 as Some).0: &&i32))); + nop; + nop; + nop; From 341c85648c612532d757afb3cafa63ebaa3693db Mon Sep 17 00:00:00 2001 From: John Millikin Date: Wed, 8 Nov 2023 09:12:01 +0900 Subject: [PATCH 361/435] Move `BorrowedBuf` and `BorrowedCursor` from `std:io` to `core::io` Assigned new feature name `core_io_borrowed_buf` to distinguish from the `Read::read_buf` functionality in `std::io`. --- compiler/rustc_span/src/lib.rs | 1 + .../src/io/borrowed_buf.rs} | 19 +------------------ library/core/src/io/mod.rs | 6 ++++++ library/core/src/lib.rs | 2 ++ .../tests/io/borrowed_buf.rs} | 4 ++-- library/core/tests/io/mod.rs | 1 + library/core/tests/lib.rs | 2 ++ library/std/src/io/impls.rs | 14 ++++++++++++++ library/std/src/io/mod.rs | 3 +-- library/std/src/lib.rs | 1 + 10 files changed, 31 insertions(+), 22 deletions(-) rename library/{std/src/io/readbuf.rs => core/src/io/borrowed_buf.rs} (96%) create mode 100644 library/core/src/io/mod.rs rename library/{std/src/io/readbuf/tests.rs => core/tests/io/borrowed_buf.rs} (98%) create mode 100644 library/core/tests/io/mod.rs diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index fc13bdff36f5..489c8d189265 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -24,6 +24,7 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(array_windows)] #![feature(cfg_match)] +#![feature(core_io_borrowed_buf)] #![feature(if_let_guard)] #![feature(let_chains)] #![feature(min_specialization)] diff --git a/library/std/src/io/readbuf.rs b/library/core/src/io/borrowed_buf.rs similarity index 96% rename from library/std/src/io/readbuf.rs rename to library/core/src/io/borrowed_buf.rs index 95044de2a09e..fe25cac280fe 100644 --- a/library/std/src/io/readbuf.rs +++ b/library/core/src/io/borrowed_buf.rs @@ -1,10 +1,6 @@ -#![unstable(feature = "read_buf", issue = "78485")] - -#[cfg(test)] -mod tests; +#![unstable(feature = "core_io_borrowed_buf", issue = "117693")] use crate::fmt::{self, Debug, Formatter}; -use crate::io::{Result, Write}; use crate::mem::{self, MaybeUninit}; use crate::{cmp, ptr}; @@ -303,16 +299,3 @@ impl<'a> BorrowedCursor<'a> { self.buf.filled += buf.len(); } } - -impl<'a> Write for BorrowedCursor<'a> { - fn write(&mut self, buf: &[u8]) -> Result { - let amt = cmp::min(buf.len(), self.capacity()); - self.append(&buf[..amt]); - Ok(amt) - } - - #[inline] - fn flush(&mut self) -> Result<()> { - Ok(()) - } -} diff --git a/library/core/src/io/mod.rs b/library/core/src/io/mod.rs new file mode 100644 index 000000000000..2f20180cdc9a --- /dev/null +++ b/library/core/src/io/mod.rs @@ -0,0 +1,6 @@ +//! Traits, helpers, and type definitions for core I/O functionality. + +mod borrowed_buf; + +#[unstable(feature = "core_io_borrowed_buf", issue = "117693")] +pub use self::borrowed_buf::{BorrowedBuf, BorrowedCursor}; diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index de643fb333ef..5a6d242a7298 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -369,6 +369,8 @@ pub mod async_iter; pub mod cell; pub mod char; pub mod ffi; +#[unstable(feature = "core_io_borrowed_buf", issue = "117693")] +pub mod io; pub mod iter; pub mod net; pub mod option; diff --git a/library/std/src/io/readbuf/tests.rs b/library/core/tests/io/borrowed_buf.rs similarity index 98% rename from library/std/src/io/readbuf/tests.rs rename to library/core/tests/io/borrowed_buf.rs index 89a2f6b2271b..69511e49acdb 100644 --- a/library/std/src/io/readbuf/tests.rs +++ b/library/core/tests/io/borrowed_buf.rs @@ -1,5 +1,5 @@ -use super::BorrowedBuf; -use crate::mem::MaybeUninit; +use core::io::BorrowedBuf; +use core::mem::MaybeUninit; /// Test that BorrowedBuf has the correct numbers when created with new #[test] diff --git a/library/core/tests/io/mod.rs b/library/core/tests/io/mod.rs new file mode 100644 index 000000000000..a24893a525a9 --- /dev/null +++ b/library/core/tests/io/mod.rs @@ -0,0 +1 @@ +mod borrowed_buf; diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index df7b34ce73b4..168b47dc99cc 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -23,6 +23,7 @@ #![feature(const_likely)] #![feature(const_location_fields)] #![feature(core_intrinsics)] +#![feature(core_io_borrowed_buf)] #![feature(core_private_bignum)] #![feature(core_private_diy_float)] #![feature(dec2flt)] @@ -135,6 +136,7 @@ mod fmt; mod future; mod hash; mod intrinsics; +mod io; mod iter; mod lazy; #[cfg(test)] diff --git a/library/std/src/io/impls.rs b/library/std/src/io/impls.rs index f438325560f5..256b043a6097 100644 --- a/library/std/src/io/impls.rs +++ b/library/std/src/io/impls.rs @@ -528,3 +528,17 @@ impl Write for VecDeque { Ok(()) } } + +#[unstable(feature = "read_buf", issue = "78485")] +impl<'a> io::Write for core::io::BorrowedCursor<'a> { + fn write(&mut self, buf: &[u8]) -> io::Result { + let amt = cmp::min(buf.len(), self.capacity()); + self.append(&buf[..amt]); + Ok(amt) + } + + #[inline] + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } +} diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index aa9a2482d2d9..7d70a0bac24f 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -330,7 +330,7 @@ pub use self::{ }; #[unstable(feature = "read_buf", issue = "78485")] -pub use self::readbuf::{BorrowedBuf, BorrowedCursor}; +pub use core::io::{BorrowedBuf, BorrowedCursor}; pub(crate) use error::const_io_error; mod buffered; @@ -339,7 +339,6 @@ mod cursor; mod error; mod impls; pub mod prelude; -mod readbuf; mod stdio; mod util; diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index f57c8d4e7e28..425890122577 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -310,6 +310,7 @@ // tidy-alphabetical-start #![feature(char_internals)] #![feature(core_intrinsics)] +#![feature(core_io_borrowed_buf)] #![feature(duration_constants)] #![feature(error_generic_member_access)] #![feature(error_in_core)] From ecc936b15511212dc54f6d0bbc6e6ce5ed8bcd6b Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 9 Nov 2023 11:36:02 +1100 Subject: [PATCH 362/435] Remove `-Z strip`. It was stabilized as `-C strip` in November 2021. The unstable option was kept around as a temporary measure to ease the transition. Two years is more than enough! --- compiler/rustc_codegen_ssa/src/back/link.rs | 12 ++---------- compiler/rustc_session/src/options.rs | 2 -- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index bcbb75d95997..dd9d277fb775 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1033,7 +1033,7 @@ fn link_natively<'a>( SplitDebuginfo::Packed => link_dwarf_object(sess, codegen_results, out_filename), } - let strip = strip_value(sess); + let strip = sess.opts.cg.strip; if sess.target.is_like_osx { match (strip, crate_type) { @@ -1070,14 +1070,6 @@ fn link_natively<'a>( Ok(()) } -// Temporarily support both -Z strip and -C strip -fn strip_value(sess: &Session) -> Strip { - match (sess.opts.unstable_opts.strip, sess.opts.cg.strip) { - (s, Strip::None) => s, - (_, s) => s, - } -} - fn strip_symbols_with_external_utility<'a>( sess: &'a Session, util: &str, @@ -2370,7 +2362,7 @@ fn add_order_independent_options( ); // Pass debuginfo, NatVis debugger visualizers and strip flags down to the linker. - cmd.debuginfo(strip_value(sess), &natvis_visualizers); + cmd.debuginfo(sess.opts.cg.strip, &natvis_visualizers); // We want to prevent the compiler from accidentally leaking in any system libraries, // so by default we tell linkers not to link to any default libraries. diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 964a26e94fed..ed00851b468e 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1841,8 +1841,6 @@ written to standard error output)"), "prefer dynamic linking to static linking for staticlibs (default: no)"), strict_init_checks: bool = (false, parse_bool, [TRACKED], "control if mem::uninitialized and mem::zeroed panic on more UB"), - strip: Strip = (Strip::None, parse_strip, [UNTRACKED], - "tell the linker which information to strip (`none` (default), `debuginfo` or `symbols`)"), #[rustc_lint_opt_deny_field_access("use `Session::teach` instead of this field")] teach: bool = (false, parse_bool, [TRACKED], "show extended diagnostic help (default: no)"), From 3d6417fc7a117c36195f45d1d5e30a43fc5365ab Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Wed, 8 Nov 2023 13:01:58 +0300 Subject: [PATCH 363/435] check config file before prompts on x setup Signed-off-by: onur-ozkan --- src/bootstrap/src/core/build_steps/setup.rs | 24 ++++++++++----------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/setup.rs b/src/bootstrap/src/core/build_steps/setup.rs index 04a164437703..f29f9873d2a7 100644 --- a/src/bootstrap/src/core/build_steps/setup.rs +++ b/src/bootstrap/src/core/build_steps/setup.rs @@ -122,6 +122,17 @@ impl Step for Profile { return; } + let path = &run.builder.config.config.clone().unwrap_or(PathBuf::from("config.toml")); + if path.exists() { + eprintln!(); + eprintln!( + "error: you asked for a new config file, but one already exists at `{}`", + t!(path.canonicalize()).display() + ); + + crate::exit!(1); + } + // for Profile, `run.paths` will have 1 and only 1 element // this is because we only accept at most 1 path from user input. // If user calls `x.py setup` without arguments, the interactive TUI @@ -204,19 +215,6 @@ fn setup_config_toml(path: &PathBuf, profile: Profile, config: &Config) { if profile == Profile::None { return; } - if path.exists() { - eprintln!(); - eprintln!( - "error: you asked `x.py` to setup a new config file, but one already exists at `{}`", - path.display() - ); - eprintln!("help: try adding `profile = \"{}\"` at the top of {}", profile, path.display()); - eprintln!( - "note: this will use the configuration in {}", - profile.include_path(&config.src).display() - ); - crate::exit!(1); - } let latest_change_id = CONFIG_CHANGE_HISTORY.last().unwrap(); let settings = format!( From 42fbf3ebf5a6ac9d976e52b4ea63081d19dba9dc Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Wed, 8 Nov 2023 13:17:58 +0300 Subject: [PATCH 364/435] allow users to override the existing configuration during x setup Instead of immediately terminating bootstrap, users are now given the option to decide whether they want to override the file or leave it unchanged. Signed-off-by: onur-ozkan --- src/bootstrap/src/core/build_steps/setup.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/src/core/build_steps/setup.rs b/src/bootstrap/src/core/build_steps/setup.rs index f29f9873d2a7..ae2b12333139 100644 --- a/src/bootstrap/src/core/build_steps/setup.rs +++ b/src/bootstrap/src/core/build_steps/setup.rs @@ -130,7 +130,17 @@ impl Step for Profile { t!(path.canonicalize()).display() ); - crate::exit!(1); + match prompt_user( + "Do you wish to override the existing configuration (which will allow the setup process to continue)?: [y/N]", + ) { + Ok(Some(PromptResult::Yes)) => { + t!(fs::remove_file(path)); + } + _ => { + println!("Exiting."); + crate::exit!(1); + } + } } // for Profile, `run.paths` will have 1 and only 1 element From d1e26401bc70a58e6daf1816d542be4573bbab84 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Wed, 8 Nov 2023 13:31:15 +0300 Subject: [PATCH 365/435] chore(bootstrap): capitalize {error, warning, info, note} tags This should enhance the readability. Signed-off-by: onur-ozkan --- src/bootstrap/bootstrap.py | 16 +++++++------- src/bootstrap/bootstrap_test.py | 2 +- src/bootstrap/configure.py | 4 ++-- src/bootstrap/src/bin/main.rs | 10 ++++----- src/bootstrap/src/bin/rustc.rs | 2 +- src/bootstrap/src/core/build_steps/clean.rs | 2 +- src/bootstrap/src/core/build_steps/compile.rs | 22 +++++++++---------- src/bootstrap/src/core/build_steps/install.rs | 2 +- src/bootstrap/src/core/build_steps/llvm.rs | 6 ++--- src/bootstrap/src/core/build_steps/setup.rs | 20 ++++++++--------- src/bootstrap/src/core/build_steps/suggest.rs | 2 +- src/bootstrap/src/core/build_steps/test.rs | 18 +++++++-------- src/bootstrap/src/core/build_steps/tool.rs | 8 +++---- .../src/core/build_steps/toolstate.rs | 8 +++---- src/bootstrap/src/core/builder.rs | 10 ++++----- src/bootstrap/src/core/config/config.rs | 18 +++++++-------- src/bootstrap/src/core/config/flags.rs | 2 +- src/bootstrap/src/core/download.rs | 14 ++++++------ src/bootstrap/src/lib.rs | 4 ++-- src/bootstrap/src/utils/bin_helpers.rs | 4 ++-- src/bootstrap/src/utils/helpers.rs | 6 ++--- src/bootstrap/src/utils/metrics.rs | 2 +- src/bootstrap/src/utils/render_tests.rs | 2 +- 23 files changed, 92 insertions(+), 92 deletions(-) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 1a1125a107fe..5a84e37f8cfa 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -211,7 +211,7 @@ def require(cmd, exit=True, exception=False): if exception: raise elif exit: - eprint("error: unable to run `{}`: {}".format(' '.join(cmd), exc)) + eprint("ERROR: unable to run `{}`: {}".format(' '.join(cmd), exc)) eprint("Please make sure it's installed and in the path.") sys.exit(1) return None @@ -681,7 +681,7 @@ class RustBuild(object): answer = self._should_fix_bins_and_dylibs = get_answer() if answer: - eprint("info: You seem to be using Nix.") + eprint("INFO: You seem to be using Nix.") return answer def fix_bin_or_dylib(self, fname): @@ -727,7 +727,7 @@ class RustBuild(object): "nix-build", "-E", nix_expr, "-o", nix_deps_dir, ]) except subprocess.CalledProcessError as reason: - eprint("warning: failed to call nix-build:", reason) + eprint("WARNING: failed to call nix-build:", reason) return self.nix_deps_dir = nix_deps_dir @@ -747,7 +747,7 @@ class RustBuild(object): try: subprocess.check_output([patchelf] + patchelf_args + [fname]) except subprocess.CalledProcessError as reason: - eprint("warning: failed to call patchelf:", reason) + eprint("WARNING: failed to call patchelf:", reason) return def rustc_stamp(self): @@ -1005,7 +1005,7 @@ class RustBuild(object): if 'SUDO_USER' in os.environ and not self.use_vendored_sources: if os.getuid() == 0: self.use_vendored_sources = True - eprint('info: looks like you\'re trying to run this command as root') + eprint('INFO: looks like you\'re trying to run this command as root') eprint(' and so in order to preserve your $HOME this will now') eprint(' use vendored sources by default.') @@ -1017,14 +1017,14 @@ class RustBuild(object): "--sync ./src/tools/rust-analyzer/Cargo.toml " \ "--sync ./compiler/rustc_codegen_cranelift/Cargo.toml " \ "--sync ./src/bootstrap/Cargo.toml " - eprint('error: vendoring required, but vendor directory does not exist.') + eprint('ERROR: vendoring required, but vendor directory does not exist.') eprint(' Run `cargo vendor {}` to initialize the ' 'vendor directory.'.format(sync_dirs)) eprint('Alternatively, use the pre-vendored `rustc-src` dist component.') raise Exception("{} not found".format(vendor_dir)) if not os.path.exists(cargo_dir): - eprint('error: vendoring required, but .cargo/config does not exist.') + eprint('ERROR: vendoring required, but .cargo/config does not exist.') raise Exception("{} not found".format(cargo_dir)) else: if os.path.exists(cargo_dir): @@ -1125,7 +1125,7 @@ def main(): # process has to happen before anything is printed out. if help_triggered: eprint( - "info: Downloading and building bootstrap before processing --help command.\n" + "INFO: Downloading and building bootstrap before processing --help command.\n" " See src/bootstrap/README.md for help with common commands.") exit_code = 0 diff --git a/src/bootstrap/bootstrap_test.py b/src/bootstrap/bootstrap_test.py index e6caabec4f64..6da410ed2f27 100644 --- a/src/bootstrap/bootstrap_test.py +++ b/src/bootstrap/bootstrap_test.py @@ -34,7 +34,7 @@ def serialize_and_parse(configure_args, bootstrap_args=None): # Verify this is actually valid TOML. tomllib.loads(build.config_toml) except ImportError: - print("warning: skipping TOML validation, need at least python 3.11", file=sys.stderr) + print("WARNING: skipping TOML validation, need at least python 3.11", file=sys.stderr) return build diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index 626ca6cf2e7a..544a42d9ada1 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -253,7 +253,7 @@ def parse_args(args): if not found: unknown_args.append(arg) - # Note: here and a few other places, we use [-1] to apply the *last* value + # NOTE: here and a few other places, we use [-1] to apply the *last* value # passed. But if option-checking is enabled, then the known_args loop will # also assert that options are only passed once. option_checking = ('option-checking' not in known_args @@ -477,7 +477,7 @@ def configure_section(lines, config): # These are used by rpm, but aren't accepted by x.py. # Give a warning that they're ignored, but not a hard error. if key in ["infodir", "localstatedir"]: - print("warning: {} will be ignored".format(key)) + print("WARNING: {} will be ignored".format(key)) else: raise RuntimeError("failed to find config line for {}".format(key)) diff --git a/src/bootstrap/src/bin/main.rs b/src/bootstrap/src/bin/main.rs index 6c0d8c8c5501..0a6072ae1a5d 100644 --- a/src/bootstrap/src/bin/main.rs +++ b/src/bootstrap/src/bin/main.rs @@ -63,7 +63,7 @@ fn main() { if suggest_setup { println!("WARNING: you have not made a `config.toml`"); println!( - "help: consider running `./x.py setup` or copying `config.example.toml` by running \ + "HELP: consider running `./x.py setup` or copying `config.example.toml` by running \ `cp config.example.toml config.toml`" ); } else if let Some(suggestion) = &changelog_suggestion { @@ -76,7 +76,7 @@ fn main() { if suggest_setup { println!("WARNING: you have not made a `config.toml`"); println!( - "help: consider running `./x.py setup` or copying `config.example.toml` by running \ + "HELP: consider running `./x.py setup` or copying `config.example.toml` by running \ `cp config.example.toml config.toml`" ); } else if let Some(suggestion) = &changelog_suggestion { @@ -97,7 +97,7 @@ fn main() { } if suggest_setup || changelog_suggestion.is_some() { - println!("note: this message was printed twice to make it more likely to be seen"); + println!("NOTE: this message was printed twice to make it more likely to be seen"); } } @@ -128,14 +128,14 @@ fn check_version(config: &Config) -> Option { msg.push_str("WARNING: there have been changes to x.py since you last updated.\n"); - msg.push_str("note: to silence this warning, "); + msg.push_str("NOTE: to silence this warning, "); msg.push_str(&format!( "update `config.toml` to use `change-id = {latest_config_id}` instead" )); } } else { msg.push_str("WARNING: The `change-id` is missing in the `config.toml`. This means that you will not be able to track the major changes made to the bootstrap configurations.\n"); - msg.push_str("note: to silence this warning, "); + msg.push_str("NOTE: to silence this warning, "); msg.push_str(&format!("add `change-id = {latest_config_id}` at the top of `config.toml`")); }; diff --git a/src/bootstrap/src/bin/rustc.rs b/src/bootstrap/src/bin/rustc.rs index 3041fd37ac80..2867d06d8568 100644 --- a/src/bootstrap/src/bin/rustc.rs +++ b/src/bootstrap/src/bin/rustc.rs @@ -242,7 +242,7 @@ fn main() { if status.success() { std::process::exit(0); - // note: everything below here is unreachable. do not put code that + // NOTE: everything below here is unreachable. do not put code that // should run on success, after this block. } if verbose > 0 { diff --git a/src/bootstrap/src/core/build_steps/clean.rs b/src/bootstrap/src/core/build_steps/clean.rs index 679770ce0ec7..84ef69317568 100644 --- a/src/bootstrap/src/core/build_steps/clean.rs +++ b/src/bootstrap/src/core/build_steps/clean.rs @@ -178,7 +178,7 @@ fn rm_rf(path: &Path) { && p.file_name().and_then(std::ffi::OsStr::to_str) == Some("bootstrap.exe") { - eprintln!("warning: failed to delete '{}'.", p.display()); + eprintln!("WARNING: failed to delete '{}'.", p.display()); return Ok(()); } Err(e) diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 8ab0ef61c502..7021a9543582 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -141,7 +141,7 @@ impl Step for Std { if builder.config.keep_stage.contains(&compiler.stage) || builder.config.keep_stage_std.contains(&compiler.stage) { - builder.info("Warning: Using a potentially old libstd. This may not behave well."); + builder.info("WARNING: Using a potentially old libstd. This may not behave well."); copy_third_party_objects(builder, &compiler, target); copy_self_contained_objects(builder, &compiler, target); @@ -817,8 +817,8 @@ impl Step for Rustc { builder.ensure(Std::new(compiler, target)); if builder.config.keep_stage.contains(&compiler.stage) { - builder.info("Warning: Using a potentially old librustc. This may not behave well."); - builder.info("Warning: Use `--keep-stage-std` if you want to rebuild the compiler when it changes"); + builder.info("WARNING: Using a potentially old librustc. This may not behave well."); + builder.info("WARNING: Use `--keep-stage-std` if you want to rebuild the compiler when it changes"); builder.ensure(RustcLink::from_rustc(self, compiler)); return; } @@ -1203,8 +1203,8 @@ fn is_codegen_cfg_needed(path: &TaskPath, run: &RunConfig<'_>) -> bool { } if needs_codegen_backend_config { run.builder.info( - "Warning: no codegen-backends config matched the requested path to build a codegen backend. \ - Help: add backend to codegen-backends in config.toml.", + "WARNING: no codegen-backends config matched the requested path to build a codegen backend. \ + HELP: add backend to codegen-backends in config.toml.", ); return true; } @@ -1250,7 +1250,7 @@ impl Step for CodegenBackend { if builder.config.keep_stage.contains(&compiler.stage) { builder.info( - "Warning: Using a potentially old codegen backend. \ + "WARNING: Using a potentially old codegen backend. \ This may not behave well.", ); // Codegen backends are linked separately from this step today, so we don't do @@ -1525,14 +1525,14 @@ impl Step for Sysroot { let sysroot_lib_rustlib_src_rust = sysroot_lib_rustlib_src.join("rust"); if let Err(e) = symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_src_rust) { eprintln!( - "warning: creating symbolic link `{}` to `{}` failed with {}", + "WARNING: creating symbolic link `{}` to `{}` failed with {}", sysroot_lib_rustlib_src_rust.display(), builder.src.display(), e, ); if builder.config.rust_remap_debuginfo { eprintln!( - "warning: some `tests/ui` tests will fail when lacking `{}`", + "WARNING: some `tests/ui` tests will fail when lacking `{}`", sysroot_lib_rustlib_src_rust.display(), ); } @@ -1545,7 +1545,7 @@ impl Step for Sysroot { symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_rustcsrc_rust) { eprintln!( - "warning: creating symbolic link `{}` to `{}` failed with {}", + "WARNING: creating symbolic link `{}` to `{}` failed with {}", sysroot_lib_rustlib_rustcsrc_rust.display(), builder.src.display(), e, @@ -1986,7 +1986,7 @@ pub fn stream_cargo( builder.verbose(&format!("running: {cargo:?}")); let mut child = match cargo.spawn() { Ok(child) => child, - Err(e) => panic!("failed to execute command: {cargo:?}\nerror: {e}"), + Err(e) => panic!("failed to execute command: {cargo:?}\nERROR: {e}"), }; // Spawn Cargo slurping up its JSON output. We'll start building up the @@ -2050,7 +2050,7 @@ pub fn strip_debug(builder: &Builder<'_>, target: TargetSelection, path: &Path) } let previous_mtime = FileTime::from_last_modification_time(&path.metadata().unwrap()); - // Note: `output` will propagate any errors here. + // NOTE: `output` will propagate any errors here. output(Command::new("strip").arg("--strip-debug").arg(path)); // After running `strip`, we have to set the file modification time to what it was before, diff --git a/src/bootstrap/src/core/build_steps/install.rs b/src/bootstrap/src/core/build_steps/install.rs index 9d03350c7232..6b4a8f597eab 100644 --- a/src/bootstrap/src/core/build_steps/install.rs +++ b/src/bootstrap/src/core/build_steps/install.rs @@ -269,7 +269,7 @@ install!((self, builder, _config), } }; RustDemangler, alias = "rust-demangler", Self::should_build(_config), only_hosts: true, { - // Note: Even though `should_build` may return true for `extended` default tools, + // NOTE: Even though `should_build` may return true for `extended` default tools, // dist::RustDemangler may still return None, unless the target-dependent `profiler` config // is also true, or the `tools` array explicitly includes "rust-demangler". if let Some(tarball) = builder.ensure(dist::RustDemangler { diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index 5b4543077216..36ccd1c25263 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -156,9 +156,9 @@ pub(crate) fn detect_llvm_sha(config: &Config, is_git: bool) -> String { if llvm_sha.is_empty() { eprintln!("error: could not find commit hash for downloading LLVM"); - eprintln!("help: maybe your repository history is too shallow?"); - eprintln!("help: consider disabling `download-ci-llvm`"); - eprintln!("help: or fetch enough history to include one upstream commit"); + eprintln!("HELP: maybe your repository history is too shallow?"); + eprintln!("HELP: consider disabling `download-ci-llvm`"); + eprintln!("HELP: or fetch enough history to include one upstream commit"); panic!(); } diff --git a/src/bootstrap/src/core/build_steps/setup.rs b/src/bootstrap/src/core/build_steps/setup.rs index ae2b12333139..486a1e20f183 100644 --- a/src/bootstrap/src/core/build_steps/setup.rs +++ b/src/bootstrap/src/core/build_steps/setup.rs @@ -126,7 +126,7 @@ impl Step for Profile { if path.exists() { eprintln!(); eprintln!( - "error: you asked for a new config file, but one already exists at `{}`", + "ERROR: you asked for a new config file, but one already exists at `{}`", t!(path.canonicalize()).display() ); @@ -212,7 +212,7 @@ pub fn setup(config: &Config, profile: Profile) { if profile == Profile::Tools { eprintln!(); eprintln!( - "note: the `tools` profile sets up the `stage2` toolchain (use \ + "NOTE: the `tools` profile sets up the `stage2` toolchain (use \ `rustup toolchain link 'name' build/host/stage2` to use rustc)" ) } @@ -414,8 +414,8 @@ pub fn interactive_path() -> io::Result { break match parse_with_abbrev(&input) { Ok(profile) => profile, Err(err) => { - eprintln!("error: {err}"); - eprintln!("note: press Ctrl+C to exit"); + eprintln!("ERROR: {err}"); + eprintln!("NOTE: press Ctrl+C to exit"); continue; } }; @@ -444,8 +444,8 @@ fn prompt_user(prompt: &str) -> io::Result> { "p" | "print" => return Ok(Some(PromptResult::Print)), "" => return Ok(None), _ => { - eprintln!("error: unrecognized option '{}'", input.trim()); - eprintln!("note: press Ctrl+C to exit"); + eprintln!("ERROR: unrecognized option '{}'", input.trim()); + eprintln!("NOTE: press Ctrl+C to exit"); } }; } @@ -512,7 +512,7 @@ undesirable, simply delete the `pre-push` file from .git/hooks." match fs::hard_link(src, &dst) { Err(e) => { eprintln!( - "error: could not create hook {}: do you already have the git hook installed?\n{}", + "ERROR: could not create hook {}: do you already have the git hook installed?\n{}", dst.display(), e ); @@ -578,10 +578,10 @@ fn create_vscode_settings_maybe(config: &Config) -> io::Result<()> { ); match mismatched_settings { Some(true) => eprintln!( - "warning: existing `.vscode/settings.json` is out of date, x.py will update it" + "WARNING: existing `.vscode/settings.json` is out of date, x.py will update it" ), Some(false) => eprintln!( - "warning: existing `.vscode/settings.json` has been modified by user, x.py will back it up and replace it" + "WARNING: existing `.vscode/settings.json` has been modified by user, x.py will back it up and replace it" ), _ => (), } @@ -608,7 +608,7 @@ fn create_vscode_settings_maybe(config: &Config) -> io::Result<()> { // exists and is not current version or outdated, so back it up let mut backup = vscode_settings.clone(); backup.set_extension("json.bak"); - eprintln!("warning: copying `settings.json` to `settings.json.bak`"); + eprintln!("WARNING: copying `settings.json` to `settings.json.bak`"); fs::copy(&vscode_settings, &backup)?; "Updated" } diff --git a/src/bootstrap/src/core/build_steps/suggest.rs b/src/bootstrap/src/core/build_steps/suggest.rs index 82fb10cebe07..103ebe8e42da 100644 --- a/src/bootstrap/src/core/build_steps/suggest.rs +++ b/src/bootstrap/src/core/build_steps/suggest.rs @@ -68,6 +68,6 @@ pub fn suggest(builder: &Builder<'_>, run: bool) { build.build(); } } else { - println!("help: consider using the `--run` flag to automatically run suggested tests"); + println!("HELP: consider using the `--run` flag to automatically run suggested tests"); } } diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index c034e5c9d69e..b6cacec60481 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -1127,10 +1127,10 @@ impl Step for Tidy { let inferred_rustfmt_dir = builder.initial_rustc.parent().unwrap(); eprintln!( "\ -error: no `rustfmt` binary found in {PATH} -info: `rust.channel` is currently set to \"{CHAN}\" -help: if you are testing a beta branch, set `rust.channel` to \"beta\" in the `config.toml` file -help: to skip test's attempt to check tidiness, pass `--skip src/tools/tidy` to `x.py test`", +ERROR: no `rustfmt` binary found in {PATH} +INFO: `rust.channel` is currently set to \"{CHAN}\" +HELP: if you are testing a beta branch, set `rust.channel` to \"beta\" in the `config.toml` file +HELP: to skip test's attempt to check tidiness, pass `--skip src/tools/tidy` to `x.py test`", PATH = inferred_rustfmt_dir.display(), CHAN = builder.config.channel, ); @@ -1183,7 +1183,7 @@ impl Step for ExpandYamlAnchors { /// appropriate configuration for all our CI providers. This step ensures the tool was called /// by the user before committing CI changes. fn run(self, builder: &Builder<'_>) { - // Note: `.github/` is not included in dist-src tarballs + // NOTE: `.github/` is not included in dist-src tarballs if !builder.src.join(".github/workflows/ci.yml").exists() { builder.info("Skipping YAML anchors check: GitHub Actions config not found"); return; @@ -1566,10 +1566,10 @@ impl Step for Compiletest { fn run(self, builder: &Builder<'_>) { if builder.top_stage == 0 && env::var("COMPILETEST_FORCE_STAGE0").is_err() { eprintln!("\ -error: `--stage 0` runs compiletest on the beta compiler, not your local changes, and will almost always cause tests to fail -help: to test the compiler, use `--stage 1` instead -help: to test the standard library, use `--stage 0 library/std` instead -note: if you're sure you want to do this, please open an issue as to why. In the meantime, you can override this with `COMPILETEST_FORCE_STAGE0=1`." +ERROR: `--stage 0` runs compiletest on the beta compiler, not your local changes, and will almost always cause tests to fail +HELP: to test the compiler, use `--stage 1` instead +HELP: to test the standard library, use `--stage 0 library/std` instead +NOTE: if you're sure you want to do this, please open an issue as to why. In the meantime, you can override this with `COMPILETEST_FORCE_STAGE0=1`." ); crate::exit!(1); } diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index d5f759ea159a..d1bc05e51d73 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -422,7 +422,7 @@ impl Step for Rustdoc { fn make_run(run: RunConfig<'_>) { run.builder.ensure(Rustdoc { - // Note: this is somewhat unique in that we actually want a *target* + // NOTE: this is somewhat unique in that we actually want a *target* // compiler here, because rustdoc *is* a compiler. We won't be using // this as the compiler to build with, but rather this is "what // compiler are we producing"? @@ -454,7 +454,7 @@ impl Step for Rustdoc { // compiler, since you do just as much work. if !builder.config.dry_run() && builder.download_rustc() && build_compiler.stage == 0 { println!( - "warning: `download-rustc` does nothing when building stage1 tools; consider using `--stage 2` instead" + "WARNING: `download-rustc` does nothing when building stage1 tools; consider using `--stage 2` instead" ); } @@ -787,9 +787,9 @@ macro_rules! tool_extended { } } -// Note: tools need to be also added to `Builder::get_step_descriptions` in `builder.rs` +// NOTE: tools need to be also added to `Builder::get_step_descriptions` in `builder.rs` // to make `./x.py build ` work. -// Note: Most submodule updates for tools are handled by bootstrap.py, since they're needed just to +// NOTE: Most submodule updates for tools are handled by bootstrap.py, since they're needed just to // invoke Cargo to build bootstrap. See the comment there for more details. tool_extended!((self, builder), Cargofmt, "src/tools/rustfmt", "cargo-fmt", stable=true; diff --git a/src/bootstrap/src/core/build_steps/toolstate.rs b/src/bootstrap/src/core/build_steps/toolstate.rs index f892577ccbf7..a451f92b6bcb 100644 --- a/src/bootstrap/src/core/build_steps/toolstate.rs +++ b/src/bootstrap/src/core/build_steps/toolstate.rs @@ -172,7 +172,7 @@ impl Step for ToolStateCheck { for (tool, _) in STABLE_TOOLS.iter().chain(NIGHTLY_TOOLS.iter()) { if !toolstates.contains_key(*tool) { did_error = true; - eprintln!("error: Tool `{tool}` was not recorded in tool state."); + eprintln!("ERROR: Tool `{tool}` was not recorded in tool state."); } } @@ -190,7 +190,7 @@ impl Step for ToolStateCheck { if state != ToolState::TestPass { if !is_nightly { did_error = true; - eprintln!("error: Tool `{tool}` should be test-pass but is {state}"); + eprintln!("ERROR: Tool `{tool}` should be test-pass but is {state}"); } else if in_beta_week { let old_state = old_toolstate .iter() @@ -200,14 +200,14 @@ impl Step for ToolStateCheck { if state < old_state { did_error = true; eprintln!( - "error: Tool `{tool}` has regressed from {old_state} to {state} during beta week." + "ERROR: Tool `{tool}` has regressed from {old_state} to {state} during beta week." ); } else { // This warning only appears in the logs, which most // people won't read. It's mostly here for testing and // debugging. eprintln!( - "warning: Tool `{tool}` is not test-pass (is `{state}`), \ + "WARNING: Tool `{tool}` is not test-pass (is `{state}`), \ this should be fixed before beta is branched." ); } diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs index 1b6ba89aadd2..cd276674dee6 100644 --- a/src/bootstrap/src/core/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -386,13 +386,13 @@ impl StepDescription { } if !paths.is_empty() { - eprintln!("error: no `{}` rules matched {:?}", builder.kind.as_str(), paths,); + eprintln!("ERROR: no `{}` rules matched {:?}", builder.kind.as_str(), paths,); eprintln!( - "help: run `x.py {} --help --verbose` to show a list of available paths", + "HELP: run `x.py {} --help --verbose` to show a list of available paths", builder.kind.as_str() ); eprintln!( - "note: if you are adding a new Step to bootstrap itself, make sure you register it with `describe!`" + "NOTE: if you are adding a new Step to bootstrap itself, make sure you register it with `describe!`" ); crate::exit!(1); } @@ -1360,9 +1360,9 @@ impl<'a> Builder<'a> { } }).unwrap_or_else(|_| { eprintln!( - "error: `x.py clippy` requires a host `rustc` toolchain with the `clippy` component" + "ERROR: `x.py clippy` requires a host `rustc` toolchain with the `clippy` component" ); - eprintln!("help: try `rustup component add clippy`"); + eprintln!("HELP: try `rustup component add clippy`"); crate::exit!(1); }); if !t!(std::str::from_utf8(&output.stdout)).contains("nightly") { diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 2eb5d06bcb3b..2f5a84bfe6ea 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -1462,7 +1462,7 @@ impl Config { if available_backends.contains(&backend) { panic!("Invalid value '{s}' for 'rust.codegen-backends'. Instead, please use '{backend}'."); } else { - println!("help: '{s}' for 'rust.codegen-backends' might fail. \ + println!("HELP: '{s}' for 'rust.codegen-backends' might fail. \ Codegen backends are mostly defined without the '{CODEGEN_BACKEND_PREFIX}' prefix. \ In this case, it would be referred to as '{backend}'."); } @@ -1806,9 +1806,9 @@ impl Config { } (channel, version) => { let src = self.src.display(); - eprintln!("error: failed to determine artifact channel and/or version"); + eprintln!("ERROR: failed to determine artifact channel and/or version"); eprintln!( - "help: consider using a git checkout or ensure these files are readable" + "HELP: consider using a git checkout or ensure these files are readable" ); if let Err(channel) = channel { eprintln!("reading {src}/src/ci/channel failed: {channel:?}"); @@ -2064,10 +2064,10 @@ impl Config { ); let commit = merge_base.trim_end(); if commit.is_empty() { - println!("error: could not find commit hash for downloading rustc"); - println!("help: maybe your repository history is too shallow?"); - println!("help: consider disabling `download-rustc`"); - println!("help: or fetch enough history to include one upstream commit"); + println!("ERROR: could not find commit hash for downloading rustc"); + println!("HELP: maybe your repository history is too shallow?"); + println!("HELP: consider disabling `download-rustc`"); + println!("HELP: or fetch enough history to include one upstream commit"); crate::exit!(1); } @@ -2081,14 +2081,14 @@ impl Config { if if_unchanged { if self.verbose > 0 { println!( - "warning: saw changes to compiler/ or library/ since {commit}; \ + "WARNING: saw changes to compiler/ or library/ since {commit}; \ ignoring `download-rustc`" ); } return None; } println!( - "warning: `download-rustc` is enabled, but there are changes to \ + "WARNING: `download-rustc` is enabled, but there are changes to \ compiler/ or library/" ); } diff --git a/src/bootstrap/src/core/config/flags.rs b/src/bootstrap/src/core/config/flags.rs index 64af114f998e..2a301007ab47 100644 --- a/src/bootstrap/src/core/config/flags.rs +++ b/src/bootstrap/src/core/config/flags.rs @@ -190,7 +190,7 @@ impl Flags { if let Ok(HelpVerboseOnly { help: true, verbose: 1.., cmd: subcommand }) = HelpVerboseOnly::try_parse_from(it.clone()) { - println!("note: updating submodules before printing available paths"); + println!("NOTE: updating submodules before printing available paths"); let config = Config::parse(&[String::from("build")]); let build = Build::new(config); let paths = Builder::get_help(&build, subcommand); diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs index 5541a2f3e35e..3327aed9600b 100644 --- a/src/bootstrap/src/core/download.rs +++ b/src/bootstrap/src/core/download.rs @@ -114,7 +114,7 @@ impl Config { is_nixos }); if val { - eprintln!("info: You seem to be using Nix."); + eprintln!("INFO: You seem to be using Nix."); } val } @@ -606,10 +606,10 @@ impl Config { let mut help_on_error = ""; if destination == "ci-rustc" { - help_on_error = "error: failed to download pre-built rustc from CI + help_on_error = "ERROR: failed to download pre-built rustc from CI -note: old builds get deleted after a certain time -help: if trying to compile an old commit of rustc, disable `download-rustc` in config.toml: +NOTE: old builds get deleted after a certain time +HELP: if trying to compile an old commit of rustc, disable `download-rustc` in config.toml: [rust] download-rustc = false @@ -685,10 +685,10 @@ download-rustc = false let filename = format!("rust-dev-{}-{}.tar.xz", version, self.build.triple); let tarball = rustc_cache.join(&filename); if !tarball.exists() { - let help_on_error = "error: failed to download llvm from ci + let help_on_error = "ERROR: failed to download llvm from ci - help: old builds get deleted after a certain time - help: if trying to compile an old commit of rustc, disable `download-ci-llvm` in config.toml: + HELP: old builds get deleted after a certain time + HELP: if trying to compile an old commit of rustc, disable `download-ci-llvm` in config.toml: [llvm] download-ci-llvm = false diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 9ec192861f46..33b8f1a7ce72 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -1568,7 +1568,7 @@ impl Build { if !stamp.exists() { eprintln!( - "Error: Unable to find the stamp file {}, did you try to keep a nonexistent build stage?", + "ERROR: Unable to find the stamp file {}, did you try to keep a nonexistent build stage?", stamp.display() ); crate::exit!(1); @@ -1697,7 +1697,7 @@ impl Build { self.verbose_than(1, &format!("Install {src:?} to {dst:?}")); t!(fs::create_dir_all(dstdir)); if !src.exists() { - panic!("Error: File \"{}\" not found!", src.display()); + panic!("ERROR: File \"{}\" not found!", src.display()); } self.copy_internal(src, &dst, true); chmod(&dst, perms); diff --git a/src/bootstrap/src/utils/bin_helpers.rs b/src/bootstrap/src/utils/bin_helpers.rs index b9177c490ac2..a588dd0d6653 100644 --- a/src/bootstrap/src/utils/bin_helpers.rs +++ b/src/bootstrap/src/utils/bin_helpers.rs @@ -22,8 +22,8 @@ pub(crate) fn parse_rustc_verbose() -> usize { pub(crate) fn parse_rustc_stage() -> String { std::env::var("RUSTC_STAGE").unwrap_or_else(|_| { // Don't panic here; it's reasonable to try and run these shims directly. Give a helpful error instead. - eprintln!("rustc shim: fatal: RUSTC_STAGE was not set"); - eprintln!("rustc shim: note: use `x.py build -vvv` to see all environment variables set by bootstrap"); + eprintln!("rustc shim: FATAL: RUSTC_STAGE was not set"); + eprintln!("rustc shim: NOTE: use `x.py build -vvv` to see all environment variables set by bootstrap"); std::process::exit(101); }) } diff --git a/src/bootstrap/src/utils/helpers.rs b/src/bootstrap/src/utils/helpers.rs index 82a5607d9037..5bc81f2d983e 100644 --- a/src/bootstrap/src/utils/helpers.rs +++ b/src/bootstrap/src/utils/helpers.rs @@ -233,7 +233,7 @@ pub fn check_run(cmd: &mut Command, print_cmd_on_fail: bool) -> bool { let status = match cmd.status() { Ok(status) => status, Err(e) => { - println!("failed to execute command: {cmd:?}\nerror: {e}"); + println!("failed to execute command: {cmd:?}\nERROR: {e}"); return false; } }; @@ -262,7 +262,7 @@ pub fn make(host: &str) -> PathBuf { pub fn output(cmd: &mut Command) -> String { let output = match cmd.stderr(Stdio::inherit()).output() { Ok(status) => status, - Err(e) => fail(&format!("failed to execute command: {cmd:?}\nerror: {e}")), + Err(e) => fail(&format!("failed to execute command: {cmd:?}\nERROR: {e}")), }; if !output.status.success() { panic!( @@ -327,7 +327,7 @@ pub(crate) fn absolute(path: &Path) -> PathBuf { } #[cfg(not(any(unix, windows)))] { - println!("warning: bootstrap is not supported on non-unix platforms"); + println!("WARNING: bootstrap is not supported on non-unix platforms"); t!(std::fs::canonicalize(t!(std::env::current_dir()))).join(path) } } diff --git a/src/bootstrap/src/utils/metrics.rs b/src/bootstrap/src/utils/metrics.rs index 65794f05d2d9..174f374224c0 100644 --- a/src/bootstrap/src/utils/metrics.rs +++ b/src/bootstrap/src/utils/metrics.rs @@ -180,7 +180,7 @@ impl BuildMetrics { t!(serde_json::from_slice::(&contents)).invocations } else { println!( - "warning: overriding existing build/metrics.json, as it's not \ + "WARNING: overriding existing build/metrics.json, as it's not \ compatible with build metrics format version {CURRENT_FORMAT_VERSION}." ); Vec::new() diff --git a/src/bootstrap/src/utils/render_tests.rs b/src/bootstrap/src/utils/render_tests.rs index f97aa9585135..bff47f65c51f 100644 --- a/src/bootstrap/src/utils/render_tests.rs +++ b/src/bootstrap/src/utils/render_tests.rs @@ -197,7 +197,7 @@ impl<'a> Renderer<'a> { println!("{stdout}"); } if let Some(message) = &failure.message { - println!("note: {message}"); + println!("NOTE: {message}"); } } } From b8648216a5eadd043a3fb1eb486a86fc55e17ab6 Mon Sep 17 00:00:00 2001 From: Ikko Eltociear Ashimine Date: Thu, 9 Nov 2023 16:10:37 +0900 Subject: [PATCH 366/435] Fix typo in internal.rs covert -> convert --- compiler/rustc_smir/src/rustc_internal/internal.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_smir/src/rustc_internal/internal.rs b/compiler/rustc_smir/src/rustc_internal/internal.rs index 78144524ac50..7cfdbbbf7037 100644 --- a/compiler/rustc_smir/src/rustc_internal/internal.rs +++ b/compiler/rustc_smir/src/rustc_internal/internal.rs @@ -54,7 +54,7 @@ fn ty_const<'tcx>(constant: &Const, tables: &mut Tables<'tcx>) -> rustc_ty::Cons match constant.internal(tables) { rustc_middle::mir::Const::Ty(c) => c, cnst => { - panic!("Trying to covert constant `{constant:?}` to type constant, but found {cnst:?}") + panic!("Trying to convert constant `{constant:?}` to type constant, but found {cnst:?}") } } } From 5693a34db2f0e929995fe7aa03d307bafa9360aa Mon Sep 17 00:00:00 2001 From: sjwang05 <63834813+sjwang05@users.noreply.github.com> Date: Thu, 9 Nov 2023 00:31:42 -0800 Subject: [PATCH 367/435] Suggest fix for ; within let-chains --- compiler/rustc_parse/src/parser/expr.rs | 24 ++++++++++-- tests/ui/parser/semi-in-let-chain.rs | 27 +++++++++++++ tests/ui/parser/semi-in-let-chain.stderr | 50 ++++++++++++++++++++++++ 3 files changed, 97 insertions(+), 4 deletions(-) create mode 100644 tests/ui/parser/semi-in-let-chain.rs create mode 100644 tests/ui/parser/semi-in-let-chain.stderr diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 19690a6964be..235b28b6e26e 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2441,10 +2441,26 @@ impl<'a> Parser<'a> { self.error_on_extra_if(&cond)?; // Parse block, which will always fail, but we can add a nice note to the error self.parse_block().map_err(|mut err| { - err.span_note( - cond_span, - "the `if` expression is missing a block after this condition", - ); + if self.prev_token == token::Semi + && self.token == token::AndAnd + && let maybe_let = self.look_ahead(1, |t| t.clone()) + && maybe_let.is_keyword(kw::Let) + { + err.span_suggestion( + self.prev_token.span, + "consider removing this semicolon to parse the `let` as part of the same chain", + "", + Applicability::MachineApplicable, + ).span_note( + self.token.span.to(maybe_let.span), + "you likely meant to continue parsing the let-chain starting here", + ); + } else { + err.span_note( + cond_span, + "the `if` expression is missing a block after this condition", + ); + } err })? } diff --git a/tests/ui/parser/semi-in-let-chain.rs b/tests/ui/parser/semi-in-let-chain.rs new file mode 100644 index 000000000000..9c21af0372d2 --- /dev/null +++ b/tests/ui/parser/semi-in-let-chain.rs @@ -0,0 +1,27 @@ +// Issue #117720 + +#![feature(let_chains)] + +fn main() { + if let () = () + && let () = (); //~ERROR + && let () = () + { + } +} + +fn foo() { + if let () = () + && () == (); //~ERROR + && 1 < 0 + { + } +} + +fn bar() { + if let () = () + && () == (); //~ERROR + && let () = () + { + } +} diff --git a/tests/ui/parser/semi-in-let-chain.stderr b/tests/ui/parser/semi-in-let-chain.stderr new file mode 100644 index 000000000000..c1a8f92965eb --- /dev/null +++ b/tests/ui/parser/semi-in-let-chain.stderr @@ -0,0 +1,50 @@ +error: expected `{`, found `;` + --> $DIR/semi-in-let-chain.rs:7:23 + | +LL | && let () = (); + | ^ expected `{` + | +note: you likely meant to continue parsing the let-chain starting here + --> $DIR/semi-in-let-chain.rs:8:9 + | +LL | && let () = () + | ^^^^^^ +help: consider removing this semicolon to parse the `let` as part of the same chain + | +LL - && let () = (); +LL + && let () = () + | + +error: expected `{`, found `;` + --> $DIR/semi-in-let-chain.rs:15:20 + | +LL | && () == (); + | ^ expected `{` + | +note: the `if` expression is missing a block after this condition + --> $DIR/semi-in-let-chain.rs:14:8 + | +LL | if let () = () + | ________^ +LL | | && () == (); + | |___________________^ + +error: expected `{`, found `;` + --> $DIR/semi-in-let-chain.rs:23:20 + | +LL | && () == (); + | ^ expected `{` + | +note: you likely meant to continue parsing the let-chain starting here + --> $DIR/semi-in-let-chain.rs:24:9 + | +LL | && let () = () + | ^^^^^^ +help: consider removing this semicolon to parse the `let` as part of the same chain + | +LL - && () == (); +LL + && () == () + | + +error: aborting due to 3 previous errors + From 7142c8d83c107339efb6fc49296295442d5688a9 Mon Sep 17 00:00:00 2001 From: klensy Date: Thu, 9 Nov 2023 14:37:30 +0300 Subject: [PATCH 368/435] bump few ICU4X leftover deps implements https://github.com/rust-lang/rust/pull/117632#issuecomment-1795027801 suggestion --- Cargo.lock | 41 +++++++++++++------------------------- src/tools/tidy/src/deps.rs | 4 ++++ 2 files changed, 18 insertions(+), 27 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index da8ef2bf3bd3..d3ecadf6e172 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4191,7 +4191,7 @@ dependencies = [ "proc-macro2", "quote", "syn 2.0.29", - "synstructure 0.13.0", + "synstructure", ] [[package]] @@ -5233,18 +5233,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "synstructure" -version = "0.12.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", - "unicode-xid", -] - [[package]] name = "synstructure" version = "0.13.0" @@ -6386,35 +6374,35 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af46c169923ed7516eef0aa32b56d2651b229f57458ebe46b49ddd6efef5b7a2" +checksum = "d5e19fb6ed40002bab5403ffa37e53e0e56f914a4450c8765f533018db1db35f" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", - "synstructure 0.12.6", + "syn 2.0.29", + "synstructure", ] [[package]] name = "zerofrom" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df54d76c3251de27615dfcce21e636c172dafb2549cd7fd93e21c66f6ca6bea2" +checksum = "655b0814c5c0b19ade497851070c640773304939a6c0fd5f5fb43da0696d05b7" dependencies = [ "zerofrom-derive", ] [[package]] name = "zerofrom-derive" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4eae7c1f7d4b8eafce526bc0771449ddc2f250881ae31c50d22c032b5a1c499" +checksum = "e6a647510471d372f2e6c2e6b7219e44d8c574d24fdc11c610a61455782f18c3" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", - "synstructure 0.12.6", + "syn 2.0.29", + "synstructure", ] [[package]] @@ -6430,14 +6418,13 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.9.4" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "486558732d5dde10d0f8cb2936507c1bb21bc539d924c949baf5f36a58e51bac" +checksum = "acabf549809064225ff8878baedc4ce3732ac3b07e7c7ce6e5c2ccdbc485c324" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", - "synstructure 0.12.6", + "syn 2.0.29", ] [[package]] diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 0286def14744..d60be354e838 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -418,7 +418,11 @@ const ICU4X_UNICODE_LICENSE_DEPENDENCIES: &[&str] = &[ "tinystr", "writeable", "yoke", + "yoke-derive", + "zerofrom", + "zerofrom-derive", "zerovec", + "zerovec-derive", // tidy-alphabetical-end ]; From 22e1576a1208eddf7c3fc0ef0227cc36a6c8db1e Mon Sep 17 00:00:00 2001 From: Alona Enraght-Moony Date: Thu, 9 Nov 2023 12:13:16 +0000 Subject: [PATCH 369/435] rustdoc-json: Fix test so it actuall checks things After #111427, no item has a `kind` field, so these assertions could never fail. Instead, assert that those two items arn't present. --- tests/rustdoc-json/reexport/pub_use_doc_hidden.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/rustdoc-json/reexport/pub_use_doc_hidden.rs b/tests/rustdoc-json/reexport/pub_use_doc_hidden.rs index 46c3da4c15b3..15d194ef5d92 100644 --- a/tests/rustdoc-json/reexport/pub_use_doc_hidden.rs +++ b/tests/rustdoc-json/reexport/pub_use_doc_hidden.rs @@ -2,11 +2,12 @@ mod repeat_n { #[doc(hidden)] + /// not here pub struct RepeatN {} } +/// not here pub use repeat_n::RepeatN; // @count "$.index[*][?(@.name=='pub_use_doc_hidden')].inner.items[*]" 0 -// @!has "$.index[*][?(@.kind=='struct')]" -// @!has "$.index[*][?(@.kind=='import')]" +// @!has "$.index[*][?(@.docs == 'not here')]" From 488dd9bc737f20e95104b9d7ab9d1769cac25f7e Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Thu, 9 Nov 2023 14:44:54 +0100 Subject: [PATCH 370/435] fmt --- src/tools/compiletest/src/common.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index f42fa588b6ec..0e00208d6baf 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -448,10 +448,7 @@ impl Config { } pub fn git_config(&self) -> GitConfig<'_> { - GitConfig { - git_repository: &self.git_repository, - nightly_branch: &self.nightly_branch, - } + GitConfig { git_repository: &self.git_repository, nightly_branch: &self.nightly_branch } } } From d32d9238cfb83bff2147212c1c11b53f0bd1563b Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Wed, 8 Nov 2023 17:36:43 -0500 Subject: [PATCH 371/435] Emit #[inline] on derive(Debug) --- .../rustc_builtin_macros/src/deriving/debug.rs | 2 +- tests/codegen/simd/unpadded-simd.rs | 9 +++++++-- tests/ui/deriving/deriving-all-codegen.stdout | 15 +++++++++++++++ 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/deriving/debug.rs b/compiler/rustc_builtin_macros/src/deriving/debug.rs index 809f9838d20b..30c9b35bbacd 100644 --- a/compiler/rustc_builtin_macros/src/deriving/debug.rs +++ b/compiler/rustc_builtin_macros/src/deriving/debug.rs @@ -33,7 +33,7 @@ pub fn expand_deriving_debug( explicit_self: true, nonself_args: vec![(fmtr, sym::f)], ret_ty: Path(path_std!(fmt::Result)), - attributes: ast::AttrVec::new(), + attributes: thin_vec![cx.attr_word(sym::inline, span)], fieldless_variants_strategy: FieldlessVariantsStrategy::SpecializeIfAllVariantsFieldless, combine_substructure: combine_substructure(Box::new(|a, b, c| { diff --git a/tests/codegen/simd/unpadded-simd.rs b/tests/codegen/simd/unpadded-simd.rs index eb44dbd93135..797bca38ffa1 100644 --- a/tests/codegen/simd/unpadded-simd.rs +++ b/tests/codegen/simd/unpadded-simd.rs @@ -5,10 +5,15 @@ #![crate_type = "lib"] #![feature(repr_simd)] -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone)] #[repr(simd)] pub struct int16x4_t(pub i16, pub i16, pub i16, pub i16); -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone)] pub struct int16x4x2_t(pub int16x4_t, pub int16x4_t); + // CHECK: %int16x4x2_t = type { <4 x i16>, <4 x i16> } +#[no_mangle] +fn takes_int16x4x2_t(t: int16x4x2_t) -> int16x4x2_t { + t +} diff --git a/tests/ui/deriving/deriving-all-codegen.stdout b/tests/ui/deriving/deriving-all-codegen.stdout index 3d9f8129d939..42154c3c3be2 100644 --- a/tests/ui/deriving/deriving-all-codegen.stdout +++ b/tests/ui/deriving/deriving-all-codegen.stdout @@ -33,6 +33,7 @@ impl ::core::clone::Clone for Empty { impl ::core::marker::Copy for Empty { } #[automatically_derived] impl ::core::fmt::Debug for Empty { + #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { ::core::fmt::Formatter::write_str(f, "Empty") } @@ -97,6 +98,7 @@ impl ::core::clone::Clone for Point { impl ::core::marker::Copy for Point { } #[automatically_derived] impl ::core::fmt::Debug for Point { + #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { ::core::fmt::Formatter::debug_struct_field2_finish(f, "Point", "x", &self.x, "y", &&self.y) @@ -183,6 +185,7 @@ impl ::core::clone::Clone for PackedPoint { impl ::core::marker::Copy for PackedPoint { } #[automatically_derived] impl ::core::fmt::Debug for PackedPoint { + #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { ::core::fmt::Formatter::debug_struct_field2_finish(f, "PackedPoint", "x", &{ self.x }, "y", &&{ self.y }) @@ -276,6 +279,7 @@ impl ::core::clone::Clone for Big { impl ::core::marker::Copy for Big { } #[automatically_derived] impl ::core::fmt::Debug for Big { + #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { let names: &'static _ = &["b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8"]; @@ -475,6 +479,7 @@ impl Copy for PackedManualCopy {} struct Unsized([u32]); #[automatically_derived] impl ::core::fmt::Debug for Unsized { + #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Unsized", &&self.0) @@ -527,6 +532,7 @@ impl ::core::cmp::Ord for Unsized { struct PackedUnsizedU8([u8]); #[automatically_derived] impl ::core::fmt::Debug for PackedUnsizedU8 { + #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { ::core::fmt::Formatter::debug_tuple_field1_finish(f, "PackedUnsizedU8", &&self.0) @@ -569,6 +575,7 @@ impl #[automatically_derived] impl ::core::fmt::Debug for Generic where T::A: ::core::fmt::Debug { + #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { ::core::fmt::Formatter::debug_struct_field3_finish(f, "Generic", "t", &self.t, "ta", &self.ta, "u", &&self.u) @@ -687,6 +694,7 @@ impl ::core::fmt::Debug for PackedGeneric where T::A: ::core::fmt::Debug + ::core::marker::Copy { + #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { ::core::fmt::Formatter::debug_tuple_field3_finish(f, "PackedGeneric", &{ self.0 }, &{ self.1 }, &&{ self.2 }) @@ -797,6 +805,7 @@ impl ::core::clone::Clone for Enum0 { impl ::core::marker::Copy for Enum0 { } #[automatically_derived] impl ::core::fmt::Debug for Enum0 { + #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { match *self {} } @@ -856,6 +865,7 @@ impl ::core::clone::Clone for Enum1 { } #[automatically_derived] impl ::core::fmt::Debug for Enum1 { + #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { match self { Enum1::Single { x: __self_0 } => @@ -932,6 +942,7 @@ impl ::core::clone::Clone for Fieldless1 { } #[automatically_derived] impl ::core::fmt::Debug for Fieldless1 { + #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { ::core::fmt::Formatter::write_str(f, "A") } @@ -995,6 +1006,7 @@ impl ::core::clone::Clone for Fieldless { impl ::core::marker::Copy for Fieldless { } #[automatically_derived] impl ::core::fmt::Debug for Fieldless { + #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { ::core::fmt::Formatter::write_str(f, match self { @@ -1083,6 +1095,7 @@ impl ::core::clone::Clone for Mixed { impl ::core::marker::Copy for Mixed { } #[automatically_derived] impl ::core::fmt::Debug for Mixed { + #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { match self { Mixed::P => ::core::fmt::Formatter::write_str(f, "P"), @@ -1217,6 +1230,7 @@ impl ::core::clone::Clone for Fielded { } #[automatically_derived] impl ::core::fmt::Debug for Fielded { + #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { match self { Fielded::X(__self_0) => @@ -1341,6 +1355,7 @@ impl ::core::marker::Copy #[automatically_derived] impl ::core::fmt::Debug for EnumGeneric { + #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { match self { EnumGeneric::One(__self_0) => From fdb72795d1e4f92fd05a86e62fe5819190a1f5a8 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Thu, 9 Nov 2023 23:04:51 +0300 Subject: [PATCH 372/435] enable unstable feature on `x clean [PATH]` Since https://github.com/rust-lang/rust/pull/111076 enables unstable cargo feature (`public-dependency`), we need to ensure that unstable features are enabled before reading libstd Cargo.toml. Signed-off-by: onur-ozkan --- src/bootstrap/src/core/build_steps/clean.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/bootstrap/src/core/build_steps/clean.rs b/src/bootstrap/src/core/build_steps/clean.rs index 679770ce0ec7..3a28ab52ff46 100644 --- a/src/bootstrap/src/core/build_steps/clean.rs +++ b/src/bootstrap/src/core/build_steps/clean.rs @@ -68,6 +68,12 @@ macro_rules! clean_crate_tree { let compiler = self.compiler; let target = compiler.host; let mut cargo = builder.bare_cargo(compiler, $mode, target, "clean"); + + // Since https://github.com/rust-lang/rust/pull/111076 enables + // unstable cargo feature (`public-dependency`), we need to ensure + // that unstable features are enabled before reading libstd Cargo.toml. + cargo.env("RUSTC_BOOTSTRAP", "1"); + for krate in &*self.crates { cargo.arg("-p"); cargo.arg(krate); From 82a9f94de5145665bb3b3e64bbe8d01969b7ab1e Mon Sep 17 00:00:00 2001 From: John Millikin Date: Thu, 9 Nov 2023 08:47:24 +0900 Subject: [PATCH 373/435] Closure-consuming helper functions for `fmt::Debug` helpers --- library/alloc/src/fmt.rs | 2 + library/core/src/fmt/builders.rs | 144 ++++++++++++++++++++++++++++--- library/core/src/fmt/mod.rs | 3 + 3 files changed, 136 insertions(+), 13 deletions(-) diff --git a/library/alloc/src/fmt.rs b/library/alloc/src/fmt.rs index 1e2c35bf735f..5b50ef7bf6c2 100644 --- a/library/alloc/src/fmt.rs +++ b/library/alloc/src/fmt.rs @@ -555,6 +555,8 @@ pub use core::fmt::Alignment; #[stable(feature = "rust1", since = "1.0.0")] pub use core::fmt::Error; +#[unstable(feature = "debug_closure_helpers", issue = "117729")] +pub use core::fmt::FormatterFn; #[stable(feature = "rust1", since = "1.0.0")] pub use core::fmt::{write, Arguments}; #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/core/src/fmt/builders.rs b/library/core/src/fmt/builders.rs index 47db53ac6f34..4ccb585862cd 100644 --- a/library/core/src/fmt/builders.rs +++ b/library/core/src/fmt/builders.rs @@ -130,6 +130,18 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> { /// ``` #[stable(feature = "debug_builders", since = "1.2.0")] pub fn field(&mut self, name: &str, value: &dyn fmt::Debug) -> &mut Self { + self.field_with(name, |f| value.fmt(f)) + } + + /// Adds a new field to the generated struct output. + /// + /// This method is equivalent to [`DebugStruct::field`], but formats the + /// value using a provided closure rather than by calling [`Debug::fmt`]. + #[unstable(feature = "debug_closure_helpers", issue = "117729")] + pub fn field_with(&mut self, name: &str, value_fmt: F) -> &mut Self + where + F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, + { self.result = self.result.and_then(|_| { if self.is_pretty() { if !self.has_fields { @@ -140,14 +152,14 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> { let mut writer = PadAdapter::wrap(self.fmt, &mut slot, &mut state); writer.write_str(name)?; writer.write_str(": ")?; - value.fmt(&mut writer)?; + value_fmt(&mut writer)?; writer.write_str(",\n") } else { let prefix = if self.has_fields { ", " } else { " { " }; self.fmt.write_str(prefix)?; self.fmt.write_str(name)?; self.fmt.write_str(": ")?; - value.fmt(self.fmt) + value_fmt(self.fmt) } }); @@ -315,6 +327,18 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> { /// ``` #[stable(feature = "debug_builders", since = "1.2.0")] pub fn field(&mut self, value: &dyn fmt::Debug) -> &mut Self { + self.field_with(|f| value.fmt(f)) + } + + /// Adds a new field to the generated tuple struct output. + /// + /// This method is equivalent to [`DebugTuple::field`], but formats the + /// value using a provided closure rather than by calling [`Debug::fmt`]. + #[unstable(feature = "debug_closure_helpers", issue = "117729")] + pub fn field_with(&mut self, value_fmt: F) -> &mut Self + where + F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, + { self.result = self.result.and_then(|_| { if self.is_pretty() { if self.fields == 0 { @@ -323,12 +347,12 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> { let mut slot = None; let mut state = Default::default(); let mut writer = PadAdapter::wrap(self.fmt, &mut slot, &mut state); - value.fmt(&mut writer)?; + value_fmt(&mut writer)?; writer.write_str(",\n") } else { let prefix = if self.fields == 0 { "(" } else { ", " }; self.fmt.write_str(prefix)?; - value.fmt(self.fmt) + value_fmt(self.fmt) } }); @@ -385,7 +409,10 @@ struct DebugInner<'a, 'b: 'a> { } impl<'a, 'b: 'a> DebugInner<'a, 'b> { - fn entry(&mut self, entry: &dyn fmt::Debug) { + fn entry_with(&mut self, entry_fmt: F) + where + F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, + { self.result = self.result.and_then(|_| { if self.is_pretty() { if !self.has_fields { @@ -394,13 +421,13 @@ impl<'a, 'b: 'a> DebugInner<'a, 'b> { let mut slot = None; let mut state = Default::default(); let mut writer = PadAdapter::wrap(self.fmt, &mut slot, &mut state); - entry.fmt(&mut writer)?; + entry_fmt(&mut writer)?; writer.write_str(",\n") } else { if self.has_fields { self.fmt.write_str(", ")? } - entry.fmt(self.fmt) + entry_fmt(self.fmt) } }); @@ -475,7 +502,20 @@ impl<'a, 'b: 'a> DebugSet<'a, 'b> { /// ``` #[stable(feature = "debug_builders", since = "1.2.0")] pub fn entry(&mut self, entry: &dyn fmt::Debug) -> &mut Self { - self.inner.entry(entry); + self.inner.entry_with(|f| entry.fmt(f)); + self + } + + /// Adds a new entry to the set output. + /// + /// This method is equivalent to [`DebugSet::entry`], but formats the + /// entry using a provided closure rather than by calling [`Debug::fmt`]. + #[unstable(feature = "debug_closure_helpers", issue = "117729")] + pub fn entry_with(&mut self, entry_fmt: F) -> &mut Self + where + F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, + { + self.inner.entry_with(entry_fmt); self } @@ -605,7 +645,20 @@ impl<'a, 'b: 'a> DebugList<'a, 'b> { /// ``` #[stable(feature = "debug_builders", since = "1.2.0")] pub fn entry(&mut self, entry: &dyn fmt::Debug) -> &mut Self { - self.inner.entry(entry); + self.inner.entry_with(|f| entry.fmt(f)); + self + } + + /// Adds a new entry to the list output. + /// + /// This method is equivalent to [`DebugList::entry`], but formats the + /// entry using a provided closure rather than by calling [`Debug::fmt`]. + #[unstable(feature = "debug_closure_helpers", issue = "117729")] + pub fn entry_with(&mut self, entry_fmt: F) -> &mut Self + where + F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, + { + self.inner.entry_with(entry_fmt); self } @@ -775,6 +828,18 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// ``` #[stable(feature = "debug_map_key_value", since = "1.42.0")] pub fn key(&mut self, key: &dyn fmt::Debug) -> &mut Self { + self.key_with(|f| key.fmt(f)) + } + + /// Adds the key part of a new entry to the map output. + /// + /// This method is equivalent to [`DebugMap::key`], but formats the + /// key using a provided closure rather than by calling [`Debug::fmt`]. + #[unstable(feature = "debug_closure_helpers", issue = "117729")] + pub fn key_with(&mut self, key_fmt: F) -> &mut Self + where + F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, + { self.result = self.result.and_then(|_| { assert!( !self.has_key, @@ -789,13 +854,13 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { let mut slot = None; self.state = Default::default(); let mut writer = PadAdapter::wrap(self.fmt, &mut slot, &mut self.state); - key.fmt(&mut writer)?; + key_fmt(&mut writer)?; writer.write_str(": ")?; } else { if self.has_fields { self.fmt.write_str(", ")? } - key.fmt(self.fmt)?; + key_fmt(self.fmt)?; self.fmt.write_str(": ")?; } @@ -839,16 +904,28 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// ``` #[stable(feature = "debug_map_key_value", since = "1.42.0")] pub fn value(&mut self, value: &dyn fmt::Debug) -> &mut Self { + self.value_with(|f| value.fmt(f)) + } + + /// Adds the value part of a new entry to the map output. + /// + /// This method is equivalent to [`DebugMap::value`], but formats the + /// value using a provided closure rather than by calling [`Debug::fmt`]. + #[unstable(feature = "debug_closure_helpers", issue = "117729")] + pub fn value_with(&mut self, value_fmt: F) -> &mut Self + where + F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, + { self.result = self.result.and_then(|_| { assert!(self.has_key, "attempted to format a map value before its key"); if self.is_pretty() { let mut slot = None; let mut writer = PadAdapter::wrap(self.fmt, &mut slot, &mut self.state); - value.fmt(&mut writer)?; + value_fmt(&mut writer)?; writer.write_str(",\n")?; } else { - value.fmt(self.fmt)?; + value_fmt(self.fmt)?; } self.has_key = false; @@ -936,3 +1013,44 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { self.fmt.alternate() } } + +/// Implements [`fmt::Debug`] and [`fmt::Display`] using a function. +/// +/// # Examples +/// +/// ``` +/// #![feature(debug_closure_helpers)] +/// use std::fmt; +/// +/// let value = 'a'; +/// assert_eq!(format!("{}", value), "a"); +/// assert_eq!(format!("{:?}", value), "'a'"); +/// +/// let wrapped = fmt::FormatterFn(|f| write!(f, "{:?}", &value)); +/// assert_eq!(format!("{}", wrapped), "'a'"); +/// assert_eq!(format!("{:?}", wrapped), "'a'"); +/// ``` +#[unstable(feature = "debug_closure_helpers", issue = "117729")] +pub struct FormatterFn(pub F) +where + F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result; + +#[unstable(feature = "debug_closure_helpers", issue = "117729")] +impl fmt::Debug for FormatterFn +where + F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + (self.0)(f) + } +} + +#[unstable(feature = "debug_closure_helpers", issue = "117729")] +impl fmt::Display for FormatterFn +where + F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + (self.0)(f) + } +} diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index c45ab094a20d..e1b7b46a1ed2 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -39,6 +39,9 @@ pub enum Alignment { #[stable(feature = "debug_builders", since = "1.2.0")] pub use self::builders::{DebugList, DebugMap, DebugSet, DebugStruct, DebugTuple}; +#[unstable(feature = "debug_closure_helpers", issue = "117729")] +pub use self::builders::FormatterFn; + /// The type returned by formatter methods. /// /// # Examples From 49908b4d90688bea6edb5ef811d78e61ba3aa5f3 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 8 Nov 2023 17:05:44 +1100 Subject: [PATCH 374/435] Simplify the `current_rustc_version` macro. It currently has the syntax `current_rustc_version!(env!("CFG_RELEASE"))` where the `env!("CFG_RELEASE")` part looks like a normal expression but it is actually parsed and processed by the `current_rustc_version` macro. The documented rationale for this is that you'll find it if you grep for `env!("CFG_RELEASE")`. But I think that's of very little use -- I would personally grep for just "CFG_RELEASE" -- and it complicates the macro, requiring the use of `syn`. This commit simplifies the macro. --- compiler/rustc_macros/src/current_version.rs | 37 +++++--------------- compiler/rustc_macros/src/lib.rs | 3 ++ compiler/rustc_session/src/version.rs | 2 +- 3 files changed, 12 insertions(+), 30 deletions(-) diff --git a/compiler/rustc_macros/src/current_version.rs b/compiler/rustc_macros/src/current_version.rs index 5e3b91c17bf6..42ca60a6d8ab 100644 --- a/compiler/rustc_macros/src/current_version.rs +++ b/compiler/rustc_macros/src/current_version.rs @@ -1,37 +1,16 @@ use proc_macro::TokenStream; use proc_macro2::Span; use quote::quote; -use syn::parse::{Parse, ParseStream}; -use syn::{parenthesized, parse_macro_input, LitStr, Token}; -pub struct Input { - variable: LitStr, -} - -mod kw { - syn::custom_keyword!(env); -} - -impl Parse for Input { - // Input syntax is `env!("CFG_RELEASE")` to facilitate grepping. - fn parse(input: ParseStream<'_>) -> syn::Result { - let paren; - input.parse::()?; - input.parse::()?; - parenthesized!(paren in input); - let variable: LitStr = paren.parse()?; - Ok(Input { variable }) - } -} - -pub(crate) fn current_version(input: TokenStream) -> TokenStream { - let input = parse_macro_input!(input as Input); - - TokenStream::from(match RustcVersion::parse_env_var(&input.variable) { +pub(crate) fn current_version(_input: TokenStream) -> TokenStream { + let env_var = "CFG_RELEASE"; + TokenStream::from(match RustcVersion::parse_cfg_release(env_var) { Ok(RustcVersion { major, minor, patch }) => quote!( + // The produced literal has type `rustc_session::RustcVersion`. Self { major: #major, minor: #minor, patch: #patch } ), - Err(err) => syn::Error::new(Span::call_site(), err).into_compile_error(), + Err(err) => syn::Error::new(Span::call_site(), format!("{env_var} env var: {err}")) + .into_compile_error(), }) } @@ -42,8 +21,8 @@ struct RustcVersion { } impl RustcVersion { - fn parse_env_var(env_var: &LitStr) -> Result> { - let value = proc_macro::tracked_env::var(env_var.value())?; + fn parse_cfg_release(env_var: &str) -> Result> { + let value = proc_macro::tracked_env::var(env_var)?; Self::parse_str(&value) .ok_or_else(|| format!("failed to parse rustc version: {:?}", value).into()) } diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs index 193dbd75fbd5..a66666360324 100644 --- a/compiler/rustc_macros/src/lib.rs +++ b/compiler/rustc_macros/src/lib.rs @@ -26,6 +26,9 @@ mod symbols; mod type_foldable; mod type_visitable; +// Reads the rust version (e.g. "1.75.0") from the CFG_RELEASE env var and +// produces a `RustcVersion` literal containing that version (e.g. +// `RustcVersion { major: 1, minor: 75, patch: 0 }`). #[proc_macro] pub fn current_rustc_version(input: TokenStream) -> TokenStream { current_version::current_version(input) diff --git a/compiler/rustc_session/src/version.rs b/compiler/rustc_session/src/version.rs index 1ad8620bfba5..c0c088bcef7d 100644 --- a/compiler/rustc_session/src/version.rs +++ b/compiler/rustc_session/src/version.rs @@ -9,7 +9,7 @@ pub struct RustcVersion { } impl RustcVersion { - pub const CURRENT: Self = current_rustc_version!(env!("CFG_RELEASE")); + pub const CURRENT: Self = current_rustc_version!(); } impl Display for RustcVersion { From b35e5766576c1355f69f57c738998edbe4c8d807 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 8 Nov 2023 18:27:19 +1100 Subject: [PATCH 375/435] Minor cleanups. - Reduce some function exposure. - Fix some comment formatting. --- compiler/rustc_macros/src/diagnostics/diagnostic.rs | 4 ++-- .../rustc_macros/src/diagnostics/diagnostic_builder.rs | 7 ++++--- compiler/rustc_macros/src/diagnostics/subdiagnostic.rs | 2 +- compiler/rustc_macros/src/diagnostics/utils.rs | 6 +++--- compiler/rustc_macros/src/hash_stable.rs | 6 ++++-- 5 files changed, 14 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic.rs b/compiler/rustc_macros/src/diagnostics/diagnostic.rs index 1a8174bfd968..31ad9cdb2161 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic.rs @@ -229,8 +229,8 @@ fn generate_test(slug: &syn::Path, structure: &Structure<'_>) -> TokenStream { } } use std::sync::atomic::{AtomicUsize, Ordering}; - // We need to make sure that the same diagnostic slug can be used multiple times without causing an - // error, so just have a global counter here. + // We need to make sure that the same diagnostic slug can be used multiple times without + // causing an error, so just have a global counter here. static COUNTER: AtomicUsize = AtomicUsize::new(0); let slug = slug.get_ident().unwrap(); let ident = quote::format_ident!("verify_{slug}_{}", COUNTER.fetch_add(1, Ordering::Relaxed)); diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs index e9a5cd9de97b..2755a161d91e 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs @@ -53,6 +53,7 @@ pub(crate) struct DiagnosticDeriveVariantBuilder<'parent> { /// Slug is a mandatory part of the struct attribute as corresponds to the Fluent message that /// has the actual diagnostic message. pub slug: SpannedOption, + /// Error codes are a optional part of the struct attribute - this is only set to detect /// multiple specifications. pub code: SpannedOption<()>, @@ -68,7 +69,7 @@ impl DiagnosticDeriveBuilder { /// Call `f` for the struct or for each variant of the enum, returning a `TokenStream` with the /// tokens from `f` wrapped in an `match` expression. Emits errors for use of derive on unions /// or attributes on the type itself when input is an enum. - pub fn each_variant<'s, F>(&mut self, structure: &mut Structure<'s>, f: F) -> TokenStream + pub(crate) fn each_variant<'s, F>(&mut self, structure: &mut Structure<'s>, f: F) -> TokenStream where F: for<'a, 'v> Fn(DiagnosticDeriveVariantBuilder<'a>, &VariantInfo<'v>) -> TokenStream, { @@ -121,7 +122,7 @@ impl DiagnosticDeriveBuilder { impl<'a> DiagnosticDeriveVariantBuilder<'a> { /// Generates calls to `code` and similar functions based on the attributes on the type or /// variant. - pub fn preamble(&mut self, variant: &VariantInfo<'_>) -> TokenStream { + pub(crate) fn preamble(&mut self, variant: &VariantInfo<'_>) -> TokenStream { let ast = variant.ast(); let attrs = &ast.attrs; let preamble = attrs.iter().map(|attr| { @@ -135,7 +136,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { /// Generates calls to `span_label` and similar functions based on the attributes on fields or /// calls to `set_arg` when no attributes are present. - pub fn body(&mut self, variant: &VariantInfo<'_>) -> TokenStream { + pub(crate) fn body(&mut self, variant: &VariantInfo<'_>) -> TokenStream { let mut body = quote! {}; // Generate `set_arg` calls first.. for binding in variant.bindings().iter().filter(|bi| should_generate_set_arg(bi.ast())) { diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index 877271ff0774..0f9e68cdc501 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -478,7 +478,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { } } - pub fn into_tokens(&mut self) -> Result { + pub(crate) fn into_tokens(&mut self) -> Result { let kind_slugs = self.identify_kind()?; if kind_slugs.is_empty() { if self.is_enum { diff --git a/compiler/rustc_macros/src/diagnostics/utils.rs b/compiler/rustc_macros/src/diagnostics/utils.rs index 125632921816..2700f02e33a6 100644 --- a/compiler/rustc_macros/src/diagnostics/utils.rs +++ b/compiler/rustc_macros/src/diagnostics/utils.rs @@ -17,7 +17,7 @@ use synstructure::{BindingInfo, VariantInfo}; use super::error::invalid_attr; thread_local! { - pub static CODE_IDENT_COUNT: RefCell = RefCell::new(0); + pub(crate) static CODE_IDENT_COUNT: RefCell = RefCell::new(0); } /// Returns an ident of the form `__code_N` where `N` is incremented once with every call. @@ -208,7 +208,7 @@ impl<'ty> FieldInnerTy<'ty> { } } - pub fn span(&self) -> proc_macro2::Span { + pub(crate) fn span(&self) -> proc_macro2::Span { match self { FieldInnerTy::Option(ty) | FieldInnerTy::Vec(ty) | FieldInnerTy::Plain(ty) => ty.span(), } @@ -537,7 +537,7 @@ impl fmt::Display for SuggestionKind { } impl SuggestionKind { - pub fn to_suggestion_style(&self) -> TokenStream { + pub(crate) fn to_suggestion_style(&self) -> TokenStream { match self { SuggestionKind::Normal => { quote! { rustc_errors::SuggestionStyle::ShowCode } diff --git a/compiler/rustc_macros/src/hash_stable.rs b/compiler/rustc_macros/src/hash_stable.rs index 75a2f7009c25..91f1253105b5 100644 --- a/compiler/rustc_macros/src/hash_stable.rs +++ b/compiler/rustc_macros/src/hash_stable.rs @@ -38,7 +38,9 @@ fn parse_attributes(field: &syn::Field) -> Attributes { attrs } -pub fn hash_stable_generic_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { +pub(crate) fn hash_stable_generic_derive( + mut s: synstructure::Structure<'_>, +) -> proc_macro2::TokenStream { let generic: syn::GenericParam = parse_quote!(__CTX); s.add_bounds(synstructure::AddBounds::Generics); s.add_impl_generic(generic); @@ -81,7 +83,7 @@ pub fn hash_stable_generic_derive(mut s: synstructure::Structure<'_>) -> proc_ma ) } -pub fn hash_stable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { +pub(crate) fn hash_stable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { let generic: syn::GenericParam = parse_quote!('__ctx); s.add_bounds(synstructure::AddBounds::Generics); s.add_impl_generic(generic); From 316ffba3c859c15ca2d0ecdefb16fad3565a46bc Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 9 Nov 2023 09:30:22 +1100 Subject: [PATCH 376/435] Update instructions in a comment. And avoid duplication. --- compiler/rustc_macros/src/symbols.rs | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_macros/src/symbols.rs b/compiler/rustc_macros/src/symbols.rs index 4129712a6b21..3de4a904e5fd 100644 --- a/compiler/rustc_macros/src/symbols.rs +++ b/compiler/rustc_macros/src/symbols.rs @@ -19,7 +19,9 @@ //! ```bash //! cargo install cargo-expand # this is necessary only once //! cd compiler/rustc_span -//! cargo expand > /tmp/rustc_span.rs # it's a big file +//! # The specific version number in CFG_RELEASE doesn't matter. +//! # The output is large. +//! CFG_RELEASE="0.0.0" cargo +nightly expand > /tmp/rustc_span.rs //! ``` use proc_macro2::{Span, TokenStream}; @@ -318,13 +320,4 @@ fn symbols_with_errors(input: TokenStream) -> (TokenStream, Vec) { }; (output, errors.list) - - // To see the generated code, use the "cargo expand" command. - // Do this once to install: - // cargo install cargo-expand - // - // Then, cd to rustc_span and run: - // cargo expand > /tmp/rustc_span_expanded.rs - // - // and read that file. } From dd6bab9eff79d3d973d0e0a771c5872375650da9 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 9 Nov 2023 09:50:21 +1100 Subject: [PATCH 377/435] Factor out some duplicated code. --- compiler/rustc_macros/src/hash_stable.rs | 73 ++++++++++-------------- 1 file changed, 31 insertions(+), 42 deletions(-) diff --git a/compiler/rustc_macros/src/hash_stable.rs b/compiler/rustc_macros/src/hash_stable.rs index 91f1253105b5..6d23b9ac99d2 100644 --- a/compiler/rustc_macros/src/hash_stable.rs +++ b/compiler/rustc_macros/src/hash_stable.rs @@ -45,28 +45,9 @@ pub(crate) fn hash_stable_generic_derive( s.add_bounds(synstructure::AddBounds::Generics); s.add_impl_generic(generic); s.add_where_predicate(parse_quote! { __CTX: crate::HashStableContext }); - let body = s.each(|bi| { - let attrs = parse_attributes(bi.ast()); - if attrs.ignore { - quote! {} - } else if let Some(project) = attrs.project { - quote! { - (&#bi.#project).hash_stable(__hcx, __hasher); - } - } else { - quote! { - #bi.hash_stable(__hcx, __hasher); - } - } - }); - let discriminant = match s.ast().data { - syn::Data::Enum(_) => quote! { - ::std::mem::discriminant(self).hash_stable(__hcx, __hasher); - }, - syn::Data::Struct(_) => quote! {}, - syn::Data::Union(_) => panic!("cannot derive on union"), - }; + let discriminant = hash_stable_discriminant(&mut s); + let body = hash_stable_body(&mut s); s.bound_impl( quote!(::rustc_data_structures::stable_hasher::HashStable<__CTX>), @@ -87,28 +68,9 @@ pub(crate) fn hash_stable_derive(mut s: synstructure::Structure<'_>) -> proc_mac let generic: syn::GenericParam = parse_quote!('__ctx); s.add_bounds(synstructure::AddBounds::Generics); s.add_impl_generic(generic); - let body = s.each(|bi| { - let attrs = parse_attributes(bi.ast()); - if attrs.ignore { - quote! {} - } else if let Some(project) = attrs.project { - quote! { - (&#bi.#project).hash_stable(__hcx, __hasher); - } - } else { - quote! { - #bi.hash_stable(__hcx, __hasher); - } - } - }); - let discriminant = match s.ast().data { - syn::Data::Enum(_) => quote! { - ::std::mem::discriminant(self).hash_stable(__hcx, __hasher); - }, - syn::Data::Struct(_) => quote! {}, - syn::Data::Union(_) => panic!("cannot derive on union"), - }; + let discriminant = hash_stable_discriminant(&mut s); + let body = hash_stable_body(&mut s); s.bound_impl( quote!( @@ -128,3 +90,30 @@ pub(crate) fn hash_stable_derive(mut s: synstructure::Structure<'_>) -> proc_mac }, ) } + +fn hash_stable_discriminant(s: &mut synstructure::Structure<'_>) -> proc_macro2::TokenStream { + match s.ast().data { + syn::Data::Enum(_) => quote! { + ::std::mem::discriminant(self).hash_stable(__hcx, __hasher); + }, + syn::Data::Struct(_) => quote! {}, + syn::Data::Union(_) => panic!("cannot derive on union"), + } +} + +fn hash_stable_body(s: &mut synstructure::Structure<'_>) -> proc_macro2::TokenStream { + s.each(|bi| { + let attrs = parse_attributes(bi.ast()); + if attrs.ignore { + quote! {} + } else if let Some(project) = attrs.project { + quote! { + (&#bi.#project).hash_stable(__hcx, __hasher); + } + } else { + quote! { + #bi.hash_stable(__hcx, __hasher); + } + } + }) +} From 00942381575bc6c081835dbb38f68ce9603c032f Mon Sep 17 00:00:00 2001 From: sjwang05 <63834813+sjwang05@users.noreply.github.com> Date: Thu, 9 Nov 2023 18:46:45 -0800 Subject: [PATCH 378/435] Catch stray { in let-chains --- compiler/rustc_parse/src/lexer/tokentrees.rs | 34 +++++++++++++++- tests/ui/parser/brace-in-let-chain.rs | 28 +++++++++++++ tests/ui/parser/brace-in-let-chain.stderr | 42 ++++++++++++++++++++ 3 files changed, 103 insertions(+), 1 deletion(-) create mode 100644 tests/ui/parser/brace-in-let-chain.rs create mode 100644 tests/ui/parser/brace-in-let-chain.stderr diff --git a/compiler/rustc_parse/src/lexer/tokentrees.rs b/compiler/rustc_parse/src/lexer/tokentrees.rs index 31d91fe80bd6..7aa4ac7c4cb3 100644 --- a/compiler/rustc_parse/src/lexer/tokentrees.rs +++ b/compiler/rustc_parse/src/lexer/tokentrees.rs @@ -5,7 +5,8 @@ use super::{StringReader, UnmatchedDelim}; use rustc_ast::token::{self, Delimiter, Token}; use rustc_ast::tokenstream::{DelimSpan, Spacing, TokenStream, TokenTree}; use rustc_ast_pretty::pprust::token_to_string; -use rustc_errors::PErr; +use rustc_errors::{Applicability, PErr}; +use rustc_span::symbol::kw; pub(super) struct TokenTreesReader<'a> { string_reader: StringReader<'a>, @@ -121,9 +122,40 @@ impl<'a> TokenTreesReader<'a> { // out instead of complaining about the unclosed delims. let mut parser = crate::stream_to_parser(self.string_reader.sess, tts, None); let mut diff_errs = vec![]; + // Suggest removing a `{` we think appears in an `if`/`while` condition + // We want to suggest removing a `{` only if we think we're in an `if`/`while` condition, but + // we have no way of tracking this in the lexer itself, so we piggyback on the parser + let mut in_cond = false; while parser.token != token::Eof { if let Err(diff_err) = parser.err_diff_marker() { diff_errs.push(diff_err); + } else if parser.token.is_keyword(kw::If) { + in_cond = true; + } else if parser.token == token::CloseDelim(Delimiter::Brace) { + in_cond = false; + } else if in_cond && parser.token == token::OpenDelim(Delimiter::Brace) { + // Store the `&&` and `let` to use their spans later when creating the diagnostic + let maybe_andand = parser.look_ahead(1, |t| t.clone()); + let maybe_let = parser.look_ahead(2, |t| t.clone()); + if maybe_andand == token::OpenDelim(Delimiter::Brace) { + // This might be the beginning of the `if`/`while` body (i.e., the end of the condition) + in_cond = false; + } else if maybe_andand == token::AndAnd && maybe_let.is_keyword(kw::Let) { + let mut err = parser.struct_span_err( + parser.token.span, + "found a `{` in the middle of a let-chain", + ); + err.span_suggestion( + parser.token.span, + "consider removing this brace to parse the `let` as part of the same chain", + "", Applicability::MachineApplicable + ); + err.span_note( + maybe_andand.span.to(maybe_let.span), + "you might have meant to continue the let-chain here", + ); + errs.push(err); + } } parser.bump(); } diff --git a/tests/ui/parser/brace-in-let-chain.rs b/tests/ui/parser/brace-in-let-chain.rs new file mode 100644 index 000000000000..4dc13fb38471 --- /dev/null +++ b/tests/ui/parser/brace-in-let-chain.rs @@ -0,0 +1,28 @@ +// issue #117766 + +#![feature(let_chains)] +fn main() { + if let () = () + && let () = () { //~ERROR: found a `{` in the middle of a let-chain + && let () = () + { + } +} + +fn foo() { + { + && let () = () +} + +fn bar() { + if false {} + { + && let () = () +} + +fn baz() { + if false { + { + && let () = () + } +} //~ERROR: this file contains an unclosed delimiter diff --git a/tests/ui/parser/brace-in-let-chain.stderr b/tests/ui/parser/brace-in-let-chain.stderr new file mode 100644 index 000000000000..7550d5c43cff --- /dev/null +++ b/tests/ui/parser/brace-in-let-chain.stderr @@ -0,0 +1,42 @@ +error: this file contains an unclosed delimiter + --> $DIR/brace-in-let-chain.rs:28:54 + | +LL | fn main() { + | - unclosed delimiter +... +LL | fn foo() { + | - unclosed delimiter +... +LL | fn bar() { + | - unclosed delimiter +... +LL | fn baz() { + | - unclosed delimiter +LL | if false { +LL | { + | - this delimiter might not be properly closed... +LL | && let () = () +LL | } + | - ...as it matches this but it has different indentation +LL | } + | ^ + +error: found a `{` in the middle of a let-chain + --> $DIR/brace-in-let-chain.rs:6:24 + | +LL | && let () = () { + | ^ + | +note: you might have meant to continue the let-chain here + --> $DIR/brace-in-let-chain.rs:7:9 + | +LL | && let () = () + | ^^^^^^ +help: consider removing this brace to parse the `let` as part of the same chain + | +LL - && let () = () { +LL + && let () = () + | + +error: aborting due to 2 previous errors + From 2e40d11f8cd9d0e2f9c62e40311f64161d3071cb Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 9 Nov 2023 13:38:30 +1100 Subject: [PATCH 379/435] Remove `-Zkeep-hygiene-data`. It was added way back in #28585 under the name `-Zkeep-mtwt-tables`. The justification was: > This is so that the resolution results can be used after analysis, > potentially for tool support. There are no uses of significance in the code base, and various Google searches for both option names (and variants) found nothing of interest. @petrochenkov says removing this part (and it's only part) of the hygiene data is dubious. It doesn't seem that big, so let's just keep it around. --- compiler/rustc_ast_lowering/src/lib.rs | 5 ----- compiler/rustc_interface/src/tests.rs | 1 - compiler/rustc_session/src/options.rs | 2 -- compiler/rustc_span/src/hygiene.rs | 4 ---- 4 files changed, 12 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index a88493acf982..55d50e5fe6a1 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -443,11 +443,6 @@ pub fn lower_to_hir(tcx: TyCtxt<'_>, (): ()) -> hir::Crate<'_> { drop(ast_index); sess.time("drop_ast", || drop(krate)); - // Discard hygiene data, which isn't required after lowering to HIR. - if !sess.opts.unstable_opts.keep_hygiene_data { - rustc_span::hygiene::clear_syntax_context_map(); - } - // Don't hash unless necessary, because it's expensive. let opt_hir_hash = if tcx.needs_crate_hash() { Some(compute_hir_hash(tcx, &owners)) } else { None }; diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index d30816955231..9d06b6496b88 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -679,7 +679,6 @@ fn test_unstable_options_tracking_hash() { untracked!(incremental_info, true); untracked!(incremental_verify_ich, true); untracked!(input_stats, true); - untracked!(keep_hygiene_data, true); untracked!(link_native_libraries, false); untracked!(llvm_time_trace, true); untracked!(ls, vec!["all".to_owned()]); diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 964a26e94fed..a4dc1b64a4ce 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1622,8 +1622,6 @@ options! { `=skip-entry` `=skip-exit` Multiple options can be combined with commas."), - keep_hygiene_data: bool = (false, parse_bool, [UNTRACKED], - "keep hygiene data after analysis (default: no)"), layout_seed: Option = (None, parse_opt_number, [TRACKED], "seed layout randomization"), link_directives: bool = (true, parse_bool, [TRACKED], diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index 36731d0fe747..988ff57254c5 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -569,10 +569,6 @@ impl HygieneData { } } -pub fn clear_syntax_context_map() { - HygieneData::with(|data| data.syntax_context_map = FxHashMap::default()); -} - pub fn walk_chain(span: Span, to: SyntaxContext) -> Span { HygieneData::with(|data| data.walk_chain(span, to)) } From 9455259450f0186df991a14d960bb3759e7eac43 Mon Sep 17 00:00:00 2001 From: sjwang05 <63834813+sjwang05@users.noreply.github.com> Date: Thu, 9 Nov 2023 20:04:55 -0800 Subject: [PATCH 380/435] Catch an edge case --- compiler/rustc_parse/src/lexer/tokentrees.rs | 6 +++++- tests/ui/parser/brace-in-let-chain.rs | 9 +++++++++ tests/ui/parser/brace-in-let-chain.stderr | 5 ++++- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_parse/src/lexer/tokentrees.rs b/compiler/rustc_parse/src/lexer/tokentrees.rs index 7aa4ac7c4cb3..e7d2c6788249 100644 --- a/compiler/rustc_parse/src/lexer/tokentrees.rs +++ b/compiler/rustc_parse/src/lexer/tokentrees.rs @@ -131,7 +131,11 @@ impl<'a> TokenTreesReader<'a> { diff_errs.push(diff_err); } else if parser.token.is_keyword(kw::If) { in_cond = true; - } else if parser.token == token::CloseDelim(Delimiter::Brace) { + } else if matches!( + parser.token.kind, + token::CloseDelim(Delimiter::Brace) | token::FatArrow + ) { + // end of the `if`/`while` body, or the end of a `match` guard in_cond = false; } else if in_cond && parser.token == token::OpenDelim(Delimiter::Brace) { // Store the `&&` and `let` to use their spans later when creating the diagnostic diff --git a/tests/ui/parser/brace-in-let-chain.rs b/tests/ui/parser/brace-in-let-chain.rs index 4dc13fb38471..78060e238d4e 100644 --- a/tests/ui/parser/brace-in-let-chain.rs +++ b/tests/ui/parser/brace-in-let-chain.rs @@ -9,6 +9,15 @@ fn main() { } } +fn qux() { + let foo = false; + match foo { + _ if foo => { + && let () = () + _ => {} + } +} + fn foo() { { && let () = () diff --git a/tests/ui/parser/brace-in-let-chain.stderr b/tests/ui/parser/brace-in-let-chain.stderr index 7550d5c43cff..8e20cc43421b 100644 --- a/tests/ui/parser/brace-in-let-chain.stderr +++ b/tests/ui/parser/brace-in-let-chain.stderr @@ -1,9 +1,12 @@ error: this file contains an unclosed delimiter - --> $DIR/brace-in-let-chain.rs:28:54 + --> $DIR/brace-in-let-chain.rs:37:54 | LL | fn main() { | - unclosed delimiter ... +LL | fn qux() { + | - unclosed delimiter +... LL | fn foo() { | - unclosed delimiter ... From e30f8ae8672c89ba473aea8662fd5f22992810fb Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 10 Nov 2023 07:34:28 +0100 Subject: [PATCH 381/435] mention null explicitly Co-authored-by: Josh Stone --- library/core/src/ptr/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 12c6922eec0c..289e234b669a 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -1991,7 +1991,7 @@ impl fmt::Debug for F { /// /// The `expr` in `addr_of!(expr)` is evaluated as a place expression, but never loads /// from the place or requires the place to be dereferenceable. This means that -/// `addr_of!(*ptr)` is defined behavior even if `ptr` is dangling or misaligned. +/// `addr_of!(*ptr)` is defined behavior even if `ptr` is null, dangling, or misaligned. /// Note however that `addr_of!((*ptr).field)` still requires the projection to /// `field` to be in-bounds, using the same rules as [`offset`]. /// @@ -2040,7 +2040,7 @@ pub macro addr_of($place:expr) { /// /// The `expr` in `addr_of_mut!(expr)` is evaluated as a place expression, but never loads /// from the place or requires the place to be dereferenceable. This means that -/// `addr_of_mut!(*ptr)` is defined behavior even if `ptr` is dangling or misaligned. +/// `addr_of_mut!(*ptr)` is defined behavior even if `ptr` is null, dangling, or misaligned. /// Note however that `addr_of_mut!((*ptr).field)` still requires the projection to /// `field` to be in-bounds, using the same rules as [`offset`]. /// From c84d1871dc4456539b7b578830268ab3539915d0 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 10 Nov 2023 11:18:14 +0000 Subject: [PATCH 382/435] Rustup to rustc 1.75.0-nightly (0f44eb32f 2023-11-09) --- patches/stdlib-lock.toml | 9 ++++----- rust-toolchain | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/patches/stdlib-lock.toml b/patches/stdlib-lock.toml index 9902bca8eab2..8a690bada0df 100644 --- a/patches/stdlib-lock.toml +++ b/patches/stdlib-lock.toml @@ -58,9 +58,9 @@ dependencies = [ [[package]] name = "compiler_builtins" -version = "0.1.100" +version = "0.1.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6c0f24437059853f0fa64afc51f338f93647a3de4cf3358ba1bb4171a199775" +checksum = "a3b73c3443a5fd2438d7ba4853c64e4c8efc2404a9e28a9234cc2d5eebc6c242" dependencies = [ "cc", "rustc-std-workspace-core", @@ -158,9 +158,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.149" +version = "0.2.150" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" +checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" dependencies = [ "rustc-std-workspace-core", ] @@ -415,7 +415,6 @@ dependencies = [ name = "unwind" version = "0.0.0" dependencies = [ - "cc", "cfg-if", "compiler_builtins", "core", diff --git a/rust-toolchain b/rust-toolchain index 54683e1ebb18..b832b06e0ffb 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2023-11-02" +channel = "nightly-2023-11-10" components = ["rust-src", "rustc-dev", "llvm-tools"] From 89a3fd4992083f40ddffa95866dec9088aa9a37b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Fri, 10 Nov 2023 15:09:52 +0200 Subject: [PATCH 383/435] Drop anymap license exception --- src/tools/tidy/src/deps.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index b10cccc79f6b..2c7fe7fc2315 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -127,7 +127,6 @@ const EXCEPTIONS_CARGO: ExceptionList = &[ const EXCEPTIONS_RUST_ANALYZER: ExceptionList = &[ // tidy-alphabetical-start - ("anymap", "BlueOak-1.0.0 OR MIT OR Apache-2.0"), // BlueOak is not acceptable, but we use it under MIT OR Apache-2 .0 ("dissimilar", "Apache-2.0"), ("instant", "BSD-3-Clause"), ("notify", "CC0-1.0"), From 6812f64c35c65e978ed0f66683b31c243ddbcd52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?O=C4=9Fuz=20A=C4=9Fcayaz=C4=B1?= Date: Fri, 10 Nov 2023 17:02:08 +0300 Subject: [PATCH 384/435] add CoroutineWitness to covered types --- compiler/rustc_smir/src/rustc_internal/mod.rs | 4 ++++ compiler/rustc_smir/src/rustc_smir/mod.rs | 6 +++++- compiler/stable_mir/src/ty.rs | 4 ++++ compiler/stable_mir/src/visitor.rs | 1 + 4 files changed, 14 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs index 4d2a518226d8..f0b368bec39c 100644 --- a/compiler/rustc_smir/src/rustc_internal/mod.rs +++ b/compiler/rustc_smir/src/rustc_internal/mod.rs @@ -104,6 +104,10 @@ impl<'tcx> Tables<'tcx> { stable_mir::ty::RegionDef(self.create_def_id(did)) } + pub fn coroutine_witness_def(&mut self, did: DefId) -> stable_mir::ty::CoroutineWitnessDef { + stable_mir::ty::CoroutineWitnessDef(self.create_def_id(did)) + } + pub fn prov(&mut self, aid: AllocId) -> stable_mir::ty::Prov { stable_mir::ty::Prov(self.create_alloc_id(aid)) } diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index 27596c08f1c1..33c763b6602e 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -1292,7 +1292,11 @@ impl<'tcx> Stable<'tcx> for ty::TyKind<'tcx> { ty::Bound(debruijn_idx, bound_ty) => { TyKind::Bound(debruijn_idx.as_usize(), bound_ty.stable(tables)) } - ty::Placeholder(..) | ty::CoroutineWitness(..) | ty::Infer(_) | ty::Error(_) => { + ty::CoroutineWitness(def_id, args) => TyKind::RigidTy(RigidTy::CoroutineWitness( + tables.coroutine_witness_def(*def_id), + args.stable(tables), + )), + ty::Placeholder(..) | ty::Infer(_) | ty::Error(_) => { unreachable!(); } } diff --git a/compiler/stable_mir/src/ty.rs b/compiler/stable_mir/src/ty.rs index 5dfaa0fd8915..713a07084021 100644 --- a/compiler/stable_mir/src/ty.rs +++ b/compiler/stable_mir/src/ty.rs @@ -156,6 +156,7 @@ pub enum RigidTy { Dynamic(Vec>, Region, DynKind), Never, Tuple(Vec), + CoroutineWitness(CoroutineWitnessDef, GenericArgs), } #[derive(Clone, Copy, Debug, PartialEq, Eq)] @@ -235,6 +236,9 @@ pub struct ImplDef(pub DefId); #[derive(Clone, PartialEq, Eq, Debug)] pub struct RegionDef(pub DefId); +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct CoroutineWitnessDef(pub DefId); + /// A list of generic arguments. #[derive(Clone, Debug, Eq, PartialEq)] pub struct GenericArgs(pub Vec); diff --git a/compiler/stable_mir/src/visitor.rs b/compiler/stable_mir/src/visitor.rs index 05e0b9b4d786..65e42879d618 100644 --- a/compiler/stable_mir/src/visitor.rs +++ b/compiler/stable_mir/src/visitor.rs @@ -149,6 +149,7 @@ impl Visitable for RigidTy { RigidTy::FnPtr(sig) => sig.visit(visitor), RigidTy::Closure(_, args) => args.visit(visitor), RigidTy::Coroutine(_, args, _) => args.visit(visitor), + RigidTy::CoroutineWitness(_, args) => args.visit(visitor), RigidTy::Dynamic(pred, r, _) => { pred.visit(visitor)?; r.visit(visitor) From 01422d17045ffd3f5436de19371dd7eee0ca81a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Fri, 10 Nov 2023 16:28:16 +0200 Subject: [PATCH 385/435] Allow rustc_private for RustAnalyzer --- src/bootstrap/src/core/build_steps/tool.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index d5f759ea159a..9912681c781d 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -603,8 +603,7 @@ pub struct RustAnalyzer { } impl RustAnalyzer { - pub const ALLOW_FEATURES: &'static str = - "proc_macro_internals,proc_macro_diagnostic,proc_macro_span,proc_macro_span_shrink"; + pub const ALLOW_FEATURES: &'static str = "rustc_private,proc_macro_internals,proc_macro_diagnostic,proc_macro_span,proc_macro_span_shrink"; } impl Step for RustAnalyzer { From a49368f00b66409ae9fcf42d52e4f8246c73c266 Mon Sep 17 00:00:00 2001 From: sjwang05 <63834813+sjwang05@users.noreply.github.com> Date: Fri, 10 Nov 2023 12:13:53 -0800 Subject: [PATCH 386/435] Correctly handle while-let-chains --- compiler/rustc_parse/src/lexer/tokentrees.rs | 2 +- compiler/rustc_parse/src/parser/mod.rs | 2 +- tests/ui/parser/brace-in-let-chain.rs | 21 ++++++++++++++ tests/ui/parser/brace-in-let-chain.stderr | 30 ++++++++++++++++++-- 4 files changed, 51 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_parse/src/lexer/tokentrees.rs b/compiler/rustc_parse/src/lexer/tokentrees.rs index e7d2c6788249..41f4d0055aa1 100644 --- a/compiler/rustc_parse/src/lexer/tokentrees.rs +++ b/compiler/rustc_parse/src/lexer/tokentrees.rs @@ -129,7 +129,7 @@ impl<'a> TokenTreesReader<'a> { while parser.token != token::Eof { if let Err(diff_err) = parser.err_diff_marker() { diff_errs.push(diff_err); - } else if parser.token.is_keyword(kw::If) { + } else if parser.is_keyword_ahead(0, &[kw::If, kw::While]) { in_cond = true; } else if matches!( parser.token.kind, diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 1a7ae4069114..6eab140117e9 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -1115,7 +1115,7 @@ impl<'a> Parser<'a> { } /// Returns whether any of the given keywords are `dist` tokens ahead of the current one. - fn is_keyword_ahead(&self, dist: usize, kws: &[Symbol]) -> bool { + pub fn is_keyword_ahead(&self, dist: usize, kws: &[Symbol]) -> bool { self.look_ahead(dist, |t| kws.iter().any(|&kw| t.is_keyword(kw))) } diff --git a/tests/ui/parser/brace-in-let-chain.rs b/tests/ui/parser/brace-in-let-chain.rs index 78060e238d4e..1f34c73a2c3b 100644 --- a/tests/ui/parser/brace-in-let-chain.rs +++ b/tests/ui/parser/brace-in-let-chain.rs @@ -9,6 +9,27 @@ fn main() { } } +fn quux() { + while let () = () + && let () = () { //~ERROR: found a `{` in the middle of a let-chain + && let () = () + { + } +} + +fn foobar() { + while false {} + { + && let () = () +} + +fn fubar() { + while false { + { + && let () = () + } +} + fn qux() { let foo = false; match foo { diff --git a/tests/ui/parser/brace-in-let-chain.stderr b/tests/ui/parser/brace-in-let-chain.stderr index 8e20cc43421b..c43310f4736d 100644 --- a/tests/ui/parser/brace-in-let-chain.stderr +++ b/tests/ui/parser/brace-in-let-chain.stderr @@ -1,9 +1,18 @@ error: this file contains an unclosed delimiter - --> $DIR/brace-in-let-chain.rs:37:54 + --> $DIR/brace-in-let-chain.rs:58:54 | LL | fn main() { | - unclosed delimiter ... +LL | fn quux() { + | - unclosed delimiter +... +LL | fn foobar() { + | - unclosed delimiter +... +LL | fn fubar() { + | - unclosed delimiter +... LL | fn qux() { | - unclosed delimiter ... @@ -24,6 +33,23 @@ LL | } LL | } | ^ +error: found a `{` in the middle of a let-chain + --> $DIR/brace-in-let-chain.rs:14:24 + | +LL | && let () = () { + | ^ + | +note: you might have meant to continue the let-chain here + --> $DIR/brace-in-let-chain.rs:15:9 + | +LL | && let () = () + | ^^^^^^ +help: consider removing this brace to parse the `let` as part of the same chain + | +LL - && let () = () { +LL + && let () = () + | + error: found a `{` in the middle of a let-chain --> $DIR/brace-in-let-chain.rs:6:24 | @@ -41,5 +67,5 @@ LL - && let () = () { LL + && let () = () | -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors From 56a109d15b5c538bb0f98739c274aa4d81d38f1a Mon Sep 17 00:00:00 2001 From: Swapna Iyer Date: Fri, 10 Nov 2023 13:00:27 -0800 Subject: [PATCH 387/435] Recurse over the method chain and maintain a stack to peek at previous receiver to align spans --- .../rustc_hir_typeck/src/method/suggest.rs | 34 ++++++++++++++++++- .../method-chain-expression-failure.rs | 31 +++++++++++++++++ .../method-chain-expression-failure.stderr | 15 ++++++++ ...chain-method-call-mutation-in-place.stderr | 5 ++- 4 files changed, 83 insertions(+), 2 deletions(-) create mode 100644 tests/ui/structs/method-chain-expression-failure.rs create mode 100644 tests/ui/structs/method-chain-expression-failure.stderr diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index b1a2df8ace40..bd40e6c10476 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -481,7 +481,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); probe.is_ok() }); - self.note_internal_mutation_in_method( &mut err, rcvr_expr, @@ -1240,7 +1239,40 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } } + // If an appropriate error source is not found, check method chain for possible candiates + if unsatisfied_predicates.is_empty() && let Mode::MethodCall = mode && let SelfSource::MethodCall(mut source_expr) = source { + let mut stack_methods = vec![]; + while let hir::ExprKind::MethodCall(_path_segment, rcvr_expr, _args, method_span) = + source_expr.kind + { + // Pop the matching receiver, to align on it's notional span + if let Some(prev_match) = stack_methods.pop() { + err.span_label(method_span, format!("{item_kind} `{item_name}` is available on `{prev_match}`")); + } + let rcvr_ty = self.resolve_vars_if_possible( + self.typeck_results + .borrow() + .expr_ty_adjusted_opt(rcvr_expr) + .unwrap_or(Ty::new_misc_error(self.tcx)),); + for _matched_method in self.probe_for_name_many( + Mode::MethodCall, + item_name, + None, + IsSuggestion(true), + rcvr_ty, + source_expr.hir_id, + ProbeScope::TraitsInScope,) { + // found a match, push to stack + stack_methods.push(rcvr_ty); + } + source_expr = rcvr_expr; + } + // If there is a match at the start of the chain, add a label for it too! + if let Some(prev_match) = stack_methods.pop() { + err.span_label(source_expr.span, format!("{item_kind} `{item_name}` is available on `{prev_match}`")); + } + } self.note_derefed_ty_has_method(&mut err, source, rcvr_ty, item_name, expected); return Some(err); } diff --git a/tests/ui/structs/method-chain-expression-failure.rs b/tests/ui/structs/method-chain-expression-failure.rs new file mode 100644 index 000000000000..43ebc5bac8cb --- /dev/null +++ b/tests/ui/structs/method-chain-expression-failure.rs @@ -0,0 +1,31 @@ +struct A; +struct B; +struct C; +struct D; +struct E; + +impl A { + fn b(&self) -> B { B } + fn foo(&self) {} +} + +impl B { + fn c(&self) -> C { C } +} + +impl C { + fn d(&self) -> D { D } + fn foo(&self) {} +} + +impl D { + fn e(&self) -> E { E } +} + +impl E { + fn f(&self) {} +} +fn main() { + A.b().c().d().e().foo(); +//~^ ERROR no method named `foo` found for struct `E` in the current scope +} diff --git a/tests/ui/structs/method-chain-expression-failure.stderr b/tests/ui/structs/method-chain-expression-failure.stderr new file mode 100644 index 000000000000..ba635ab1fe67 --- /dev/null +++ b/tests/ui/structs/method-chain-expression-failure.stderr @@ -0,0 +1,15 @@ +error[E0599]: no method named `foo` found for struct `E` in the current scope + --> $DIR/method-chain-expression-failure.rs:29:23 + | +LL | struct E; + | -------- method `foo` not found for this struct +... +LL | A.b().c().d().e().foo(); + | - --- ^^^ method not found in `E` + | | | + | | method `foo` is available on `&C` + | method `foo` is available on `&A` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/suggestions/chain-method-call-mutation-in-place.stderr b/tests/ui/suggestions/chain-method-call-mutation-in-place.stderr index 128160f10adb..2dd6fb6a3bf6 100644 --- a/tests/ui/suggestions/chain-method-call-mutation-in-place.stderr +++ b/tests/ui/suggestions/chain-method-call-mutation-in-place.stderr @@ -18,7 +18,10 @@ error[E0599]: no method named `sort` found for unit type `()` in the current sco --> $DIR/chain-method-call-mutation-in-place.rs:3:72 | LL | vec![1, 2, 3].into_iter().collect::>().sort_by_key(|i| i).sort(); - | ^^^^ method not found in `()` + | ------------- --------------------- ^^^^ method not found in `()` + | | | + | | method `sort` is available on `&mut [i32]` + | method `sort` is available on `Vec` | note: method `sort_by_key` modifies its receiver in-place, it is not meant to be used in method chains. --> $DIR/chain-method-call-mutation-in-place.rs:3:53 From 8a2bee415c053c66374f3c78bcfdd8d0645adf64 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Fri, 10 Nov 2023 18:18:37 -0500 Subject: [PATCH 388/435] Update cargo --- src/tools/cargo | 2 +- src/tools/tidy/src/deps.rs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index 7046d992f9f3..6790a5127895 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 7046d992f9f32ba209a8079f662ebccf9da8de25 +Subproject commit 6790a5127895debec95c24aefaeb18e059270df3 diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index d60be354e838..f88f91655962 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -121,6 +121,7 @@ const EXCEPTIONS_CARGO: ExceptionList = &[ ("similar", "Apache-2.0"), ("sized-chunks", "MPL-2.0+"), ("subtle", "BSD-3-Clause"), + ("supports-hyperlinks", "Apache-2.0"), ("unicode-bom", "Apache-2.0"), // tidy-alphabetical-end ]; From d7fd2dec7c950a00fe595a21ab11c684affefc74 Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Fri, 10 Nov 2023 23:13:15 +0000 Subject: [PATCH 389/435] Switch `fuchsia-test-runner.py` to `ffx product` The subcommand `ffx product-bundle` has been removed, and replaced with the subcommand `ffx product`. This changes `fuchsia-test-runner.py` to use it to download the SDK and product bundle for the latest release of Fuchsia. --- src/ci/docker/scripts/fuchsia-test-runner.py | 48 ++++++++++++++++--- src/doc/rustc/src/platform-support/fuchsia.md | 4 +- 2 files changed, 44 insertions(+), 8 deletions(-) diff --git a/src/ci/docker/scripts/fuchsia-test-runner.py b/src/ci/docker/scripts/fuchsia-test-runner.py index f78d446c8b7c..437b51641fc9 100755 --- a/src/ci/docker/scripts/fuchsia-test-runner.py +++ b/src/ci/docker/scripts/fuchsia-test-runner.py @@ -12,6 +12,7 @@ from dataclasses import dataclass import fcntl import glob import hashlib +import io import json import os import platform @@ -276,27 +277,60 @@ class TestEnvironment: stderr=self.subprocess_output(), ) - # Start emulator - self.log_info("Starting emulator...") - product_bundle = "terminal.qemu-" + self.triple_to_arch(self.target) + # Look up the product bundle transfer manifest. + self.log_info("Looking up the product bundle transfer manifest...") + product_name = "minimal." + self.triple_to_arch(self.target) + fuchsia_version = "14.20230811.2.1" + + # FIXME: We should be able to replace this with the machine parsable + # `ffx --machine json product lookup ...` once F15 is released. + out = subprocess.check_output( + [ + ffx_path, + "product", + "lookup", + product_name, + fuchsia_version, + "--base-url", + "gs://fuchsia/development/" + fuchsia_version, + ], + env=ffx_env, + stderr=self.subprocess_output(), + ) + + self.log_debug(out) + + for line in io.BytesIO(out): + if line.startswith(b"gs://"): + transfer_manifest_url = line.rstrip() + break + else: + raise Exception("Unable to parse transfer manifest") + + # Download the product bundle. + product_bundle_dir = os.path.join(self.tmp_dir(), 'product-bundle') subprocess.check_call( [ ffx_path, - "product-bundle", - "get", - product_bundle, + "product", + "download", + transfer_manifest_url, + product_bundle_dir, + "--force", ], env=ffx_env, stdout=self.subprocess_output(), stderr=self.subprocess_output(), ) + + # Start emulator # FIXME: condition --accel hyper on target arch matching host arch subprocess.check_call( [ ffx_path, "emu", "start", - product_bundle, + product_bundle_dir, "--headless", "--log", self.emulator_log_path(), diff --git a/src/doc/rustc/src/platform-support/fuchsia.md b/src/doc/rustc/src/platform-support/fuchsia.md index f7cce35b1232..34ab3cdaf25e 100644 --- a/src/doc/rustc/src/platform-support/fuchsia.md +++ b/src/doc/rustc/src/platform-support/fuchsia.md @@ -692,10 +692,12 @@ Fuchsia's test runner interacts with the Fuchsia emulator and is located at test environment with: ```sh -src/ci/docker/scripts/fuchsia-test-runner.py start \ +( \ + src/ci/docker/scripts/fuchsia-test-runner.py start \ --rust-build ${RUST_SRC_PATH}/build \ --sdk ${SDK_PATH} \ --target {x86_64-unknown-fuchsia|aarch64-unknown-fuchsia} \ +) ``` Where `${RUST_SRC_PATH}/build` is the `build-dir` set in `config.toml` and From d7d2e761e0628c52da4d972f4c7984ed5e8f1c78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Sat, 11 Nov 2023 00:00:00 +0000 Subject: [PATCH 390/435] Remove incorrect transformation from RemoveZsts Partial removal of storage statements for a local is incorrect, so a decision to optimize cannot be make independently for each statement. Avoid the issue by performing the transformation completely or not at all. --- compiler/rustc_mir_transform/src/remove_zsts.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_mir_transform/src/remove_zsts.rs b/compiler/rustc_mir_transform/src/remove_zsts.rs index 5aa3c3cfe4dd..9f59f9d12452 100644 --- a/compiler/rustc_mir_transform/src/remove_zsts.rs +++ b/compiler/rustc_mir_transform/src/remove_zsts.rs @@ -17,6 +17,11 @@ impl<'tcx> MirPass<'tcx> for RemoveZsts { if tcx.type_of(body.source.def_id()).instantiate_identity().is_coroutine() { return; } + + if !tcx.consider_optimizing(|| format!("RemoveZsts - {:?}", body.source.def_id())) { + return; + } + let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); let local_decls = &body.local_decls; let mut replacer = Replacer { tcx, param_env, local_decls }; @@ -125,12 +130,6 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'_, 'tcx> { if let Some(place_for_ty) = place_for_ty && let ty = place_for_ty.ty(self.local_decls, self.tcx).ty && self.known_to_be_zst(ty) - && self.tcx.consider_optimizing(|| { - format!( - "RemoveZsts - Place: {:?} SourceInfo: {:?}", - place_for_ty, statement.source_info - ) - }) { statement.make_nop(); } else { From be67b7bdc752c0ef1c1ba166682291a7e5827e6f Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sat, 11 Nov 2023 11:29:33 -0500 Subject: [PATCH 391/435] Bump nightly version --- src/version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version b/src/version index 7c7053aa2388..32a6ce3c719b 100644 --- a/src/version +++ b/src/version @@ -1 +1 @@ -1.75.0 +1.76.0 From f88cf0206faa5fb169deebbbd1024d9a0381ecd3 Mon Sep 17 00:00:00 2001 From: sjwang05 <63834813+sjwang05@users.noreply.github.com> Date: Sat, 11 Nov 2023 13:39:08 -0800 Subject: [PATCH 392/435] Move unclosed delim errors to separate function --- compiler/rustc_parse/src/lexer/tokentrees.rs | 111 ++++++++++--------- tests/ui/parser/brace-in-let-chain.stderr | 14 +-- 2 files changed, 62 insertions(+), 63 deletions(-) diff --git a/compiler/rustc_parse/src/lexer/tokentrees.rs b/compiler/rustc_parse/src/lexer/tokentrees.rs index 41f4d0055aa1..db795ce9f723 100644 --- a/compiler/rustc_parse/src/lexer/tokentrees.rs +++ b/compiler/rustc_parse/src/lexer/tokentrees.rs @@ -117,59 +117,8 @@ impl<'a> TokenTreesReader<'a> { // We stop at any delimiter so we can try to recover if the user // uses an incorrect delimiter. let (tts, res) = self.parse_token_trees(/* is_delimited */ true); - if let Err(mut errs) = res { - // If there are unclosed delims, see if there are diff markers and if so, point them - // out instead of complaining about the unclosed delims. - let mut parser = crate::stream_to_parser(self.string_reader.sess, tts, None); - let mut diff_errs = vec![]; - // Suggest removing a `{` we think appears in an `if`/`while` condition - // We want to suggest removing a `{` only if we think we're in an `if`/`while` condition, but - // we have no way of tracking this in the lexer itself, so we piggyback on the parser - let mut in_cond = false; - while parser.token != token::Eof { - if let Err(diff_err) = parser.err_diff_marker() { - diff_errs.push(diff_err); - } else if parser.is_keyword_ahead(0, &[kw::If, kw::While]) { - in_cond = true; - } else if matches!( - parser.token.kind, - token::CloseDelim(Delimiter::Brace) | token::FatArrow - ) { - // end of the `if`/`while` body, or the end of a `match` guard - in_cond = false; - } else if in_cond && parser.token == token::OpenDelim(Delimiter::Brace) { - // Store the `&&` and `let` to use their spans later when creating the diagnostic - let maybe_andand = parser.look_ahead(1, |t| t.clone()); - let maybe_let = parser.look_ahead(2, |t| t.clone()); - if maybe_andand == token::OpenDelim(Delimiter::Brace) { - // This might be the beginning of the `if`/`while` body (i.e., the end of the condition) - in_cond = false; - } else if maybe_andand == token::AndAnd && maybe_let.is_keyword(kw::Let) { - let mut err = parser.struct_span_err( - parser.token.span, - "found a `{` in the middle of a let-chain", - ); - err.span_suggestion( - parser.token.span, - "consider removing this brace to parse the `let` as part of the same chain", - "", Applicability::MachineApplicable - ); - err.span_note( - maybe_andand.span.to(maybe_let.span), - "you might have meant to continue the let-chain here", - ); - errs.push(err); - } - } - parser.bump(); - } - if !diff_errs.is_empty() { - errs.iter_mut().for_each(|err| { - err.delay_as_bug(); - }); - return Err(diff_errs); - } - return Err(errs); + if let Err(errs) = res { + return Err(self.unclosed_delim_err(tts, errs)); } // Expand to cover the entire delimited token tree @@ -256,6 +205,62 @@ impl<'a> TokenTreesReader<'a> { Ok(TokenTree::Delimited(delim_span, open_delim, tts)) } + fn unclosed_delim_err(&mut self, tts: TokenStream, mut errs: Vec>) -> Vec> { + // If there are unclosed delims, see if there are diff markers and if so, point them + // out instead of complaining about the unclosed delims. + let mut parser = crate::stream_to_parser(self.string_reader.sess, tts, None); + let mut diff_errs = vec![]; + // Suggest removing a `{` we think appears in an `if`/`while` condition + // We want to suggest removing a `{` only if we think we're in an `if`/`while` condition, but + // we have no way of tracking this in the lexer itself, so we piggyback on the parser + let mut in_cond = false; + while parser.token != token::Eof { + if let Err(diff_err) = parser.err_diff_marker() { + diff_errs.push(diff_err); + } else if parser.is_keyword_ahead(0, &[kw::If, kw::While]) { + in_cond = true; + } else if matches!( + parser.token.kind, + token::CloseDelim(Delimiter::Brace) | token::FatArrow + ) { + // end of the `if`/`while` body, or the end of a `match` guard + in_cond = false; + } else if in_cond && parser.token == token::OpenDelim(Delimiter::Brace) { + // Store the `&&` and `let` to use their spans later when creating the diagnostic + let maybe_andand = parser.look_ahead(1, |t| t.clone()); + let maybe_let = parser.look_ahead(2, |t| t.clone()); + if maybe_andand == token::OpenDelim(Delimiter::Brace) { + // This might be the beginning of the `if`/`while` body (i.e., the end of the condition) + in_cond = false; + } else if maybe_andand == token::AndAnd && maybe_let.is_keyword(kw::Let) { + let mut err = parser.struct_span_err( + parser.token.span, + "found a `{` in the middle of a let-chain", + ); + err.span_suggestion( + parser.token.span, + "consider removing this brace to parse the `let` as part of the same chain", + "", + Applicability::MachineApplicable, + ); + err.span_label( + maybe_andand.span.to(maybe_let.span), + "you might have meant to continue the let-chain here", + ); + errs.push(err); + } + } + parser.bump(); + } + if !diff_errs.is_empty() { + errs.iter_mut().for_each(|err| { + err.delay_as_bug(); + }); + return diff_errs; + } + return errs; + } + fn close_delim_err(&mut self, delim: Delimiter) -> PErr<'a> { // An unexpected closing delimiter (i.e., there is no // matching opening delimiter). diff --git a/tests/ui/parser/brace-in-let-chain.stderr b/tests/ui/parser/brace-in-let-chain.stderr index c43310f4736d..7182d86d001d 100644 --- a/tests/ui/parser/brace-in-let-chain.stderr +++ b/tests/ui/parser/brace-in-let-chain.stderr @@ -38,12 +38,9 @@ error: found a `{` in the middle of a let-chain | LL | && let () = () { | ^ - | -note: you might have meant to continue the let-chain here - --> $DIR/brace-in-let-chain.rs:15:9 - | LL | && let () = () - | ^^^^^^ + | ------ you might have meant to continue the let-chain here + | help: consider removing this brace to parse the `let` as part of the same chain | LL - && let () = () { @@ -55,12 +52,9 @@ error: found a `{` in the middle of a let-chain | LL | && let () = () { | ^ - | -note: you might have meant to continue the let-chain here - --> $DIR/brace-in-let-chain.rs:7:9 - | LL | && let () = () - | ^^^^^^ + | ------ you might have meant to continue the let-chain here + | help: consider removing this brace to parse the `let` as part of the same chain | LL - && let () = () { From e81964e6f900fbe725ce0fad3c7a29d6536146e9 Mon Sep 17 00:00:00 2001 From: James Dietz Date: Sat, 30 Sep 2023 16:01:01 -0400 Subject: [PATCH 393/435] fix rounding issue with exponents in fmt --- library/core/src/fmt/num.rs | 8 + library/core/tests/fmt/num.rs | 353 +++++++++++++++++++++++++++++++++- 2 files changed, 357 insertions(+), 4 deletions(-) diff --git a/library/core/src/fmt/num.rs b/library/core/src/fmt/num.rs index 4f42f73ebbaf..a1467384c9c0 100644 --- a/library/core/src/fmt/num.rs +++ b/library/core/src/fmt/num.rs @@ -334,8 +334,16 @@ macro_rules! impl_Exp { // round up last digit if rem >= 5 { n += 1; + // if the digit is rounded to the next power + // instead adjust the exponent + if n % 10 == 0 { + n /= 10; + exponent += 1; + } } + // n = 100 } + // assert!(n == 666, "{}\n{}\n{}\n",n, exponent, added_precision); (n, exponent, exponent, added_precision) }; diff --git a/library/core/tests/fmt/num.rs b/library/core/tests/fmt/num.rs index b9ede65c9ff0..540f306e8f6d 100644 --- a/library/core/tests/fmt/num.rs +++ b/library/core/tests/fmt/num.rs @@ -128,30 +128,375 @@ fn test_format_int_exp_precision() { let big_int: u32 = 314_159_265; assert_eq!(format!("{big_int:.1e}"), format!("{:.1e}", f64::from(big_int))); - //test adding precision + // test adding precision assert_eq!(format!("{:.10e}", i8::MIN), "-1.2800000000e2"); assert_eq!(format!("{:.10e}", i16::MIN), "-3.2768000000e4"); assert_eq!(format!("{:.10e}", i32::MIN), "-2.1474836480e9"); assert_eq!(format!("{:.20e}", i64::MIN), "-9.22337203685477580800e18"); assert_eq!(format!("{:.40e}", i128::MIN), "-1.7014118346046923173168730371588410572800e38"); - //test rounding + // test rounding assert_eq!(format!("{:.1e}", i8::MIN), "-1.3e2"); assert_eq!(format!("{:.1e}", i16::MIN), "-3.3e4"); assert_eq!(format!("{:.1e}", i32::MIN), "-2.1e9"); assert_eq!(format!("{:.1e}", i64::MIN), "-9.2e18"); assert_eq!(format!("{:.1e}", i128::MIN), "-1.7e38"); - //test huge precision + // test huge precision assert_eq!(format!("{:.1000e}", 1), format!("1.{}e0", "0".repeat(1000))); //test zero precision assert_eq!(format!("{:.0e}", 1), format!("1e0",)); assert_eq!(format!("{:.0e}", 35), format!("4e1",)); - //test padding with precision (and sign) + // test padding with precision (and sign) assert_eq!(format!("{:+10.3e}", 1), " +1.000e0"); } +#[test] +fn new_test() { + // test precision remains correct when rounding to next power + assert_eq!(format!("{:.1e}", 999), "1.0e3"); + assert_eq!(format!("{:.1e}", 1001), "1.0e3"); + assert_eq!(format!("{:.1e}", 1000), "1.0e3"); + assert_eq!(format!("{:.0e}", -999), "-1e3"); + assert_eq!(format!("{:.0e}", -998), "-1e3"); + assert_eq!(format!("{:.0e}", -997), "-1e3"); + assert_eq!(format!("{:.0e}", -996), "-1e3"); + assert_eq!(format!("{:.0e}", -995), "-1e3"); + assert_eq!(format!("{:.0e}", -994), "-1e3"); + assert_eq!(format!("{:.0e}", -993), "-1e3"); + assert_eq!(format!("{:.0e}", -992), "-1e3"); + assert_eq!(format!("{:.0e}", -991), "-1e3"); + assert_eq!(format!("{:.0e}", -990), "-1e3"); + assert_eq!(format!("{:.0e}", -989), "-1e3"); + assert_eq!(format!("{:.0e}", -988), "-1e3"); + assert_eq!(format!("{:.0e}", -987), "-1e3"); + assert_eq!(format!("{:.0e}", -986), "-1e3"); + assert_eq!(format!("{:.0e}", -985), "-1e3"); + assert_eq!(format!("{:.0e}", -984), "-1e3"); + assert_eq!(format!("{:.0e}", -983), "-1e3"); + assert_eq!(format!("{:.0e}", -982), "-1e3"); + assert_eq!(format!("{:.0e}", -981), "-1e3"); + assert_eq!(format!("{:.0e}", -980), "-1e3"); + assert_eq!(format!("{:.0e}", -979), "-1e3"); + assert_eq!(format!("{:.0e}", -978), "-1e3"); + assert_eq!(format!("{:.0e}", -977), "-1e3"); + assert_eq!(format!("{:.0e}", -976), "-1e3"); + assert_eq!(format!("{:.0e}", -975), "-1e3"); + assert_eq!(format!("{:.0e}", -974), "-1e3"); + assert_eq!(format!("{:.0e}", -973), "-1e3"); + assert_eq!(format!("{:.0e}", -972), "-1e3"); + assert_eq!(format!("{:.0e}", -971), "-1e3"); + assert_eq!(format!("{:.0e}", -970), "-1e3"); + assert_eq!(format!("{:.0e}", -969), "-1e3"); + assert_eq!(format!("{:.0e}", -968), "-1e3"); + assert_eq!(format!("{:.0e}", -967), "-1e3"); + assert_eq!(format!("{:.0e}", -966), "-1e3"); + assert_eq!(format!("{:.0e}", -965), "-1e3"); + assert_eq!(format!("{:.0e}", -964), "-1e3"); + assert_eq!(format!("{:.0e}", -963), "-1e3"); + assert_eq!(format!("{:.0e}", -962), "-1e3"); + assert_eq!(format!("{:.0e}", -961), "-1e3"); + assert_eq!(format!("{:.0e}", -960), "-1e3"); + assert_eq!(format!("{:.0e}", -959), "-1e3"); + assert_eq!(format!("{:.0e}", -958), "-1e3"); + assert_eq!(format!("{:.0e}", -957), "-1e3"); + assert_eq!(format!("{:.0e}", -956), "-1e3"); + assert_eq!(format!("{:.0e}", -955), "-1e3"); + assert_eq!(format!("{:.0e}", -954), "-1e3"); + assert_eq!(format!("{:.0e}", -953), "-1e3"); + assert_eq!(format!("{:.0e}", -952), "-1e3"); + assert_eq!(format!("{:.0e}", -951), "-1e3"); + assert_eq!(format!("{:.0e}", -950), "-1e3"); + assert_eq!(format!("{:.0e}", -850), "-9e2"); + assert_eq!(format!("{:.0e}", -650), "-7e2"); + assert_eq!(format!("{:.0e}", -450), "-5e2"); + assert_eq!(format!("{:.0e}", -250), "-3e2"); + assert_eq!(format!("{:.0e}", -99), "-1e2"); + assert_eq!(format!("{:.0e}", -98), "-1e2"); + assert_eq!(format!("{:.0e}", -97), "-1e2"); + assert_eq!(format!("{:.0e}", -96), "-1e2"); + assert_eq!(format!("{:.0e}", -95), "-1e2"); + assert_eq!(format!("{:.0e}", -85), "-9e1"); + assert_eq!(format!("{:.0e}", -65), "-7e1"); + assert_eq!(format!("{:.0e}", -45), "-5e1"); + assert_eq!(format!("{:.0e}", -25), "-3e1"); + assert_eq!(format!("{:.0e}", 25), "3e1"); + assert_eq!(format!("{:.0e}", 45), "5e1"); + assert_eq!(format!("{:.0e}", 65), "7e1"); + assert_eq!(format!("{:.0e}", 85), "9e1"); + assert_eq!(format!("{:.0e}", 94), "9e1"); + assert_eq!(format!("{:.0e}", 95), "1e2"); + assert_eq!(format!("{:.0e}", 96), "1e2"); + assert_eq!(format!("{:.0e}", 97), "1e2"); + assert_eq!(format!("{:.0e}", 98), "1e2"); + assert_eq!(format!("{:.0e}", 99), "1e2"); + assert_eq!(format!("{:.0e}", 250), "3e2"); + assert_eq!(format!("{:.0e}", 450), "5e2"); + assert_eq!(format!("{:.0e}", 650), "7e2"); + assert_eq!(format!("{:.0e}", 850), "9e2"); + assert_eq!(format!("{:.0e}", 950), "1e3"); + assert_eq!(format!("{:.0e}", 951), "1e3"); + assert_eq!(format!("{:.0e}", 952), "1e3"); + assert_eq!(format!("{:.0e}", 953), "1e3"); + assert_eq!(format!("{:.0e}", 954), "1e3"); + assert_eq!(format!("{:.0e}", 955), "1e3"); + assert_eq!(format!("{:.0e}", 956), "1e3"); + assert_eq!(format!("{:.0e}", 957), "1e3"); + assert_eq!(format!("{:.0e}", 958), "1e3"); + assert_eq!(format!("{:.0e}", 959), "1e3"); + assert_eq!(format!("{:.0e}", 960), "1e3"); + assert_eq!(format!("{:.0e}", 961), "1e3"); + assert_eq!(format!("{:.0e}", 962), "1e3"); + assert_eq!(format!("{:.0e}", 963), "1e3"); + assert_eq!(format!("{:.0e}", 964), "1e3"); + assert_eq!(format!("{:.0e}", 965), "1e3"); + assert_eq!(format!("{:.0e}", 966), "1e3"); + assert_eq!(format!("{:.0e}", 967), "1e3"); + assert_eq!(format!("{:.0e}", 968), "1e3"); + assert_eq!(format!("{:.0e}", 969), "1e3"); + assert_eq!(format!("{:.0e}", 970), "1e3"); + assert_eq!(format!("{:.0e}", 971), "1e3"); + assert_eq!(format!("{:.0e}", 972), "1e3"); + assert_eq!(format!("{:.0e}", 973), "1e3"); + assert_eq!(format!("{:.0e}", 974), "1e3"); + assert_eq!(format!("{:.0e}", 975), "1e3"); + assert_eq!(format!("{:.0e}", 976), "1e3"); + assert_eq!(format!("{:.0e}", 977), "1e3"); + assert_eq!(format!("{:.0e}", 978), "1e3"); + assert_eq!(format!("{:.0e}", 979), "1e3"); + assert_eq!(format!("{:.0e}", 980), "1e3"); + assert_eq!(format!("{:.0e}", 981), "1e3"); + assert_eq!(format!("{:.0e}", 982), "1e3"); + assert_eq!(format!("{:.0e}", 983), "1e3"); + assert_eq!(format!("{:.0e}", 984), "1e3"); + assert_eq!(format!("{:.0e}", 985), "1e3"); + assert_eq!(format!("{:.0e}", 986), "1e3"); + assert_eq!(format!("{:.0e}", 987), "1e3"); + assert_eq!(format!("{:.0e}", 988), "1e3"); + assert_eq!(format!("{:.0e}", 989), "1e3"); + assert_eq!(format!("{:.0e}", 990), "1e3"); + assert_eq!(format!("{:.0e}", 991), "1e3"); + assert_eq!(format!("{:.0e}", 992), "1e3"); + assert_eq!(format!("{:.0e}", 993), "1e3"); + assert_eq!(format!("{:.0e}", 994), "1e3"); + assert_eq!(format!("{:.0e}", 995), "1e3"); + assert_eq!(format!("{:.0e}", 996), "1e3"); + assert_eq!(format!("{:.0e}", 997), "1e3"); + assert_eq!(format!("{:.0e}", 998), "1e3"); + assert_eq!(format!("{:.0e}", 999), "1e3"); + assert_eq!(format!("{:.1e}", -1850), "-1.9e3"); + assert_eq!(format!("{:.1e}", -1650), "-1.7e3"); + assert_eq!(format!("{:.1e}", -1450), "-1.5e3"); + assert_eq!(format!("{:.1e}", -1250), "-1.3e3"); + assert_eq!(format!("{:.1e}", -1050), "-1.1e3"); + assert_eq!(format!("{:.1e}", -999), "-1.0e3"); + assert_eq!(format!("{:.1e}", -998), "-1.0e3"); + assert_eq!(format!("{:.1e}", -997), "-1.0e3"); + assert_eq!(format!("{:.1e}", -996), "-1.0e3"); + assert_eq!(format!("{:.1e}", -995), "-1.0e3"); + assert_eq!(format!("{:.1e}", -985), "-9.9e2"); + assert_eq!(format!("{:.1e}", -965), "-9.7e2"); + assert_eq!(format!("{:.1e}", -945), "-9.5e2"); + assert_eq!(format!("{:.1e}", -925), "-9.3e2"); + assert_eq!(format!("{:.1e}", -905), "-9.1e2"); + assert_eq!(format!("{:.1e}", -885), "-8.9e2"); + assert_eq!(format!("{:.1e}", -865), "-8.7e2"); + assert_eq!(format!("{:.1e}", -845), "-8.5e2"); + assert_eq!(format!("{:.1e}", -825), "-8.3e2"); + assert_eq!(format!("{:.1e}", -805), "-8.1e2"); + assert_eq!(format!("{:.1e}", -785), "-7.9e2"); + assert_eq!(format!("{:.1e}", -765), "-7.7e2"); + assert_eq!(format!("{:.1e}", -745), "-7.5e2"); + assert_eq!(format!("{:.1e}", -725), "-7.3e2"); + assert_eq!(format!("{:.1e}", -705), "-7.1e2"); + assert_eq!(format!("{:.1e}", -685), "-6.9e2"); + assert_eq!(format!("{:.1e}", -665), "-6.7e2"); + assert_eq!(format!("{:.1e}", -645), "-6.5e2"); + assert_eq!(format!("{:.1e}", -625), "-6.3e2"); + assert_eq!(format!("{:.1e}", -605), "-6.1e2"); + assert_eq!(format!("{:.1e}", -585), "-5.9e2"); + assert_eq!(format!("{:.1e}", -565), "-5.7e2"); + assert_eq!(format!("{:.1e}", -545), "-5.5e2"); + assert_eq!(format!("{:.1e}", -525), "-5.3e2"); + assert_eq!(format!("{:.1e}", -505), "-5.1e2"); + assert_eq!(format!("{:.1e}", -485), "-4.9e2"); + assert_eq!(format!("{:.1e}", -465), "-4.7e2"); + assert_eq!(format!("{:.1e}", -445), "-4.5e2"); + assert_eq!(format!("{:.1e}", -425), "-4.3e2"); + assert_eq!(format!("{:.1e}", -405), "-4.1e2"); + assert_eq!(format!("{:.1e}", -385), "-3.9e2"); + assert_eq!(format!("{:.1e}", -365), "-3.7e2"); + assert_eq!(format!("{:.1e}", -345), "-3.5e2"); + assert_eq!(format!("{:.1e}", -325), "-3.3e2"); + assert_eq!(format!("{:.1e}", -305), "-3.1e2"); + assert_eq!(format!("{:.1e}", -285), "-2.9e2"); + assert_eq!(format!("{:.1e}", -265), "-2.7e2"); + assert_eq!(format!("{:.1e}", -245), "-2.5e2"); + assert_eq!(format!("{:.1e}", -225), "-2.3e2"); + assert_eq!(format!("{:.1e}", -205), "-2.1e2"); + assert_eq!(format!("{:.1e}", -185), "-1.9e2"); + assert_eq!(format!("{:.1e}", -165), "-1.7e2"); + assert_eq!(format!("{:.1e}", -145), "-1.5e2"); + assert_eq!(format!("{:.1e}", -125), "-1.3e2"); + assert_eq!(format!("{:.1e}", -105), "-1.1e2"); + assert_eq!(format!("{:.1e}", 105), "1.1e2"); + assert_eq!(format!("{:.1e}", 125), "1.3e2"); + assert_eq!(format!("{:.1e}", 145), "1.5e2"); + assert_eq!(format!("{:.1e}", 165), "1.7e2"); + assert_eq!(format!("{:.1e}", 185), "1.9e2"); + assert_eq!(format!("{:.1e}", 205), "2.1e2"); + assert_eq!(format!("{:.1e}", 225), "2.3e2"); + assert_eq!(format!("{:.1e}", 245), "2.5e2"); + assert_eq!(format!("{:.1e}", 265), "2.7e2"); + assert_eq!(format!("{:.1e}", 285), "2.9e2"); + assert_eq!(format!("{:.1e}", 305), "3.1e2"); + assert_eq!(format!("{:.1e}", 325), "3.3e2"); + assert_eq!(format!("{:.1e}", 345), "3.5e2"); + assert_eq!(format!("{:.1e}", 365), "3.7e2"); + assert_eq!(format!("{:.1e}", 385), "3.9e2"); + assert_eq!(format!("{:.1e}", 405), "4.1e2"); + assert_eq!(format!("{:.1e}", 425), "4.3e2"); + assert_eq!(format!("{:.1e}", 445), "4.5e2"); + assert_eq!(format!("{:.1e}", 465), "4.7e2"); + assert_eq!(format!("{:.1e}", 485), "4.9e2"); + assert_eq!(format!("{:.1e}", 505), "5.1e2"); + assert_eq!(format!("{:.1e}", 525), "5.3e2"); + assert_eq!(format!("{:.1e}", 545), "5.5e2"); + assert_eq!(format!("{:.1e}", 565), "5.7e2"); + assert_eq!(format!("{:.1e}", 585), "5.9e2"); + assert_eq!(format!("{:.1e}", 605), "6.1e2"); + assert_eq!(format!("{:.1e}", 625), "6.3e2"); + assert_eq!(format!("{:.1e}", 645), "6.5e2"); + assert_eq!(format!("{:.1e}", 665), "6.7e2"); + assert_eq!(format!("{:.1e}", 685), "6.9e2"); + assert_eq!(format!("{:.1e}", 705), "7.1e2"); + assert_eq!(format!("{:.1e}", 725), "7.3e2"); + assert_eq!(format!("{:.1e}", 745), "7.5e2"); + assert_eq!(format!("{:.1e}", 765), "7.7e2"); + assert_eq!(format!("{:.1e}", 785), "7.9e2"); + assert_eq!(format!("{:.1e}", 805), "8.1e2"); + assert_eq!(format!("{:.1e}", 825), "8.3e2"); + assert_eq!(format!("{:.1e}", 845), "8.5e2"); + assert_eq!(format!("{:.1e}", 865), "8.7e2"); + assert_eq!(format!("{:.1e}", 885), "8.9e2"); + assert_eq!(format!("{:.1e}", 905), "9.1e2"); + assert_eq!(format!("{:.1e}", 925), "9.3e2"); + assert_eq!(format!("{:.1e}", 945), "9.5e2"); + assert_eq!(format!("{:.1e}", 965), "9.7e2"); + assert_eq!(format!("{:.1e}", 985), "9.9e2"); + assert_eq!(format!("{:.1e}", 995), "1.0e3"); + assert_eq!(format!("{:.1e}", 996), "1.0e3"); + assert_eq!(format!("{:.1e}", 997), "1.0e3"); + assert_eq!(format!("{:.1e}", 998), "1.0e3"); + assert_eq!(format!("{:.1e}", 999), "1.0e3"); + assert_eq!(format!("{:.1e}", 1050), "1.1e3"); + assert_eq!(format!("{:.1e}", 1250), "1.3e3"); + assert_eq!(format!("{:.1e}", 1450), "1.5e3"); + assert_eq!(format!("{:.1e}", 1650), "1.7e3"); + assert_eq!(format!("{:.1e}", 1850), "1.9e3"); + assert_eq!(format!("{:.2e}", -1985), "-1.99e3"); + assert_eq!(format!("{:.2e}", -1965), "-1.97e3"); + assert_eq!(format!("{:.2e}", -1945), "-1.95e3"); + assert_eq!(format!("{:.2e}", -1925), "-1.93e3"); + assert_eq!(format!("{:.2e}", -1905), "-1.91e3"); + assert_eq!(format!("{:.2e}", -1885), "-1.89e3"); + assert_eq!(format!("{:.2e}", -1865), "-1.87e3"); + assert_eq!(format!("{:.2e}", -1845), "-1.85e3"); + assert_eq!(format!("{:.2e}", -1825), "-1.83e3"); + assert_eq!(format!("{:.2e}", -1805), "-1.81e3"); + assert_eq!(format!("{:.2e}", -1785), "-1.79e3"); + assert_eq!(format!("{:.2e}", -1765), "-1.77e3"); + assert_eq!(format!("{:.2e}", -1745), "-1.75e3"); + assert_eq!(format!("{:.2e}", -1725), "-1.73e3"); + assert_eq!(format!("{:.2e}", -1705), "-1.71e3"); + assert_eq!(format!("{:.2e}", -1685), "-1.69e3"); + assert_eq!(format!("{:.2e}", -1665), "-1.67e3"); + assert_eq!(format!("{:.2e}", -1645), "-1.65e3"); + assert_eq!(format!("{:.2e}", -1625), "-1.63e3"); + assert_eq!(format!("{:.2e}", -1605), "-1.61e3"); + assert_eq!(format!("{:.2e}", -1585), "-1.59e3"); + assert_eq!(format!("{:.2e}", -1565), "-1.57e3"); + assert_eq!(format!("{:.2e}", -1545), "-1.55e3"); + assert_eq!(format!("{:.2e}", -1525), "-1.53e3"); + assert_eq!(format!("{:.2e}", -1505), "-1.51e3"); + assert_eq!(format!("{:.2e}", -1485), "-1.49e3"); + assert_eq!(format!("{:.2e}", -1465), "-1.47e3"); + assert_eq!(format!("{:.2e}", -1445), "-1.45e3"); + assert_eq!(format!("{:.2e}", -1425), "-1.43e3"); + assert_eq!(format!("{:.2e}", -1405), "-1.41e3"); + assert_eq!(format!("{:.2e}", -1385), "-1.39e3"); + assert_eq!(format!("{:.2e}", -1365), "-1.37e3"); + assert_eq!(format!("{:.2e}", -1345), "-1.35e3"); + assert_eq!(format!("{:.2e}", -1325), "-1.33e3"); + assert_eq!(format!("{:.2e}", -1305), "-1.31e3"); + assert_eq!(format!("{:.2e}", -1285), "-1.29e3"); + assert_eq!(format!("{:.2e}", -1265), "-1.27e3"); + assert_eq!(format!("{:.2e}", -1245), "-1.25e3"); + assert_eq!(format!("{:.2e}", -1225), "-1.23e3"); + assert_eq!(format!("{:.2e}", -1205), "-1.21e3"); + assert_eq!(format!("{:.2e}", -1185), "-1.19e3"); + assert_eq!(format!("{:.2e}", -1165), "-1.17e3"); + assert_eq!(format!("{:.2e}", -1145), "-1.15e3"); + assert_eq!(format!("{:.2e}", -1125), "-1.13e3"); + assert_eq!(format!("{:.2e}", -1105), "-1.11e3"); + assert_eq!(format!("{:.2e}", -1085), "-1.09e3"); + assert_eq!(format!("{:.2e}", -1065), "-1.07e3"); + assert_eq!(format!("{:.2e}", -1045), "-1.05e3"); + assert_eq!(format!("{:.2e}", -1025), "-1.03e3"); + assert_eq!(format!("{:.2e}", -1005), "-1.01e3"); + assert_eq!(format!("{:.2e}", 1005), "1.01e3" ); + assert_eq!(format!("{:.2e}", 1025), "1.03e3" ); + assert_eq!(format!("{:.2e}", 1045), "1.05e3" ); + assert_eq!(format!("{:.2e}", 1065), "1.07e3" ); + assert_eq!(format!("{:.2e}", 1085), "1.09e3" ); + assert_eq!(format!("{:.2e}", 1105), "1.11e3" ); + assert_eq!(format!("{:.2e}", 1125), "1.13e3" ); + assert_eq!(format!("{:.2e}", 1145), "1.15e3" ); + assert_eq!(format!("{:.2e}", 1165), "1.17e3" ); + assert_eq!(format!("{:.2e}", 1185), "1.19e3" ); + assert_eq!(format!("{:.2e}", 1205), "1.21e3" ); + assert_eq!(format!("{:.2e}", 1225), "1.23e3" ); + assert_eq!(format!("{:.2e}", 1245), "1.25e3" ); + assert_eq!(format!("{:.2e}", 1265), "1.27e3" ); + assert_eq!(format!("{:.2e}", 1285), "1.29e3" ); + assert_eq!(format!("{:.2e}", 1305), "1.31e3" ); + assert_eq!(format!("{:.2e}", 1325), "1.33e3" ); + assert_eq!(format!("{:.2e}", 1345), "1.35e3" ); + assert_eq!(format!("{:.2e}", 1365), "1.37e3" ); + assert_eq!(format!("{:.2e}", 1385), "1.39e3" ); + assert_eq!(format!("{:.2e}", 1405), "1.41e3" ); + assert_eq!(format!("{:.2e}", 1425), "1.43e3" ); + assert_eq!(format!("{:.2e}", 1445), "1.45e3" ); + assert_eq!(format!("{:.2e}", 1465), "1.47e3" ); + assert_eq!(format!("{:.2e}", 1485), "1.49e3" ); + assert_eq!(format!("{:.2e}", 1505), "1.51e3" ); + assert_eq!(format!("{:.2e}", 1525), "1.53e3" ); + assert_eq!(format!("{:.2e}", 1545), "1.55e3" ); + assert_eq!(format!("{:.2e}", 1565), "1.57e3" ); + assert_eq!(format!("{:.2e}", 1585), "1.59e3" ); + assert_eq!(format!("{:.2e}", 1605), "1.61e3" ); + assert_eq!(format!("{:.2e}", 1625), "1.63e3" ); + assert_eq!(format!("{:.2e}", 1645), "1.65e3" ); + assert_eq!(format!("{:.2e}", 1665), "1.67e3" ); + assert_eq!(format!("{:.2e}", 1685), "1.69e3" ); + assert_eq!(format!("{:.2e}", 1705), "1.71e3" ); + assert_eq!(format!("{:.2e}", 1725), "1.73e3" ); + assert_eq!(format!("{:.2e}", 1745), "1.75e3" ); + assert_eq!(format!("{:.2e}", 1765), "1.77e3" ); + assert_eq!(format!("{:.2e}", 1785), "1.79e3" ); + assert_eq!(format!("{:.2e}", 1805), "1.81e3" ); + assert_eq!(format!("{:.2e}", 1825), "1.83e3" ); + assert_eq!(format!("{:.2e}", 1845), "1.85e3" ); + assert_eq!(format!("{:.2e}", 1865), "1.87e3" ); + assert_eq!(format!("{:.2e}", 1885), "1.89e3" ); + assert_eq!(format!("{:.2e}", 1905), "1.91e3" ); + assert_eq!(format!("{:.2e}", 1925), "1.93e3" ); + assert_eq!(format!("{:.2e}", 1945), "1.95e3" ); + assert_eq!(format!("{:.2e}", 1965), "1.97e3" ); + assert_eq!(format!("{:.2e}", 1985), "1.99e3" ); +} + #[test] fn test_format_int_zero() { assert_eq!(format!("{}", 0), "0"); From 3f0908f47cff0f80bf4da69e845b6efdd333f6ea Mon Sep 17 00:00:00 2001 From: James Dietz Date: Fri, 27 Oct 2023 17:14:40 -0400 Subject: [PATCH 394/435] round to even --- library/core/src/fmt/num.rs | 9 +- library/core/tests/fmt/num.rs | 353 +--------------------------------- 2 files changed, 13 insertions(+), 349 deletions(-) diff --git a/library/core/src/fmt/num.rs b/library/core/src/fmt/num.rs index a1467384c9c0..778515f8616c 100644 --- a/library/core/src/fmt/num.rs +++ b/library/core/src/fmt/num.rs @@ -309,7 +309,6 @@ macro_rules! impl_Exp { n /= 10; exponent += 1; } - let (added_precision, subtracted_precision) = match f.precision() { Some(fmt_prec) => { // number of decimal digits minus 1 @@ -331,19 +330,17 @@ macro_rules! impl_Exp { let rem = n % 10; n /= 10; exponent += 1; - // round up last digit - if rem >= 5 { + // round up last digit, round to even on a tie + if rem > 5 || (rem == 5 && (n % 2 != 0 || subtracted_precision > 1 )) { n += 1; // if the digit is rounded to the next power // instead adjust the exponent - if n % 10 == 0 { + if n.ilog10() > (n - 1).ilog10() { n /= 10; exponent += 1; } } - // n = 100 } - // assert!(n == 666, "{}\n{}\n{}\n",n, exponent, added_precision); (n, exponent, exponent, added_precision) }; diff --git a/library/core/tests/fmt/num.rs b/library/core/tests/fmt/num.rs index 540f306e8f6d..1ddcd5ab7955 100644 --- a/library/core/tests/fmt/num.rs +++ b/library/core/tests/fmt/num.rs @@ -150,351 +150,18 @@ fn test_format_int_exp_precision() { // test padding with precision (and sign) assert_eq!(format!("{:+10.3e}", 1), " +1.000e0"); -} -#[test] -fn new_test() { // test precision remains correct when rounding to next power - assert_eq!(format!("{:.1e}", 999), "1.0e3"); - assert_eq!(format!("{:.1e}", 1001), "1.0e3"); - assert_eq!(format!("{:.1e}", 1000), "1.0e3"); - assert_eq!(format!("{:.0e}", -999), "-1e3"); - assert_eq!(format!("{:.0e}", -998), "-1e3"); - assert_eq!(format!("{:.0e}", -997), "-1e3"); - assert_eq!(format!("{:.0e}", -996), "-1e3"); - assert_eq!(format!("{:.0e}", -995), "-1e3"); - assert_eq!(format!("{:.0e}", -994), "-1e3"); - assert_eq!(format!("{:.0e}", -993), "-1e3"); - assert_eq!(format!("{:.0e}", -992), "-1e3"); - assert_eq!(format!("{:.0e}", -991), "-1e3"); - assert_eq!(format!("{:.0e}", -990), "-1e3"); - assert_eq!(format!("{:.0e}", -989), "-1e3"); - assert_eq!(format!("{:.0e}", -988), "-1e3"); - assert_eq!(format!("{:.0e}", -987), "-1e3"); - assert_eq!(format!("{:.0e}", -986), "-1e3"); - assert_eq!(format!("{:.0e}", -985), "-1e3"); - assert_eq!(format!("{:.0e}", -984), "-1e3"); - assert_eq!(format!("{:.0e}", -983), "-1e3"); - assert_eq!(format!("{:.0e}", -982), "-1e3"); - assert_eq!(format!("{:.0e}", -981), "-1e3"); - assert_eq!(format!("{:.0e}", -980), "-1e3"); - assert_eq!(format!("{:.0e}", -979), "-1e3"); - assert_eq!(format!("{:.0e}", -978), "-1e3"); - assert_eq!(format!("{:.0e}", -977), "-1e3"); - assert_eq!(format!("{:.0e}", -976), "-1e3"); - assert_eq!(format!("{:.0e}", -975), "-1e3"); - assert_eq!(format!("{:.0e}", -974), "-1e3"); - assert_eq!(format!("{:.0e}", -973), "-1e3"); - assert_eq!(format!("{:.0e}", -972), "-1e3"); - assert_eq!(format!("{:.0e}", -971), "-1e3"); - assert_eq!(format!("{:.0e}", -970), "-1e3"); - assert_eq!(format!("{:.0e}", -969), "-1e3"); - assert_eq!(format!("{:.0e}", -968), "-1e3"); - assert_eq!(format!("{:.0e}", -967), "-1e3"); - assert_eq!(format!("{:.0e}", -966), "-1e3"); - assert_eq!(format!("{:.0e}", -965), "-1e3"); - assert_eq!(format!("{:.0e}", -964), "-1e3"); - assert_eq!(format!("{:.0e}", -963), "-1e3"); - assert_eq!(format!("{:.0e}", -962), "-1e3"); - assert_eq!(format!("{:.0e}", -961), "-1e3"); - assert_eq!(format!("{:.0e}", -960), "-1e3"); - assert_eq!(format!("{:.0e}", -959), "-1e3"); - assert_eq!(format!("{:.0e}", -958), "-1e3"); - assert_eq!(format!("{:.0e}", -957), "-1e3"); - assert_eq!(format!("{:.0e}", -956), "-1e3"); - assert_eq!(format!("{:.0e}", -955), "-1e3"); - assert_eq!(format!("{:.0e}", -954), "-1e3"); - assert_eq!(format!("{:.0e}", -953), "-1e3"); - assert_eq!(format!("{:.0e}", -952), "-1e3"); - assert_eq!(format!("{:.0e}", -951), "-1e3"); - assert_eq!(format!("{:.0e}", -950), "-1e3"); - assert_eq!(format!("{:.0e}", -850), "-9e2"); - assert_eq!(format!("{:.0e}", -650), "-7e2"); - assert_eq!(format!("{:.0e}", -450), "-5e2"); - assert_eq!(format!("{:.0e}", -250), "-3e2"); - assert_eq!(format!("{:.0e}", -99), "-1e2"); - assert_eq!(format!("{:.0e}", -98), "-1e2"); - assert_eq!(format!("{:.0e}", -97), "-1e2"); - assert_eq!(format!("{:.0e}", -96), "-1e2"); - assert_eq!(format!("{:.0e}", -95), "-1e2"); - assert_eq!(format!("{:.0e}", -85), "-9e1"); - assert_eq!(format!("{:.0e}", -65), "-7e1"); - assert_eq!(format!("{:.0e}", -45), "-5e1"); - assert_eq!(format!("{:.0e}", -25), "-3e1"); - assert_eq!(format!("{:.0e}", 25), "3e1"); - assert_eq!(format!("{:.0e}", 45), "5e1"); - assert_eq!(format!("{:.0e}", 65), "7e1"); - assert_eq!(format!("{:.0e}", 85), "9e1"); - assert_eq!(format!("{:.0e}", 94), "9e1"); - assert_eq!(format!("{:.0e}", 95), "1e2"); - assert_eq!(format!("{:.0e}", 96), "1e2"); - assert_eq!(format!("{:.0e}", 97), "1e2"); - assert_eq!(format!("{:.0e}", 98), "1e2"); - assert_eq!(format!("{:.0e}", 99), "1e2"); - assert_eq!(format!("{:.0e}", 250), "3e2"); - assert_eq!(format!("{:.0e}", 450), "5e2"); - assert_eq!(format!("{:.0e}", 650), "7e2"); - assert_eq!(format!("{:.0e}", 850), "9e2"); - assert_eq!(format!("{:.0e}", 950), "1e3"); - assert_eq!(format!("{:.0e}", 951), "1e3"); - assert_eq!(format!("{:.0e}", 952), "1e3"); - assert_eq!(format!("{:.0e}", 953), "1e3"); - assert_eq!(format!("{:.0e}", 954), "1e3"); - assert_eq!(format!("{:.0e}", 955), "1e3"); - assert_eq!(format!("{:.0e}", 956), "1e3"); - assert_eq!(format!("{:.0e}", 957), "1e3"); - assert_eq!(format!("{:.0e}", 958), "1e3"); - assert_eq!(format!("{:.0e}", 959), "1e3"); - assert_eq!(format!("{:.0e}", 960), "1e3"); - assert_eq!(format!("{:.0e}", 961), "1e3"); - assert_eq!(format!("{:.0e}", 962), "1e3"); - assert_eq!(format!("{:.0e}", 963), "1e3"); - assert_eq!(format!("{:.0e}", 964), "1e3"); - assert_eq!(format!("{:.0e}", 965), "1e3"); - assert_eq!(format!("{:.0e}", 966), "1e3"); - assert_eq!(format!("{:.0e}", 967), "1e3"); - assert_eq!(format!("{:.0e}", 968), "1e3"); - assert_eq!(format!("{:.0e}", 969), "1e3"); - assert_eq!(format!("{:.0e}", 970), "1e3"); - assert_eq!(format!("{:.0e}", 971), "1e3"); - assert_eq!(format!("{:.0e}", 972), "1e3"); - assert_eq!(format!("{:.0e}", 973), "1e3"); - assert_eq!(format!("{:.0e}", 974), "1e3"); - assert_eq!(format!("{:.0e}", 975), "1e3"); - assert_eq!(format!("{:.0e}", 976), "1e3"); - assert_eq!(format!("{:.0e}", 977), "1e3"); - assert_eq!(format!("{:.0e}", 978), "1e3"); - assert_eq!(format!("{:.0e}", 979), "1e3"); - assert_eq!(format!("{:.0e}", 980), "1e3"); - assert_eq!(format!("{:.0e}", 981), "1e3"); - assert_eq!(format!("{:.0e}", 982), "1e3"); - assert_eq!(format!("{:.0e}", 983), "1e3"); - assert_eq!(format!("{:.0e}", 984), "1e3"); - assert_eq!(format!("{:.0e}", 985), "1e3"); - assert_eq!(format!("{:.0e}", 986), "1e3"); - assert_eq!(format!("{:.0e}", 987), "1e3"); - assert_eq!(format!("{:.0e}", 988), "1e3"); - assert_eq!(format!("{:.0e}", 989), "1e3"); - assert_eq!(format!("{:.0e}", 990), "1e3"); - assert_eq!(format!("{:.0e}", 991), "1e3"); - assert_eq!(format!("{:.0e}", 992), "1e3"); - assert_eq!(format!("{:.0e}", 993), "1e3"); - assert_eq!(format!("{:.0e}", 994), "1e3"); - assert_eq!(format!("{:.0e}", 995), "1e3"); - assert_eq!(format!("{:.0e}", 996), "1e3"); - assert_eq!(format!("{:.0e}", 997), "1e3"); - assert_eq!(format!("{:.0e}", 998), "1e3"); - assert_eq!(format!("{:.0e}", 999), "1e3"); - assert_eq!(format!("{:.1e}", -1850), "-1.9e3"); - assert_eq!(format!("{:.1e}", -1650), "-1.7e3"); - assert_eq!(format!("{:.1e}", -1450), "-1.5e3"); - assert_eq!(format!("{:.1e}", -1250), "-1.3e3"); - assert_eq!(format!("{:.1e}", -1050), "-1.1e3"); - assert_eq!(format!("{:.1e}", -999), "-1.0e3"); - assert_eq!(format!("{:.1e}", -998), "-1.0e3"); - assert_eq!(format!("{:.1e}", -997), "-1.0e3"); - assert_eq!(format!("{:.1e}", -996), "-1.0e3"); - assert_eq!(format!("{:.1e}", -995), "-1.0e3"); - assert_eq!(format!("{:.1e}", -985), "-9.9e2"); - assert_eq!(format!("{:.1e}", -965), "-9.7e2"); - assert_eq!(format!("{:.1e}", -945), "-9.5e2"); - assert_eq!(format!("{:.1e}", -925), "-9.3e2"); - assert_eq!(format!("{:.1e}", -905), "-9.1e2"); - assert_eq!(format!("{:.1e}", -885), "-8.9e2"); - assert_eq!(format!("{:.1e}", -865), "-8.7e2"); - assert_eq!(format!("{:.1e}", -845), "-8.5e2"); - assert_eq!(format!("{:.1e}", -825), "-8.3e2"); - assert_eq!(format!("{:.1e}", -805), "-8.1e2"); - assert_eq!(format!("{:.1e}", -785), "-7.9e2"); - assert_eq!(format!("{:.1e}", -765), "-7.7e2"); - assert_eq!(format!("{:.1e}", -745), "-7.5e2"); - assert_eq!(format!("{:.1e}", -725), "-7.3e2"); - assert_eq!(format!("{:.1e}", -705), "-7.1e2"); - assert_eq!(format!("{:.1e}", -685), "-6.9e2"); - assert_eq!(format!("{:.1e}", -665), "-6.7e2"); - assert_eq!(format!("{:.1e}", -645), "-6.5e2"); - assert_eq!(format!("{:.1e}", -625), "-6.3e2"); - assert_eq!(format!("{:.1e}", -605), "-6.1e2"); - assert_eq!(format!("{:.1e}", -585), "-5.9e2"); - assert_eq!(format!("{:.1e}", -565), "-5.7e2"); - assert_eq!(format!("{:.1e}", -545), "-5.5e2"); - assert_eq!(format!("{:.1e}", -525), "-5.3e2"); - assert_eq!(format!("{:.1e}", -505), "-5.1e2"); - assert_eq!(format!("{:.1e}", -485), "-4.9e2"); - assert_eq!(format!("{:.1e}", -465), "-4.7e2"); - assert_eq!(format!("{:.1e}", -445), "-4.5e2"); - assert_eq!(format!("{:.1e}", -425), "-4.3e2"); - assert_eq!(format!("{:.1e}", -405), "-4.1e2"); - assert_eq!(format!("{:.1e}", -385), "-3.9e2"); - assert_eq!(format!("{:.1e}", -365), "-3.7e2"); - assert_eq!(format!("{:.1e}", -345), "-3.5e2"); - assert_eq!(format!("{:.1e}", -325), "-3.3e2"); - assert_eq!(format!("{:.1e}", -305), "-3.1e2"); - assert_eq!(format!("{:.1e}", -285), "-2.9e2"); - assert_eq!(format!("{:.1e}", -265), "-2.7e2"); - assert_eq!(format!("{:.1e}", -245), "-2.5e2"); - assert_eq!(format!("{:.1e}", -225), "-2.3e2"); - assert_eq!(format!("{:.1e}", -205), "-2.1e2"); - assert_eq!(format!("{:.1e}", -185), "-1.9e2"); - assert_eq!(format!("{:.1e}", -165), "-1.7e2"); - assert_eq!(format!("{:.1e}", -145), "-1.5e2"); - assert_eq!(format!("{:.1e}", -125), "-1.3e2"); - assert_eq!(format!("{:.1e}", -105), "-1.1e2"); - assert_eq!(format!("{:.1e}", 105), "1.1e2"); - assert_eq!(format!("{:.1e}", 125), "1.3e2"); - assert_eq!(format!("{:.1e}", 145), "1.5e2"); - assert_eq!(format!("{:.1e}", 165), "1.7e2"); - assert_eq!(format!("{:.1e}", 185), "1.9e2"); - assert_eq!(format!("{:.1e}", 205), "2.1e2"); - assert_eq!(format!("{:.1e}", 225), "2.3e2"); - assert_eq!(format!("{:.1e}", 245), "2.5e2"); - assert_eq!(format!("{:.1e}", 265), "2.7e2"); - assert_eq!(format!("{:.1e}", 285), "2.9e2"); - assert_eq!(format!("{:.1e}", 305), "3.1e2"); - assert_eq!(format!("{:.1e}", 325), "3.3e2"); - assert_eq!(format!("{:.1e}", 345), "3.5e2"); - assert_eq!(format!("{:.1e}", 365), "3.7e2"); - assert_eq!(format!("{:.1e}", 385), "3.9e2"); - assert_eq!(format!("{:.1e}", 405), "4.1e2"); - assert_eq!(format!("{:.1e}", 425), "4.3e2"); - assert_eq!(format!("{:.1e}", 445), "4.5e2"); - assert_eq!(format!("{:.1e}", 465), "4.7e2"); - assert_eq!(format!("{:.1e}", 485), "4.9e2"); - assert_eq!(format!("{:.1e}", 505), "5.1e2"); - assert_eq!(format!("{:.1e}", 525), "5.3e2"); - assert_eq!(format!("{:.1e}", 545), "5.5e2"); - assert_eq!(format!("{:.1e}", 565), "5.7e2"); - assert_eq!(format!("{:.1e}", 585), "5.9e2"); - assert_eq!(format!("{:.1e}", 605), "6.1e2"); - assert_eq!(format!("{:.1e}", 625), "6.3e2"); - assert_eq!(format!("{:.1e}", 645), "6.5e2"); - assert_eq!(format!("{:.1e}", 665), "6.7e2"); - assert_eq!(format!("{:.1e}", 685), "6.9e2"); - assert_eq!(format!("{:.1e}", 705), "7.1e2"); - assert_eq!(format!("{:.1e}", 725), "7.3e2"); - assert_eq!(format!("{:.1e}", 745), "7.5e2"); - assert_eq!(format!("{:.1e}", 765), "7.7e2"); - assert_eq!(format!("{:.1e}", 785), "7.9e2"); - assert_eq!(format!("{:.1e}", 805), "8.1e2"); - assert_eq!(format!("{:.1e}", 825), "8.3e2"); - assert_eq!(format!("{:.1e}", 845), "8.5e2"); - assert_eq!(format!("{:.1e}", 865), "8.7e2"); - assert_eq!(format!("{:.1e}", 885), "8.9e2"); - assert_eq!(format!("{:.1e}", 905), "9.1e2"); - assert_eq!(format!("{:.1e}", 925), "9.3e2"); - assert_eq!(format!("{:.1e}", 945), "9.5e2"); - assert_eq!(format!("{:.1e}", 965), "9.7e2"); - assert_eq!(format!("{:.1e}", 985), "9.9e2"); - assert_eq!(format!("{:.1e}", 995), "1.0e3"); - assert_eq!(format!("{:.1e}", 996), "1.0e3"); - assert_eq!(format!("{:.1e}", 997), "1.0e3"); - assert_eq!(format!("{:.1e}", 998), "1.0e3"); - assert_eq!(format!("{:.1e}", 999), "1.0e3"); - assert_eq!(format!("{:.1e}", 1050), "1.1e3"); - assert_eq!(format!("{:.1e}", 1250), "1.3e3"); - assert_eq!(format!("{:.1e}", 1450), "1.5e3"); - assert_eq!(format!("{:.1e}", 1650), "1.7e3"); - assert_eq!(format!("{:.1e}", 1850), "1.9e3"); - assert_eq!(format!("{:.2e}", -1985), "-1.99e3"); - assert_eq!(format!("{:.2e}", -1965), "-1.97e3"); - assert_eq!(format!("{:.2e}", -1945), "-1.95e3"); - assert_eq!(format!("{:.2e}", -1925), "-1.93e3"); - assert_eq!(format!("{:.2e}", -1905), "-1.91e3"); - assert_eq!(format!("{:.2e}", -1885), "-1.89e3"); - assert_eq!(format!("{:.2e}", -1865), "-1.87e3"); - assert_eq!(format!("{:.2e}", -1845), "-1.85e3"); - assert_eq!(format!("{:.2e}", -1825), "-1.83e3"); - assert_eq!(format!("{:.2e}", -1805), "-1.81e3"); - assert_eq!(format!("{:.2e}", -1785), "-1.79e3"); - assert_eq!(format!("{:.2e}", -1765), "-1.77e3"); - assert_eq!(format!("{:.2e}", -1745), "-1.75e3"); - assert_eq!(format!("{:.2e}", -1725), "-1.73e3"); - assert_eq!(format!("{:.2e}", -1705), "-1.71e3"); - assert_eq!(format!("{:.2e}", -1685), "-1.69e3"); - assert_eq!(format!("{:.2e}", -1665), "-1.67e3"); - assert_eq!(format!("{:.2e}", -1645), "-1.65e3"); - assert_eq!(format!("{:.2e}", -1625), "-1.63e3"); - assert_eq!(format!("{:.2e}", -1605), "-1.61e3"); - assert_eq!(format!("{:.2e}", -1585), "-1.59e3"); - assert_eq!(format!("{:.2e}", -1565), "-1.57e3"); - assert_eq!(format!("{:.2e}", -1545), "-1.55e3"); - assert_eq!(format!("{:.2e}", -1525), "-1.53e3"); - assert_eq!(format!("{:.2e}", -1505), "-1.51e3"); - assert_eq!(format!("{:.2e}", -1485), "-1.49e3"); - assert_eq!(format!("{:.2e}", -1465), "-1.47e3"); - assert_eq!(format!("{:.2e}", -1445), "-1.45e3"); - assert_eq!(format!("{:.2e}", -1425), "-1.43e3"); - assert_eq!(format!("{:.2e}", -1405), "-1.41e3"); - assert_eq!(format!("{:.2e}", -1385), "-1.39e3"); - assert_eq!(format!("{:.2e}", -1365), "-1.37e3"); - assert_eq!(format!("{:.2e}", -1345), "-1.35e3"); - assert_eq!(format!("{:.2e}", -1325), "-1.33e3"); - assert_eq!(format!("{:.2e}", -1305), "-1.31e3"); - assert_eq!(format!("{:.2e}", -1285), "-1.29e3"); - assert_eq!(format!("{:.2e}", -1265), "-1.27e3"); - assert_eq!(format!("{:.2e}", -1245), "-1.25e3"); - assert_eq!(format!("{:.2e}", -1225), "-1.23e3"); - assert_eq!(format!("{:.2e}", -1205), "-1.21e3"); - assert_eq!(format!("{:.2e}", -1185), "-1.19e3"); - assert_eq!(format!("{:.2e}", -1165), "-1.17e3"); - assert_eq!(format!("{:.2e}", -1145), "-1.15e3"); - assert_eq!(format!("{:.2e}", -1125), "-1.13e3"); - assert_eq!(format!("{:.2e}", -1105), "-1.11e3"); - assert_eq!(format!("{:.2e}", -1085), "-1.09e3"); - assert_eq!(format!("{:.2e}", -1065), "-1.07e3"); - assert_eq!(format!("{:.2e}", -1045), "-1.05e3"); - assert_eq!(format!("{:.2e}", -1025), "-1.03e3"); - assert_eq!(format!("{:.2e}", -1005), "-1.01e3"); - assert_eq!(format!("{:.2e}", 1005), "1.01e3" ); - assert_eq!(format!("{:.2e}", 1025), "1.03e3" ); - assert_eq!(format!("{:.2e}", 1045), "1.05e3" ); - assert_eq!(format!("{:.2e}", 1065), "1.07e3" ); - assert_eq!(format!("{:.2e}", 1085), "1.09e3" ); - assert_eq!(format!("{:.2e}", 1105), "1.11e3" ); - assert_eq!(format!("{:.2e}", 1125), "1.13e3" ); - assert_eq!(format!("{:.2e}", 1145), "1.15e3" ); - assert_eq!(format!("{:.2e}", 1165), "1.17e3" ); - assert_eq!(format!("{:.2e}", 1185), "1.19e3" ); - assert_eq!(format!("{:.2e}", 1205), "1.21e3" ); - assert_eq!(format!("{:.2e}", 1225), "1.23e3" ); - assert_eq!(format!("{:.2e}", 1245), "1.25e3" ); - assert_eq!(format!("{:.2e}", 1265), "1.27e3" ); - assert_eq!(format!("{:.2e}", 1285), "1.29e3" ); - assert_eq!(format!("{:.2e}", 1305), "1.31e3" ); - assert_eq!(format!("{:.2e}", 1325), "1.33e3" ); - assert_eq!(format!("{:.2e}", 1345), "1.35e3" ); - assert_eq!(format!("{:.2e}", 1365), "1.37e3" ); - assert_eq!(format!("{:.2e}", 1385), "1.39e3" ); - assert_eq!(format!("{:.2e}", 1405), "1.41e3" ); - assert_eq!(format!("{:.2e}", 1425), "1.43e3" ); - assert_eq!(format!("{:.2e}", 1445), "1.45e3" ); - assert_eq!(format!("{:.2e}", 1465), "1.47e3" ); - assert_eq!(format!("{:.2e}", 1485), "1.49e3" ); - assert_eq!(format!("{:.2e}", 1505), "1.51e3" ); - assert_eq!(format!("{:.2e}", 1525), "1.53e3" ); - assert_eq!(format!("{:.2e}", 1545), "1.55e3" ); - assert_eq!(format!("{:.2e}", 1565), "1.57e3" ); - assert_eq!(format!("{:.2e}", 1585), "1.59e3" ); - assert_eq!(format!("{:.2e}", 1605), "1.61e3" ); - assert_eq!(format!("{:.2e}", 1625), "1.63e3" ); - assert_eq!(format!("{:.2e}", 1645), "1.65e3" ); - assert_eq!(format!("{:.2e}", 1665), "1.67e3" ); - assert_eq!(format!("{:.2e}", 1685), "1.69e3" ); - assert_eq!(format!("{:.2e}", 1705), "1.71e3" ); - assert_eq!(format!("{:.2e}", 1725), "1.73e3" ); - assert_eq!(format!("{:.2e}", 1745), "1.75e3" ); - assert_eq!(format!("{:.2e}", 1765), "1.77e3" ); - assert_eq!(format!("{:.2e}", 1785), "1.79e3" ); - assert_eq!(format!("{:.2e}", 1805), "1.81e3" ); - assert_eq!(format!("{:.2e}", 1825), "1.83e3" ); - assert_eq!(format!("{:.2e}", 1845), "1.85e3" ); - assert_eq!(format!("{:.2e}", 1865), "1.87e3" ); - assert_eq!(format!("{:.2e}", 1885), "1.89e3" ); - assert_eq!(format!("{:.2e}", 1905), "1.91e3" ); - assert_eq!(format!("{:.2e}", 1925), "1.93e3" ); - assert_eq!(format!("{:.2e}", 1945), "1.95e3" ); - assert_eq!(format!("{:.2e}", 1965), "1.97e3" ); - assert_eq!(format!("{:.2e}", 1985), "1.99e3" ); + + for i in i16::MIN..=i16::MAX { + for p in 0..=5 { + assert_eq!( + format!("{i:.p$e}"), + format!("{:.p$e}", f32::from(i)), + "integer {i} at precision {p}" + ); + } + } } #[test] From 8ce5d784a62e093edfec294a6d92c4101b38e9c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Sat, 11 Nov 2023 15:01:58 +0100 Subject: [PATCH 395/435] Deny more `~const` trait bounds --- compiler/rustc_ast_passes/messages.ftl | 5 +- .../rustc_ast_passes/src/ast_validation.rs | 75 +++--- compiler/rustc_ast_passes/src/errors.rs | 16 +- .../generic-const-items/const-trait-impl.rs | 4 +- .../const-trait-impl.stderr | 6 +- .../assoc-type-const-bound-usage.stderr | 10 +- .../assoc-type.stderr | 10 +- .../const-bound-on-not-const-associated-fn.rs | 2 +- ...st-bound-on-not-const-associated-fn.stderr | 0 .../const-drop.precise.stderr | 21 +- .../rfc-2632-const-trait-impl/const-drop.rs | 1 + .../const-drop.stock.stderr | 21 +- .../rfc-2632-const-trait-impl/issue-90052.rs | 9 - .../issue-90052.stderr | 14 - ...fault-bound-non-const-specialized-bound.rs | 6 +- .../super-traits-fail-2.nn.stderr | 14 +- .../super-traits-fail-2.yn.stderr | 15 +- .../super-traits-fail-3.nn.stderr | 16 +- .../super-traits-fail-3.rs | 1 + .../super-traits-fail-3.yn.stderr | 16 +- .../super-traits-fail-3.yy.stderr | 2 +- .../tilde-const-invalid-places.rs | 54 +++- .../tilde-const-invalid-places.stderr | 246 +++++++++++++++++- .../tilde-const-maybe-trait.rs | 6 + .../tilde-const-maybe-trait.stderr | 8 + 25 files changed, 444 insertions(+), 134 deletions(-) rename tests/ui/rfcs/rfc-2632-const-trait-impl/{effects => }/const-bound-on-not-const-associated-fn.rs (92%) rename tests/ui/rfcs/rfc-2632-const-trait-impl/{effects => }/const-bound-on-not-const-associated-fn.stderr (100%) delete mode 100644 tests/ui/rfcs/rfc-2632-const-trait-impl/issue-90052.rs delete mode 100644 tests/ui/rfcs/rfc-2632-const-trait-impl/issue-90052.stderr create mode 100644 tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-maybe-trait.rs create mode 100644 tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-maybe-trait.stderr diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl index 43020a930788..5ce2383b9731 100644 --- a/compiler/rustc_ast_passes/messages.ftl +++ b/compiler/rustc_ast_passes/messages.ftl @@ -214,9 +214,12 @@ ast_passes_static_without_body = .suggestion = provide a definition for the static ast_passes_tilde_const_disallowed = `~const` is not allowed here - .trait = trait objects cannot have `~const` trait bounds .closure = closures cannot have `~const` trait bounds .function = this function is not `const`, so it cannot have `~const` trait bounds + .trait = this trait is not a `#[const_trait]`, so it cannot have `~const` trait bounds + .impl = this impl is not `const`, so it cannot have `~const` trait bounds + .object = trait objects cannot have `~const` trait bounds + .item = this item cannot have `~const` trait bounds ast_passes_trait_fn_const = functions in traits cannot be declared const diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 0477c7b2ba99..12a384339532 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -40,6 +40,9 @@ enum SelfSemantic { enum DisallowTildeConstContext<'a> { TraitObject, Fn(FnKind<'a>), + Trait(Span), + Impl(Span), + Item, } struct AstValidator<'a> { @@ -110,18 +113,6 @@ impl<'a> AstValidator<'a> { self.disallow_tilde_const = old; } - fn with_tilde_const_allowed(&mut self, f: impl FnOnce(&mut Self)) { - self.with_tilde_const(None, f) - } - - fn with_banned_tilde_const( - &mut self, - ctx: DisallowTildeConstContext<'a>, - f: impl FnOnce(&mut Self), - ) { - self.with_tilde_const(Some(ctx), f) - } - fn check_type_alias_where_clause_location( &mut self, ty_alias: &TyAlias, @@ -173,7 +164,7 @@ impl<'a> AstValidator<'a> { self.with_impl_trait(Some(t.span), |this| visit::walk_ty(this, t)) } TyKind::TraitObject(..) => self - .with_banned_tilde_const(DisallowTildeConstContext::TraitObject, |this| { + .with_tilde_const(Some(DisallowTildeConstContext::TraitObject), |this| { visit::walk_ty(this, t) }), TyKind::Path(qself, path) => { @@ -822,11 +813,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> { this.visit_vis(&item.vis); this.visit_ident(item.ident); - if let Const::Yes(_) = constness { - this.with_tilde_const_allowed(|this| this.visit_generics(generics)); - } else { - this.visit_generics(generics); - } + let disallowed = matches!(constness, Const::No) + .then(|| DisallowTildeConstContext::Impl(item.span)); + this.with_tilde_const(disallowed, |this| this.visit_generics(generics)); this.visit_trait_ref(t); this.visit_ty(self_ty); @@ -840,10 +829,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> { polarity, defaultness, constness, - generics: _, + generics, of_trait: None, self_ty, - items: _, + items, }) => { let error = |annotation_span, annotation, only_trait: bool| errors::InherentImplCannot { @@ -875,6 +864,14 @@ impl<'a> Visitor<'a> for AstValidator<'a> { if let &Const::Yes(span) = constness { self.err_handler().emit_err(error(span, "`const`", true)); } + + self.visit_vis(&item.vis); + self.visit_ident(item.ident); + self.with_tilde_const(None, |this| this.visit_generics(generics)); + self.visit_ty(self_ty); + walk_list!(self, visit_assoc_item, items, AssocCtxt::Impl); + walk_list!(self, visit_attribute, &item.attrs); + return; // Avoid visiting again. } ItemKind::Fn(box Fn { defaultness, sig, generics, body }) => { self.check_defaultness(item.span, *defaultness); @@ -955,8 +952,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> { // context for the supertraits. this.visit_vis(&item.vis); this.visit_ident(item.ident); - this.visit_generics(generics); - this.with_tilde_const_allowed(|this| { + let disallowed = + (!is_const_trait).then(|| DisallowTildeConstContext::Trait(item.span)); + this.with_tilde_const(disallowed, |this| { + this.visit_generics(generics); walk_list!(this, visit_param_bound, bounds, BoundKind::SuperTraits) }); walk_list!(this, visit_assoc_item, items, AssocCtxt::Trait); @@ -976,16 +975,11 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } } ItemKind::Struct(vdata, generics) => match vdata { - // Duplicating the `Visitor` logic allows catching all cases - // of `Anonymous(Struct, Union)` outside of a field struct or union. - // - // Inside `visit_ty` the validator catches every `Anonymous(Struct, Union)` it - // encounters, and only on `ItemKind::Struct` and `ItemKind::Union` - // it uses `visit_ty_common`, which doesn't contain that specific check. VariantData::Struct(fields, ..) => { self.visit_vis(&item.vis); self.visit_ident(item.ident); self.visit_generics(generics); + // Permit `Anon{Struct,Union}` as field type. walk_list!(self, visit_struct_field_def, fields); walk_list!(self, visit_attribute, &item.attrs); return; @@ -1001,6 +995,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.visit_vis(&item.vis); self.visit_ident(item.ident); self.visit_generics(generics); + // Permit `Anon{Struct,Union}` as field type. walk_list!(self, visit_struct_field_def, fields); walk_list!(self, visit_attribute, &item.attrs); return; @@ -1189,15 +1184,18 @@ impl<'a> Visitor<'a> for AstValidator<'a> { if let Some(reason) = &self.disallow_tilde_const => { let reason = match reason { - DisallowTildeConstContext::TraitObject => { - errors::TildeConstReason::TraitObject - } DisallowTildeConstContext::Fn(FnKind::Closure(..)) => { errors::TildeConstReason::Closure } DisallowTildeConstContext::Fn(FnKind::Fn(_, ident, ..)) => { errors::TildeConstReason::Function { ident: ident.span } } + &DisallowTildeConstContext::Trait(span) => errors::TildeConstReason::Trait { span }, + &DisallowTildeConstContext::Impl(span) => errors::TildeConstReason::Impl { span }, + DisallowTildeConstContext::TraitObject => { + errors::TildeConstReason::TraitObject + } + DisallowTildeConstContext::Item => errors::TildeConstReason::Item, }; self.err_handler() .emit_err(errors::TildeConstDisallowed { span: bound.span(), reason }); @@ -1305,7 +1303,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> { || matches!(fk.ctxt(), Some(FnCtxt::Assoc(_)) if self.in_const_trait_or_impl); let disallowed = (!tilde_const_allowed).then(|| DisallowTildeConstContext::Fn(fk)); - self.with_tilde_const(disallowed, |this| visit::walk_fn(this, fk)); } @@ -1374,18 +1371,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } match &item.kind { - AssocItemKind::Type(box TyAlias { generics, bounds, ty, .. }) - if ctxt == AssocCtxt::Trait => - { - self.visit_vis(&item.vis); - self.visit_ident(item.ident); - walk_list!(self, visit_attribute, &item.attrs); - self.with_tilde_const_allowed(|this| { - this.visit_generics(generics); - walk_list!(this, visit_param_bound, bounds, BoundKind::Bound); - }); - walk_list!(self, visit_ty, ty); - } AssocItemKind::Fn(box Fn { sig, generics, body, .. }) if self.in_const_trait_or_impl || ctxt == AssocCtxt::Trait @@ -1537,7 +1522,7 @@ pub fn check_crate( in_const_trait_or_impl: false, has_proc_macro_decls: false, outer_impl_trait: None, - disallow_tilde_const: None, + disallow_tilde_const: Some(DisallowTildeConstContext::Item), is_impl_trait_banned: false, lint_buffer: lints, }; diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index e74d94e43474..60afb8adc045 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -551,8 +551,6 @@ pub struct TildeConstDisallowed { #[derive(Subdiagnostic)] pub enum TildeConstReason { - #[note(ast_passes_trait)] - TraitObject, #[note(ast_passes_closure)] Closure, #[note(ast_passes_function)] @@ -560,6 +558,20 @@ pub enum TildeConstReason { #[primary_span] ident: Span, }, + #[note(ast_passes_trait)] + Trait { + #[primary_span] + span: Span, + }, + #[note(ast_passes_impl)] + Impl { + #[primary_span] + span: Span, + }, + #[note(ast_passes_object)] + TraitObject, + #[note(ast_passes_item)] + Item, } #[derive(Diagnostic)] diff --git a/tests/ui/generic-const-items/const-trait-impl.rs b/tests/ui/generic-const-items/const-trait-impl.rs index d30f7af170dc..43cdf818c469 100644 --- a/tests/ui/generic-const-items/const-trait-impl.rs +++ b/tests/ui/generic-const-items/const-trait-impl.rs @@ -7,8 +7,8 @@ #![allow(incomplete_features)] #![crate_type = "lib"] -// FIXME(generic_const_items): Interpret `~const` as always-const. -const CREATE: T = T::create(); +// FIXME(generic_const_items, effects): Introduce `const` bounds to make this work. +const CREATE: T = T::create(); pub const K0: i32 = CREATE::; pub const K1: i32 = CREATE; // arg inferred diff --git a/tests/ui/generic-const-items/const-trait-impl.stderr b/tests/ui/generic-const-items/const-trait-impl.stderr index 34360c581d53..64aa8adf8a76 100644 --- a/tests/ui/generic-const-items/const-trait-impl.stderr +++ b/tests/ui/generic-const-items/const-trait-impl.stderr @@ -1,8 +1,8 @@ error[E0015]: cannot call non-const fn `::create` in constants - --> $DIR/const-trait-impl.rs:11:37 + --> $DIR/const-trait-impl.rs:11:30 | -LL | const CREATE: T = T::create(); - | ^^^^^^^^^^^ +LL | const CREATE: T = T::create(); + | ^^^^^^^^^^^ | = note: calls in constants are limited to constant functions, tuple structs and tuple variants diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.stderr index 6d436018bf4b..e6b663c47d75 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.stderr @@ -1,3 +1,11 @@ +error: `~const` is not allowed here + --> $DIR/assoc-type-const-bound-usage.rs:7:17 + | +LL | type Assoc: ~const Foo; + | ^^^^^^^^^^ + | + = note: this item cannot have `~const` trait bounds + error[E0308]: mismatched types --> $DIR/assoc-type-const-bound-usage.rs:12:5 | @@ -7,6 +15,6 @@ LL | ::Assoc::foo(); = note: expected constant `host` found constant `true` -error: aborting due to previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.stderr index 0cffae1da8d9..7df16ca5a3b4 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.stderr @@ -1,8 +1,16 @@ +error: `~const` is not allowed here + --> $DIR/assoc-type.rs:17:15 + | +LL | type Bar: ~const std::ops::Add; + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: this item cannot have `~const` trait bounds + error: ~const can only be applied to `#[const_trait]` traits --> $DIR/assoc-type.rs:17:22 | LL | type Bar: ~const std::ops::Add; | ^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 2 previous errors diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const-bound-on-not-const-associated-fn.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-bound-on-not-const-associated-fn.rs similarity index 92% rename from tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const-bound-on-not-const-associated-fn.rs rename to tests/ui/rfcs/rfc-2632-const-trait-impl/const-bound-on-not-const-associated-fn.rs index 1e22ddcea8d3..0025449c4921 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const-bound-on-not-const-associated-fn.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-bound-on-not-const-associated-fn.rs @@ -1,4 +1,4 @@ -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl)] #[const_trait] trait MyTrait { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const-bound-on-not-const-associated-fn.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-bound-on-not-const-associated-fn.stderr similarity index 100% rename from tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const-bound-on-not-const-associated-fn.stderr rename to tests/ui/rfcs/rfc-2632-const-trait-impl/const-bound-on-not-const-associated-fn.stderr diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.precise.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.precise.stderr index 23e368870258..be75e852e0ac 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.precise.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.precise.stderr @@ -1,19 +1,10 @@ -error[E0493]: destructor of `T` cannot be evaluated at compile-time - --> $DIR/const-drop.rs:19:32 +error: `~const` is not allowed here + --> $DIR/const-drop.rs:67:38 | -LL | const fn a(_: T) {} - | ^ - value is dropped here - | | - | the destructor for this type cannot be evaluated in constant functions - -error[E0493]: destructor of `S<'_>` cannot be evaluated at compile-time - --> $DIR/const-drop.rs:24:13 +LL | pub struct ConstDropWithBound(pub core::marker::PhantomData); + | ^^^^^^^^^^^^^^^^ | -LL | let _ = S(&mut c); - | ^^^^^^^^^- value is dropped here - | | - | the destructor for this type cannot be evaluated in constant functions + = note: this item cannot have `~const` trait bounds -error: aborting due to 2 previous errors +error: aborting due to previous error -For more information about this error, try `rustc --explain E0493`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.rs index 0a9cf638a2d2..9da84cdb0525 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.rs @@ -63,6 +63,7 @@ mod t { fn foo() {} } + // FIXME(effects): This should be a `const` bound instead of a `~const` one. pub struct ConstDropWithBound(pub core::marker::PhantomData); impl const Drop for ConstDropWithBound { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.stock.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.stock.stderr index 23e368870258..be75e852e0ac 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.stock.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.stock.stderr @@ -1,19 +1,10 @@ -error[E0493]: destructor of `T` cannot be evaluated at compile-time - --> $DIR/const-drop.rs:19:32 +error: `~const` is not allowed here + --> $DIR/const-drop.rs:67:38 | -LL | const fn a(_: T) {} - | ^ - value is dropped here - | | - | the destructor for this type cannot be evaluated in constant functions - -error[E0493]: destructor of `S<'_>` cannot be evaluated at compile-time - --> $DIR/const-drop.rs:24:13 +LL | pub struct ConstDropWithBound(pub core::marker::PhantomData); + | ^^^^^^^^^^^^^^^^ | -LL | let _ = S(&mut c); - | ^^^^^^^^^- value is dropped here - | | - | the destructor for this type cannot be evaluated in constant functions + = note: this item cannot have `~const` trait bounds -error: aborting due to 2 previous errors +error: aborting due to previous error -For more information about this error, try `rustc --explain E0493`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-90052.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-90052.rs deleted file mode 100644 index 21ddf4ab4e5f..000000000000 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-90052.rs +++ /dev/null @@ -1,9 +0,0 @@ -#![feature(const_trait_impl)] - -#[const_trait] -trait Bar {} - -fn foo() where T: ~const Bar {} -//~^ ERROR `~const` is not allowed - -fn main() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-90052.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-90052.stderr deleted file mode 100644 index b2a9365378b3..000000000000 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-90052.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error: `~const` is not allowed here - --> $DIR/issue-90052.rs:6:22 - | -LL | fn foo() where T: ~const Bar {} - | ^^^^^^^^^^ - | -note: this function is not `const`, so it cannot have `~const` trait bounds - --> $DIR/issue-90052.rs:6:4 - | -LL | fn foo() where T: ~const Bar {} - | ^^^ - -error: aborting due to previous error - diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.rs index 3db59631ef8d..234b0dd00638 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.rs @@ -18,11 +18,7 @@ trait Bar { fn bar(); } -// bgr360: I was only able to exercise the code path that raises the -// "missing ~const qualifier" error by making this base impl non-const, even -// though that doesn't really make sense to do. As seen below, if the base impl -// is made const, rustc fails earlier with an overlapping impl failure. -impl Bar for T +impl const Bar for T where T: ~const Foo, { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr index b60399c57dca..204f0f9f89ff 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr @@ -1,3 +1,15 @@ +error: `~const` is not allowed here + --> $DIR/super-traits-fail-2.rs:11:12 + | +LL | trait Bar: ~const Foo {} + | ^^^^^^^^^^ + | +note: this trait is not a `#[const_trait]`, so it cannot have `~const` trait bounds + --> $DIR/super-traits-fail-2.rs:11:1 + | +LL | trait Bar: ~const Foo {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ + error: ~const can only be applied to `#[const_trait]` traits --> $DIR/super-traits-fail-2.rs:11:19 | @@ -12,5 +24,5 @@ LL | trait Bar: ~const Foo {} | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr index 5d34156a5196..06330958b8e0 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr @@ -1,11 +1,14 @@ -error[E0015]: cannot call non-const fn `::a` in constant functions - --> $DIR/super-traits-fail-2.rs:16:7 +error: `~const` is not allowed here + --> $DIR/super-traits-fail-2.rs:11:12 | -LL | x.a(); - | ^^^ +LL | trait Bar: ~const Foo {} + | ^^^^^^^^^^ | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +note: this trait is not a `#[const_trait]`, so it cannot have `~const` trait bounds + --> $DIR/super-traits-fail-2.rs:11:1 + | +LL | trait Bar: ~const Foo {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error -For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr index eb12a236d8c3..77b13a351e2b 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr @@ -1,3 +1,15 @@ +error: `~const` is not allowed here + --> $DIR/super-traits-fail-3.rs:13:12 + | +LL | trait Bar: ~const Foo {} + | ^^^^^^^^^^ + | +note: this trait is not a `#[const_trait]`, so it cannot have `~const` trait bounds + --> $DIR/super-traits-fail-3.rs:13:1 + | +LL | trait Bar: ~const Foo {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ + error: ~const can only be applied to `#[const_trait]` traits --> $DIR/super-traits-fail-3.rs:13:19 | @@ -13,10 +25,10 @@ LL | trait Bar: ~const Foo {} = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: ~const can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-3.rs:17:24 + --> $DIR/super-traits-fail-3.rs:18:24 | LL | const fn foo(x: &T) { | ^^^ -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.rs index 16c592830d78..5994057b2db2 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.rs @@ -13,6 +13,7 @@ trait Foo { trait Bar: ~const Foo {} //[ny,nn]~^ ERROR: ~const can only be applied to `#[const_trait]` //[ny,nn]~| ERROR: ~const can only be applied to `#[const_trait]` +//[yn,nn]~^^^ ERROR: `~const` is not allowed here const fn foo(x: &T) { //[yn,nn]~^ ERROR: ~const can only be applied to `#[const_trait]` diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr index 58225b945912..2e41eb9b4c45 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr @@ -1,8 +1,20 @@ +error: `~const` is not allowed here + --> $DIR/super-traits-fail-3.rs:13:12 + | +LL | trait Bar: ~const Foo {} + | ^^^^^^^^^^ + | +note: this trait is not a `#[const_trait]`, so it cannot have `~const` trait bounds + --> $DIR/super-traits-fail-3.rs:13:1 + | +LL | trait Bar: ~const Foo {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ + error: ~const can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-3.rs:17:24 + --> $DIR/super-traits-fail-3.rs:18:24 | LL | const fn foo(x: &T) { | ^^^ -error: aborting due to previous error +error: aborting due to 2 previous errors diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yy.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yy.stderr index 6bc643e68710..d81d9aa94da3 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yy.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yy.stderr @@ -1,5 +1,5 @@ error[E0015]: cannot call non-const fn `::a` in constant functions - --> $DIR/super-traits-fail-3.rs:19:7 + --> $DIR/super-traits-fail-3.rs:20:7 | LL | x.a(); | ^^^ diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places.rs index 95f7aaba0fc3..bbe1194f7a31 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places.rs @@ -1,7 +1,55 @@ #![feature(const_trait_impl)] -#![feature(associated_type_bounds)] -struct TildeQuestion(std::marker::PhantomData); -//~^ ERROR `~const` and `?` are mutually exclusive +#[const_trait] +trait Trait {} + +// Regression test for issue #90052. +fn non_const_function() {} //~ ERROR `~const` is not allowed + +struct Struct { field: T } //~ ERROR `~const` is not allowed here +struct TupleStruct(T); //~ ERROR `~const` is not allowed here +struct UnitStruct; //~ ERROR `~const` is not allowed here + +enum Enum { Variant(T) } //~ ERROR `~const` is not allowed here + +union Union { field: T } //~ ERROR `~const` is not allowed here + +type Type = T; //~ ERROR `~const` is not allowed here + +const CONSTANT: () = (); //~ ERROR `~const` is not allowed here +//~^ ERROR generic const items are experimental + +trait NonConstTrait { + type Type: ~const Trait; + //~^ ERROR `~const` is not allowed + //~| ERROR `~const` is not allowed + fn non_const_function(); //~ ERROR `~const` is not allowed + const CONSTANT: (); //~ ERROR `~const` is not allowed + //~^ ERROR generic const items are experimental +} + +impl NonConstTrait for () { + type Type = (); //~ ERROR `~const` is not allowed + fn non_const_function() {} //~ ERROR `~const` is not allowed + const CONSTANT: () = (); //~ ERROR `~const` is not allowed + //~^ ERROR generic const items are experimental +} + +struct Implementor; + +impl Implementor { + type Type = (); //~ ERROR `~const` is not allowed + //~^ ERROR inherent associated types are unstable + fn non_const_function() {} //~ ERROR `~const` is not allowed + const CONSTANT: () = (); //~ ERROR `~const` is not allowed + //~^ ERROR generic const items are experimental +} + +// non-const traits +trait Child0: ~const Trait {} //~ ERROR `~const` is not allowed +trait Child1 where Self: ~const Trait {} //~ ERROR `~const` is not allowed + +// non-const impl +impl Trait for T {} //~ ERROR `~const` is not allowed fn main() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr index d20f146df3f1..c14f9a990358 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr @@ -1,8 +1,244 @@ -error: `~const` and `?` are mutually exclusive - --> $DIR/tilde-const-invalid-places.rs:4:25 +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:7:26 | -LL | struct TildeQuestion(std::marker::PhantomData); - | ^^^^^^^^^^^^^ +LL | fn non_const_function() {} + | ^^^^^^^^^^^^ + | +note: this function is not `const`, so it cannot have `~const` trait bounds + --> $DIR/tilde-const-invalid-places.rs:7:4 + | +LL | fn non_const_function() {} + | ^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:9:18 + | +LL | struct Struct { field: T } + | ^^^^^^^^^^^^ + | + = note: this item cannot have `~const` trait bounds +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:10:23 + | +LL | struct TupleStruct(T); + | ^^^^^^^^^^^^ + | + = note: this item cannot have `~const` trait bounds + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:11:22 + | +LL | struct UnitStruct; + | ^^^^^^^^^^^^ + | + = note: this item cannot have `~const` trait bounds + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:13:14 + | +LL | enum Enum { Variant(T) } + | ^^^^^^^^^^^^ + | + = note: this item cannot have `~const` trait bounds + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:15:16 + | +LL | union Union { field: T } + | ^^^^^^^^^^^^ + | + = note: this item cannot have `~const` trait bounds + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:17:14 + | +LL | type Type = T; + | ^^^^^^^^^^^^ + | + = note: this item cannot have `~const` trait bounds + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:19:19 + | +LL | const CONSTANT: () = (); + | ^^^^^^^^^^^^ + | + = note: this item cannot have `~const` trait bounds + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:23:18 + | +LL | type Type: ~const Trait; + | ^^^^^^^^^^^^ + | + = note: this item cannot have `~const` trait bounds + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:23:33 + | +LL | type Type: ~const Trait; + | ^^^^^^^^^^^^ + | + = note: this item cannot have `~const` trait bounds + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:26:30 + | +LL | fn non_const_function(); + | ^^^^^^^^^^^^ + | +note: this function is not `const`, so it cannot have `~const` trait bounds + --> $DIR/tilde-const-invalid-places.rs:26:8 + | +LL | fn non_const_function(); + | ^^^^^^^^^^^^^^^^^^ + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:27:23 + | +LL | const CONSTANT: (); + | ^^^^^^^^^^^^ + | + = note: this item cannot have `~const` trait bounds + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:32:18 + | +LL | type Type = (); + | ^^^^^^^^^^^^ + | + = note: this item cannot have `~const` trait bounds + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:33:30 + | +LL | fn non_const_function() {} + | ^^^^^^^^^^^^ + | +note: this function is not `const`, so it cannot have `~const` trait bounds + --> $DIR/tilde-const-invalid-places.rs:33:8 + | +LL | fn non_const_function() {} + | ^^^^^^^^^^^^^^^^^^ + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:34:23 + | +LL | const CONSTANT: () = (); + | ^^^^^^^^^^^^ + | + = note: this item cannot have `~const` trait bounds + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:41:18 + | +LL | type Type = (); + | ^^^^^^^^^^^^ + | + = note: this item cannot have `~const` trait bounds + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:43:30 + | +LL | fn non_const_function() {} + | ^^^^^^^^^^^^ + | +note: this function is not `const`, so it cannot have `~const` trait bounds + --> $DIR/tilde-const-invalid-places.rs:43:8 + | +LL | fn non_const_function() {} + | ^^^^^^^^^^^^^^^^^^ + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:44:23 + | +LL | const CONSTANT: () = (); + | ^^^^^^^^^^^^ + | + = note: this item cannot have `~const` trait bounds + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:49:15 + | +LL | trait Child0: ~const Trait {} + | ^^^^^^^^^^^^ + | +note: this trait is not a `#[const_trait]`, so it cannot have `~const` trait bounds + --> $DIR/tilde-const-invalid-places.rs:49:1 + | +LL | trait Child0: ~const Trait {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:50:26 + | +LL | trait Child1 where Self: ~const Trait {} + | ^^^^^^^^^^^^ + | +note: this trait is not a `#[const_trait]`, so it cannot have `~const` trait bounds + --> $DIR/tilde-const-invalid-places.rs:50:1 + | +LL | trait Child1 where Self: ~const Trait {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:53:9 + | +LL | impl Trait for T {} + | ^^^^^^^^^^^^ + | +note: this impl is not `const`, so it cannot have `~const` trait bounds + --> $DIR/tilde-const-invalid-places.rs:53:1 + | +LL | impl Trait for T {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0658]: generic const items are experimental + --> $DIR/tilde-const-invalid-places.rs:19:15 + | +LL | const CONSTANT: () = (); + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #113521 for more information + = help: add `#![feature(generic_const_items)]` to the crate attributes to enable + +error[E0658]: generic const items are experimental + --> $DIR/tilde-const-invalid-places.rs:27:19 + | +LL | const CONSTANT: (); + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #113521 for more information + = help: add `#![feature(generic_const_items)]` to the crate attributes to enable + +error[E0658]: generic const items are experimental + --> $DIR/tilde-const-invalid-places.rs:34:19 + | +LL | const CONSTANT: () = (); + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #113521 for more information + = help: add `#![feature(generic_const_items)]` to the crate attributes to enable + +error[E0658]: generic const items are experimental + --> $DIR/tilde-const-invalid-places.rs:44:19 + | +LL | const CONSTANT: () = (); + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #113521 for more information + = help: add `#![feature(generic_const_items)]` to the crate attributes to enable + +error[E0658]: inherent associated types are unstable + --> $DIR/tilde-const-invalid-places.rs:41:5 + | +LL | type Type = (); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #8995 for more information + = help: add `#![feature(inherent_associated_types)]` to the crate attributes to enable + +error: aborting due to 26 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-maybe-trait.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-maybe-trait.rs new file mode 100644 index 000000000000..ed911d965d63 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-maybe-trait.rs @@ -0,0 +1,6 @@ +#![feature(const_trait_impl)] + +const fn tilde_question() {} +//~^ ERROR `~const` and `?` are mutually exclusive + +fn main() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-maybe-trait.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-maybe-trait.stderr new file mode 100644 index 000000000000..ce74ff8dde75 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-maybe-trait.stderr @@ -0,0 +1,8 @@ +error: `~const` and `?` are mutually exclusive + --> $DIR/tilde-const-maybe-trait.rs:3:28 + | +LL | const fn tilde_question() {} + | ^^^^^^^^^^^^^ + +error: aborting due to previous error + From ed8298b825b8c2c5b57471cdd13dec9f94e26c03 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sun, 12 Nov 2023 18:07:28 +1100 Subject: [PATCH 396/435] coverage: Avoid creating malformed macro name spans This method is trying to detect macro invocations, so that it can split a span into two parts just after the `!` of the invocation. Under some circumstances (probably involving nested macros), it gets confused and produces a span that is larger than the original span, and possibly extends outside its enclosing function and even into an adjacent file. In extreme cases, that can result in malformed coverage mappings that cause `llvm-cov` to fail. For now, we at least want to detect these egregious cases and avoid them, so that coverage reports can still be produced. --- compiler/rustc_mir_transform/src/coverage/spans.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs index 704eea413e11..b318134ae672 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans.rs @@ -381,6 +381,12 @@ impl<'a> CoverageSpansGenerator<'a> { let merged_prefix_len = self.curr_original_span.lo() - curr.span.lo(); let after_macro_bang = merged_prefix_len + BytePos(visible_macro.as_str().len() as u32 + 1); + if self.curr().span.lo() + after_macro_bang > self.curr().span.hi() { + // Something is wrong with the macro name span; + // return now to avoid emitting malformed mappings. + // FIXME(#117788): Track down why this happens. + return; + } let mut macro_name_cov = curr.clone(); self.curr_mut().span = curr.span.with_lo(curr.span.lo() + after_macro_bang); macro_name_cov.span = From 8bcd221b4c354a51771dd5bde4d58738908922e8 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sun, 12 Nov 2023 11:59:01 +0100 Subject: [PATCH 397/435] Small improvements in object lifetime default code I found those while trying to understand how the code works. --- compiler/rustc_hir_analysis/src/astconv/mod.rs | 3 +-- .../rustc_hir_analysis/src/collect/resolve_bound_vars.rs | 2 +- compiler/rustc_trait_selection/src/traits/wf.rs | 9 ++------- 3 files changed, 4 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 2fcb45ef8aa1..f392028528bd 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -2845,6 +2845,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { /// provided, if they provided one, and otherwise search the supertypes of trait bounds /// for region bounds. It may be that we can derive no bound at all, in which case /// we return `None`. + #[instrument(level = "debug", skip(self, span), ret)] fn compute_object_lifetime_bound( &self, span: Span, @@ -2853,8 +2854,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { { let tcx = self.tcx(); - debug!("compute_opt_region_bound(existential_predicates={:?})", existential_predicates); - // No explicit region bound specified. Therefore, examine trait // bounds and see if we can derive region bounds from those. let derived_region_bounds = object_region_bounds(tcx, existential_predicates); diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 6424d1c79311..d51e9eb5983a 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -1848,8 +1848,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { } } + #[instrument(level = "debug", skip(self))] fn resolve_object_lifetime_default(&mut self, lifetime_ref: &'tcx hir::Lifetime) { - debug!("resolve_object_lifetime_default(lifetime_ref={:?})", lifetime_ref); let mut late_depth = 0; let mut scope = self.scope; let lifetime = loop { diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index fe5b625e4836..9751cb60ed89 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -913,20 +913,15 @@ pub fn object_region_bounds<'tcx>( tcx: TyCtxt<'tcx>, existential_predicates: &'tcx ty::List>, ) -> Vec> { - // Since we don't actually *know* the self type for an object, - // this "open(err)" serves as a kind of dummy standin -- basically - // a placeholder type. - let open_ty = Ty::new_fresh(tcx, 0); - let predicates = existential_predicates.iter().filter_map(|predicate| { if let ty::ExistentialPredicate::Projection(_) = predicate.skip_binder() { None } else { - Some(predicate.with_self_ty(tcx, open_ty)) + Some(predicate.with_self_ty(tcx, tcx.types.trait_object_dummy_self)) } }); - required_region_bounds(tcx, open_ty, predicates) + required_region_bounds(tcx, tcx.types.trait_object_dummy_self, predicates) } /// Given a set of predicates that apply to an object type, returns From 5b5006916bfdebf2a96f0b4491828390e8ed68b5 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 12 Nov 2023 12:41:22 +0100 Subject: [PATCH 398/435] target_feature: make it more clear what that 'Option' means --- compiler/rustc_codegen_gcc/src/lib.rs | 2 +- compiler/rustc_codegen_llvm/src/llvm_util.rs | 5 +- .../rustc_codegen_ssa/src/target_features.rs | 512 +++++++++--------- 3 files changed, 274 insertions(+), 245 deletions(-) diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs index a530fc994a22..40373ee1d271 100644 --- a/compiler/rustc_codegen_gcc/src/lib.rs +++ b/compiler/rustc_codegen_gcc/src/lib.rs @@ -384,7 +384,7 @@ pub fn target_features(sess: &Session, allow_unstable: bool, target_info: &Locke .iter() .filter_map( |&(feature, gate)| { - if sess.is_nightly_build() || allow_unstable || gate.is_none() { Some(feature) } else { None } + if sess.is_nightly_build() || allow_unstable || gate.is_stable() { Some(feature) } else { None } }, ) .filter(|_feature| { diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index cc4ccaf19c28..c86bf81fc131 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -293,7 +293,7 @@ pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec { supported_target_features(sess) .iter() .filter_map(|&(feature, gate)| { - if sess.is_nightly_build() || allow_unstable || gate.is_none() { + if sess.is_nightly_build() || allow_unstable || gate.is_stable() { Some(feature) } else { None @@ -554,7 +554,8 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec Option { + match self { + Stable => None, + Unstable(s) => Some(s), + } + } + + pub fn is_stable(self) -> bool { + matches!(self, Stable) + } +} + +// Here we list target features that rustc "understands": they can be used in `#[target_feature]` +// and `#[cfg(target_feature)]`. They also do not trigger any warnings when used with +// `-Ctarget-feature`. +// // When adding features to the below lists // check whether they're named already elsewhere in rust // e.g. in stdarch and whether the given name matches LLVM's @@ -30,139 +59,138 @@ pub const RUSTC_SPECIFIC_FEATURES: &[&str] = &["crt-static"]; // example of this going wrong), but features enabling new SIMD registers are also a concern (see // https://github.com/rust-lang/rust/issues/116558 for an example of this going wrong). // -// Stabilizing a target feature (setting the 2nd component of the pair to `None`) requires t-lang -// approval. +// Stabilizing a target feature requires t-lang approval. -const ARM_ALLOWED_FEATURES: &[(&str, Option)] = &[ +const ARM_ALLOWED_FEATURES: &[(&str, Stability)] = &[ // tidy-alphabetical-start - ("aclass", Some(sym::arm_target_feature)), - ("aes", Some(sym::arm_target_feature)), - ("crc", Some(sym::arm_target_feature)), - ("d32", Some(sym::arm_target_feature)), - ("dotprod", Some(sym::arm_target_feature)), - ("dsp", Some(sym::arm_target_feature)), - ("fp-armv8", Some(sym::arm_target_feature)), - ("i8mm", Some(sym::arm_target_feature)), - ("mclass", Some(sym::arm_target_feature)), - ("neon", Some(sym::arm_target_feature)), - ("rclass", Some(sym::arm_target_feature)), - ("sha2", Some(sym::arm_target_feature)), + ("aclass", Unstable(sym::arm_target_feature)), + ("aes", Unstable(sym::arm_target_feature)), + ("crc", Unstable(sym::arm_target_feature)), + ("d32", Unstable(sym::arm_target_feature)), + ("dotprod", Unstable(sym::arm_target_feature)), + ("dsp", Unstable(sym::arm_target_feature)), + ("fp-armv8", Unstable(sym::arm_target_feature)), + ("i8mm", Unstable(sym::arm_target_feature)), + ("mclass", Unstable(sym::arm_target_feature)), + ("neon", Unstable(sym::arm_target_feature)), + ("rclass", Unstable(sym::arm_target_feature)), + ("sha2", Unstable(sym::arm_target_feature)), // This is needed for inline assembly, but shouldn't be stabilized as-is // since it should be enabled per-function using #[instruction_set], not // #[target_feature]. - ("thumb-mode", Some(sym::arm_target_feature)), - ("thumb2", Some(sym::arm_target_feature)), - ("trustzone", Some(sym::arm_target_feature)), - ("v5te", Some(sym::arm_target_feature)), - ("v6", Some(sym::arm_target_feature)), - ("v6k", Some(sym::arm_target_feature)), - ("v6t2", Some(sym::arm_target_feature)), - ("v7", Some(sym::arm_target_feature)), - ("v8", Some(sym::arm_target_feature)), - ("vfp2", Some(sym::arm_target_feature)), - ("vfp3", Some(sym::arm_target_feature)), - ("vfp4", Some(sym::arm_target_feature)), - ("virtualization", Some(sym::arm_target_feature)), + ("thumb-mode", Unstable(sym::arm_target_feature)), + ("thumb2", Unstable(sym::arm_target_feature)), + ("trustzone", Unstable(sym::arm_target_feature)), + ("v5te", Unstable(sym::arm_target_feature)), + ("v6", Unstable(sym::arm_target_feature)), + ("v6k", Unstable(sym::arm_target_feature)), + ("v6t2", Unstable(sym::arm_target_feature)), + ("v7", Unstable(sym::arm_target_feature)), + ("v8", Unstable(sym::arm_target_feature)), + ("vfp2", Unstable(sym::arm_target_feature)), + ("vfp3", Unstable(sym::arm_target_feature)), + ("vfp4", Unstable(sym::arm_target_feature)), + ("virtualization", Unstable(sym::arm_target_feature)), // tidy-alphabetical-end ]; -const AARCH64_ALLOWED_FEATURES: &[(&str, Option)] = &[ +const AARCH64_ALLOWED_FEATURES: &[(&str, Stability)] = &[ // tidy-alphabetical-start // FEAT_AES - ("aes", None), + ("aes", Stable), // FEAT_BF16 - ("bf16", None), + ("bf16", Stable), // FEAT_BTI - ("bti", None), + ("bti", Stable), // FEAT_CRC - ("crc", None), + ("crc", Stable), // FEAT_DIT - ("dit", None), + ("dit", Stable), // FEAT_DotProd - ("dotprod", None), + ("dotprod", Stable), // FEAT_DPB - ("dpb", None), + ("dpb", Stable), // FEAT_DPB2 - ("dpb2", None), + ("dpb2", Stable), // FEAT_F32MM - ("f32mm", None), + ("f32mm", Stable), // FEAT_F64MM - ("f64mm", None), + ("f64mm", Stable), // FEAT_FCMA - ("fcma", None), + ("fcma", Stable), // FEAT_FHM - ("fhm", None), + ("fhm", Stable), // FEAT_FLAGM - ("flagm", None), + ("flagm", Stable), // FEAT_FP16 - ("fp16", None), + ("fp16", Stable), // FEAT_FRINTTS - ("frintts", None), + ("frintts", Stable), // FEAT_I8MM - ("i8mm", None), + ("i8mm", Stable), // FEAT_JSCVT - ("jsconv", None), + ("jsconv", Stable), // FEAT_LOR - ("lor", None), + ("lor", Stable), // FEAT_LSE - ("lse", None), + ("lse", Stable), // FEAT_MTE - ("mte", None), + ("mte", Stable), // FEAT_AdvSimd & FEAT_FP - ("neon", None), + ("neon", Stable), // FEAT_PAUTH (address authentication) - ("paca", None), + ("paca", Stable), // FEAT_PAUTH (generic authentication) - ("pacg", None), + ("pacg", Stable), // FEAT_PAN - ("pan", None), + ("pan", Stable), // FEAT_PMUv3 - ("pmuv3", None), + ("pmuv3", Stable), // FEAT_RAND - ("rand", None), + ("rand", Stable), // FEAT_RAS - ("ras", None), + ("ras", Stable), // FEAT_RCPC - ("rcpc", None), + ("rcpc", Stable), // FEAT_RCPC2 - ("rcpc2", None), + ("rcpc2", Stable), // FEAT_RDM - ("rdm", None), + ("rdm", Stable), // FEAT_SB - ("sb", None), + ("sb", Stable), // FEAT_SHA1 & FEAT_SHA256 - ("sha2", None), + ("sha2", Stable), // FEAT_SHA512 & FEAT_SHA3 - ("sha3", None), + ("sha3", Stable), // FEAT_SM3 & FEAT_SM4 - ("sm4", None), + ("sm4", Stable), // FEAT_SPE - ("spe", None), + ("spe", Stable), // FEAT_SSBS - ("ssbs", None), + ("ssbs", Stable), // FEAT_SVE - ("sve", None), + ("sve", Stable), // FEAT_SVE2 - ("sve2", None), + ("sve2", Stable), // FEAT_SVE2_AES - ("sve2-aes", None), + ("sve2-aes", Stable), // FEAT_SVE2_BitPerm - ("sve2-bitperm", None), + ("sve2-bitperm", Stable), // FEAT_SVE2_SHA3 - ("sve2-sha3", None), + ("sve2-sha3", Stable), // FEAT_SVE2_SM4 - ("sve2-sm4", None), + ("sve2-sm4", Stable), // FEAT_TME - ("tme", None), - ("v8.1a", Some(sym::aarch64_ver_target_feature)), - ("v8.2a", Some(sym::aarch64_ver_target_feature)), - ("v8.3a", Some(sym::aarch64_ver_target_feature)), - ("v8.4a", Some(sym::aarch64_ver_target_feature)), - ("v8.5a", Some(sym::aarch64_ver_target_feature)), - ("v8.6a", Some(sym::aarch64_ver_target_feature)), - ("v8.7a", Some(sym::aarch64_ver_target_feature)), + ("tme", Stable), + ("v8.1a", Unstable(sym::aarch64_ver_target_feature)), + ("v8.2a", Unstable(sym::aarch64_ver_target_feature)), + ("v8.3a", Unstable(sym::aarch64_ver_target_feature)), + ("v8.4a", Unstable(sym::aarch64_ver_target_feature)), + ("v8.5a", Unstable(sym::aarch64_ver_target_feature)), + ("v8.6a", Unstable(sym::aarch64_ver_target_feature)), + ("v8.7a", Unstable(sym::aarch64_ver_target_feature)), // FEAT_VHE - ("vh", None), + ("vh", Stable), // tidy-alphabetical-end ]; @@ -170,197 +198,197 @@ const AARCH64_TIED_FEATURES: &[&[&str]] = &[ &["paca", "pacg"], // Together these represent `pauth` in LLVM ]; -const X86_ALLOWED_FEATURES: &[(&str, Option)] = &[ +const X86_ALLOWED_FEATURES: &[(&str, Stability)] = &[ // tidy-alphabetical-start - ("adx", None), - ("aes", None), - ("avx", None), - ("avx2", None), - ("avx512bf16", Some(sym::avx512_target_feature)), - ("avx512bitalg", Some(sym::avx512_target_feature)), - ("avx512bw", Some(sym::avx512_target_feature)), - ("avx512cd", Some(sym::avx512_target_feature)), - ("avx512dq", Some(sym::avx512_target_feature)), - ("avx512er", Some(sym::avx512_target_feature)), - ("avx512f", Some(sym::avx512_target_feature)), - ("avx512ifma", Some(sym::avx512_target_feature)), - ("avx512pf", Some(sym::avx512_target_feature)), - ("avx512vbmi", Some(sym::avx512_target_feature)), - ("avx512vbmi2", Some(sym::avx512_target_feature)), - ("avx512vl", Some(sym::avx512_target_feature)), - ("avx512vnni", Some(sym::avx512_target_feature)), - ("avx512vp2intersect", Some(sym::avx512_target_feature)), - ("avx512vpopcntdq", Some(sym::avx512_target_feature)), - ("bmi1", None), - ("bmi2", None), - ("cmpxchg16b", None), - ("ermsb", Some(sym::ermsb_target_feature)), - ("f16c", None), - ("fma", None), - ("fxsr", None), - ("gfni", Some(sym::avx512_target_feature)), - ("lzcnt", None), - ("movbe", None), - ("pclmulqdq", None), - ("popcnt", None), - ("rdrand", None), - ("rdseed", None), - ("rtm", Some(sym::rtm_target_feature)), - ("sha", None), - ("sse", None), - ("sse2", None), - ("sse3", None), - ("sse4.1", None), - ("sse4.2", None), - ("sse4a", Some(sym::sse4a_target_feature)), - ("ssse3", None), - ("tbm", Some(sym::tbm_target_feature)), - ("vaes", Some(sym::avx512_target_feature)), - ("vpclmulqdq", Some(sym::avx512_target_feature)), - ("xsave", None), - ("xsavec", None), - ("xsaveopt", None), - ("xsaves", None), + ("adx", Stable), + ("aes", Stable), + ("avx", Stable), + ("avx2", Stable), + ("avx512bf16", Unstable(sym::avx512_target_feature)), + ("avx512bitalg", Unstable(sym::avx512_target_feature)), + ("avx512bw", Unstable(sym::avx512_target_feature)), + ("avx512cd", Unstable(sym::avx512_target_feature)), + ("avx512dq", Unstable(sym::avx512_target_feature)), + ("avx512er", Unstable(sym::avx512_target_feature)), + ("avx512f", Unstable(sym::avx512_target_feature)), + ("avx512ifma", Unstable(sym::avx512_target_feature)), + ("avx512pf", Unstable(sym::avx512_target_feature)), + ("avx512vbmi", Unstable(sym::avx512_target_feature)), + ("avx512vbmi2", Unstable(sym::avx512_target_feature)), + ("avx512vl", Unstable(sym::avx512_target_feature)), + ("avx512vnni", Unstable(sym::avx512_target_feature)), + ("avx512vp2intersect", Unstable(sym::avx512_target_feature)), + ("avx512vpopcntdq", Unstable(sym::avx512_target_feature)), + ("bmi1", Stable), + ("bmi2", Stable), + ("cmpxchg16b", Stable), + ("ermsb", Unstable(sym::ermsb_target_feature)), + ("f16c", Stable), + ("fma", Stable), + ("fxsr", Stable), + ("gfni", Unstable(sym::avx512_target_feature)), + ("lzcnt", Stable), + ("movbe", Stable), + ("pclmulqdq", Stable), + ("popcnt", Stable), + ("rdrand", Stable), + ("rdseed", Stable), + ("rtm", Unstable(sym::rtm_target_feature)), + ("sha", Stable), + ("sse", Stable), + ("sse2", Stable), + ("sse3", Stable), + ("sse4.1", Stable), + ("sse4.2", Stable), + ("sse4a", Unstable(sym::sse4a_target_feature)), + ("ssse3", Stable), + ("tbm", Unstable(sym::tbm_target_feature)), + ("vaes", Unstable(sym::avx512_target_feature)), + ("vpclmulqdq", Unstable(sym::avx512_target_feature)), + ("xsave", Stable), + ("xsavec", Stable), + ("xsaveopt", Stable), + ("xsaves", Stable), // tidy-alphabetical-end ]; -const HEXAGON_ALLOWED_FEATURES: &[(&str, Option)] = &[ +const HEXAGON_ALLOWED_FEATURES: &[(&str, Stability)] = &[ // tidy-alphabetical-start - ("hvx", Some(sym::hexagon_target_feature)), - ("hvx-length128b", Some(sym::hexagon_target_feature)), + ("hvx", Unstable(sym::hexagon_target_feature)), + ("hvx-length128b", Unstable(sym::hexagon_target_feature)), // tidy-alphabetical-end ]; -const POWERPC_ALLOWED_FEATURES: &[(&str, Option)] = &[ +const POWERPC_ALLOWED_FEATURES: &[(&str, Stability)] = &[ // tidy-alphabetical-start - ("altivec", Some(sym::powerpc_target_feature)), - ("power10-vector", Some(sym::powerpc_target_feature)), - ("power8-altivec", Some(sym::powerpc_target_feature)), - ("power8-vector", Some(sym::powerpc_target_feature)), - ("power9-altivec", Some(sym::powerpc_target_feature)), - ("power9-vector", Some(sym::powerpc_target_feature)), - ("vsx", Some(sym::powerpc_target_feature)), + ("altivec", Unstable(sym::powerpc_target_feature)), + ("power10-vector", Unstable(sym::powerpc_target_feature)), + ("power8-altivec", Unstable(sym::powerpc_target_feature)), + ("power8-vector", Unstable(sym::powerpc_target_feature)), + ("power9-altivec", Unstable(sym::powerpc_target_feature)), + ("power9-vector", Unstable(sym::powerpc_target_feature)), + ("vsx", Unstable(sym::powerpc_target_feature)), // tidy-alphabetical-end ]; -const MIPS_ALLOWED_FEATURES: &[(&str, Option)] = &[ +const MIPS_ALLOWED_FEATURES: &[(&str, Stability)] = &[ // tidy-alphabetical-start - ("fp64", Some(sym::mips_target_feature)), - ("msa", Some(sym::mips_target_feature)), - ("virt", Some(sym::mips_target_feature)), + ("fp64", Unstable(sym::mips_target_feature)), + ("msa", Unstable(sym::mips_target_feature)), + ("virt", Unstable(sym::mips_target_feature)), // tidy-alphabetical-end ]; -const RISCV_ALLOWED_FEATURES: &[(&str, Option)] = &[ +const RISCV_ALLOWED_FEATURES: &[(&str, Stability)] = &[ // tidy-alphabetical-start - ("a", None), - ("c", None), - ("d", Some(sym::riscv_target_feature)), - ("e", Some(sym::riscv_target_feature)), - ("f", Some(sym::riscv_target_feature)), - ("m", None), - ("relax", Some(sym::riscv_target_feature)), - ("unaligned-scalar-mem", Some(sym::riscv_target_feature)), - ("v", Some(sym::riscv_target_feature)), - ("zba", None), - ("zbb", None), - ("zbc", None), - ("zbkb", None), - ("zbkc", None), - ("zbkx", None), - ("zbs", None), - ("zdinx", Some(sym::riscv_target_feature)), - ("zfh", Some(sym::riscv_target_feature)), - ("zfhmin", Some(sym::riscv_target_feature)), - ("zfinx", Some(sym::riscv_target_feature)), - ("zhinx", Some(sym::riscv_target_feature)), - ("zhinxmin", Some(sym::riscv_target_feature)), - ("zk", None), - ("zkn", None), - ("zknd", None), - ("zkne", None), - ("zknh", None), - ("zkr", None), - ("zks", None), - ("zksed", None), - ("zksh", None), - ("zkt", None), + ("a", Stable), + ("c", Stable), + ("d", Unstable(sym::riscv_target_feature)), + ("e", Unstable(sym::riscv_target_feature)), + ("f", Unstable(sym::riscv_target_feature)), + ("m", Stable), + ("relax", Unstable(sym::riscv_target_feature)), + ("unaligned-scalar-mem", Unstable(sym::riscv_target_feature)), + ("v", Unstable(sym::riscv_target_feature)), + ("zba", Stable), + ("zbb", Stable), + ("zbc", Stable), + ("zbkb", Stable), + ("zbkc", Stable), + ("zbkx", Stable), + ("zbs", Stable), + ("zdinx", Unstable(sym::riscv_target_feature)), + ("zfh", Unstable(sym::riscv_target_feature)), + ("zfhmin", Unstable(sym::riscv_target_feature)), + ("zfinx", Unstable(sym::riscv_target_feature)), + ("zhinx", Unstable(sym::riscv_target_feature)), + ("zhinxmin", Unstable(sym::riscv_target_feature)), + ("zk", Stable), + ("zkn", Stable), + ("zknd", Stable), + ("zkne", Stable), + ("zknh", Stable), + ("zkr", Stable), + ("zks", Stable), + ("zksed", Stable), + ("zksh", Stable), + ("zkt", Stable), // tidy-alphabetical-end ]; -const WASM_ALLOWED_FEATURES: &[(&str, Option)] = &[ +const WASM_ALLOWED_FEATURES: &[(&str, Stability)] = &[ // tidy-alphabetical-start - ("atomics", Some(sym::wasm_target_feature)), - ("bulk-memory", Some(sym::wasm_target_feature)), - ("exception-handling", Some(sym::wasm_target_feature)), - ("multivalue", Some(sym::wasm_target_feature)), - ("mutable-globals", Some(sym::wasm_target_feature)), - ("nontrapping-fptoint", Some(sym::wasm_target_feature)), - ("reference-types", Some(sym::wasm_target_feature)), - ("relaxed-simd", Some(sym::wasm_target_feature)), - ("sign-ext", Some(sym::wasm_target_feature)), - ("simd128", None), + ("atomics", Unstable(sym::wasm_target_feature)), + ("bulk-memory", Unstable(sym::wasm_target_feature)), + ("exception-handling", Unstable(sym::wasm_target_feature)), + ("multivalue", Unstable(sym::wasm_target_feature)), + ("mutable-globals", Unstable(sym::wasm_target_feature)), + ("nontrapping-fptoint", Unstable(sym::wasm_target_feature)), + ("reference-types", Unstable(sym::wasm_target_feature)), + ("relaxed-simd", Unstable(sym::wasm_target_feature)), + ("sign-ext", Unstable(sym::wasm_target_feature)), + ("simd128", Stable), // tidy-alphabetical-end ]; -const BPF_ALLOWED_FEATURES: &[(&str, Option)] = &[("alu32", Some(sym::bpf_target_feature))]; +const BPF_ALLOWED_FEATURES: &[(&str, Stability)] = &[("alu32", Unstable(sym::bpf_target_feature))]; -const CSKY_ALLOWED_FEATURES: &[(&str, Option)] = &[ +const CSKY_ALLOWED_FEATURES: &[(&str, Stability)] = &[ // tidy-alphabetical-start - ("10e60", Some(sym::csky_target_feature)), - ("2e3", Some(sym::csky_target_feature)), - ("3e3r1", Some(sym::csky_target_feature)), - ("3e3r2", Some(sym::csky_target_feature)), - ("3e3r3", Some(sym::csky_target_feature)), - ("3e7", Some(sym::csky_target_feature)), - ("7e10", Some(sym::csky_target_feature)), - ("cache", Some(sym::csky_target_feature)), - ("doloop", Some(sym::csky_target_feature)), - ("dsp1e2", Some(sym::csky_target_feature)), - ("dspe60", Some(sym::csky_target_feature)), - ("e1", Some(sym::csky_target_feature)), - ("e2", Some(sym::csky_target_feature)), - ("edsp", Some(sym::csky_target_feature)), - ("elrw", Some(sym::csky_target_feature)), - ("float1e2", Some(sym::csky_target_feature)), - ("float1e3", Some(sym::csky_target_feature)), - ("float3e4", Some(sym::csky_target_feature)), - ("float7e60", Some(sym::csky_target_feature)), - ("floate1", Some(sym::csky_target_feature)), - ("hard-tp", Some(sym::csky_target_feature)), - ("high-registers", Some(sym::csky_target_feature)), - ("hwdiv", Some(sym::csky_target_feature)), - ("mp", Some(sym::csky_target_feature)), - ("mp1e2", Some(sym::csky_target_feature)), - ("nvic", Some(sym::csky_target_feature)), - ("trust", Some(sym::csky_target_feature)), - ("vdsp2e60f", Some(sym::csky_target_feature)), - ("vdspv1", Some(sym::csky_target_feature)), - ("vdspv2", Some(sym::csky_target_feature)), + ("10e60", Unstable(sym::csky_target_feature)), + ("2e3", Unstable(sym::csky_target_feature)), + ("3e3r1", Unstable(sym::csky_target_feature)), + ("3e3r2", Unstable(sym::csky_target_feature)), + ("3e3r3", Unstable(sym::csky_target_feature)), + ("3e7", Unstable(sym::csky_target_feature)), + ("7e10", Unstable(sym::csky_target_feature)), + ("cache", Unstable(sym::csky_target_feature)), + ("doloop", Unstable(sym::csky_target_feature)), + ("dsp1e2", Unstable(sym::csky_target_feature)), + ("dspe60", Unstable(sym::csky_target_feature)), + ("e1", Unstable(sym::csky_target_feature)), + ("e2", Unstable(sym::csky_target_feature)), + ("edsp", Unstable(sym::csky_target_feature)), + ("elrw", Unstable(sym::csky_target_feature)), + ("float1e2", Unstable(sym::csky_target_feature)), + ("float1e3", Unstable(sym::csky_target_feature)), + ("float3e4", Unstable(sym::csky_target_feature)), + ("float7e60", Unstable(sym::csky_target_feature)), + ("floate1", Unstable(sym::csky_target_feature)), + ("hard-tp", Unstable(sym::csky_target_feature)), + ("high-registers", Unstable(sym::csky_target_feature)), + ("hwdiv", Unstable(sym::csky_target_feature)), + ("mp", Unstable(sym::csky_target_feature)), + ("mp1e2", Unstable(sym::csky_target_feature)), + ("nvic", Unstable(sym::csky_target_feature)), + ("trust", Unstable(sym::csky_target_feature)), + ("vdsp2e60f", Unstable(sym::csky_target_feature)), + ("vdspv1", Unstable(sym::csky_target_feature)), + ("vdspv2", Unstable(sym::csky_target_feature)), // tidy-alphabetical-end //fpu // tidy-alphabetical-start - ("fdivdu", Some(sym::csky_target_feature)), - ("fpuv2_df", Some(sym::csky_target_feature)), - ("fpuv2_sf", Some(sym::csky_target_feature)), - ("fpuv3_df", Some(sym::csky_target_feature)), - ("fpuv3_hf", Some(sym::csky_target_feature)), - ("fpuv3_hi", Some(sym::csky_target_feature)), - ("fpuv3_sf", Some(sym::csky_target_feature)), - ("hard-float", Some(sym::csky_target_feature)), - ("hard-float-abi", Some(sym::csky_target_feature)), + ("fdivdu", Unstable(sym::csky_target_feature)), + ("fpuv2_df", Unstable(sym::csky_target_feature)), + ("fpuv2_sf", Unstable(sym::csky_target_feature)), + ("fpuv3_df", Unstable(sym::csky_target_feature)), + ("fpuv3_hf", Unstable(sym::csky_target_feature)), + ("fpuv3_hi", Unstable(sym::csky_target_feature)), + ("fpuv3_sf", Unstable(sym::csky_target_feature)), + ("hard-float", Unstable(sym::csky_target_feature)), + ("hard-float-abi", Unstable(sym::csky_target_feature)), // tidy-alphabetical-end ]; -const LOONGARCH_ALLOWED_FEATURES: &[(&str, Option)] = &[ +const LOONGARCH_ALLOWED_FEATURES: &[(&str, Stability)] = &[ // tidy-alphabetical-start - ("d", Some(sym::loongarch_target_feature)), - ("f", Some(sym::loongarch_target_feature)), - ("lasx", Some(sym::loongarch_target_feature)), - ("lbt", Some(sym::loongarch_target_feature)), - ("lsx", Some(sym::loongarch_target_feature)), - ("lvz", Some(sym::loongarch_target_feature)), - ("ual", Some(sym::loongarch_target_feature)), + ("d", Unstable(sym::loongarch_target_feature)), + ("f", Unstable(sym::loongarch_target_feature)), + ("lasx", Unstable(sym::loongarch_target_feature)), + ("lbt", Unstable(sym::loongarch_target_feature)), + ("lsx", Unstable(sym::loongarch_target_feature)), + ("lvz", Unstable(sym::loongarch_target_feature)), + ("ual", Unstable(sym::loongarch_target_feature)), // tidy-alphabetical-end ]; @@ -368,7 +396,7 @@ const LOONGARCH_ALLOWED_FEATURES: &[(&str, Option)] = &[ /// primitives may be documented. /// /// IMPORTANT: If you're adding another feature list above, make sure to add it to this iterator! -pub fn all_known_features() -> impl Iterator)> { +pub fn all_known_features() -> impl Iterator { std::iter::empty() .chain(ARM_ALLOWED_FEATURES.iter()) .chain(AARCH64_ALLOWED_FEATURES.iter()) @@ -384,7 +412,7 @@ pub fn all_known_features() -> impl Iterator &'static [(&'static str, Option)] { +pub fn supported_target_features(sess: &Session) -> &'static [(&'static str, Stability)] { match &*sess.target.arch { "arm" => ARM_ALLOWED_FEATURES, "aarch64" => AARCH64_ALLOWED_FEATURES, @@ -529,11 +557,11 @@ pub(crate) fn provide(providers: &mut Providers) { if tcx.sess.opts.actually_rustdoc { // rustdoc needs to be able to document functions that use all the features, so // whitelist them all - all_known_features().map(|(a, b)| (a.to_string(), b)).collect() + all_known_features().map(|(a, b)| (a.to_string(), b.as_feature_name())).collect() } else { supported_target_features(tcx.sess) .iter() - .map(|&(a, b)| (a.to_string(), b)) + .map(|&(a, b)| (a.to_string(), b.as_feature_name())) .collect() } }, From ff7c684ed05e90c9332a64da2f9a520ce44daf73 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sun, 15 Oct 2023 22:19:32 -0400 Subject: [PATCH 399/435] Add initial 1.74 release notes --- RELEASES.md | 115 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) diff --git a/RELEASES.md b/RELEASES.md index 1cc110e6607f..3b764fd773b6 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,118 @@ +Version 1.74.0 (2023-11-16) +========================== + + + +Language +-------- + +- [Codify that `std::mem::Discriminant` does not depend on any lifetimes in T](https://github.com/rust-lang/rust/pull/104299/) +- [Replace `private_in_public` lint with `private_interfaces` and `private_bounds` per RFC 2145](https://github.com/rust-lang/rust/pull/113126/) + Read more in [RFC 2145](https://rust-lang.github.io/rfcs/2145-type-privacy.html). +- [Allow explicit `#[repr(Rust)]`](https://github.com/rust-lang/rust/pull/114201/) +- [closure field capturing: don't depend on alignment of packed fields](https://github.com/rust-lang/rust/pull/115315/) +- [Enable MIR-based drop-tracking for `async` blocks](https://github.com/rust-lang/rust/pull/107421/) + + + +Compiler +-------- + +- [stabilize combining +bundle and +whole-archive link modifiers](https://github.com/rust-lang/rust/pull/113301/) +- [Stabilize `PATH` option for `--print KIND=PATH`](https://github.com/rust-lang/rust/pull/114183/) +- [Enable ASAN/LSAN/TSAN for `*-apple-ios-macabi`](https://github.com/rust-lang/rust/pull/115644/) +- [Promote loongarch64-unknown-none* to Tier 2](https://github.com/rust-lang/rust/pull/115368/) +- [Add `i686-pc-windows-gnullvm` as a tier 3 target](https://github.com/rust-lang/rust/pull/115687/) + + + +Libraries +--------- + +- [Implement `From` for ChildStdin/out/err](https://github.com/rust-lang/rust/pull/98704/) +- [Implement `From<{&,&mut} [T; N]>` for `Vec` where `T: Clone`](https://github.com/rust-lang/rust/pull/111278/) +- [impl Step for IP addresses](https://github.com/rust-lang/rust/pull/113748/) +- [Implement `From<[T; N]>` for `Rc<[T]>` and `Arc<[T]>`](https://github.com/rust-lang/rust/pull/114041/) +- [`impl TryFrom for u16`](https://github.com/rust-lang/rust/pull/114065/) +- [Stabilize `io_error_other` feature](https://github.com/rust-lang/rust/pull/115453/) +- [Stabilize the `Saturating` type](https://github.com/rust-lang/rust/pull/115477/) +- [Stabilize const_transmute_copy](https://github.com/rust-lang/rust/pull/115520/) + + + +Stabilized APIs +--------------- + +- [`core::num::Saturating`](https://doc.rust-lang.org/stable/std/num/struct.Saturating.html) +- [`impl From for std::process::Stdio`](https://doc.rust-lang.org/stable/std/process/struct.Stdio.html#impl-From%3CStdout%3E-for-Stdio) +- [`impl From for std::process::Stdio`](https://doc.rust-lang.org/stable/std/process/struct.Stdio.html#impl-From%3CStderr%3E-for-Stdio) +- [`impl From for std::process::Child{Stdin, Stdout, Stderr}`](https://doc.rust-lang.org/stable/std/process/struct.Stdio.html#impl-From%3CStderr%3E-for-Stdio) +- [`impl From for std::process::Child{Stdin, Stdout, Stderr}`](https://doc.rust-lang.org/stable/std/process/struct.Stdio.html#impl-From%3CStderr%3E-for-Stdio) +- [`std::ffi::OsString::from_encoded_bytes_unchecked`](https://doc.rust-lang.org/stable/std/ffi/struct.OsString.html#method.from_encoded_bytes_unchecked) +- [`std::ffi::OsString::into_encoded_bytes`](https://doc.rust-lang.org/stable/std/ffi/struct.OsString.html#method.into_encoded_bytes) +- [`std::ffi::OsStr::from_encoded_bytes_unchecked`](https://doc.rust-lang.org/stable/std/ffi/struct.OsStr.html#method.from_encoded_bytes_unchecked) +- [`std::ffi::OsStr::as_encoded_bytes`](https://doc.rust-lang.org/stable/std/ffi/struct.OsStr.html#method.as_encoded_bytes) +- [`std::io::Error::other`](https://doc.rust-lang.org/stable/std/io/struct.Error.html#method.other) +- [`impl TryFrom for u16`](https://doc.rust-lang.org/stable/std/primitive.u16.html#impl-TryFrom%3Cchar%3E-for-u16) +- [`impl From<&[T; N]> for Vec`](https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#impl-From%3C%26%5BT;+N%5D%3E-for-Vec%3CT,+Global%3E) +- [`impl From<&mut [T; N]> for Vec`](https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#impl-From%3C%26mut+%5BT;+N%5D%3E-for-Vec%3CT,+Global%3E) +- [`impl From<[T; N]> for Arc<[T]>`](https://doc.rust-lang.org/stable/std/sync/struct.Arc.html#impl-From%3C%5BT;+N%5D%3E-for-Arc%3C%5BT%5D,+Global%3E) +- [`impl From<[T; N]> for Rc<[T]>`](https://doc.rust-lang.org/stable/std/rc/struct.Rc.html#impl-From%3C%5BT;+N%5D%3E-for-Rc%3C%5BT%5D,+Global%3E) + +These APIs are now stable in const contexts: + +- [`core::mem::transmute_copy`](https://doc.rust-lang.org/beta/std/mem/fn.transmute_copy.html) +- [`str::is_ascii`](https://doc.rust-lang.org/beta/std/primitive.str.html#method.is_ascii) +- [`[u8]::is_ascii`](https://doc.rust-lang.org/beta/std/primitive.slice.html#method.is_ascii) + + + +Cargo +----- + +- [fix: Set MSRV for internal packages](https://github.com/rust-lang/cargo/pull/12381/) +- [config: merge lists in precedence order](https://github.com/rust-lang/cargo/pull/12515/) +- [fix(update): Clarify meaning of --aggressive as --recursive](https://github.com/rust-lang/cargo/pull/12544/) +- [fix(update): Make `-p` more convenient by being positional](https://github.com/rust-lang/cargo/pull/12545/) +- [feat(help): Add styling to help output ](https://github.com/rust-lang/cargo/pull/12578/) +- [feat(pkgid): Allow incomplete versions when unambigious](https://github.com/rust-lang/cargo/pull/12614/) +- [feat: stabilize credential-process and registry-auth](https://github.com/rust-lang/cargo/pull/12649/) +- [feat(cli): Add '-n' to dry-run](https://github.com/rust-lang/cargo/pull/12660/) +- [Add support for `target.'cfg(..)'.linker`](https://github.com/rust-lang/cargo/pull/12535/) +- [Stabilize `--keep-going`](https://github.com/rust-lang/cargo/pull/12568/) +- [feat: Stabilize lints](https://github.com/rust-lang/cargo/pull/12648/) + + + +Rustdoc +------- + +- [Add warning block support in rustdoc](https://github.com/rust-lang/rust/pull/106561/) +- [Accept additional user-defined syntax classes in fenced code blocks](https://github.com/rust-lang/rust/pull/110800/) +- [rustdoc-search: add support for type parameters](https://github.com/rust-lang/rust/pull/112725/) +- [rustdoc: show inner enum and struct in type definition for concrete type](https://github.com/rust-lang/rust/pull/114855/) + + + +Compatibility Notes +------------------- + +- [Raise minimum supported Apple OS versions](https://github.com/rust-lang/rust/pull/104385/) +- [make Cell::swap panic if the Cells partially overlap](https://github.com/rust-lang/rust/pull/114795/) +- [Reject invalid crate names in `--extern`](https://github.com/rust-lang/rust/pull/116001/) +- [Don't resolve generic impls that may be shadowed by dyn built-in impls](https://github.com/rust-lang/rust/pull/114941/) + + + +Internal Changes +---------------- + +These changes do not affect any public interfaces of Rust, but they represent +significant improvements to the performance or internals of rustc and related +tools. + +None this cycle. + Version 1.73.0 (2023-10-05) ========================== From 121d9f5b16cae379c6b57e27ff14f25e431c44fa Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 8 Nov 2023 05:13:35 +0000 Subject: [PATCH 400/435] make LayoutError::Cycle carry ErrorGuaranteed --- compiler/rustc_middle/src/ty/layout.rs | 10 +++++----- compiler/rustc_middle/src/values.rs | 5 ++--- src/librustdoc/html/templates/type_layout.html | 2 +- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 4223e503f5e2..aca6acd783b9 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -215,7 +215,7 @@ pub enum LayoutError<'tcx> { SizeOverflow(Ty<'tcx>), NormalizationFailure(Ty<'tcx>, NormalizationError<'tcx>), ReferencesError(ErrorGuaranteed), - Cycle, + Cycle(ErrorGuaranteed), } impl<'tcx> LayoutError<'tcx> { @@ -226,7 +226,7 @@ impl<'tcx> LayoutError<'tcx> { Unknown(_) => middle_unknown_layout, SizeOverflow(_) => middle_values_too_big, NormalizationFailure(_, _) => middle_cannot_be_normalized, - Cycle => middle_cycle, + Cycle(_) => middle_cycle, ReferencesError(_) => middle_layout_references_error, } } @@ -240,7 +240,7 @@ impl<'tcx> LayoutError<'tcx> { NormalizationFailure(ty, e) => { E::NormalizationFailure { ty, failure_ty: e.get_type_for_failure() } } - Cycle => E::Cycle, + Cycle(_) => E::Cycle, ReferencesError(_) => E::ReferencesError, } } @@ -261,7 +261,7 @@ impl<'tcx> fmt::Display for LayoutError<'tcx> { t, e.get_type_for_failure() ), - LayoutError::Cycle => write!(f, "a cycle occurred during layout computation"), + LayoutError::Cycle(_) => write!(f, "a cycle occurred during layout computation"), LayoutError::ReferencesError(_) => write!(f, "the type has an unknown layout"), } } @@ -333,7 +333,7 @@ impl<'tcx> SizeSkeleton<'tcx> { Err(err @ LayoutError::Unknown(_)) => err, // We can't extract SizeSkeleton info from other layout errors Err( - e @ LayoutError::Cycle + e @ LayoutError::Cycle(_) | e @ LayoutError::SizeOverflow(_) | e @ LayoutError::NormalizationFailure(..) | e @ LayoutError::ReferencesError(_), diff --git a/compiler/rustc_middle/src/values.rs b/compiler/rustc_middle/src/values.rs index f30993c9a694..2b4ae3736269 100644 --- a/compiler/rustc_middle/src/values.rs +++ b/compiler/rustc_middle/src/values.rs @@ -114,12 +114,11 @@ impl<'tcx> Value> for ty::EarlyBinder> } impl<'tcx, T> Value> for Result> { - fn from_cycle_error(_tcx: TyCtxt<'tcx>, _cycle: &[QueryInfo], _guar: ErrorGuaranteed) -> Self { + fn from_cycle_error(_tcx: TyCtxt<'tcx>, _cycle: &[QueryInfo], guar: ErrorGuaranteed) -> Self { // tcx.arena.alloc cannot be used because we are not allowed to use &'tcx LayoutError under // min_specialization. Since this is an error path anyways, leaking doesn't matter (and really, // tcx.arena.alloc is pretty much equal to leaking). - // FIXME: `Cycle` should carry the ErrorGuaranteed - Err(Box::leak(Box::new(ty::layout::LayoutError::Cycle))) + Err(Box::leak(Box::new(ty::layout::LayoutError::Cycle(guar)))) } } diff --git a/src/librustdoc/html/templates/type_layout.html b/src/librustdoc/html/templates/type_layout.html index b8b7785a2a19..c75fc34a9dfe 100644 --- a/src/librustdoc/html/templates/type_layout.html +++ b/src/librustdoc/html/templates/type_layout.html @@ -54,7 +54,7 @@ Note: Encountered an error during type layout; {#+ #} the type failed to be normalized. {# #}

      {# #} - {% when Err(LayoutError::Cycle) %} + {% when Err(LayoutError::Cycle(_)) %}

      {# #} Note: Encountered an error during type layout; {#+ #} the type's layout depended on the type's layout itself. {# #} From aefbb616afdc71e3d9358ad12ce07d80cd6c3cfb Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 9 Nov 2023 14:11:39 +1100 Subject: [PATCH 401/435] Remove `-Zperf-stats`. The included measurements have varied over the years. At one point there were quite a few more, but #49558 deleted a lot that were no longer used. Today there's just four, and it's a motley collection that doesn't seem particularly valuable. I think it has been well and truly subsumed by self-profiling, which collects way more data. --- compiler/rustc_driver_impl/src/lib.rs | 4 -- .../src/infer/canonical/canonicalizer.rs | 7 --- compiler/rustc_interface/src/tests.rs | 1 - compiler/rustc_session/src/options.rs | 2 - compiler/rustc_session/src/session.rs | 46 +-------------- compiler/rustc_symbol_mangling/src/legacy.rs | 57 +++++++++---------- .../src/normalize_erasing_regions.rs | 6 -- .../src/normalize_projection_ty.rs | 3 - 8 files changed, 29 insertions(+), 97 deletions(-) diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 84ae45d6a2b6..7905a0e3924b 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -496,10 +496,6 @@ fn run_compiler( linker.link()? } - if sess.opts.unstable_opts.perf_stats { - sess.print_perf_stats(); - } - if sess.opts.unstable_opts.print_fuel.is_some() { eprintln!( "Fuel used by {}: {}", diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index 0e2f9ba70fec..88cf0fa56935 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -13,7 +13,6 @@ use rustc_middle::ty::flags::FlagComputation; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::GenericArg; use rustc_middle::ty::{self, BoundVar, InferConst, List, Ty, TyCtxt, TypeFlags, TypeVisitableExt}; -use std::sync::atomic::Ordering; use rustc_data_structures::fx::FxHashMap; use rustc_index::Idx; @@ -43,8 +42,6 @@ impl<'tcx> InferCtxt<'tcx> { where V: TypeFoldable>, { - self.tcx.sess.perf_stats.queries_canonicalized.fetch_add(1, Ordering::Relaxed); - Canonicalizer::canonicalize(value, self, self.tcx, &CanonicalizeAllFreeRegions, query_state) } @@ -62,8 +59,6 @@ impl<'tcx> InferCtxt<'tcx> { where V: TypeFoldable>, { - self.tcx.sess.perf_stats.queries_canonicalized.fetch_add(1, Ordering::Relaxed); - Canonicalizer::canonicalize( value, self, @@ -138,8 +133,6 @@ impl<'tcx> InferCtxt<'tcx> { where V: TypeFoldable>, { - self.tcx.sess.perf_stats.queries_canonicalized.fetch_add(1, Ordering::Relaxed); - Canonicalizer::canonicalize( value, self, diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index d30816955231..4909b7517edb 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -691,7 +691,6 @@ fn test_unstable_options_tracking_hash() { untracked!(no_leak_check, true); untracked!(no_parallel_llvm, true); untracked!(parse_only, true); - untracked!(perf_stats, true); // `pre_link_arg` is omitted because it just forwards to `pre_link_args`. untracked!(pre_link_args, vec![String::from("abc"), String::from("def")]); untracked!(print_codegen_stats, true); diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 76d69646f1df..faaf6be98179 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1710,8 +1710,6 @@ options! { "panic strategy for panics in drops"), parse_only: bool = (false, parse_bool, [UNTRACKED], "parse only; do not compile, assemble, or link (default: no)"), - perf_stats: bool = (false, parse_bool, [UNTRACKED], - "print some performance-related statistics (default: no)"), plt: Option = (None, parse_opt_bool, [TRACKED], "whether to use the PLT when calling into shared libraries; only has effect for PIC code on systems with ELF binaries diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 80a549b30f79..e9655a5587db 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -15,10 +15,8 @@ pub use rustc_ast::Attribute; use rustc_data_structures::flock; use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; use rustc_data_structures::jobserver::{self, Client}; -use rustc_data_structures::profiling::{duration_to_secs_str, SelfProfiler, SelfProfilerRef}; -use rustc_data_structures::sync::{ - AtomicU64, AtomicUsize, Lock, Lrc, OneThread, Ordering, Ordering::SeqCst, -}; +use rustc_data_structures::profiling::{SelfProfiler, SelfProfilerRef}; +use rustc_data_structures::sync::{AtomicU64, Lock, Lrc, OneThread, Ordering::SeqCst}; use rustc_errors::annotate_snippet_emitter_writer::AnnotateSnippetEmitterWriter; use rustc_errors::emitter::{DynEmitter, EmitterWriter, HumanReadableErrorType}; use rustc_errors::json::JsonEmitter; @@ -46,7 +44,6 @@ use std::ops::{Div, Mul}; use std::path::{Path, PathBuf}; use std::str::FromStr; use std::sync::{atomic::AtomicBool, Arc}; -use std::time::Duration; pub struct OptimizationFuel { /// If `-zfuel=crate=n` is specified, initially set to `n`, otherwise `0`. @@ -157,9 +154,6 @@ pub struct Session { /// Used by `-Z self-profile`. pub prof: SelfProfilerRef, - /// Some measurements that are being gathered during compilation. - pub perf_stats: PerfStats, - /// Data about code being compiled, gathered during compilation. pub code_stats: CodeStats, @@ -215,17 +209,6 @@ pub struct Session { pub expanded_args: Vec, } -pub struct PerfStats { - /// The accumulated time spent on computing symbol hashes. - pub symbol_hash_time: Lock, - /// Total number of values canonicalized queries constructed. - pub queries_canonicalized: AtomicUsize, - /// Number of times this query is invoked. - pub normalize_generic_arg_after_erasing_regions: AtomicUsize, - /// Number of times this query is invoked. - pub normalize_projection_ty: AtomicUsize, -} - #[derive(PartialEq, Eq, PartialOrd, Ord)] pub enum MetadataKind { None, @@ -883,25 +866,6 @@ impl Session { self.opts.incremental.as_ref().map(|_| self.incr_comp_session_dir()) } - pub fn print_perf_stats(&self) { - eprintln!( - "Total time spent computing symbol hashes: {}", - duration_to_secs_str(*self.perf_stats.symbol_hash_time.lock()) - ); - eprintln!( - "Total queries canonicalized: {}", - self.perf_stats.queries_canonicalized.load(Ordering::Relaxed) - ); - eprintln!( - "normalize_generic_arg_after_erasing_regions: {}", - self.perf_stats.normalize_generic_arg_after_erasing_regions.load(Ordering::Relaxed) - ); - eprintln!( - "normalize_projection_ty: {}", - self.perf_stats.normalize_projection_ty.load(Ordering::Relaxed) - ); - } - /// We want to know if we're allowed to do an optimization for crate foo from -z fuel=foo=n. /// This expends fuel if applicable, and records fuel if applicable. pub fn consider_optimizing( @@ -1515,12 +1479,6 @@ pub fn build_session( io, incr_comp_session: OneThread::new(RefCell::new(IncrCompSession::NotInitialized)), prof, - perf_stats: PerfStats { - symbol_hash_time: Lock::new(Duration::from_secs(0)), - queries_canonicalized: AtomicUsize::new(0), - normalize_generic_arg_after_erasing_regions: AtomicUsize::new(0), - normalize_projection_ty: AtomicUsize::new(0), - }, code_stats: Default::default(), optimization_fuel, print_fuel, diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs index 53925eeaaa0d..0178ff53b24a 100644 --- a/compiler/rustc_symbol_mangling/src/legacy.rs +++ b/compiler/rustc_symbol_mangling/src/legacy.rs @@ -4,7 +4,6 @@ use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData}; use rustc_middle::ty::print::{PrettyPrinter, Print, PrintError, Printer}; use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeVisitableExt}; use rustc_middle::ty::{GenericArg, GenericArgKind}; -use rustc_middle::util::common::record_time; use std::fmt::{self, Write}; use std::mem::{self, discriminant}; @@ -101,40 +100,38 @@ fn get_symbol_hash<'tcx>( tcx.with_stable_hashing_context(|mut hcx| { let mut hasher = StableHasher::new(); - record_time(&tcx.sess.perf_stats.symbol_hash_time, || { - // the main symbol name is not necessarily unique; hash in the - // compiler's internal def-path, guaranteeing each symbol has a - // truly unique path - tcx.def_path_hash(def_id).hash_stable(&mut hcx, &mut hasher); + // the main symbol name is not necessarily unique; hash in the + // compiler's internal def-path, guaranteeing each symbol has a + // truly unique path + tcx.def_path_hash(def_id).hash_stable(&mut hcx, &mut hasher); - // Include the main item-type. Note that, in this case, the - // assertions about `has_param` may not hold, but this item-type - // ought to be the same for every reference anyway. - assert!(!item_type.has_erasable_regions()); - hcx.while_hashing_spans(false, |hcx| { - item_type.hash_stable(hcx, &mut hasher); + // Include the main item-type. Note that, in this case, the + // assertions about `has_param` may not hold, but this item-type + // ought to be the same for every reference anyway. + assert!(!item_type.has_erasable_regions()); + hcx.while_hashing_spans(false, |hcx| { + item_type.hash_stable(hcx, &mut hasher); - // If this is a function, we hash the signature as well. - // This is not *strictly* needed, but it may help in some - // situations, see the `run-make/a-b-a-linker-guard` test. - if let ty::FnDef(..) = item_type.kind() { - item_type.fn_sig(tcx).hash_stable(hcx, &mut hasher); - } + // If this is a function, we hash the signature as well. + // This is not *strictly* needed, but it may help in some + // situations, see the `run-make/a-b-a-linker-guard` test. + if let ty::FnDef(..) = item_type.kind() { + item_type.fn_sig(tcx).hash_stable(hcx, &mut hasher); + } - // also include any type parameters (for generic items) - args.hash_stable(hcx, &mut hasher); + // also include any type parameters (for generic items) + args.hash_stable(hcx, &mut hasher); - if let Some(instantiating_crate) = instantiating_crate { - tcx.def_path_hash(instantiating_crate.as_def_id()) - .stable_crate_id() - .hash_stable(hcx, &mut hasher); - } + if let Some(instantiating_crate) = instantiating_crate { + tcx.def_path_hash(instantiating_crate.as_def_id()) + .stable_crate_id() + .hash_stable(hcx, &mut hasher); + } - // We want to avoid accidental collision between different types of instances. - // Especially, `VTableShim`s and `ReifyShim`s may overlap with their original - // instances without this. - discriminant(&instance.def).hash_stable(hcx, &mut hasher); - }); + // We want to avoid accidental collision between different types of instances. + // Especially, `VTableShim`s and `ReifyShim`s may overlap with their original + // instances without this. + discriminant(&instance.def).hash_stable(hcx, &mut hasher); }); // 64 bits should be enough to avoid collisions. diff --git a/compiler/rustc_traits/src/normalize_erasing_regions.rs b/compiler/rustc_traits/src/normalize_erasing_regions.rs index 2563e3ed1a34..cb2a36cb998b 100644 --- a/compiler/rustc_traits/src/normalize_erasing_regions.rs +++ b/compiler/rustc_traits/src/normalize_erasing_regions.rs @@ -4,18 +4,12 @@ use rustc_middle::traits::query::NoSolution; use rustc_middle::ty::{self, ParamEnvAnd, TyCtxt, TypeFoldable, TypeVisitableExt}; use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt; use rustc_trait_selection::traits::{Normalized, ObligationCause}; -use std::sync::atomic::Ordering; pub(crate) fn provide(p: &mut Providers) { *p = Providers { try_normalize_generic_arg_after_erasing_regions: |tcx, goal| { debug!("try_normalize_generic_arg_after_erasing_regions(goal={:#?}", goal); - tcx.sess - .perf_stats - .normalize_generic_arg_after_erasing_regions - .fetch_add(1, Ordering::Relaxed); - try_normalize_after_erasing_regions(tcx, goal) }, ..*p diff --git a/compiler/rustc_traits/src/normalize_projection_ty.rs b/compiler/rustc_traits/src/normalize_projection_ty.rs index 01bb1ca70eb4..b8c71bc96f88 100644 --- a/compiler/rustc_traits/src/normalize_projection_ty.rs +++ b/compiler/rustc_traits/src/normalize_projection_ty.rs @@ -10,7 +10,6 @@ use rustc_trait_selection::traits::query::{ use rustc_trait_selection::traits::{ self, FulfillmentErrorCode, ObligationCause, SelectionContext, }; -use std::sync::atomic::Ordering; pub(crate) fn provide(p: &mut Providers) { *p = Providers { @@ -27,7 +26,6 @@ fn normalize_projection_ty<'tcx>( ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, NormalizationResult<'tcx>>>, NoSolution> { debug!("normalize_provider(goal={:#?})", goal); - tcx.sess.perf_stats.normalize_projection_ty.fetch_add(1, Ordering::Relaxed); tcx.infer_ctxt().enter_canonical_trait_query( &goal, |ocx, ParamEnvAnd { param_env, value: goal }| { @@ -78,7 +76,6 @@ fn normalize_weak_ty<'tcx>( ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, NormalizationResult<'tcx>>>, NoSolution> { debug!("normalize_provider(goal={:#?})", goal); - tcx.sess.perf_stats.normalize_projection_ty.fetch_add(1, Ordering::Relaxed); tcx.infer_ctxt().enter_canonical_trait_query( &goal, |ocx, ParamEnvAnd { param_env, value: goal }| { From 274824b917c290d6ac9227e1c263a3358ba6e6f2 Mon Sep 17 00:00:00 2001 From: sjwang05 <63834813+sjwang05@users.noreply.github.com> Date: Sun, 12 Nov 2023 14:46:01 -0800 Subject: [PATCH 402/435] Fix `is_keyword_ahead` visibility Co-authored-by: Takayuki Maeda --- compiler/rustc_parse/src/parser/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 6eab140117e9..76f3f21a5164 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -1115,7 +1115,7 @@ impl<'a> Parser<'a> { } /// Returns whether any of the given keywords are `dist` tokens ahead of the current one. - pub fn is_keyword_ahead(&self, dist: usize, kws: &[Symbol]) -> bool { + pub(crate) fn is_keyword_ahead(&self, dist: usize, kws: &[Symbol]) -> bool { self.look_ahead(dist, |t| kws.iter().any(|&kw| t.is_keyword(kw))) } From 62b6529e039ccba88a02e1a2cdff65a7f0d25bef Mon Sep 17 00:00:00 2001 From: Mu001999 Date: Mon, 13 Nov 2023 08:36:12 +0800 Subject: [PATCH 403/435] Turn assert_eq into a delay_span_bug --- .../src/coherence/orphan.rs | 8 ++++++- tests/ui/auto-traits/issue-117789.rs | 7 +++++++ tests/ui/auto-traits/issue-117789.stderr | 21 +++++++++++++++++++ 3 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 tests/ui/auto-traits/issue-117789.rs create mode 100644 tests/ui/auto-traits/issue-117789.stderr diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs index 7eeb7837467f..8d87cb57b907 100644 --- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs +++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs @@ -452,7 +452,13 @@ fn lint_auto_trait_impl<'tcx>( trait_ref: ty::TraitRef<'tcx>, impl_def_id: LocalDefId, ) { - assert_eq!(trait_ref.args.len(), 1); + if trait_ref.args.len() != 1 { + tcx.sess.diagnostic().delay_span_bug( + tcx.def_span(impl_def_id), + "auto traits cannot have generic parameters", + ); + return; + } let self_ty = trait_ref.self_ty(); let (self_type_did, args) = match self_ty.kind() { ty::Adt(def, args) => (def.did(), args), diff --git a/tests/ui/auto-traits/issue-117789.rs b/tests/ui/auto-traits/issue-117789.rs new file mode 100644 index 000000000000..0c30931a1b50 --- /dev/null +++ b/tests/ui/auto-traits/issue-117789.rs @@ -0,0 +1,7 @@ +#![deny(suspicious_auto_trait_impls)] + +auto trait Trait

      {} //~ ERROR auto traits cannot have generic parameters +//~^ ERROR auto traits are experimental and possibly buggy +impl

      Trait

      for () {} + +fn main() {} diff --git a/tests/ui/auto-traits/issue-117789.stderr b/tests/ui/auto-traits/issue-117789.stderr new file mode 100644 index 000000000000..9a3a7efed3e1 --- /dev/null +++ b/tests/ui/auto-traits/issue-117789.stderr @@ -0,0 +1,21 @@ +error[E0567]: auto traits cannot have generic parameters + --> $DIR/issue-117789.rs:3:17 + | +LL | auto trait Trait

      {} + | -----^^^ help: remove the parameters + | | + | auto trait cannot have generic parameters + +error[E0658]: auto traits are experimental and possibly buggy + --> $DIR/issue-117789.rs:3:1 + | +LL | auto trait Trait

      {} + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #13231 for more information + = help: add `#![feature(auto_traits)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0567, E0658. +For more information about an error, try `rustc --explain E0567`. From 69634f2077bc4f223cca7dfb63e104ac1efa0752 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 13 Nov 2023 00:52:10 +0000 Subject: [PATCH 404/435] Always point at index span on index obligation failure Use more targetted span for index obligation failures by rewriting the obligation cause span. CC #66023 --- compiler/rustc_hir_typeck/src/expr.rs | 14 ++------------ .../point-at-index-for-obligation-failure.rs | 7 +++++++ .../point-at-index-for-obligation-failure.stderr | 13 +++++++++++++ 3 files changed, 22 insertions(+), 12 deletions(-) create mode 100644 tests/ui/indexing/point-at-index-for-obligation-failure.rs create mode 100644 tests/ui/indexing/point-at-index-for-obligation-failure.stderr diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 9f439a2b32aa..7298e1e57022 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -2877,7 +2877,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // two-phase not needed because index_ty is never mutable self.demand_coerce(idx, idx_t, index_ty, None, AllowTwoPhase::No); self.select_obligations_where_possible(|errors| { - self.point_at_index_if_possible(errors, idx.span) + self.point_at_index(errors, idx.span) }); element_ty } @@ -3036,18 +3036,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .ok() } - fn point_at_index_if_possible( - &self, - errors: &mut Vec>, - span: Span, - ) { + fn point_at_index(&self, errors: &mut Vec>, span: Span) { for error in errors { - match error.obligation.predicate.kind().skip_binder() { - ty::PredicateKind::Clause(ty::ClauseKind::Trait(predicate)) - if self.tcx.is_diagnostic_item(sym::SliceIndex, predicate.trait_ref.def_id) => { - } - _ => continue, - } error.obligation.cause.span = span; } } diff --git a/tests/ui/indexing/point-at-index-for-obligation-failure.rs b/tests/ui/indexing/point-at-index-for-obligation-failure.rs new file mode 100644 index 000000000000..e9c429b53ced --- /dev/null +++ b/tests/ui/indexing/point-at-index-for-obligation-failure.rs @@ -0,0 +1,7 @@ +fn main() { + let a = std::collections::HashMap::::new(); + let s = "hello"; + let _b = a[ + &s //~ ERROR E0277 + ]; +} diff --git a/tests/ui/indexing/point-at-index-for-obligation-failure.stderr b/tests/ui/indexing/point-at-index-for-obligation-failure.stderr new file mode 100644 index 000000000000..3e2fbc2ab6f2 --- /dev/null +++ b/tests/ui/indexing/point-at-index-for-obligation-failure.stderr @@ -0,0 +1,13 @@ +error[E0277]: the trait bound `String: Borrow<&str>` is not satisfied + --> $DIR/point-at-index-for-obligation-failure.rs:5:9 + | +LL | &s + | ^^ the trait `Borrow<&str>` is not implemented for `String` + | + = help: the trait `Borrow` is implemented for `String` + = help: for that trait implementation, expected `str`, found `&str` + = note: required for `HashMap` to implement `Index<&&str>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. From 514e324c32db0790a13f52a96e230663f3fe0525 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 13 Nov 2023 11:33:44 +1100 Subject: [PATCH 405/435] coverage: Regression test for #117788 Without the workaround applied, this test will produce malformed mappings that cause `llvm-cov` to fail. (And if it does emit well-formed mappings, they should be obviously incorrect.) --- .../auxiliary/macro_name_span_helper.rs | 10 +++++ tests/coverage/macro_name_span.cov-map | 16 ++++++++ tests/coverage/macro_name_span.coverage | 39 +++++++++++++++++++ tests/coverage/macro_name_span.rs | 25 ++++++++++++ 4 files changed, 90 insertions(+) create mode 100644 tests/coverage/auxiliary/macro_name_span_helper.rs create mode 100644 tests/coverage/macro_name_span.cov-map create mode 100644 tests/coverage/macro_name_span.coverage create mode 100644 tests/coverage/macro_name_span.rs diff --git a/tests/coverage/auxiliary/macro_name_span_helper.rs b/tests/coverage/auxiliary/macro_name_span_helper.rs new file mode 100644 index 000000000000..6797c081d938 --- /dev/null +++ b/tests/coverage/auxiliary/macro_name_span_helper.rs @@ -0,0 +1,10 @@ +// edition: 2021 + +#[macro_export] +macro_rules! macro_that_defines_a_function { + (fn $name:ident () $body:tt) => { + fn $name () -> () $body + } +} + +// Non-executable comment. diff --git a/tests/coverage/macro_name_span.cov-map b/tests/coverage/macro_name_span.cov-map new file mode 100644 index 000000000000..b84628fc788c --- /dev/null +++ b/tests/coverage/macro_name_span.cov-map @@ -0,0 +1,16 @@ +Function name: macro_name_span::affected_function +Raw bytes (9): 0x[01, 01, 00, 01, 01, 06, 1b, 00, 20] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 6, 27) to (start + 0, 32) + +Function name: macro_name_span::main +Raw bytes (9): 0x[01, 02, 00, 01, 01, 0b, 01, 02, 02] +Number of files: 1 +- file 0 => global file 2 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 11, 1) to (start + 2, 2) + diff --git a/tests/coverage/macro_name_span.coverage b/tests/coverage/macro_name_span.coverage new file mode 100644 index 000000000000..cadf7024657e --- /dev/null +++ b/tests/coverage/macro_name_span.coverage @@ -0,0 +1,39 @@ +$DIR/auxiliary/macro_name_span_helper.rs: + LL| |// edition: 2021 + LL| | + LL| |#[macro_export] + LL| |macro_rules! macro_that_defines_a_function { + LL| | (fn $name:ident () $body:tt) => { + LL| 1| fn $name () -> () $body + LL| | } + LL| |} + LL| | + LL| |// Non-executable comment. + +$DIR/macro_name_span.rs: + LL| |// edition: 2021 + LL| | + LL| |// Regression test for . + LL| |// Under some circumstances, the heuristics that detect macro name spans can + LL| |// get confused and produce incorrect spans beyond the bounds of the span + LL| |// being processed. + LL| | + LL| |// aux-build: macro_name_span_helper.rs + LL| |extern crate macro_name_span_helper; + LL| | + LL| 1|fn main() { + LL| 1| affected_function(); + LL| 1|} + LL| | + LL| |macro_rules! macro_with_an_unreasonably_and_egregiously_long_name { + LL| | () => { + LL| | println!("hello"); + LL| | }; + LL| |} + LL| | + LL| |macro_name_span_helper::macro_that_defines_a_function! { + LL| | fn affected_function() { + LL| | macro_with_an_unreasonably_and_egregiously_long_name!(); + LL| | } + LL| |} + diff --git a/tests/coverage/macro_name_span.rs b/tests/coverage/macro_name_span.rs new file mode 100644 index 000000000000..5d15977c498f --- /dev/null +++ b/tests/coverage/macro_name_span.rs @@ -0,0 +1,25 @@ +// edition: 2021 + +// Regression test for . +// Under some circumstances, the heuristics that detect macro name spans can +// get confused and produce incorrect spans beyond the bounds of the span +// being processed. + +// aux-build: macro_name_span_helper.rs +extern crate macro_name_span_helper; + +fn main() { + affected_function(); +} + +macro_rules! macro_with_an_unreasonably_and_egregiously_long_name { + () => { + println!("hello"); + }; +} + +macro_name_span_helper::macro_that_defines_a_function! { + fn affected_function() { + macro_with_an_unreasonably_and_egregiously_long_name!(); + } +} From 7994b5849ca583cdbbcb55e71e1152ada7a6c077 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 8 Nov 2023 04:20:57 +0000 Subject: [PATCH 406/435] Compute layout with spans for better cycle errors in coroutines --- compiler/rustc_ast_lowering/src/expr.rs | 7 +++-- compiler/rustc_ty_utils/src/layout.rs | 10 +++---- ...await.b-{closure#0}.coroutine_resume.0.mir | 4 +-- .../indirect-recursion-issue-112047.rs | 2 +- .../indirect-recursion-issue-112047.stderr | 26 ++++++++++++------- 5 files changed, 30 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 0fff9a6be926..c07dbbc9d67e 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -792,8 +792,11 @@ impl<'hir> LoweringContext<'_, 'hir> { // debuggers and debugger extensions expect it to be called `__awaitee`. They use // this name to identify what is being awaited by a suspended async functions. let awaitee_ident = Ident::with_dummy_span(sym::__awaitee); - let (awaitee_pat, awaitee_pat_hid) = - self.pat_ident_binding_mode(span, awaitee_ident, hir::BindingAnnotation::MUT); + let (awaitee_pat, awaitee_pat_hid) = self.pat_ident_binding_mode( + gen_future_span, + awaitee_ident, + hir::BindingAnnotation::MUT, + ); let task_context_ident = Ident::with_dummy_span(sym::_task_context); diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 283862b5e1cc..52f723eba80e 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -740,11 +740,11 @@ fn coroutine_layout<'tcx>( }; let tag_layout = cx.tcx.mk_layout(LayoutS::scalar(cx, tag)); - let promoted_layouts = ineligible_locals - .iter() - .map(|local| subst_field(info.field_tys[local].ty)) - .map(|ty| Ty::new_maybe_uninit(tcx, ty)) - .map(|ty| Ok(cx.layout_of(ty)?.layout)); + let promoted_layouts = ineligible_locals.iter().map(|local| { + let field_ty = subst_field(info.field_tys[local].ty); + let uninit_ty = Ty::new_maybe_uninit(tcx, field_ty); + Ok(cx.spanned_layout_of(uninit_ty, info.field_tys[local].source_info.span)?.layout) + }); let prefix_layouts = args .as_coroutine() .prefix_tys() diff --git a/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir b/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir index 396e4a378f6f..111dd8e97f9a 100644 --- a/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir +++ b/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir @@ -14,7 +14,7 @@ Static, ), source_info: SourceInfo { - span: $DIR/async_await.rs:16:9: 16:14 (#8), + span: $DIR/async_await.rs:16:5: 16:14 (#9), scope: scope[0], }, ignore_for_traits: false, @@ -32,7 +32,7 @@ Static, ), source_info: SourceInfo { - span: $DIR/async_await.rs:17:9: 17:14 (#10), + span: $DIR/async_await.rs:17:5: 17:14 (#11), scope: scope[0], }, ignore_for_traits: false, diff --git a/tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.rs b/tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.rs index f6cbbf04d826..6a2ee761e191 100644 --- a/tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.rs +++ b/tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.rs @@ -1,6 +1,5 @@ // edition: 2021 // build-fail -//~^^ ERROR cycle detected when computing layout of #![feature(impl_trait_in_assoc_type)] @@ -21,6 +20,7 @@ impl Recur for () { fn recur(self) -> Self::Recur { async move { recur(self).await; } + //~^ ERROR cycle detected when computing layout of } } diff --git a/tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.stderr b/tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.stderr index 2063becdb083..80b6aaaf919f 100644 --- a/tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.stderr +++ b/tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.stderr @@ -1,14 +1,22 @@ -error[E0391]: cycle detected when computing layout of `{async block@$DIR/indirect-recursion-issue-112047.rs:23:9: 23:42}` +error[E0391]: cycle detected when computing layout of `{async block@$DIR/indirect-recursion-issue-112047.rs:22:9: 22:42}` + --> $DIR/indirect-recursion-issue-112047.rs:22:22 | - = note: ...which requires computing layout of `core::mem::maybe_uninit::MaybeUninit<{async fn body@$DIR/indirect-recursion-issue-112047.rs:15:31: 17:2}>`... - = note: ...which requires computing layout of `core::mem::manually_drop::ManuallyDrop<{async fn body@$DIR/indirect-recursion-issue-112047.rs:15:31: 17:2}>`... - = note: ...which requires computing layout of `{async fn body@$DIR/indirect-recursion-issue-112047.rs:15:31: 17:2}`... +LL | async move { recur(self).await; } + | ^^^^^^^^^^^^^^^^^ + | + = note: ...which requires computing layout of `core::mem::maybe_uninit::MaybeUninit<{async fn body@$DIR/indirect-recursion-issue-112047.rs:14:31: 16:2}>`... + = note: ...which requires computing layout of `core::mem::manually_drop::ManuallyDrop<{async fn body@$DIR/indirect-recursion-issue-112047.rs:14:31: 16:2}>`... +note: ...which requires computing layout of `{async fn body@$DIR/indirect-recursion-issue-112047.rs:14:31: 16:2}`... + --> $DIR/indirect-recursion-issue-112047.rs:15:5 + | +LL | t.recur().await; + | ^^^^^^^^^^^^^^^ = note: ...which requires computing layout of `core::mem::maybe_uninit::MaybeUninit<<() as Recur>::Recur>`... - = note: ...which requires computing layout of `core::mem::maybe_uninit::MaybeUninit<{async block@$DIR/indirect-recursion-issue-112047.rs:23:9: 23:42}>`... - = note: ...which requires computing layout of `core::mem::manually_drop::ManuallyDrop<{async block@$DIR/indirect-recursion-issue-112047.rs:23:9: 23:42}>`... - = note: ...which again requires computing layout of `{async block@$DIR/indirect-recursion-issue-112047.rs:23:9: 23:42}`, completing the cycle -note: cycle used when elaborating drops for `::recur` - --> $DIR/indirect-recursion-issue-112047.rs:22:5 + = note: ...which requires computing layout of `core::mem::maybe_uninit::MaybeUninit<{async block@$DIR/indirect-recursion-issue-112047.rs:22:9: 22:42}>`... + = note: ...which requires computing layout of `core::mem::manually_drop::ManuallyDrop<{async block@$DIR/indirect-recursion-issue-112047.rs:22:9: 22:42}>`... + = note: ...which again requires computing layout of `{async block@$DIR/indirect-recursion-issue-112047.rs:22:9: 22:42}`, completing the cycle +note: cycle used when elaborating drops for `::recur` + --> $DIR/indirect-recursion-issue-112047.rs:21:5 | LL | fn recur(self) -> Self::Recur { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From 8e2da60f0de9ced272623338a43241f1544c0d58 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sun, 12 Nov 2023 15:19:04 -0500 Subject: [PATCH 407/435] Cranelift isn't available on non-nightly channels --- src/bootstrap/src/core/build_steps/dist.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index 950845b736f8..c485481b9a1e 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -1630,14 +1630,11 @@ impl Step for Extended { prepare("rust-analysis"); prepare("clippy"); prepare("rust-analyzer"); - for tool in &["rust-docs", "rust-demangler", "miri"] { + for tool in &["rust-docs", "rust-demangler", "miri", "rustc-codegen-cranelift"] { if built_tools.contains(tool) { prepare(tool); } } - if builder.config.rust_codegen_backends.contains(&INTERNER.intern_str("cranelift")) { - prepare("rustc-codegen-cranelift"); - } // create an 'uninstall' package builder.install(&etc.join("pkg/postinstall"), &pkg.join("uninstall"), 0o755); pkgbuild("uninstall"); From 8c0ae837236f99896fba19c265251d0338be1440 Mon Sep 17 00:00:00 2001 From: Sleep_AllDay <37238439+SpeedReach@users.noreply.github.com> Date: Mon, 13 Nov 2023 13:15:55 +0800 Subject: [PATCH 408/435] Fix comment Gt => Greater than => `>` Ge => Greater equal => `>=` --- compiler/rustc_ast/src/token.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 914c97a14ac0..a6ee93e8a6ba 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -238,9 +238,9 @@ pub enum TokenKind { EqEq, /// `!=` Ne, - /// `>` - Ge, /// `>=` + Ge, + /// `>` Gt, /// `&&` AndAnd, From 06faf589acda706f9fa556d2cbeba50f99e6c34c Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 13 Nov 2023 16:24:16 +1100 Subject: [PATCH 409/435] Remove `BitSet::words`. --- compiler/rustc_index/src/bit_set.rs | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_index/src/bit_set.rs b/compiler/rustc_index/src/bit_set.rs index ece61ff12520..af8a53a991f5 100644 --- a/compiler/rustc_index/src/bit_set.rs +++ b/compiler/rustc_index/src/bit_set.rs @@ -237,11 +237,6 @@ impl BitSet { new_word != word } - /// Gets a slice of the underlying words. - pub fn words(&self) -> &[Word] { - &self.words - } - /// Iterates over the indices of set bits in a sorted order. #[inline] pub fn iter(&self) -> BitIter<'_, T> { @@ -1601,11 +1596,11 @@ impl BitMatrix { pub fn from_row_n(row: &BitSet, num_rows: usize) -> BitMatrix { let num_columns = row.domain_size(); let words_per_row = num_words(num_columns); - assert_eq!(words_per_row, row.words().len()); + assert_eq!(words_per_row, row.words.len()); BitMatrix { num_rows, num_columns, - words: iter::repeat(row.words()).take(num_rows).flatten().cloned().collect(), + words: iter::repeat(&row.words).take(num_rows).flatten().cloned().collect(), marker: PhantomData, } } @@ -1700,9 +1695,9 @@ impl BitMatrix { assert_eq!(with.domain_size(), self.num_columns); let (write_start, write_end) = self.range(write); let mut changed = false; - for (read_index, write_index) in iter::zip(0..with.words().len(), write_start..write_end) { + for (read_index, write_index) in iter::zip(0..with.words.len(), write_start..write_end) { let word = self.words[write_index]; - let new_word = word | with.words()[read_index]; + let new_word = word | with.words[read_index]; self.words[write_index] = new_word; changed |= word != new_word; } From b7cf697a6d47fff7e81e44895c3ffe565ebe0e07 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 13 Nov 2023 16:26:26 +1100 Subject: [PATCH 410/435] Remove `BitSet::to_hybrid`. --- compiler/rustc_index/src/bit_set.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/compiler/rustc_index/src/bit_set.rs b/compiler/rustc_index/src/bit_set.rs index af8a53a991f5..d0ce5678b963 100644 --- a/compiler/rustc_index/src/bit_set.rs +++ b/compiler/rustc_index/src/bit_set.rs @@ -243,12 +243,6 @@ impl BitSet { BitIter::new(&self.words) } - /// Duplicates the set as a hybrid set. - pub fn to_hybrid(&self) -> HybridBitSet { - // Note: we currently don't bother trying to make a Sparse set. - HybridBitSet::Dense(self.to_owned()) - } - /// Set `self = self | other`. In contrast to `union` returns `true` if the set contains at /// least one bit that is not in `other` (i.e. `other` is not a superset of `self`). /// From 8b18c16ecbb626f5f4f3c83a06c37d880a93767f Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 13 Nov 2023 16:42:08 +1100 Subject: [PATCH 411/435] Remove `impl FiniteBitSetTy for {u64,u128}`. Only the impl for `u32` is used. These can be reinstated easily if needed in the future. --- compiler/rustc_index/src/bit_set.rs | 48 ----------------------------- 1 file changed, 48 deletions(-) diff --git a/compiler/rustc_index/src/bit_set.rs b/compiler/rustc_index/src/bit_set.rs index d0ce5678b963..d0b4889b45fa 100644 --- a/compiler/rustc_index/src/bit_set.rs +++ b/compiler/rustc_index/src/bit_set.rs @@ -1991,54 +1991,6 @@ impl std::fmt::Debug for FiniteBitSet { } } -impl FiniteBitSetTy for u64 { - const DOMAIN_SIZE: u32 = 64; - - const FILLED: Self = Self::MAX; - const EMPTY: Self = Self::MIN; - - const ONE: Self = 1u64; - const ZERO: Self = 0u64; - - fn checked_shl(self, rhs: u32) -> Option { - self.checked_shl(rhs) - } - - fn checked_shr(self, rhs: u32) -> Option { - self.checked_shr(rhs) - } -} - -impl std::fmt::Debug for FiniteBitSet { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{:064b}", self.0) - } -} - -impl FiniteBitSetTy for u128 { - const DOMAIN_SIZE: u32 = 128; - - const FILLED: Self = Self::MAX; - const EMPTY: Self = Self::MIN; - - const ONE: Self = 1u128; - const ZERO: Self = 0u128; - - fn checked_shl(self, rhs: u32) -> Option { - self.checked_shl(rhs) - } - - fn checked_shr(self, rhs: u32) -> Option { - self.checked_shr(rhs) - } -} - -impl std::fmt::Debug for FiniteBitSet { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{:0128b}", self.0) - } -} - /// A fixed-sized bitset type represented by an integer type. Indices outwith than the range /// representable by `T` are considered set. #[derive(Copy, Clone, Eq, PartialEq, Decodable, Encodable)] From 2433542b412edc3e25366426ddcdae811767f27f Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 13 Nov 2023 17:00:48 +1100 Subject: [PATCH 412/435] Remove `IndexSlice::convert_index_type`. --- compiler/rustc_index/src/vec.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/compiler/rustc_index/src/vec.rs b/compiler/rustc_index/src/vec.rs index 99e72e49f8eb..66c5cc774b22 100644 --- a/compiler/rustc_index/src/vec.rs +++ b/compiler/rustc_index/src/vec.rs @@ -137,10 +137,6 @@ impl IndexVec { self.raw.truncate(a) } - pub fn convert_index_type(self) -> IndexVec { - IndexVec::from_raw(self.raw) - } - /// Grows the index vector so that it contains an entry for /// `elem`; if that is already true, then has no /// effect. Otherwise, inserts new values as needed by invoking From 82e396a4baaefecbf7eb88cbfffbc4a8b3526aac Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 13 Nov 2023 17:09:26 +1100 Subject: [PATCH 413/435] Remove unnecessary annotation. --- compiler/rustc_index/src/vec/tests.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/compiler/rustc_index/src/vec/tests.rs b/compiler/rustc_index/src/vec/tests.rs index cb0f0db220d9..7e5e41bd2d19 100644 --- a/compiler/rustc_index/src/vec/tests.rs +++ b/compiler/rustc_index/src/vec/tests.rs @@ -1,5 +1,3 @@ -#![allow(dead_code)] - // Allows the macro invocation below to work use crate as rustc_index; From 8b1bcc8d5ba65ecf6741436246ed27f74a71d40c Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sun, 12 Nov 2023 23:21:21 -0700 Subject: [PATCH 414/435] rustdoc: use `.rustdoc` class instead of `body` This didn't show up in our local tests, because the problem is actually caused by docs.rs rewritten HTML (which relocates the classes that this code looked for from the body tag to a child div). Fixes #117290 --- src/librustdoc/html/static/js/main.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 7c052606abac..615fb08c76f3 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -54,7 +54,7 @@ function setMobileTopbar() { if (mobileTopbar) { const mobileTitle = document.createElement("h2"); mobileTitle.className = "location"; - if (hasClass(document.body, "crate")) { + if (hasClass(document.querySelector(".rustdoc"), "crate")) { mobileTitle.innerText = `Crate ${window.currentCrate}`; } else if (locationTitle) { mobileTitle.innerHTML = locationTitle.innerHTML; @@ -485,7 +485,7 @@ function preLoadCss(cssUrl) { return; } - const modpath = hasClass(document.body, "mod") ? "../" : ""; + const modpath = hasClass(document.querySelector(".rustdoc"), "mod") ? "../" : ""; const h3 = document.createElement("h3"); h3.innerHTML = `${longty}`; From 6dd2ea0f35e0e30bf52b481971d039a18f96eef1 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 13 Nov 2023 09:41:45 +0100 Subject: [PATCH 415/435] features must be additive --- compiler/rustc_codegen_ssa/src/target_features.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index 8973042401f6..d802816bb756 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -51,7 +51,12 @@ impl Stability { // When adding features to the below lists // check whether they're named already elsewhere in rust // e.g. in stdarch and whether the given name matches LLVM's -// if it doesn't, to_llvm_feature in llvm_util in rustc_codegen_llvm needs to be adapted +// if it doesn't, to_llvm_feature in llvm_util in rustc_codegen_llvm needs to be adapted. +// +// Also note that all target features listed here must be purely additive: for target_feature 1.1 to +// be sound, we can never allow features like `+soft-float` (on x86) to be controlled on a +// per-function level, since we would then allow safe calls from functions with `+soft-float` to +// functions without that feature! // // When adding a new feature, be particularly mindful of features that affect function ABIs. Those // need to be treated very carefully to avoid introducing unsoundness! This often affects features From 42945fc1e225821f4eea61a8529c624a3d43b415 Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 13 Nov 2023 11:27:15 +0000 Subject: [PATCH 416/435] args~~_ref~~_may_unify --- compiler/rustc_middle/src/ty/fast_reject.rs | 8 ++++---- .../rustc_trait_selection/src/solve/project_goals/mod.rs | 2 +- compiler/rustc_trait_selection/src/solve/trait_goals.rs | 4 +--- compiler/rustc_trait_selection/src/traits/coherence.rs | 2 +- .../src/traits/select/candidate_assembly.rs | 2 +- 5 files changed, 8 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs index 75ea53195a3a..f95ceeff1507 100644 --- a/compiler/rustc_middle/src/ty/fast_reject.rs +++ b/compiler/rustc_middle/src/ty/fast_reject.rs @@ -189,14 +189,14 @@ pub struct DeepRejectCtxt { } impl DeepRejectCtxt { - pub fn args_refs_may_unify<'tcx>( + pub fn args_may_unify<'tcx>( self, obligation_args: GenericArgsRef<'tcx>, impl_args: GenericArgsRef<'tcx>, ) -> bool { iter::zip(obligation_args, impl_args).all(|(obl, imp)| { match (obl.unpack(), imp.unpack()) { - // We don't fast reject based on regions for now. + // We don't fast reject based on regions. (GenericArgKind::Lifetime(_), GenericArgKind::Lifetime(_)) => true, (GenericArgKind::Type(obl), GenericArgKind::Type(imp)) => { self.types_may_unify(obl, imp) @@ -231,7 +231,7 @@ impl DeepRejectCtxt { | ty::Never | ty::Tuple(..) | ty::FnPtr(..) - | ty::Foreign(..) => {} + | ty::Foreign(..) => debug_assert!(impl_ty.is_known_rigid()), ty::FnDef(..) | ty::Closure(..) | ty::Coroutine(..) @@ -260,7 +260,7 @@ impl DeepRejectCtxt { }, ty::Adt(obl_def, obl_args) => match k { &ty::Adt(impl_def, impl_args) => { - obl_def == impl_def && self.args_refs_may_unify(obl_args, impl_args) + obl_def == impl_def && self.args_may_unify(obl_args, impl_args) } _ => false, }, diff --git a/compiler/rustc_trait_selection/src/solve/project_goals/mod.rs b/compiler/rustc_trait_selection/src/solve/project_goals/mod.rs index 240141065dcc..7fb550aa3e06 100644 --- a/compiler/rustc_trait_selection/src/solve/project_goals/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/project_goals/mod.rs @@ -160,7 +160,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> { let goal_trait_ref = goal.predicate.projection_ty.trait_ref(tcx); let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap(); let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::ForLookup }; - if !drcx.args_refs_may_unify(goal_trait_ref.args, impl_trait_ref.skip_binder().args) { + if !drcx.args_may_unify(goal_trait_ref.args, impl_trait_ref.skip_binder().args) { return Err(NoSolution); } diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index a0e2ad6e2027..84baec4ff4c1 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -43,9 +43,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap(); let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::ForLookup }; - if !drcx - .args_refs_may_unify(goal.predicate.trait_ref.args, impl_trait_ref.skip_binder().args) - { + if !drcx.args_may_unify(goal.predicate.trait_ref.args, impl_trait_ref.skip_binder().args) { return Err(NoSolution); } diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index dcf5fd869290..787d80630058 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -100,7 +100,7 @@ pub fn overlapping_impls( let impl1_ref = tcx.impl_trait_ref(impl1_def_id); let impl2_ref = tcx.impl_trait_ref(impl2_def_id); let may_overlap = match (impl1_ref, impl2_ref) { - (Some(a), Some(b)) => drcx.args_refs_may_unify(a.skip_binder().args, b.skip_binder().args), + (Some(a), Some(b)) => drcx.args_may_unify(a.skip_binder().args, b.skip_binder().args), (None, None) => { let self_ty1 = tcx.type_of(impl1_def_id).skip_binder(); let self_ty2 = tcx.type_of(impl2_def_id).skip_binder(); diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index f4b6d3bcfda2..c1d44601891b 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -375,7 +375,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // consider a "quick reject". This avoids creating more types // and so forth that we need to. let impl_trait_ref = self.tcx().impl_trait_ref(impl_def_id).unwrap(); - if !drcx.args_refs_may_unify(obligation_args, impl_trait_ref.skip_binder().args) { + if !drcx.args_may_unify(obligation_args, impl_trait_ref.skip_binder().args) { return; } if self.reject_fn_ptr_impls( From 85883503c30f672fc53e36f43e5852438238a6d5 Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 13 Nov 2023 12:59:58 +0000 Subject: [PATCH 417/435] add fixme to `RegionCtxt` --- compiler/rustc_borrowck/src/renumber.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/compiler/rustc_borrowck/src/renumber.rs b/compiler/rustc_borrowck/src/renumber.rs index ec0131c5349a..a31d39e14cd2 100644 --- a/compiler/rustc_borrowck/src/renumber.rs +++ b/compiler/rustc_borrowck/src/renumber.rs @@ -28,6 +28,9 @@ pub fn renumber_mir<'tcx>( renumberer.visit_body(body); } +// FIXME(@lcnr): A lot of these variants overlap and it seems like +// this type is only used to decide which region should be used +// as representative. This should be cleaned up. #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] pub(crate) enum RegionCtxt { Location(Location), From 28328c8389a08ddcfe9db5475835394b6a8555db Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 13 Nov 2023 13:00:16 +0000 Subject: [PATCH 418/435] remove unnecessary `_` in variable name --- compiler/rustc_borrowck/src/type_check/relate_tys.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index c1f82e19c02e..ee0bd13109bb 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -107,12 +107,12 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> fn next_existential_region_var( &mut self, from_forall: bool, - _name: Option, + name: Option, ) -> ty::Region<'tcx> { let origin = NllRegionVariableOrigin::Existential { from_forall }; let reg_var = - self.type_checker.infcx.next_nll_region_var(origin, || RegionCtxt::Existential(_name)); + self.type_checker.infcx.next_nll_region_var(origin, || RegionCtxt::Existential(name)); reg_var } From 86fa1317a327eea002db57fbb009ccab9ae9d7dc Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 13 Nov 2023 14:00:05 +0000 Subject: [PATCH 419/435] rename `ReLateBound` to `ReBound` other changes: - `Region::new_late_bound` -> `Region::new_bound` - `Region::is_late_bound` -> `Region::is_bound` --- .../rustc_borrowck/src/diagnostics/mod.rs | 4 +-- .../src/diagnostics/region_name.rs | 2 +- .../rustc_borrowck/src/universal_regions.rs | 2 +- .../rustc_hir_analysis/src/astconv/bounds.rs | 2 +- .../rustc_hir_analysis/src/astconv/mod.rs | 6 ++-- .../src/check/compare_impl_item.rs | 2 +- .../rustc_hir_analysis/src/check/intrinsic.rs | 13 ++++---- .../rustc_hir_analysis/src/check/wfcheck.rs | 2 +- .../rustc_hir_analysis/src/hir_wf_check.rs | 3 +- .../rustc_hir_analysis/src/outlives/utils.rs | 4 +-- .../src/variance/constraints.rs | 8 +++-- compiler/rustc_hir_typeck/src/check.rs | 4 +-- compiler/rustc_hir_typeck/src/writeback.rs | 4 +-- .../src/errors/note_and_explain.rs | 7 +++-- .../src/infer/canonical/canonicalizer.rs | 6 ++-- .../src/infer/canonical/query_response.rs | 2 +- .../src/infer/error_reporting/mod.rs | 10 +++---- .../src/infer/error_reporting/suggest.rs | 4 +-- compiler/rustc_infer/src/infer/freshen.rs | 2 +- compiler/rustc_infer/src/infer/generalize.rs | 2 +- .../src/infer/lexical_region_resolve/mod.rs | 8 ++--- .../rustc_infer/src/infer/opaque_types.rs | 2 +- .../src/infer/outlives/components.rs | 8 ++--- .../src/infer/outlives/for_liveness.rs | 2 +- .../src/infer/outlives/test_type_match.rs | 4 +-- .../src/infer/region_constraints/mod.rs | 6 ++-- compiler/rustc_infer/src/traits/util.rs | 4 +-- compiler/rustc_middle/src/infer/canonical.rs | 6 ++-- compiler/rustc_middle/src/infer/unify_key.rs | 5 ++-- compiler/rustc_middle/src/mir/query.rs | 4 +-- compiler/rustc_middle/src/ty/context.rs | 4 +-- compiler/rustc_middle/src/ty/erase_regions.rs | 13 +++----- compiler/rustc_middle/src/ty/flags.rs | 2 +- compiler/rustc_middle/src/ty/fold.rs | 30 +++++++++---------- compiler/rustc_middle/src/ty/generic_args.rs | 2 +- compiler/rustc_middle/src/ty/opaque_types.rs | 5 ++-- compiler/rustc_middle/src/ty/print/pretty.rs | 22 ++++++-------- compiler/rustc_middle/src/ty/sty.rs | 18 +++++------ .../rustc_middle/src/ty/typeck_results.rs | 2 +- compiler/rustc_middle/src/ty/util.rs | 2 +- compiler/rustc_middle/src/ty/visit.rs | 6 ++-- compiler/rustc_mir_build/src/thir/cx/mod.rs | 2 +- compiler/rustc_smir/src/rustc_smir/mod.rs | 2 +- .../src/typeid/typeid_itanium_cxx_abi.rs | 3 +- compiler/rustc_symbol_mangling/src/v0.rs | 4 +-- .../src/solve/assembly/structural_traits.rs | 2 +- .../src/solve/canonicalize.rs | 4 +-- .../src/solve/eval_ctxt/canonical.rs | 2 +- .../src/traits/auto_trait.rs | 8 ++--- .../src/traits/error_reporting/suggestions.rs | 2 +- .../src/traits/project.rs | 10 +++---- .../src/traits/query/normalize.rs | 2 +- .../src/traits/select/confirmation.rs | 2 +- .../src/traits/select/mod.rs | 2 +- compiler/rustc_ty_utils/src/abi.rs | 5 ++-- compiler/rustc_ty_utils/src/ty.rs | 4 +-- compiler/rustc_type_ir/src/flags.rs | 4 +-- compiler/rustc_type_ir/src/region_kind.rs | 23 +++++++++----- compiler/stable_mir/src/ty.rs | 2 +- src/librustdoc/clean/auto_trait.rs | 2 +- src/librustdoc/clean/mod.rs | 12 +++----- .../clippy/clippy_lints/src/eta_reduction.rs | 4 +-- .../clippy_lints/src/pass_by_ref_or_value.rs | 2 +- src/tools/clippy/clippy_lints/src/ptr.rs | 2 +- src/tools/clippy/clippy_utils/src/ty.rs | 2 +- tests/ui/coroutine/issue-57084.rs | 2 +- .../escape-argument-callee.stderr | 2 +- .../escape-argument.stderr | 2 +- ...pagate-approximated-fail-no-postdom.stderr | 2 +- .../propagate-approximated-ref.stderr | 2 +- ...er-to-static-comparing-against-free.stderr | 4 +-- ...oximated-shorter-to-static-no-bound.stderr | 2 +- ...mated-shorter-to-static-wrong-bound.stderr | 2 +- .../propagate-approximated-val.stderr | 2 +- .../propagate-despite-same-free-region.stderr | 2 +- ...ail-to-approximate-longer-no-bounds.stderr | 2 +- ...-to-approximate-longer-wrong-bounds.stderr | 2 +- .../return-wrong-bound-region.stderr | 2 +- ...ram-closure-approximate-lower-bound.stderr | 4 +-- .../higher-ranked-fn-type.verbose.stderr | 4 +-- 80 files changed, 192 insertions(+), 195 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index c4323fef9355..8aef34d9e763 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -462,7 +462,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // lifetimes without names with the value `'0`. if let ty::Ref(region, ..) = ty.kind() { match **region { - ty::ReLateBound(_, ty::BoundRegion { kind: br, .. }) + ty::ReBound(_, ty::BoundRegion { kind: br, .. }) | ty::RePlaceholder(ty::PlaceholderRegion { bound: ty::BoundRegion { kind: br, .. }, .. @@ -482,7 +482,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let region = if let ty::Ref(region, ..) = ty.kind() { match **region { - ty::ReLateBound(_, ty::BoundRegion { kind: br, .. }) + ty::ReBound(_, ty::BoundRegion { kind: br, .. }) | ty::RePlaceholder(ty::PlaceholderRegion { bound: ty::BoundRegion { kind: br, .. }, .. diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index d38cfbc54d7a..9d6b0a0e91ba 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -357,7 +357,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { ty::BoundRegionKind::BrAnon => None, }, - ty::ReLateBound(..) + ty::ReBound(..) | ty::ReVar(..) | ty::RePlaceholder(..) | ty::ReErased diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index 7897a5a63ba8..ae7f9c5244c3 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -665,7 +665,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { var: ty::BoundVar::from_usize(bound_vars.len() - 1), kind: ty::BrEnv, }; - let env_region = ty::Region::new_late_bound(tcx, ty::INNERMOST, br); + let env_region = ty::Region::new_bound(tcx, ty::INNERMOST, br); let closure_ty = tcx.closure_env_ty(def_id, args, env_region).unwrap(); // The "inputs" of the closure in the diff --git a/compiler/rustc_hir_analysis/src/astconv/bounds.rs b/compiler/rustc_hir_analysis/src/astconv/bounds.rs index 3e700f2da869..cb9259998e3d 100644 --- a/compiler/rustc_hir_analysis/src/astconv/bounds.rs +++ b/compiler/rustc_hir_analysis/src/astconv/bounds.rs @@ -350,7 +350,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { let args = candidate.skip_binder().args.extend_to(tcx, assoc_item.def_id, |param, _| { let subst = match param.kind { - ty::GenericParamDefKind::Lifetime => ty::Region::new_late_bound( + ty::GenericParamDefKind::Lifetime => ty::Region::new_bound( tcx, ty::INNERMOST, ty::BoundRegion { diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 2fcb45ef8aa1..e7a2131011cc 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -250,7 +250,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { var: ty::BoundVar::from_u32(index), kind: ty::BrNamed(def_id, name), }; - ty::Region::new_late_bound(tcx, debruijn, br) + ty::Region::new_bound(tcx, debruijn, br) } Some(rbv::ResolvedArg::EarlyBound(def_id)) => { @@ -1622,7 +1622,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - if r.is_late_bound() { self.tcx.lifetimes.re_erased } else { r } + // FIXME(@lcnr): This is broken, erasing bound regions + // impacts selection as it results in different types. + if r.is_bound() { self.tcx.lifetimes.re_erased } else { r } } fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 857515f971a8..d3a383ff7c55 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -2345,7 +2345,7 @@ fn param_env_with_gat_bounds<'tcx>( let kind = ty::BoundRegionKind::BrNamed(param.def_id, param.name); let bound_var = ty::BoundVariableKind::Region(kind); bound_vars.push(bound_var); - ty::Region::new_late_bound( + ty::Region::new_bound( tcx, ty::INNERMOST, ty::BoundRegion { diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index c61719c1fd29..eb009b9368f9 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -143,12 +143,12 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { ]); let mk_va_list_ty = |mutbl| { tcx.lang_items().va_list().map(|did| { - let region = ty::Region::new_late_bound( + let region = ty::Region::new_bound( tcx, ty::INNERMOST, ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon }, ); - let env_region = ty::Region::new_late_bound( + let env_region = ty::Region::new_bound( tcx, ty::INNERMOST, ty::BoundRegion { var: ty::BoundVar::from_u32(1), kind: ty::BrEnv }, @@ -411,7 +411,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { 1, vec![Ty::new_imm_ref( tcx, - ty::Region::new_late_bound(tcx, ty::INNERMOST, br), + ty::Region::new_bound(tcx, ty::INNERMOST, br), param(0), )], Ty::new_projection(tcx, discriminant_def_id, tcx.mk_args(&[param(0).into()])), @@ -465,11 +465,8 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { sym::raw_eq => { let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon }; - let param_ty = Ty::new_imm_ref( - tcx, - ty::Region::new_late_bound(tcx, ty::INNERMOST, br), - param(0), - ); + let param_ty = + Ty::new_imm_ref(tcx, ty::Region::new_bound(tcx, ty::INNERMOST, br), param(0)); (1, vec![param_ty; 2], tcx.types.bool) } diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index eb4491b89bf1..729e9f2f1d17 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -763,7 +763,7 @@ impl<'tcx> TypeVisitor> for GATSubstCollector<'tcx> { ty::Alias(ty::Projection, p) if p.def_id == self.gat => { for (idx, subst) in p.args.iter().enumerate() { match subst.unpack() { - GenericArgKind::Lifetime(lt) if !lt.is_late_bound() => { + GenericArgKind::Lifetime(lt) if !lt.is_bound() => { self.regions.insert((lt, idx)); } GenericArgKind::Type(t) => { diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs index ca7679cfba06..d5fb4340e1c8 100644 --- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs @@ -196,6 +196,7 @@ impl<'tcx> TypeFolder> for EraseAllBoundRegions<'tcx> { self.tcx } fn fold_region(&mut self, r: Region<'tcx>) -> Region<'tcx> { - if r.is_late_bound() { self.tcx.lifetimes.re_erased } else { r } + // FIXME(@lcnr): only erase escaping bound regions! + if r.is_bound() { self.tcx.lifetimes.re_erased } else { r } } } diff --git a/compiler/rustc_hir_analysis/src/outlives/utils.rs b/compiler/rustc_hir_analysis/src/outlives/utils.rs index a6410c944f77..85703c60c30a 100644 --- a/compiler/rustc_hir_analysis/src/outlives/utils.rs +++ b/compiler/rustc_hir_analysis/src/outlives/utils.rs @@ -167,8 +167,8 @@ fn is_free_region(region: Region<'_>) -> bool { // } // // The type above might generate a `T: 'b` bound, but we can - // ignore it. We can't put it on the struct header anyway. - ty::ReLateBound(..) => false, + // ignore it. We can't name this lifetime pn the struct header anyway. + ty::ReBound(..) => false, ty::ReError(_) => false, diff --git a/compiler/rustc_hir_analysis/src/variance/constraints.rs b/compiler/rustc_hir_analysis/src/variance/constraints.rs index 5f8b1ace68b7..6c1efb6470e8 100644 --- a/compiler/rustc_hir_analysis/src/variance/constraints.rs +++ b/compiler/rustc_hir_analysis/src/variance/constraints.rs @@ -419,9 +419,11 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { ty::ReStatic => {} - ty::ReLateBound(..) => { - // Late-bound regions do not get substituted the same - // way early-bound regions do, so we skip them here. + ty::ReBound(..) => { + // Either a higher-ranked region inside of a type or a + // late-bound function parameter. + // + // We do not compute constraints for either of these. } ty::ReError(_) => {} diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs index b8a265d4971d..1edc3efbc778 100644 --- a/compiler/rustc_hir_typeck/src/check.rs +++ b/compiler/rustc_hir_typeck/src/check.rs @@ -214,7 +214,7 @@ fn check_panic_info_fn(tcx: TyCtxt<'_>, fn_id: LocalDefId, fn_sig: ty::FnSig<'_> // build type `for<'a, 'b> fn(&'a PanicInfo<'b>) -> !` let panic_info_ty = tcx.type_of(panic_info_did).instantiate( tcx, - &[ty::GenericArg::from(ty::Region::new_late_bound( + &[ty::GenericArg::from(ty::Region::new_bound( tcx, ty::INNERMOST, ty::BoundRegion { var: ty::BoundVar::from_u32(1), kind: ty::BrAnon }, @@ -222,7 +222,7 @@ fn check_panic_info_fn(tcx: TyCtxt<'_>, fn_id: LocalDefId, fn_sig: ty::FnSig<'_> ); let panic_info_ref_ty = Ty::new_imm_ref( tcx, - ty::Region::new_late_bound( + ty::Region::new_bound( tcx, ty::INNERMOST, ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon }, diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index 896aacc69931..2dfe72726734 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -784,7 +784,7 @@ impl<'tcx> TypeFolder> for EraseEarlyRegions<'tcx> { } } fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - if r.is_late_bound() { r } else { self.tcx.lifetimes.re_erased } + if r.is_bound() { r } else { self.tcx.lifetimes.re_erased } } } @@ -822,7 +822,7 @@ impl<'cx, 'tcx> TypeFolder> for Resolver<'cx, 'tcx> { } fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - debug_assert!(!r.is_late_bound(), "Should not be resolving bound region."); + debug_assert!(!r.is_bound(), "Should not be resolving bound region."); self.fcx.tcx.lifetimes.re_erased } diff --git a/compiler/rustc_infer/src/errors/note_and_explain.rs b/compiler/rustc_infer/src/errors/note_and_explain.rs index 57bc14ebcb3f..869878420aeb 100644 --- a/compiler/rustc_infer/src/errors/note_and_explain.rs +++ b/compiler/rustc_infer/src/errors/note_and_explain.rs @@ -73,8 +73,11 @@ impl<'a> DescriptionCtx<'a> { // ReFree rather than dumping Debug output on the user. // // We shouldn't really be having unification failures with ReVar - // and ReLateBound though. - ty::ReVar(_) | ty::ReLateBound(..) | ty::ReErased => { + // and ReBound though. + // + // FIXME(@lcnr): figure out why we `ReBound` have to handle `ReBound` + // here, this feels somewhat off. + ty::ReVar(_) | ty::ReBound(..) | ty::ReErased => { (alt_span, "revar", format!("{region:?}")) } }; diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index 0e2f9ba70fec..ff8e354f53d7 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -232,7 +232,7 @@ impl CanonicalizeMode for CanonicalizeUserTypeAnnotation { match *r { ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReErased | ty::ReStatic | ty::ReError(_) => r, ty::ReVar(_) => canonicalizer.canonical_var_for_region_in_root_universe(r), - ty::RePlaceholder(..) | ty::ReLateBound(..) => { + ty::RePlaceholder(..) | ty::ReBound(..) => { // We only expect region names that the user can type. bug!("unexpected region in query response: `{:?}`", r) } @@ -343,7 +343,7 @@ impl<'cx, 'tcx> TypeFolder> for Canonicalizer<'cx, 'tcx> { fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { match *r { - ty::ReLateBound(index, ..) => { + ty::ReBound(index, ..) => { if index >= self.binder_index { bug!("escaping late-bound region during canonicalization"); } else { @@ -776,7 +776,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { ) -> ty::Region<'tcx> { let var = self.canonical_var(info, r.into()); let br = ty::BoundRegion { var, kind: ty::BrAnon }; - ty::Region::new_late_bound(self.interner(), self.binder_index, br) + ty::Region::new_bound(self.interner(), self.binder_index, br) } /// Given a type variable `ty_var` of the given kind, first check diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index ed101082130c..d911e28484c2 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -460,7 +460,7 @@ impl<'tcx> InferCtxt<'tcx> { } GenericArgKind::Lifetime(result_value) => { // e.g., here `result_value` might be `'?1` in the example above... - if let ty::ReLateBound(debruijn, br) = *result_value { + if let ty::ReBound(debruijn, br) = *result_value { // ... in which case we would set `canonical_vars[0]` to `Some('static)`. // We only allow a `ty::INNERMOST` index in substitutions. diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 26d071a01397..07155f8f74f4 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -175,10 +175,10 @@ pub(super) fn note_and_explain_region<'tcx>( ty::ReError(_) => return, // We shouldn't really be having unification failures with ReVar - // and ReLateBound though. - ty::ReVar(_) | ty::ReLateBound(..) | ty::ReErased => { - (format!("lifetime `{region}`"), alt_span) - } + // and ReBound though. + // + // FIXME(@lcnr): Figure out whether this is reachable and if so, why. + ty::ReVar(_) | ty::ReBound(..) | ty::ReErased => (format!("lifetime `{region}`"), alt_span), }; emit_msg_span(err, prefix, description, span, suffix); @@ -1285,7 +1285,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { if lifetimes.0 != lifetimes.1 { values.0.push_highlighted(l1); values.1.push_highlighted(l2); - } else if lifetimes.0.is_late_bound() { + } else if lifetimes.0.is_bound() { values.0.push_normal(l1); values.1.push_normal(l2); } else { diff --git a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs index fe18d00293aa..f0b33d30e2c6 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs @@ -572,8 +572,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { if let ty::Ref(expected_region, _, _) = expected.kind() && let ty::Ref(found_region, _, _) = found.kind() - && expected_region.is_late_bound() - && !found_region.is_late_bound() + && expected_region.is_bound() + && !found_region.is_bound() && let hir::TyKind::Infer = arg_hir.kind { // If the expected region is late bound, the found region is not, and users are asking compiler diff --git a/compiler/rustc_infer/src/infer/freshen.rs b/compiler/rustc_infer/src/infer/freshen.rs index 35204478c54d..e212547eaafb 100644 --- a/compiler/rustc_infer/src/infer/freshen.rs +++ b/compiler/rustc_infer/src/infer/freshen.rs @@ -110,7 +110,7 @@ impl<'a, 'tcx> TypeFolder> for TypeFreshener<'a, 'tcx> { fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { match *r { - ty::ReLateBound(..) => { + ty::ReBound(..) => { // leave bound regions alone r } diff --git a/compiler/rustc_infer/src/infer/generalize.rs b/compiler/rustc_infer/src/infer/generalize.rs index 17fe3aa7b44c..84891022720c 100644 --- a/compiler/rustc_infer/src/infer/generalize.rs +++ b/compiler/rustc_infer/src/infer/generalize.rs @@ -327,7 +327,7 @@ where match *r { // Never make variables for regions bound within the type itself, // nor for erased regions. - ty::ReLateBound(..) | ty::ReErased => { + ty::ReBound(..) | ty::ReErased => { return Ok(r); } diff --git a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs index bee0a978ad04..4ff9d7494226 100644 --- a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs +++ b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs @@ -16,8 +16,8 @@ use rustc_data_structures::intern::Interned; use rustc_index::{IndexSlice, IndexVec}; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_middle::ty::{ReBound, RePlaceholder, ReVar}; use rustc_middle::ty::{ReEarlyBound, ReErased, ReError, ReFree, ReStatic}; -use rustc_middle::ty::{ReLateBound, RePlaceholder, ReVar}; use rustc_middle::ty::{Region, RegionVid}; use rustc_span::Span; use std::fmt; @@ -378,7 +378,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { // so it doesn't really matter if it's shorter or longer than an empty region ReError(_) => false, - ReLateBound(..) | ReErased => { + ReBound(..) | ReErased => { bug!("cannot relate region: {:?}", a); } @@ -411,7 +411,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { // so it doesn't really matter if it's shorter or longer than an empty region ReError(_) => false, - ReLateBound(..) | ReErased => { + ReBound(..) | ReErased => { bug!("cannot relate region: {:?}", b); } @@ -478,7 +478,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { #[instrument(level = "trace", skip(self), ret)] fn lub_concrete_regions(&self, a: Region<'tcx>, b: Region<'tcx>) -> Region<'tcx> { match (*a, *b) { - (ReLateBound(..), _) | (_, ReLateBound(..)) | (ReErased, _) | (_, ReErased) => { + (ReBound(..), _) | (_, ReBound(..)) | (ReErased, _) | (_, ReErased) => { bug!("cannot relate region: LUB({:?}, {:?})", a, b); } diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 7a5dec22fe04..7a792d30cc74 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -432,7 +432,7 @@ where fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { match *r { // ignore bound regions, keep visiting - ty::ReLateBound(_, _) => ControlFlow::Continue(()), + ty::ReBound(_, _) => ControlFlow::Continue(()), _ => { (self.op)(r); ControlFlow::Continue(()) diff --git a/compiler/rustc_infer/src/infer/outlives/components.rs b/compiler/rustc_infer/src/infer/outlives/components.rs index 38819e8ad8a6..f867876a2e63 100644 --- a/compiler/rustc_infer/src/infer/outlives/components.rs +++ b/compiler/rustc_infer/src/infer/outlives/components.rs @@ -213,8 +213,8 @@ pub(super) fn compute_alias_components_recursive<'tcx>( compute_components(tcx, ty, out, visited); } GenericArgKind::Lifetime(lt) => { - // Ignore late-bound regions. - if !lt.is_late_bound() { + // Ignore higher ranked regions. + if !lt.is_bound() { out.push(Component::Region(lt)); } } @@ -241,8 +241,8 @@ fn compute_components_recursive<'tcx>( compute_components(tcx, ty, out, visited); } GenericArgKind::Lifetime(lt) => { - // Ignore late-bound regions. - if !lt.is_late_bound() { + // Ignore higher ranked regions. + if !lt.is_bound() { out.push(Component::Region(lt)); } } diff --git a/compiler/rustc_infer/src/infer/outlives/for_liveness.rs b/compiler/rustc_infer/src/infer/outlives/for_liveness.rs index 398ac94ee368..2db8579af52a 100644 --- a/compiler/rustc_infer/src/infer/outlives/for_liveness.rs +++ b/compiler/rustc_infer/src/infer/outlives/for_liveness.rs @@ -37,7 +37,7 @@ where fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { match *r { // ignore bound regions, keep visiting - ty::ReLateBound(_, _) => ControlFlow::Continue(()), + ty::ReBound(_, _) => ControlFlow::Continue(()), _ => { (self.op)(r); ControlFlow::Continue(()) diff --git a/compiler/rustc_infer/src/infer/outlives/test_type_match.rs b/compiler/rustc_infer/src/infer/outlives/test_type_match.rs index 6f973ee37f5e..959b34aa1457 100644 --- a/compiler/rustc_infer/src/infer/outlives/test_type_match.rs +++ b/compiler/rustc_infer/src/infer/outlives/test_type_match.rs @@ -48,7 +48,7 @@ pub fn extract_verify_if_eq<'tcx>( let verify_if_eq = verify_if_eq_b.skip_binder(); m.relate(verify_if_eq.ty, test_ty).ok()?; - if let ty::RegionKind::ReLateBound(depth, br) = verify_if_eq.bound.kind() { + if let ty::RegionKind::ReBound(depth, br) = verify_if_eq.bound.kind() { assert!(depth == ty::INNERMOST); match m.map.get(&br) { Some(&r) => Some(r), @@ -177,7 +177,7 @@ impl<'tcx> TypeRelation<'tcx> for MatchAgainstHigherRankedOutlives<'tcx> { value: ty::Region<'tcx>, ) -> RelateResult<'tcx, ty::Region<'tcx>> { debug!("self.pattern_depth = {:?}", self.pattern_depth); - if let ty::RegionKind::ReLateBound(depth, br) = pattern.kind() + if let ty::RegionKind::ReBound(depth, br) = pattern.kind() && depth == self.pattern_depth { self.bind(br, value) diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs index 3fa9a7333a45..de142f05fb76 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs @@ -16,7 +16,7 @@ use rustc_index::IndexVec; use rustc_middle::infer::unify_key::{RegionVidKey, UnifiedRegion}; use rustc_middle::ty::ReStatic; use rustc_middle::ty::{self, Ty, TyCtxt}; -use rustc_middle::ty::{ReLateBound, ReVar}; +use rustc_middle::ty::{ReBound, ReVar}; use rustc_middle::ty::{Region, RegionVid}; use rustc_span::Span; @@ -531,7 +531,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { debug!("origin = {:#?}", origin); match (*sub, *sup) { - (ReLateBound(..), _) | (_, ReLateBound(..)) => { + (ReBound(..), _) | (_, ReBound(..)) => { span_bug!(origin.span(), "cannot relate bound region: {:?} <= {:?}", sub, sup); } (_, ReStatic) => { @@ -667,7 +667,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { | ty::ReError(_) => ty::UniverseIndex::ROOT, ty::RePlaceholder(placeholder) => placeholder.universe, ty::ReVar(vid) => self.var_universe(vid), - ty::ReLateBound(..) => bug!("universe(): encountered bound region {:?}", region), + ty::ReBound(..) => bug!("universe(): encountered bound region {:?}", region), } } diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs index 3c566e0dd6da..8cee13ce4ec7 100644 --- a/compiler/rustc_infer/src/traits/util.rs +++ b/compiler/rustc_infer/src/traits/util.rs @@ -340,7 +340,7 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> { // consider this as evidence that `T: 'static`, but // I'm a bit wary of such constructions and so for now // I want to be conservative. --nmatsakis - if r_min.is_late_bound() { + if r_min.is_bound() { return; } @@ -351,7 +351,7 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> { .into_iter() .filter_map(|component| match component { Component::Region(r) => { - if r.is_late_bound() { + if r.is_bound() { None } else { Some(ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate( diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs index 64b63f4c5eb4..5a957d2c26d6 100644 --- a/compiler/rustc_middle/src/infer/canonical.rs +++ b/compiler/rustc_middle/src/infer/canonical.rs @@ -63,7 +63,7 @@ impl CanonicalVarValues<'_> { pub fn is_identity(&self) -> bool { self.var_values.iter().enumerate().all(|(bv, arg)| match arg.unpack() { ty::GenericArgKind::Lifetime(r) => { - matches!(*r, ty::ReLateBound(ty::INNERMOST, br) if br.var.as_usize() == bv) + matches!(*r, ty::ReBound(ty::INNERMOST, br) if br.var.as_usize() == bv) } ty::GenericArgKind::Type(ty) => { matches!(*ty.kind(), ty::Bound(ty::INNERMOST, bt) if bt.var.as_usize() == bv) @@ -79,7 +79,7 @@ impl CanonicalVarValues<'_> { for arg in self.var_values { match arg.unpack() { ty::GenericArgKind::Lifetime(r) => { - if let ty::ReLateBound(ty::INNERMOST, br) = *r + if let ty::ReBound(ty::INNERMOST, br) = *r && var == br.var { var = var + 1; @@ -389,7 +389,7 @@ impl<'tcx> CanonicalVarValues<'tcx> { var: ty::BoundVar::from_usize(i), kind: ty::BrAnon, }; - ty::Region::new_late_bound(tcx, ty::INNERMOST, br).into() + ty::Region::new_bound(tcx, ty::INNERMOST, br).into() } CanonicalVarKind::Effect => ty::Const::new_bound( tcx, diff --git a/compiler/rustc_middle/src/infer/unify_key.rs b/compiler/rustc_middle/src/infer/unify_key.rs index 041a63776d11..92d1fcc7ed24 100644 --- a/compiler/rustc_middle/src/infer/unify_key.rs +++ b/compiler/rustc_middle/src/infer/unify_key.rs @@ -58,8 +58,7 @@ impl<'tcx> UnifyValue for UnifiedRegion<'tcx> { fn unify_values(value1: &Self, value2: &Self) -> Result { // We pick the value of the least universe because it is compatible with more variables. - // This is *not* necessary for soundness, but it allows more region variables to be - // resolved to the said value. + // This is *not* necessary for completeness. #[cold] fn min_universe<'tcx>(r1: Region<'tcx>, r2: Region<'tcx>) -> Region<'tcx> { cmp::min_by_key(r1, r2, |r| match r.kind() { @@ -69,7 +68,7 @@ impl<'tcx> UnifyValue for UnifiedRegion<'tcx> { | ty::ReEarlyBound(..) | ty::ReError(_) => ty::UniverseIndex::ROOT, ty::RePlaceholder(placeholder) => placeholder.universe, - ty::ReVar(..) | ty::ReLateBound(..) => bug!("not a universal region"), + ty::ReVar(..) | ty::ReBound(..) => bug!("not a universal region"), }) } diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index 0540eb0efd6c..d609965f36fe 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -416,7 +416,7 @@ impl<'tcx> ClosureOutlivesSubjectTy<'tcx> { let inner = tcx.fold_regions(ty, |r, depth| match r.kind() { ty::ReVar(vid) => { let br = ty::BoundRegion { var: ty::BoundVar::new(vid.index()), kind: ty::BrAnon }; - ty::Region::new_late_bound(tcx, depth, br) + ty::Region::new_bound(tcx, depth, br) } _ => bug!("unexpected region in ClosureOutlivesSubjectTy: {r:?}"), }); @@ -430,7 +430,7 @@ impl<'tcx> ClosureOutlivesSubjectTy<'tcx> { mut map: impl FnMut(ty::RegionVid) -> ty::Region<'tcx>, ) -> Ty<'tcx> { tcx.fold_regions(self.inner, |r, depth| match r.kind() { - ty::ReLateBound(debruijn, br) => { + ty::ReBound(debruijn, br) => { debug_assert_eq!(debruijn, depth); map(ty::RegionVid::new(br.var.index())) } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 551c4a15dd0d..1598d05251d4 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -327,7 +327,7 @@ pub struct CommonLifetimes<'tcx> { pub re_vars: Vec>, /// Pre-interned values of the form: - /// `ReLateBound(DebruijnIndex(i), BoundRegion { var: v, kind: BrAnon })` + /// `ReBound(DebruijnIndex(i), BoundRegion { var: v, kind: BrAnon })` /// for small values of `i` and `v`. pub re_late_bounds: Vec>>, } @@ -402,7 +402,7 @@ impl<'tcx> CommonLifetimes<'tcx> { .map(|i| { (0..NUM_PREINTERNED_RE_LATE_BOUNDS_V) .map(|v| { - mk(ty::ReLateBound( + mk(ty::ReBound( ty::DebruijnIndex::from(i), ty::BoundRegion { var: ty::BoundVar::from(v), kind: ty::BrAnon }, )) diff --git a/compiler/rustc_middle/src/ty/erase_regions.rs b/compiler/rustc_middle/src/ty/erase_regions.rs index 3371ea3bec8c..cfd36fd8c7c3 100644 --- a/compiler/rustc_middle/src/ty/erase_regions.rs +++ b/compiler/rustc_middle/src/ty/erase_regions.rs @@ -53,16 +53,11 @@ impl<'tcx> TypeFolder> for RegionEraserVisitor<'tcx> { } fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - // because late-bound regions affect subtyping, we can't - // erase the bound/free distinction, but we can replace - // all free regions with 'erased. - // - // Note that we *CAN* replace early-bound regions -- the - // type system never "sees" those, they get substituted - // away. In codegen, they will always be erased to 'erased - // whenever a substitution occurs. + // We must not erase bound regions. `for<'a> fn(&'a ())` and + // `fn(&'free ())` are different types: they may implement different + // traits and have a different `TypeId`. match *r { - ty::ReLateBound(..) => r, + ty::ReBound(..) => r, _ => self.tcx.lifetimes.re_erased, } } diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index ec36bdc5a518..a2e709165d55 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -294,7 +294,7 @@ impl FlagComputation { fn add_region(&mut self, r: ty::Region<'_>) { self.add_flags(r.type_flags()); - if let ty::ReLateBound(debruijn, _) = *r { + if let ty::ReBound(debruijn, _) = *r { self.add_bound_var(debruijn); } } diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index 00529a1e066c..e8ff3b230cbb 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -68,12 +68,10 @@ impl<'tcx> TyCtxt<'tcx> { /// Folds over the substructure of a type, visiting its component /// types and all regions that occur *free* within it. /// -/// That is, `Ty` can contain function or method types that bind -/// regions at the call site (`ReLateBound`), and occurrences of -/// regions (aka "lifetimes") that are bound within a type are not -/// visited by this folder; only regions that occur free will be +/// That is, function pointer types and trait object can introduce +/// new bound regions which are not visited by this visitors as +/// they are not free; only regions that occur free will be /// visited by `fld_r`. - pub struct RegionFolder<'a, 'tcx> { tcx: TyCtxt<'tcx>, @@ -117,7 +115,7 @@ impl<'a, 'tcx> TypeFolder> for RegionFolder<'a, 'tcx> { #[instrument(skip(self), level = "debug", ret)] fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { match *r { - ty::ReLateBound(debruijn, _) if debruijn < self.current_index => { + ty::ReBound(debruijn, _) if debruijn < self.current_index => { debug!(?self.current_index, "skipped bound region"); r } @@ -205,15 +203,15 @@ where fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { match *r { - ty::ReLateBound(debruijn, br) if debruijn == self.current_index => { + ty::ReBound(debruijn, br) if debruijn == self.current_index => { let region = self.delegate.replace_region(br); - if let ty::ReLateBound(debruijn1, br) = *region { - // If the callback returns a late-bound region, + if let ty::ReBound(debruijn1, br) = *region { + // If the callback returns a bound region, // that region should always use the INNERMOST // debruijn index. Then we adjust it to the // correct depth. assert_eq!(debruijn1, ty::INNERMOST); - ty::Region::new_late_bound(self.tcx, debruijn, br) + ty::Region::new_bound(self.tcx, debruijn, br) } else { region } @@ -341,7 +339,7 @@ impl<'tcx> TyCtxt<'tcx> { value, FnMutDelegate { regions: &mut |r: ty::BoundRegion| { - ty::Region::new_late_bound( + ty::Region::new_bound( self, ty::INNERMOST, ty::BoundRegion { var: shift_bv(r.var), kind: r.kind }, @@ -388,7 +386,7 @@ impl<'tcx> TyCtxt<'tcx> { .or_insert_with(|| ty::BoundVariableKind::Region(ty::BrAnon)) .expect_region(); let br = ty::BoundRegion { var, kind }; - ty::Region::new_late_bound(self.tcx, ty::INNERMOST, br) + ty::Region::new_bound(self.tcx, ty::INNERMOST, br) } fn replace_ty(&mut self, bt: ty::BoundTy) -> Ty<'tcx> { let entry = self.map.entry(bt.var); @@ -454,9 +452,9 @@ impl<'tcx> TypeFolder> for Shifter<'tcx> { fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { match *r { - ty::ReLateBound(debruijn, br) if debruijn >= self.current_index => { + ty::ReBound(debruijn, br) if debruijn >= self.current_index => { let debruijn = debruijn.shifted_in(self.amount); - ty::Region::new_late_bound(self.tcx, debruijn, br) + ty::Region::new_bound(self.tcx, debruijn, br) } _ => r, } @@ -496,8 +494,8 @@ pub fn shift_region<'tcx>( amount: u32, ) -> ty::Region<'tcx> { match *region { - ty::ReLateBound(debruijn, br) if amount > 0 => { - ty::Region::new_late_bound(tcx, debruijn.shifted_in(amount), br) + ty::ReBound(debruijn, br) if amount > 0 => { + ty::Region::new_bound(tcx, debruijn.shifted_in(amount), br) } _ => region, } diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs index 41a1bf04e5f3..c9607b2245a7 100644 --- a/compiler/rustc_middle/src/ty/generic_args.rs +++ b/compiler/rustc_middle/src/ty/generic_args.rs @@ -843,7 +843,7 @@ impl<'a, 'tcx> TypeFolder> for ArgFolder<'a, 'tcx> { None => region_param_out_of_range(data, self.args), } } - ty::ReLateBound(..) + ty::ReBound(..) | ty::ReFree(_) | ty::ReStatic | ty::RePlaceholder(_) diff --git a/compiler/rustc_middle/src/ty/opaque_types.rs b/compiler/rustc_middle/src/ty/opaque_types.rs index 8d895732dff2..cabf2ab5dfec 100644 --- a/compiler/rustc_middle/src/ty/opaque_types.rs +++ b/compiler/rustc_middle/src/ty/opaque_types.rs @@ -102,8 +102,9 @@ impl<'tcx> TypeFolder> for ReverseMapper<'tcx> { // Ignore bound regions and `'static` regions that appear in the // type, we only need to remap regions that reference lifetimes // from the function declaration. - // This would ignore `'r` in a type like `for<'r> fn(&'r u32)`. - ty::ReLateBound(..) | ty::ReStatic => return r, + // + // E.g. We ignore `'r` in a type like `for<'r> fn(&'r u32)`. + ty::ReBound(..) | ty::ReStatic => return r, // If regions have been erased (by writeback), don't try to unerase // them. diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index baf160bcc99d..21bf5b4b3b1b 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -2160,7 +2160,7 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> { match *region { ty::ReEarlyBound(ref data) => data.has_name(), - ty::ReLateBound(_, ty::BoundRegion { kind: br, .. }) + ty::ReBound(_, ty::BoundRegion { kind: br, .. }) | ty::ReFree(ty::FreeRegion { bound_region: br, .. }) | ty::RePlaceholder(ty::Placeholder { bound: ty::BoundRegion { kind: br, .. }, .. @@ -2234,7 +2234,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { return Ok(()); } } - ty::ReLateBound(_, ty::BoundRegion { kind: br, .. }) + ty::ReBound(_, ty::BoundRegion { kind: br, .. }) | ty::ReFree(ty::FreeRegion { bound_region: br, .. }) | ty::RePlaceholder(ty::Placeholder { bound: ty::BoundRegion { kind: br, .. }, .. @@ -2315,7 +2315,7 @@ impl<'a, 'tcx> ty::TypeFolder> for RegionFolder<'a, 'tcx> { fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { let name = &mut self.name; let region = match *r { - ty::ReLateBound(db, br) if db >= self.current_index => { + ty::ReBound(db, br) if db >= self.current_index => { *self.region_map.entry(br).or_insert_with(|| name(Some(db), self.current_index, br)) } ty::RePlaceholder(ty::PlaceholderRegion { @@ -2338,9 +2338,9 @@ impl<'a, 'tcx> ty::TypeFolder> for RegionFolder<'a, 'tcx> { } _ => return r, }; - if let ty::ReLateBound(debruijn1, br) = *region { + if let ty::ReBound(debruijn1, br) = *region { assert_eq!(debruijn1, ty::INNERMOST); - ty::Region::new_late_bound(self.tcx, self.current_index, br) + ty::Region::new_bound(self.tcx, self.current_index, br) } else { region } @@ -2450,7 +2450,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { if let Some(lt_idx) = lifetime_idx { if lt_idx > binder_level_idx { let kind = ty::BrNamed(CRATE_DEF_ID.to_def_id(), name); - return ty::Region::new_late_bound( + return ty::Region::new_bound( tcx, ty::INNERMOST, ty::BoundRegion { var: br.var, kind }, @@ -2466,7 +2466,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { if let Some(lt_idx) = lifetime_idx { if lt_idx > binder_level_idx { let kind = ty::BrNamed(def_id, name); - return ty::Region::new_late_bound( + return ty::Region::new_bound( tcx, ty::INNERMOST, ty::BoundRegion { var: br.var, kind }, @@ -2480,7 +2480,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { if let Some(lt_idx) = lifetime_idx { if lt_idx > binder_level_idx { let kind = br.kind; - return ty::Region::new_late_bound( + return ty::Region::new_bound( tcx, ty::INNERMOST, ty::BoundRegion { var: br.var, kind }, @@ -2496,11 +2496,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { start_or_continue(self, "for<", ", "); do_continue(self, name); } - ty::Region::new_late_bound( - tcx, - ty::INNERMOST, - ty::BoundRegion { var: br.var, kind }, - ) + ty::Region::new_bound(tcx, ty::INNERMOST, ty::BoundRegion { var: br.var, kind }) }; let mut folder = RegionFolder { tcx, diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 44592b10d557..ca6ad4ea5c7c 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1476,7 +1476,7 @@ impl<'tcx> Region<'tcx> { } #[inline] - pub fn new_late_bound( + pub fn new_bound( tcx: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, bound_region: ty::BoundRegion, @@ -1488,7 +1488,7 @@ impl<'tcx> Region<'tcx> { { re } else { - tcx.intern_region(ty::ReLateBound(debruijn, bound_region)) + tcx.intern_region(ty::ReBound(debruijn, bound_region)) } } @@ -1550,7 +1550,7 @@ impl<'tcx> Region<'tcx> { pub fn new_from_kind(tcx: TyCtxt<'tcx>, kind: RegionKind<'tcx>) -> Region<'tcx> { match kind { ty::ReEarlyBound(region) => Region::new_early_bound(tcx, region), - ty::ReLateBound(debruijn, region) => Region::new_late_bound(tcx, debruijn, region), + ty::ReBound(debruijn, region) => Region::new_bound(tcx, debruijn, region), ty::ReFree(ty::FreeRegion { scope, bound_region }) => { Region::new_free(tcx, scope, bound_region) } @@ -1723,7 +1723,7 @@ impl<'tcx> Region<'tcx> { if self.has_name() { match *self { ty::ReEarlyBound(ebr) => Some(ebr.name), - ty::ReLateBound(_, br) => br.kind.get_name(), + ty::ReBound(_, br) => br.kind.get_name(), ty::ReFree(fr) => fr.bound_region.get_name(), ty::ReStatic => Some(kw::StaticLifetime), ty::RePlaceholder(placeholder) => placeholder.bound.kind.get_name(), @@ -1745,7 +1745,7 @@ impl<'tcx> Region<'tcx> { pub fn has_name(self) -> bool { match *self { ty::ReEarlyBound(ebr) => ebr.has_name(), - ty::ReLateBound(_, br) => br.kind.is_named(), + ty::ReBound(_, br) => br.kind.is_named(), ty::ReFree(fr) => fr.bound_region.is_named(), ty::ReStatic => true, ty::ReVar(..) => false, @@ -1771,8 +1771,8 @@ impl<'tcx> Region<'tcx> { } #[inline] - pub fn is_late_bound(self) -> bool { - matches!(*self, ty::ReLateBound(..)) + pub fn is_bound(self) -> bool { + matches!(*self, ty::ReBound(..)) } #[inline] @@ -1783,7 +1783,7 @@ impl<'tcx> Region<'tcx> { #[inline] pub fn bound_at_or_above_binder(self, index: ty::DebruijnIndex) -> bool { match *self { - ty::ReLateBound(debruijn, _) => debruijn >= index, + ty::ReBound(debruijn, _) => debruijn >= index, _ => false, } } @@ -1814,7 +1814,7 @@ impl<'tcx> Region<'tcx> { ty::ReStatic => { flags = flags | TypeFlags::HAS_FREE_REGIONS; } - ty::ReLateBound(..) => { + ty::ReBound(..) => { flags = flags | TypeFlags::HAS_RE_LATE_BOUND; } ty::ReErased => { diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs index e9240d1b268e..1a76a8d350d2 100644 --- a/compiler/rustc_middle/src/ty/typeck_results.rs +++ b/compiler/rustc_middle/src/ty/typeck_results.rs @@ -638,7 +638,7 @@ impl<'tcx> IsIdentity for CanonicalUserType<'tcx> { }, GenericArgKind::Lifetime(r) => match *r { - ty::ReLateBound(debruijn, br) => { + ty::ReBound(debruijn, br) => { // We only allow a `ty::INNERMOST` index in substitutions. assert_eq!(debruijn, ty::INNERMOST); cvar == br.var diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index a251518d1457..144e98f784a4 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -468,7 +468,7 @@ impl<'tcx> TyCtxt<'tcx> { for arg in args { match arg.unpack() { GenericArgKind::Lifetime(lt) => match (ignore_regions, lt.kind()) { - (CheckRegions::Bound, ty::ReLateBound(di, reg)) => { + (CheckRegions::Bound, ty::ReBound(di, reg)) => { if !seen_late.insert((di, reg)) { return Err(NotUniqueParam::DuplicateParam(lt.into())); } diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs index 8fc5c0302778..ee1cd76aa8be 100644 --- a/compiler/rustc_middle/src/ty/visit.rs +++ b/compiler/rustc_middle/src/ty/visit.rs @@ -204,7 +204,7 @@ impl<'tcx> TyCtxt<'tcx> { fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { match *r { - ty::ReLateBound(debruijn, _) if debruijn < self.outer_index => { + ty::ReBound(debruijn, _) if debruijn < self.outer_index => { ControlFlow::Continue(()) } _ => { @@ -337,7 +337,7 @@ impl<'tcx> TypeVisitor> for ValidateBoundVars<'tcx> { fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { match *r { - ty::ReLateBound(index, br) if index == self.binder_index => { + ty::ReBound(index, br) if index == self.binder_index => { if self.bound_vars.len() <= br.var.as_usize() { bug!("Not enough bound vars: {:?} not found in {:?}", br, self.bound_vars); } @@ -613,7 +613,7 @@ impl<'tcx> TypeVisitor> for LateBoundRegionsCollector { } fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { - if let ty::ReLateBound(debruijn, br) = *r { + if let ty::ReBound(debruijn, br) = *r { if debruijn == self.current_index { self.regions.insert(br.kind); } diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs index b6adb383fa6b..bcd9140f0e18 100644 --- a/compiler/rustc_mir_build/src/thir/cx/mod.rs +++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs @@ -132,7 +132,7 @@ impl<'tcx> Cx<'tcx> { var: ty::BoundVar::from_usize(bound_vars.len() - 1), kind: ty::BrEnv, }; - let env_region = ty::Region::new_late_bound(self.tcx, ty::INNERMOST, br); + let env_region = ty::Region::new_bound(self.tcx, ty::INNERMOST, br); let closure_env_ty = self.tcx.closure_env_ty(closure_def_id, closure_args, env_region).unwrap(); let liberated_closure_env_ty = self.tcx.erase_late_bound_regions( diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index 27596c08f1c1..d3bd87bb360e 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -1696,7 +1696,7 @@ impl<'tcx> Stable<'tcx> for ty::RegionKind<'tcx> { index: early_reg.index, name: early_reg.name.to_string(), }), - ty::ReLateBound(db_index, bound_reg) => RegionKind::ReLateBound( + ty::ReBound(db_index, bound_reg) => RegionKind::ReBound( db_index.as_u32(), BoundRegion { var: bound_reg.var.as_u32(), kind: bound_reg.kind.stable(tables) }, ), diff --git a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs index 5ce188488ce5..80dec80bf03a 100644 --- a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs +++ b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs @@ -270,7 +270,7 @@ fn encode_region<'tcx>( // u6region[I[][]E] as vendor extended type let mut s = String::new(); match region.kind() { - RegionKind::ReLateBound(debruijn, r) => { + RegionKind::ReBound(debruijn, r) => { s.push_str("u6regionI"); // Debruijn index, which identifies the binder, as region disambiguator let num = debruijn.index() as u64; @@ -282,6 +282,7 @@ fn encode_region<'tcx>( s.push('E'); compress(dict, DictKey::Region(region), &mut s); } + // FIXME(@lcnr): Why is `ReEarlyBound` reachable here. RegionKind::ReEarlyBound(..) | RegionKind::ReErased => { s.push_str("u6region"); compress(dict, DictKey::Region(region), &mut s); diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index ad3d291dfa08..01cbee3a7159 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -319,9 +319,9 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { // shorter mangling of `L_`. ty::ReErased => 0, - // Late-bound lifetimes use indices starting at 1, + // Bound lifetimes use indices starting at 1, // see `BinderLevel` for more details. - ty::ReLateBound(debruijn, ty::BoundRegion { var, kind: ty::BrAnon }) => { + ty::ReBound(debruijn, ty::BoundRegion { var, kind: ty::BrAnon }) => { let binder = &self.binders[self.binders.len() - 1 - debruijn.index()]; let depth = binder.lifetime_depths.start + var.as_u32(); diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs index 839968b25a1b..03b78681fa29 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs @@ -97,7 +97,7 @@ pub(in crate::solve) fn replace_erased_lifetimes_with_bound_vars<'tcx>( ty::ReErased => { let br = ty::BoundRegion { var: ty::BoundVar::from_u32(counter), kind: ty::BrAnon }; counter += 1; - ty::Region::new_late_bound(tcx, current_depth, br) + ty::Region::new_bound(tcx, current_depth, br) } // All free regions should be erased here. r => bug!("unexpected region: {r:?}"), diff --git a/compiler/rustc_trait_selection/src/solve/canonicalize.rs b/compiler/rustc_trait_selection/src/solve/canonicalize.rs index 377ae1b4e85f..5f08bc0039ae 100644 --- a/compiler/rustc_trait_selection/src/solve/canonicalize.rs +++ b/compiler/rustc_trait_selection/src/solve/canonicalize.rs @@ -222,7 +222,7 @@ impl<'tcx> TypeFolder> for Canonicalizer<'_, 'tcx> { } let kind = match *r { - ty::ReLateBound(..) => return r, + ty::ReBound(..) => return r, // We may encounter `ReStatic` in item signatures or the hidden type // of an opaque. `ReErased` should only be encountered in the hidden @@ -278,7 +278,7 @@ impl<'tcx> TypeFolder> for Canonicalizer<'_, 'tcx> { var }); let br = ty::BoundRegion { var, kind: BrAnon }; - ty::Region::new_late_bound(self.interner(), self.binder_index, br) + ty::Region::new_bound(self.interner(), self.binder_index, br) } fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs index b3f9218d7619..ae7f6ca2f7a0 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs @@ -262,7 +262,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { } } GenericArgKind::Lifetime(r) => { - if let ty::ReLateBound(debruijn, br) = *r { + if let ty::ReBound(debruijn, br) = *r { assert_eq!(debruijn, ty::INNERMOST); opt_values[br.var] = Some(*original_value); } diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 8096d7969f39..dbf6749b5237 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -410,11 +410,11 @@ impl<'tcx> AutoTraitFinder<'tcx> { iter::zip(new_args.regions(), old_args.regions()) { match (*new_region, *old_region) { - // If both predicates have an `ReLateBound` (a HRTB) in the + // If both predicates have an `ReBound` (a HRTB) in the // same spot, we do nothing. - (ty::ReLateBound(_, _), ty::ReLateBound(_, _)) => {} + (ty::ReBound(_, _), ty::ReBound(_, _)) => {} - (ty::ReLateBound(_, _), _) | (_, ty::ReVar(_)) => { + (ty::ReBound(_, _), _) | (_, ty::ReVar(_)) => { // One of these is true: // The new predicate has a HRTB in a spot where the old // predicate does not (if they both had a HRTB, the previous @@ -440,7 +440,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { // `user_computed_preds`. return false; } - (_, ty::ReLateBound(_, _)) | (ty::ReVar(_), _) => { + (_, ty::ReBound(_, _)) | (ty::ReVar(_), _) => { // This is the opposite situation as the previous arm. // One of these is true: // diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 6b09bc89873e..3afab24acb61 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -740,7 +740,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } // We `erase_late_bound_regions` here because `make_subregion` does not handle - // `ReLateBound`, and we don't particularly care about the regions. + // `ReBound`, and we don't particularly care about the regions. let real_ty = self.tcx.erase_late_bound_regions(real_trait_pred.self_ty()); if !self.can_eq(obligation.param_env, real_ty, arg_ty) { continue; diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 471d10dbdbd8..d03704c1d64e 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -894,16 +894,16 @@ impl<'tcx> TypeFolder> for BoundVarReplacer<'_, 'tcx> { fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { match *r { - ty::ReLateBound(debruijn, _) - if debruijn.as_usize() + 1 - > self.current_index.as_usize() + self.universe_indices.len() => + ty::ReBound(debruijn, _) + if debruijn.as_usize() + >= self.current_index.as_usize() + self.universe_indices.len() => { bug!( "Bound vars {r:#?} outside of `self.universe_indices`: {:#?}", self.universe_indices ); } - ty::ReLateBound(debruijn, br) if debruijn >= self.current_index => { + ty::ReBound(debruijn, br) if debruijn >= self.current_index => { let universe = self.universe_for(debruijn); let p = ty::PlaceholderRegion { universe, bound: br }; self.mapped_regions.insert(p, br); @@ -1034,7 +1034,7 @@ impl<'tcx> TypeFolder> for PlaceholderReplacer<'_, 'tcx> { let db = ty::DebruijnIndex::from_usize( self.universe_indices.len() - index + self.current_index.as_usize() - 1, ); - ty::Region::new_late_bound(self.interner(), db, *replace_var) + ty::Region::new_bound(self.interner(), db, *replace_var) } None => r1, } diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index 2e31b560b38f..dba00ce0154b 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -150,7 +150,7 @@ impl<'tcx> TypeVisitor> for MaxEscapingBoundVarVisitor { #[inline] fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { match *r { - ty::ReLateBound(debruijn, _) if debruijn > self.outer_index => { + ty::ReBound(debruijn, _) if debruijn > self.outer_index => { self.escaping = self.escaping.max(debruijn.as_usize() - self.outer_index.as_usize()); } diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 4bfa341e3332..6205ef052202 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -592,7 +592,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let kind = ty::BoundRegionKind::BrNamed(param.def_id, param.name); let bound_var = ty::BoundVariableKind::Region(kind); bound_vars.push(bound_var); - ty::Region::new_late_bound( + ty::Region::new_bound( tcx, ty::INNERMOST, ty::BoundRegion { diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 08208cc60475..6d13f4dbc997 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -3103,7 +3103,7 @@ fn bind_coroutine_hidden_types_above<'tcx>( kind: ty::BrAnon, }; counter += 1; - ty::Region::new_late_bound(tcx, current_depth, br) + ty::Region::new_bound(tcx, current_depth, br) } r => bug!("unexpected region: {r:?}"), }) diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index fcf6626bbf05..38f2d616f9a5 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -82,7 +82,7 @@ fn fn_sig_for_fn_abi<'tcx>( var: ty::BoundVar::from_usize(bound_vars.len() - 1), kind: ty::BoundRegionKind::BrEnv, }; - let env_region = ty::Region::new_late_bound(tcx, ty::INNERMOST, br); + let env_region = ty::Region::new_bound(tcx, ty::INNERMOST, br); let env_ty = tcx.closure_env_ty(def_id, args, env_region).unwrap(); let sig = sig.skip_binder(); @@ -107,8 +107,7 @@ fn fn_sig_for_fn_abi<'tcx>( var: ty::BoundVar::from_usize(bound_vars.len() - 1), kind: ty::BoundRegionKind::BrEnv, }; - let env_ty = - Ty::new_mut_ref(tcx, ty::Region::new_late_bound(tcx, ty::INNERMOST, br), ty); + let env_ty = Ty::new_mut_ref(tcx, ty::Region::new_bound(tcx, ty::INNERMOST, br), ty); let pin_did = tcx.require_lang_item(LangItem::Pin, None); let pin_adt_ref = tcx.adt_def(pin_did); diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index abf3e108ed48..2b262cfdebd3 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -195,7 +195,7 @@ impl<'tcx> TypeVisitor> for ImplTraitInTraitFinder<'_, 'tcx> { // bounds of the RPITIT. Shift these binders back out when // constructing the top-level projection predicate. let shifted_alias_ty = self.tcx.fold_regions(unshifted_alias_ty, |re, depth| { - if let ty::ReLateBound(index, bv) = re.kind() { + if let ty::ReBound(index, bv) = re.kind() { if depth != ty::INNERMOST { return ty::Region::new_error_with_message( self.tcx, @@ -203,7 +203,7 @@ impl<'tcx> TypeVisitor> for ImplTraitInTraitFinder<'_, 'tcx> { "we shouldn't walk non-predicate binders with `impl Trait`...", ); } - ty::Region::new_late_bound( + ty::Region::new_bound( self.tcx, index.shifted_out_to_binder(self.depth), bv, diff --git a/compiler/rustc_type_ir/src/flags.rs b/compiler/rustc_type_ir/src/flags.rs index 8472a0845053..a7dda717517b 100644 --- a/compiler/rustc_type_ir/src/flags.rs +++ b/compiler/rustc_type_ir/src/flags.rs @@ -85,10 +85,10 @@ bitflags! { const HAS_ERROR = 1 << 14; /// Does this have any region that "appears free" in the type? - /// Basically anything but `ReLateBound` and `ReErased`. + /// Basically anything but `ReBound` and `ReErased`. const HAS_FREE_REGIONS = 1 << 15; - /// Does this have any `ReLateBound` regions? + /// Does this have any `ReBound` regions? const HAS_RE_LATE_BOUND = 1 << 16; /// Does this have any `Bound` types? const HAS_TY_LATE_BOUND = 1 << 17; diff --git a/compiler/rustc_type_ir/src/region_kind.rs b/compiler/rustc_type_ir/src/region_kind.rs index 69ed5badaea3..fc9eaf63ac82 100644 --- a/compiler/rustc_type_ir/src/region_kind.rs +++ b/compiler/rustc_type_ir/src/region_kind.rs @@ -128,9 +128,16 @@ pub enum RegionKind { /// parameters are substituted. ReEarlyBound(I::EarlyBoundRegion), - /// Region bound in a function scope, which will be substituted when the - /// function is called. - ReLateBound(DebruijnIndex, I::BoundRegion), + /// A higher-ranked region. These represent either late-bound function parameters + /// or bound variables from a `for<'a>`-binder. + /// + /// While inside of a function, e.g. during typeck, the late-bound function parameters + /// can be converted to `ReFree` by calling `tcx.liberate_late_bound_regions`. + /// + /// Bound regions inside of types **must not** be erased, as they impact trait + /// selection and the `TypeId` of that type. `for<'a> fn(&'a ())` and + /// `fn(&'static ())` are different types and have to be treated as such. + ReBound(DebruijnIndex, I::BoundRegion), /// When checking a function body, the types of all arguments and so forth /// that refer to bound region parameters are modified to refer to free @@ -160,7 +167,7 @@ pub enum RegionKind { const fn regionkind_discriminant(value: &RegionKind) -> usize { match value { ReEarlyBound(_) => 0, - ReLateBound(_, _) => 1, + ReBound(_, _) => 1, ReFree(_) => 2, ReStatic => 3, ReVar(_) => 4, @@ -189,7 +196,7 @@ impl PartialEq for RegionKind { regionkind_discriminant(self) == regionkind_discriminant(other) && match (self, other) { (ReEarlyBound(a_r), ReEarlyBound(b_r)) => a_r == b_r, - (ReLateBound(a_d, a_r), ReLateBound(b_d, b_r)) => a_d == b_d && a_r == b_r, + (ReBound(a_d, a_r), ReBound(b_d, b_r)) => a_d == b_d && a_r == b_r, (ReFree(a_r), ReFree(b_r)) => a_r == b_r, (ReStatic, ReStatic) => true, (ReVar(a_r), ReVar(b_r)) => a_r == b_r, @@ -218,8 +225,8 @@ impl DebugWithInfcx for RegionKind { match this.data { ReEarlyBound(data) => write!(f, "ReEarlyBound({data:?})"), - ReLateBound(binder_id, bound_region) => { - write!(f, "ReLateBound({binder_id:?}, {bound_region:?})") + ReBound(binder_id, bound_region) => { + write!(f, "ReBound({binder_id:?}, {bound_region:?})") } ReFree(fr) => write!(f, "{fr:?}"), @@ -258,7 +265,7 @@ where ReErased | ReStatic | ReError(_) => { // No variant fields to hash for these ... } - ReLateBound(d, r) => { + ReBound(d, r) => { d.hash_stable(hcx, hasher); r.hash_stable(hcx, hasher); } diff --git a/compiler/stable_mir/src/ty.rs b/compiler/stable_mir/src/ty.rs index 5dfaa0fd8915..bd3feef60185 100644 --- a/compiler/stable_mir/src/ty.rs +++ b/compiler/stable_mir/src/ty.rs @@ -62,7 +62,7 @@ pub struct Region { #[derive(Clone, Debug, Eq, PartialEq)] pub enum RegionKind { ReEarlyBound(EarlyBoundRegion), - ReLateBound(DebruijnIndex, BoundRegion), + ReBound(DebruijnIndex, BoundRegion), ReStatic, RePlaceholder(Placeholder), ReErased, diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index bdf6a0f6b239..eb946e82f399 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -743,7 +743,7 @@ impl<'a, 'tcx> TypeFolder> for RegionReplacer<'a, 'tcx> { match *r { // These are the regions that can be seen in the AST. ty::ReVar(vid) => self.vid_to_region.get(&vid).cloned().unwrap_or(r), - ty::ReEarlyBound(_) | ty::ReStatic | ty::ReLateBound(..) | ty::ReError(_) => r, + ty::ReEarlyBound(_) | ty::ReStatic | ty::ReBound(..) | ty::ReError(_) => r, r => bug!("unexpected region: {r:?}"), } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 1b7ca7bf7dd0..d33e41dc2b39 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -286,11 +286,9 @@ pub(crate) fn clean_middle_region<'tcx>(region: ty::Region<'tcx>) -> Option Some(Lifetime::statik()), _ if !region.has_name() => None, - ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name), .. }) => { - Some(Lifetime(name)) - } + ty::ReBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name), .. }) => Some(Lifetime(name)), ty::ReEarlyBound(ref data) => Some(Lifetime(data.name)), - ty::ReLateBound(..) + ty::ReBound(..) | ty::ReFree(..) | ty::ReVar(..) | ty::ReError(_) @@ -1931,13 +1929,11 @@ fn clean_trait_object_lifetime_bound<'tcx>( match *region { ty::ReStatic => Some(Lifetime::statik()), ty::ReEarlyBound(region) if region.name != kw::Empty => Some(Lifetime(region.name)), - ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name), .. }) - if name != kw::Empty => - { + ty::ReBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name), .. }) if name != kw::Empty => { Some(Lifetime(name)) } ty::ReEarlyBound(_) - | ty::ReLateBound(..) + | ty::ReBound(..) | ty::ReFree(_) | ty::ReVar(_) | ty::RePlaceholder(_) diff --git a/src/tools/clippy/clippy_lints/src/eta_reduction.rs b/src/tools/clippy/clippy_lints/src/eta_reduction.rs index fad8fbf04497..150b1c777db1 100644 --- a/src/tools/clippy/clippy_lints/src/eta_reduction.rs +++ b/src/tools/clippy/clippy_lints/src/eta_reduction.rs @@ -247,8 +247,8 @@ fn check_sig<'tcx>(cx: &LateContext<'tcx>, closure: ClosureArgs<'tcx>, call_sig: /// This is needed because rustc is unable to late bind early-bound regions in a function signature. fn has_late_bound_to_non_late_bound_regions(from_sig: FnSig<'_>, to_sig: FnSig<'_>) -> bool { fn check_region(from_region: Region<'_>, to_region: Region<'_>) -> bool { - matches!(from_region.kind(), RegionKind::ReLateBound(..)) - && !matches!(to_region.kind(), RegionKind::ReLateBound(..)) + matches!(from_region.kind(), RegionKind::ReBound(..)) + && !matches!(to_region.kind(), RegionKind::ReBound(..)) } fn check_subs(from_subs: &[GenericArg<'_>], to_subs: &[GenericArg<'_>]) -> bool { diff --git a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs index 4d7a055dae17..d6fa742b7968 100644 --- a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs +++ b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs @@ -168,7 +168,7 @@ impl<'tcx> PassByRefOrValue { match *ty.skip_binder().kind() { ty::Ref(lt, ty, Mutability::Not) => { match lt.kind() { - RegionKind::ReLateBound(index, region) + RegionKind::ReBound(index, region) if index.as_u32() == 0 && output_regions.contains(®ion) => { continue; diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs index 83863b92caff..c6ac96a4539c 100644 --- a/src/tools/clippy/clippy_lints/src/ptr.rs +++ b/src/tools/clippy/clippy_lints/src/ptr.rs @@ -466,7 +466,7 @@ fn check_fn_args<'cx, 'tcx: 'cx>( .filter_map(|arg| { arg.as_region().and_then(|lifetime| match lifetime.kind() { ty::ReEarlyBound(r) => Some(r.def_id), - ty::ReLateBound(_, r) => r.kind.get_id(), + ty::ReBound(_, r) => r.kind.get_id(), ty::ReFree(r) => r.bound_region.get_id(), ty::ReStatic | ty::ReVar(_) diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index 7eff93881b26..758aa40a2dd1 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -890,7 +890,7 @@ pub fn for_each_top_level_late_bound_region( impl<'tcx, B, F: FnMut(BoundRegion) -> ControlFlow> TypeVisitor> for V { type BreakTy = B; fn visit_region(&mut self, r: Region<'tcx>) -> ControlFlow { - if let RegionKind::ReLateBound(idx, bound) = r.kind() + if let RegionKind::ReBound(idx, bound) = r.kind() && idx.as_u32() == self.index { (self.f)(bound) diff --git a/tests/ui/coroutine/issue-57084.rs b/tests/ui/coroutine/issue-57084.rs index 95bed5b151ea..e0aeae667350 100644 --- a/tests/ui/coroutine/issue-57084.rs +++ b/tests/ui/coroutine/issue-57084.rs @@ -1,5 +1,5 @@ // This issue reproduces an ICE on compile (E.g. fails on 2018-12-19 nightly). -// "cannot relate bound region: ReLateBound(DebruijnIndex(1), BrAnon(1)) <= '?1" +// "cannot relate bound region: ReBound(DebruijnIndex(1), BrAnon(1)) <= '?1" // run-pass // edition:2018 #![feature(coroutines,coroutine_trait)] diff --git a/tests/ui/nll/closure-requirements/escape-argument-callee.stderr b/tests/ui/nll/closure-requirements/escape-argument-callee.stderr index b3cb7813e19c..a8f6559e4253 100644 --- a/tests/ui/nll/closure-requirements/escape-argument-callee.stderr +++ b/tests/ui/nll/closure-requirements/escape-argument-callee.stderr @@ -6,7 +6,7 @@ LL | let mut closure = expect_sig(|p, y| *p = y); | = note: defining type: test::{closure#0} with closure args [ i16, - for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) mut &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon }) i32)), + for extern "rust-call" fn((&ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) mut &ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) i32, &ReBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon }) i32)), (), ] diff --git a/tests/ui/nll/closure-requirements/escape-argument.stderr b/tests/ui/nll/closure-requirements/escape-argument.stderr index 4f0156728ac1..40f04bb6da67 100644 --- a/tests/ui/nll/closure-requirements/escape-argument.stderr +++ b/tests/ui/nll/closure-requirements/escape-argument.stderr @@ -6,7 +6,7 @@ LL | let mut closure = expect_sig(|p, y| *p = y); | = note: defining type: test::{closure#0} with closure args [ i16, - for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) mut &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) i32)), + for extern "rust-call" fn((&ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) mut &ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) i32, &ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) i32)), (), ] diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr index ccf56bf6f37d..ef2cb4067d7e 100644 --- a/tests/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr +++ b/tests/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr @@ -6,7 +6,7 @@ LL | |_outlives1, _outlives2, _outlives3, x, y| { | = note: defining type: supply::{closure#0} with closure args [ i16, - for extern "rust-call" fn((std::cell::Cell<&'?1 &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>, std::cell::Cell<&'?2 &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) &'?3 u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>)), + for extern "rust-call" fn((std::cell::Cell<&'?1 &ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>, std::cell::Cell<&'?2 &ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>, std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) &'?3 u32>, std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>, std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>)), (), ] = note: late-bound region is '?4 diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-ref.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-ref.stderr index a16433c9d374..db48a4ce70cb 100644 --- a/tests/ui/nll/closure-requirements/propagate-approximated-ref.stderr +++ b/tests/ui/nll/closure-requirements/propagate-approximated-ref.stderr @@ -6,7 +6,7 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y | = note: defining type: supply::{closure#0} with closure args [ i16, - for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) std::cell::Cell<&'?1 &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon }) &'?2 u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrAnon }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon }) u32>)), + for extern "rust-call" fn((&ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) std::cell::Cell<&'?1 &ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>, &ReBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon }) std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon }) &'?2 u32>, &ReBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon }) std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>, &ReBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrAnon }) std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon }) u32>)), (), ] = note: late-bound region is '?3 diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr index 9e0f16c0fc78..5ce3dae5a33d 100644 --- a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr +++ b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr @@ -6,7 +6,7 @@ LL | foo(cell, |cell_a, cell_x| { | = note: defining type: case1::{closure#0} with closure args [ i32, - for extern "rust-call" fn((std::cell::Cell<&'?1 u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>)), + for extern "rust-call" fn((std::cell::Cell<&'?1 u32>, std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>)), (), ] @@ -36,7 +36,7 @@ LL | foo(cell, |cell_a, cell_x| { | = note: defining type: case2::{closure#0} with closure args [ i32, - for extern "rust-call" fn((std::cell::Cell<&'?1 u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>)), + for extern "rust-call" fn((std::cell::Cell<&'?1 u32>, std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>)), (), ] = note: number of external vids: 2 diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr index e4989e321550..ffd526d90afa 100644 --- a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr +++ b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr @@ -6,7 +6,7 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { | = note: defining type: supply::{closure#0} with closure args [ i16, - for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) std::cell::Cell<&'?1 &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon }) u32>)), + for extern "rust-call" fn((&ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) std::cell::Cell<&'?1 &ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>, &ReBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon }) std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>, &ReBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon }) std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon }) u32>)), (), ] = note: late-bound region is '?2 diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr index be35e62d0704..726d0dc2a4c7 100644 --- a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr +++ b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr @@ -6,7 +6,7 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y | = note: defining type: supply::{closure#0} with closure args [ i16, - for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) std::cell::Cell<&'?1 &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon }) std::cell::Cell<&'?2 &ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrAnon }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon }) u32>)), + for extern "rust-call" fn((&ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) std::cell::Cell<&'?1 &ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>, &ReBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon }) std::cell::Cell<&'?2 &ReBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon }) u32>, &ReBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon }) std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>, &ReBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrAnon }) std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon }) u32>)), (), ] = note: late-bound region is '?3 diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-val.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-val.stderr index 8880dd816a1f..5a65c7684485 100644 --- a/tests/ui/nll/closure-requirements/propagate-approximated-val.stderr +++ b/tests/ui/nll/closure-requirements/propagate-approximated-val.stderr @@ -6,7 +6,7 @@ LL | establish_relationships(cell_a, cell_b, |outlives1, outlives2, x, y| { | = note: defining type: test::{closure#0} with closure args [ i16, - for extern "rust-call" fn((std::cell::Cell<&'?1 &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) &'?2 u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>)), + for extern "rust-call" fn((std::cell::Cell<&'?1 &ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>, std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) &'?2 u32>, std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>, std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>)), (), ] = note: late-bound region is '?3 diff --git a/tests/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr b/tests/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr index 47774b63f818..0dd53f81ae13 100644 --- a/tests/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr +++ b/tests/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr @@ -6,7 +6,7 @@ LL | |_outlives1, _outlives2, x, y| { | = note: defining type: supply::{closure#0} with closure args [ i16, - for extern "rust-call" fn((std::cell::Cell<&'?1 &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) &'?2 u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>)), + for extern "rust-call" fn((std::cell::Cell<&'?1 &ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>, std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) &'?2 u32>, std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>, std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>)), (), ] = note: late-bound region is '?3 diff --git a/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr b/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr index 3404bb128278..f7a0ee9b18d2 100644 --- a/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr +++ b/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr @@ -6,7 +6,7 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { | = note: defining type: supply::{closure#0} with closure args [ i16, - for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) &'?1 u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>)), + for extern "rust-call" fn((&ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) &'?1 u32>, &ReBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon }) std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon }) u32>, &ReBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon }) std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>)), (), ] = note: late-bound region is '?2 diff --git a/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr b/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr index e40648912e3c..fa9fa9e8f3c7 100644 --- a/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr +++ b/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr @@ -6,7 +6,7 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y | = note: defining type: supply::{closure#0} with closure args [ i16, - for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) &'?1 u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon }) &'?2 u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrAnon }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon }) u32>)), + for extern "rust-call" fn((&ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) &'?1 u32>, &ReBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon }) std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon }) &'?2 u32>, &ReBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon }) std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>, &ReBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrAnon }) std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon }) u32>)), (), ] = note: late-bound region is '?3 diff --git a/tests/ui/nll/closure-requirements/return-wrong-bound-region.stderr b/tests/ui/nll/closure-requirements/return-wrong-bound-region.stderr index 18fb7195d021..35e4a16c8daf 100644 --- a/tests/ui/nll/closure-requirements/return-wrong-bound-region.stderr +++ b/tests/ui/nll/closure-requirements/return-wrong-bound-region.stderr @@ -6,7 +6,7 @@ LL | expect_sig(|a, b| b); // ought to return `a` | = note: defining type: test::{closure#0} with closure args [ i16, - for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) i32)) -> &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) i32, + for extern "rust-call" fn((&ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) i32, &ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) i32)) -> &ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) i32, (), ] diff --git a/tests/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr b/tests/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr index 59e29e9a420f..0048eef6779e 100644 --- a/tests/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr +++ b/tests/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr @@ -6,7 +6,7 @@ LL | twice(cell, value, |a, b| invoke(a, b)); | = note: defining type: generic::::{closure#0} with closure args [ i16, - for extern "rust-call" fn((std::option::Option>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) T)), + for extern "rust-call" fn((std::option::Option>, &ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) T)), (), ] = note: number of external vids: 2 @@ -28,7 +28,7 @@ LL | twice(cell, value, |a, b| invoke(a, b)); | = note: defining type: generic_fail::::{closure#0} with closure args [ i16, - for extern "rust-call" fn((std::option::Option>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) T)), + for extern "rust-call" fn((std::option::Option>, &ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) T)), (), ] = note: late-bound region is '?2 diff --git a/tests/ui/where-clauses/higher-ranked-fn-type.verbose.stderr b/tests/ui/where-clauses/higher-ranked-fn-type.verbose.stderr index 54afeaa7edab..782e7dc5e005 100644 --- a/tests/ui/where-clauses/higher-ranked-fn-type.verbose.stderr +++ b/tests/ui/where-clauses/higher-ranked-fn-type.verbose.stderr @@ -1,8 +1,8 @@ -error[E0277]: the trait bound `for fn(&ReLateBound(DebruijnIndex(1), BoundRegion { var: 0, kind: BrNamed(DefId(0:6 ~ higher_ranked_fn_type[9e51]::called::'b), 'b) }) ()): Foo` is not satisfied +error[E0277]: the trait bound `for fn(&ReBound(DebruijnIndex(1), BoundRegion { var: 0, kind: BrNamed(DefId(0:6 ~ higher_ranked_fn_type[9e51]::called::'b), 'b) }) ()): Foo` is not satisfied --> $DIR/higher-ranked-fn-type.rs:20:5 | LL | called() - | ^^^^^^ the trait `for Foo` is not implemented for `fn(&ReLateBound(DebruijnIndex(1), BoundRegion { var: 0, kind: BrNamed(DefId(0:6 ~ higher_ranked_fn_type[9e51]::called::'b), 'b) }) ())` + | ^^^^^^ the trait `for Foo` is not implemented for `fn(&ReBound(DebruijnIndex(1), BoundRegion { var: 0, kind: BrNamed(DefId(0:6 ~ higher_ranked_fn_type[9e51]::called::'b), 'b) }) ())` | help: this trait has no implementations, consider adding one --> $DIR/higher-ranked-fn-type.rs:6:1 From dd0739aabe9d67eac30887821df5922ac7a8bcfe Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 13 Nov 2023 14:01:16 +0000 Subject: [PATCH 420/435] continue renaming - `RegionVariableOrigin::~~Late~~BoundRegion` - `~~Late~~BoundRegionConversionTime` --- .../rustc_borrowck/src/diagnostics/mod.rs | 4 ++-- .../src/type_check/input_output.rs | 4 ++-- compiler/rustc_borrowck/src/type_check/mod.rs | 6 ++--- compiler/rustc_hir_typeck/src/closure.rs | 6 ++--- compiler/rustc_hir_typeck/src/expr.rs | 4 ++-- compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs | 2 +- compiler/rustc_hir_typeck/src/method/probe.rs | 4 ++-- .../src/infer/error_reporting/mod.rs | 6 ++--- compiler/rustc_infer/src/infer/mod.rs | 22 +++++++++---------- .../src/solve/eval_ctxt/mod.rs | 4 ++-- .../src/traits/error_reporting/ambiguity.rs | 4 ++-- .../src/traits/error_reporting/suggestions.rs | 10 ++++----- .../error_reporting/type_err_ctxt_ext.rs | 2 +- .../src/traits/project.rs | 4 ++-- .../src/traits/select/confirmation.rs | 2 +- .../src/traits/select/mod.rs | 4 ++-- 16 files changed, 44 insertions(+), 44 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 8aef34d9e763..c85b2f0a9d75 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -10,7 +10,7 @@ use rustc_hir as hir; use rustc_hir::def::{CtorKind, Namespace}; use rustc_hir::CoroutineKind; use rustc_index::IndexSlice; -use rustc_infer::infer::LateBoundRegionConversionTime; +use rustc_infer::infer::BoundRegionConversionTime; use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::mir::{ AggregateKind, CallSource, ConstOperand, FakeReadCause, Local, LocalInfo, LocalKind, Location, @@ -1113,7 +1113,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { && let ty::Ref(_, _, hir::Mutability::Mut) = args.type_at(0).kind() && let self_ty = self.infcx.instantiate_binder_with_fresh_vars( fn_call_span, - LateBoundRegionConversionTime::FnCall, + BoundRegionConversionTime::FnCall, tcx.fn_sig(method_did).instantiate(tcx, method_args).input(0), ) && self.infcx.can_eq(self.param_env, ty, self_ty) diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs index d053d0a4b3ba..28cc8be8ac95 100644 --- a/compiler/rustc_borrowck/src/type_check/input_output.rs +++ b/compiler/rustc_borrowck/src/type_check/input_output.rs @@ -7,7 +7,7 @@ //! `RETURN_PLACE` the MIR arguments) are always fully normalized (and //! contain revealed `impl Trait` values). -use rustc_infer::infer::LateBoundRegionConversionTime; +use rustc_infer::infer::BoundRegionConversionTime; use rustc_middle::mir::*; use rustc_middle::ty::{self, Ty}; use rustc_span::Span; @@ -35,7 +35,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { .instantiate_canonical_with_fresh_inference_vars(body.span, &user_provided_poly_sig); let user_provided_sig = self.infcx.instantiate_binder_with_fresh_vars( body.span, - LateBoundRegionConversionTime::FnCall, + BoundRegionConversionTime::FnCall, user_provided_sig, ); diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 608d010394f6..bd01210544fa 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -21,7 +21,7 @@ use rustc_infer::infer::outlives::env::RegionBoundPairs; use rustc_infer::infer::region_constraints::RegionConstraintData; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::{ - InferCtxt, LateBoundRegion, LateBoundRegionConversionTime, NllRegionVariableOrigin, + BoundRegion, BoundRegionConversionTime, InferCtxt, NllRegionVariableOrigin, }; use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor}; @@ -1401,10 +1401,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { }; self.infcx.next_region_var( - LateBoundRegion( + BoundRegion( term.source_info.span, br.kind, - LateBoundRegionConversionTime::FnCall, + BoundRegionConversionTime::FnCall, ), region_ctxt_fn, ) diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index a70ead8e57d6..7807ff6547d2 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -7,7 +7,7 @@ use rustc_hir as hir; use rustc_hir::lang_items::LangItem; use rustc_hir_analysis::astconv::AstConv; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use rustc_infer::infer::{DefineOpaqueTypes, LateBoundRegionConversionTime}; +use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes}; use rustc_infer::infer::{InferOk, InferResult}; use rustc_macros::{TypeFoldable, TypeVisitable}; use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt}; @@ -558,7 +558,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Instantiate (this part of..) S to S', i.e., with fresh variables. self.instantiate_binder_with_fresh_vars( hir_ty.span, - LateBoundRegionConversionTime::FnCall, + BoundRegionConversionTime::FnCall, // (*) binder moved to here supplied_sig.inputs().rebind(supplied_ty), ) @@ -583,7 +583,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let supplied_output_ty = self.instantiate_binder_with_fresh_vars( decl.output.span(), - LateBoundRegionConversionTime::FnCall, + BoundRegionConversionTime::FnCall, supplied_sig.output(), ); let cause = &self.misc(decl.output.span()); diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 9f439a2b32aa..811d8a4b94e2 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -564,7 +564,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let span = args.get(i).map(|a| a.span).unwrap_or(expr.span); let input = self.instantiate_binder_with_fresh_vars( span, - infer::LateBoundRegionConversionTime::FnCall, + infer::BoundRegionConversionTime::FnCall, fn_sig.input(i), ); self.require_type_is_sized_deferred( @@ -582,7 +582,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // with fresh vars. let output = self.instantiate_binder_with_fresh_vars( expr.span, - infer::LateBoundRegionConversionTime::FnCall, + infer::BoundRegionConversionTime::FnCall, fn_sig.output(), ); self.require_type_is_sized_deferred(output, expr.span, traits::SizedReturnType); diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index e93d180fc139..a1ce5983f30e 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -289,7 +289,7 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> { ) -> Ty<'tcx> { let trait_ref = self.instantiate_binder_with_fresh_vars( span, - infer::LateBoundRegionConversionTime::AssocTypeProjection(item_def_id), + infer::BoundRegionConversionTime::AssocTypeProjection(item_def_id), poly_trait_ref, ); diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 74f469cb39cb..096b5f7db631 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -853,7 +853,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { self.elaborate_bounds(bounds, |this, poly_trait_ref, item| { let trait_ref = this.instantiate_binder_with_fresh_vars( this.span, - infer::LateBoundRegionConversionTime::FnCall, + infer::BoundRegionConversionTime::FnCall, poly_trait_ref, ); @@ -971,7 +971,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } else { let new_trait_ref = self.instantiate_binder_with_fresh_vars( self.span, - infer::LateBoundRegionConversionTime::FnCall, + infer::BoundRegionConversionTime::FnCall, bound_trait_ref, ); diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 07155f8f74f4..f09a33be839b 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -2768,13 +2768,13 @@ impl<'tcx> InferCtxt<'tcx> { infer::AddrOfRegion(_) => " for borrow expression".to_string(), infer::Autoref(_) => " for autoref".to_string(), infer::Coercion(_) => " for automatic coercion".to_string(), - infer::LateBoundRegion(_, br, infer::FnCall) => { + infer::BoundRegion(_, br, infer::FnCall) => { format!(" for lifetime parameter {}in function call", br_string(br)) } - infer::LateBoundRegion(_, br, infer::HigherRankedType) => { + infer::BoundRegion(_, br, infer::HigherRankedType) => { format!(" for lifetime parameter {}in generic type", br_string(br)) } - infer::LateBoundRegion(_, br, infer::AssocTypeProjection(def_id)) => format!( + infer::BoundRegion(_, br, infer::AssocTypeProjection(def_id)) => format!( " for lifetime parameter {}in trait containing associated type `{}`", br_string(br), self.tcx.associated_item(def_id).name diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 4ee897ffe984..3c539f18eb92 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1,7 +1,7 @@ pub use self::at::DefineOpaqueTypes; pub use self::freshen::TypeFreshener; pub use self::lexical_region_resolve::RegionResolutionError; -pub use self::LateBoundRegionConversionTime::*; +pub use self::BoundRegionConversionTime::*; pub use self::RegionVariableOrigin::*; pub use self::SubregionOrigin::*; pub use self::ValuePairs::*; @@ -472,9 +472,9 @@ impl<'tcx> SubregionOrigin<'tcx> { } } -/// Times when we replace late-bound regions with variables: +/// Times when we replace bound regions with existentials: #[derive(Clone, Copy, Debug)] -pub enum LateBoundRegionConversionTime { +pub enum BoundRegionConversionTime { /// when a fn is called FnCall, @@ -510,9 +510,9 @@ pub enum RegionVariableOrigin { /// Region variables created as the values for early-bound regions. EarlyBoundRegion(Span, Symbol), - /// Region variables created for bound regions - /// in a function or method that is called. - LateBoundRegion(Span, ty::BoundRegionKind, LateBoundRegionConversionTime), + /// Region variables created when instantiating a binder with + /// existential variables, e.g. when calling a function or method. + BoundRegion(Span, ty::BoundRegionKind, BoundRegionConversionTime), UpvarRegion(ty::UpvarId, Span), @@ -1456,13 +1456,13 @@ impl<'tcx> InferCtxt<'tcx> { // variables in the current universe. // // Use this method if you'd like to find some substitution of the binder's - // variables (e.g. during a method call). If there isn't a [`LateBoundRegionConversionTime`] + // variables (e.g. during a method call). If there isn't a [`BoundRegionConversionTime`] // that corresponds to your use case, consider whether or not you should // use [`InferCtxt::instantiate_binder_with_placeholders`] instead. pub fn instantiate_binder_with_fresh_vars( &self, span: Span, - lbrct: LateBoundRegionConversionTime, + lbrct: BoundRegionConversionTime, value: ty::Binder<'tcx, T>, ) -> T where @@ -1475,7 +1475,7 @@ impl<'tcx> InferCtxt<'tcx> { struct ToFreshVars<'a, 'tcx> { infcx: &'a InferCtxt<'tcx>, span: Span, - lbrct: LateBoundRegionConversionTime, + lbrct: BoundRegionConversionTime, map: FxHashMap>, } @@ -1485,7 +1485,7 @@ impl<'tcx> InferCtxt<'tcx> { .entry(br.var) .or_insert_with(|| { self.infcx - .next_region_var(LateBoundRegion(self.span, br.kind, self.lbrct)) + .next_region_var(BoundRegion(self.span, br.kind, self.lbrct)) .into() }) .expect_region() @@ -2042,7 +2042,7 @@ impl RegionVariableOrigin { | Autoref(a) | Coercion(a) | EarlyBoundRegion(a, ..) - | LateBoundRegion(a, ..) + | BoundRegion(a, ..) | UpvarRegion(_, a) => a, Nll(..) => bug!("NLL variable used with `span`"), } diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs index 70235b710e2b..583eb9f96a9d 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs @@ -4,7 +4,7 @@ use rustc_infer::infer::at::ToTrace; use rustc_infer::infer::canonical::CanonicalVarValues; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::{ - DefineOpaqueTypes, InferCtxt, InferOk, LateBoundRegionConversionTime, TyCtxtInferExt, + BoundRegionConversionTime, DefineOpaqueTypes, InferCtxt, InferOk, TyCtxtInferExt, }; use rustc_infer::traits::query::NoSolution; use rustc_infer::traits::ObligationCause; @@ -780,7 +780,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { ) -> T { self.infcx.instantiate_binder_with_fresh_vars( DUMMY_SP, - LateBoundRegionConversionTime::HigherRankedType, + BoundRegionConversionTime::HigherRankedType, value, ) } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs index 5bc5a12a8fed..b246e476bedf 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs @@ -1,5 +1,5 @@ use rustc_hir::def_id::DefId; -use rustc_infer::infer::{InferCtxt, LateBoundRegionConversionTime}; +use rustc_infer::infer::{BoundRegionConversionTime, InferCtxt}; use rustc_infer::traits::util::elaborate; use rustc_infer::traits::{Obligation, ObligationCause, PolyTraitObligation}; use rustc_middle::ty; @@ -53,7 +53,7 @@ pub fn recompute_applicable_impls<'tcx>( let param_env_predicate = infcx.instantiate_binder_with_fresh_vars( DUMMY_SP, - LateBoundRegionConversionTime::HigherRankedType, + BoundRegionConversionTime::HigherRankedType, poly_trait_predicate, ); let param_env_trait_ref = diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 3afab24acb61..262bed8610c0 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -26,7 +26,7 @@ use rustc_hir::{CoroutineKind, CoroutineSource, Node}; use rustc_hir::{Expr, HirId}; use rustc_infer::infer::error_reporting::TypeErrCtxt; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use rustc_infer::infer::{DefineOpaqueTypes, InferOk, LateBoundRegionConversionTime}; +use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferOk}; use rustc_middle::hir::map; use rustc_middle::traits::IsConstable; use rustc_middle::ty::error::TypeError::{self, Sorts}; @@ -908,7 +908,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let self_ty = self.instantiate_binder_with_fresh_vars( DUMMY_SP, - LateBoundRegionConversionTime::FnCall, + BoundRegionConversionTime::FnCall, trait_pred.self_ty(), ); @@ -1237,7 +1237,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let output = self.instantiate_binder_with_fresh_vars( DUMMY_SP, - LateBoundRegionConversionTime::FnCall, + BoundRegionConversionTime::FnCall, output, ); let inputs = inputs @@ -1246,7 +1246,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { .map(|ty| { self.instantiate_binder_with_fresh_vars( DUMMY_SP, - LateBoundRegionConversionTime::FnCall, + BoundRegionConversionTime::FnCall, inputs.rebind(*ty), ) }) @@ -3595,7 +3595,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let where_pred = self.instantiate_binder_with_placeholders(where_pred); let failed_pred = self.instantiate_binder_with_fresh_vars( expr.span, - LateBoundRegionConversionTime::FnCall, + BoundRegionConversionTime::FnCall, failed_pred, ); diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index ba2e3d1ae282..aa284cfc9c58 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -1377,7 +1377,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { { let data = self.instantiate_binder_with_fresh_vars( obligation.cause.span, - infer::LateBoundRegionConversionTime::HigherRankedType, + infer::BoundRegionConversionTime::HigherRankedType, bound_predicate.rebind(data), ); let unnormalized_term = match data.term.unpack() { diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index d03704c1d64e..3bc401128b3a 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -18,7 +18,7 @@ use rustc_middle::traits::ImplSourceUserDefinedData; use crate::errors::InherentProjectionNormalizationOverflow; use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use crate::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime}; +use crate::infer::{BoundRegionConversionTime, InferCtxt, InferOk}; use crate::traits::error_reporting::TypeErrCtxtExt as _; use crate::traits::query::evaluate_obligation::InferCtxtExt as _; use crate::traits::select::ProjectionMatchesProjection; @@ -2319,7 +2319,7 @@ fn confirm_param_env_candidate<'cx, 'tcx>( let cache_entry = infcx.instantiate_binder_with_fresh_vars( cause.span, - LateBoundRegionConversionTime::HigherRankedType, + BoundRegionConversionTime::HigherRankedType, poly_cache_entry, ); diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 6205ef052202..cbf36c37f5a3 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -9,7 +9,7 @@ use rustc_ast::Mutability; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir::lang_items::LangItem; -use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType; +use rustc_infer::infer::BoundRegionConversionTime::HigherRankedType; use rustc_infer::infer::{DefineOpaqueTypes, InferOk}; use rustc_middle::traits::{BuiltinImplSource, SelectionOutputTypeParameterMismatch}; use rustc_middle::ty::{ diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 6d13f4dbc997..2bd2f07c108a 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -32,8 +32,8 @@ use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::Diagnostic; use rustc_hir as hir; use rustc_hir::def_id::DefId; +use rustc_infer::infer::BoundRegionConversionTime; use rustc_infer::infer::DefineOpaqueTypes; -use rustc_infer::infer::LateBoundRegionConversionTime; use rustc_infer::traits::TraitObligation; use rustc_middle::dep_graph::dep_kinds; use rustc_middle::dep_graph::DepNodeIndex; @@ -1751,7 +1751,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let mut nested_obligations = Vec::new(); let infer_predicate = self.infcx.instantiate_binder_with_fresh_vars( obligation.cause.span, - LateBoundRegionConversionTime::HigherRankedType, + BoundRegionConversionTime::HigherRankedType, env_predicate, ); let infer_projection = if potentially_unnormalized_candidates { From 8935a1be016cc0734f081d85d4414a5b534eeac1 Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 13 Nov 2023 14:12:56 +0000 Subject: [PATCH 421/435] update type flags - `HAS_RE_LATE_BOUND` -> `HAS_RE_BOUND` - `HAS_TY_LATE_BOUND` -> `HAS_TY_BOUND` - `HAS_CT_LATE_BOUND` -> `HAS_CT_BOUND` - `HAS_LATE_BOUND` -> `HAS_BOUND_VARS` - `fn has_late_bound_regions` -> `fn has_bound_regions` - `fnhas_non_region_late_bound` -> `fn has_non_region_bound_vars` - `fn has_late_bound_vars` -> `fn has_bound_vars` --- compiler/rustc_hir_typeck/src/method/probe.rs | 2 +- compiler/rustc_middle/src/ty/flags.rs | 4 ++-- compiler/rustc_middle/src/ty/sty.rs | 2 +- compiler/rustc_middle/src/ty/visit.rs | 14 +++++++------- .../src/solve/assembly/structural_traits.rs | 2 +- .../src/traits/object_safety.rs | 2 +- .../src/traits/select/confirmation.rs | 2 +- .../rustc_trait_selection/src/traits/select/mod.rs | 4 ++-- compiler/rustc_type_ir/src/flags.rs | 12 ++++++------ src/tools/clippy/clippy_lints/src/eta_reduction.rs | 2 +- src/tools/clippy/clippy_utils/src/ty.rs | 4 ++-- 11 files changed, 25 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 096b5f7db631..a51fa8354c9e 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -801,7 +801,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { // a `&self` method will wind up with an argument type like `&dyn Trait`. let trait_ref = principal.with_self_ty(self.tcx, self_ty); self.elaborate_bounds(iter::once(trait_ref), |this, new_trait_ref, item| { - if new_trait_ref.has_non_region_late_bound() { + if new_trait_ref.has_non_region_bound_vars() { this.tcx.sess.delay_span_bug( this.span, "tried to select method from HRTB with non-lifetime bound vars", diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index a2e709165d55..4d7b12662c66 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -137,7 +137,7 @@ impl FlagComputation { &ty::Bound(debruijn, _) => { self.add_bound_var(debruijn); - self.add_flags(TypeFlags::HAS_TY_LATE_BOUND); + self.add_flags(TypeFlags::HAS_TY_BOUND); } &ty::Placeholder(..) => { @@ -317,7 +317,7 @@ impl FlagComputation { } ty::ConstKind::Bound(debruijn, _) => { self.add_bound_var(debruijn); - self.add_flags(TypeFlags::HAS_CT_LATE_BOUND); + self.add_flags(TypeFlags::HAS_CT_BOUND); } ty::ConstKind::Param(_) => { self.add_flags(TypeFlags::HAS_CT_PARAM); diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index ca6ad4ea5c7c..d0df4498a66e 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1815,7 +1815,7 @@ impl<'tcx> Region<'tcx> { flags = flags | TypeFlags::HAS_FREE_REGIONS; } ty::ReBound(..) => { - flags = flags | TypeFlags::HAS_RE_LATE_BOUND; + flags = flags | TypeFlags::HAS_RE_BOUND; } ty::ReErased => { flags = flags | TypeFlags::HAS_RE_ERASED; diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs index ee1cd76aa8be..f14232d34352 100644 --- a/compiler/rustc_middle/src/ty/visit.rs +++ b/compiler/rustc_middle/src/ty/visit.rs @@ -111,16 +111,16 @@ pub trait TypeVisitableExt<'tcx>: TypeVisitable> { } /// True if there are any late-bound regions - fn has_late_bound_regions(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_RE_LATE_BOUND) + fn has_bound_regions(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_RE_BOUND) } /// True if there are any late-bound non-region variables - fn has_non_region_late_bound(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_LATE_BOUND - TypeFlags::HAS_RE_LATE_BOUND) + fn has_non_region_bound_vars(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_BOUND_VARS - TypeFlags::HAS_RE_BOUND) } - /// True if there are any late-bound variables - fn has_late_bound_vars(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_LATE_BOUND) + /// True if there are any bound variables + fn has_bound_vars(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_BOUND_VARS) } /// Indicates whether this value still has parameters/placeholders/inference variables diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs index 03b78681fa29..6eefccbde04c 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs @@ -91,7 +91,7 @@ pub(in crate::solve) fn replace_erased_lifetimes_with_bound_vars<'tcx>( tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, ) -> ty::Binder<'tcx, Ty<'tcx>> { - debug_assert!(!ty.has_late_bound_regions()); + debug_assert!(!ty.has_bound_regions()); let mut counter = 0; let ty = tcx.fold_regions(ty, |r, current_depth| match r.kind() { ty::ReErased => { diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index 17c7f94ee883..3e5dd8c50d4a 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -329,7 +329,7 @@ fn super_predicates_have_non_lifetime_binders( tcx.super_predicates_of(trait_def_id) .predicates .iter() - .filter_map(|(pred, span)| pred.has_non_region_late_bound().then_some(*span)) + .filter_map(|(pred, span)| pred.has_non_region_bound_vars().then_some(*span)) .collect() } diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index cbf36c37f5a3..abb4e71a9af5 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -1277,7 +1277,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let tcx = self.tcx(); stack.extend(tcx.coroutine_hidden_types(def_id).map(|bty| { let ty = bty.instantiate(tcx, args); - debug_assert!(!ty.has_late_bound_regions()); + debug_assert!(!ty.has_bound_regions()); ty })) } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 2bd2f07c108a..1ed0da59b64f 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -799,7 +799,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // A global type with no free lifetimes or generic parameters // outlives anything. if pred.0.has_free_regions() - || pred.0.has_late_bound_regions() + || pred.0.has_bound_regions() || pred.0.has_non_region_infer() || pred.0.has_non_region_infer() { @@ -1841,7 +1841,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { // the param_env so that it can be given the lowest priority. See // #50825 for the motivation for this. let is_global = - |cand: &ty::PolyTraitPredicate<'tcx>| cand.is_global() && !cand.has_late_bound_vars(); + |cand: &ty::PolyTraitPredicate<'tcx>| cand.is_global() && !cand.has_bound_vars(); // (*) Prefer `BuiltinCandidate { has_nested: false }`, `PointeeCandidate`, // `DiscriminantKindCandidate`, `ConstDestructCandidate` diff --git a/compiler/rustc_type_ir/src/flags.rs b/compiler/rustc_type_ir/src/flags.rs index a7dda717517b..d10927b0d939 100644 --- a/compiler/rustc_type_ir/src/flags.rs +++ b/compiler/rustc_type_ir/src/flags.rs @@ -89,16 +89,16 @@ bitflags! { const HAS_FREE_REGIONS = 1 << 15; /// Does this have any `ReBound` regions? - const HAS_RE_LATE_BOUND = 1 << 16; + const HAS_RE_BOUND = 1 << 16; /// Does this have any `Bound` types? - const HAS_TY_LATE_BOUND = 1 << 17; + const HAS_TY_BOUND = 1 << 17; /// Does this have any `ConstKind::Bound` consts? - const HAS_CT_LATE_BOUND = 1 << 18; + const HAS_CT_BOUND = 1 << 18; /// Does this have any bound variables? /// Used to check if a global bound is safe to evaluate. - const HAS_LATE_BOUND = TypeFlags::HAS_RE_LATE_BOUND.bits - | TypeFlags::HAS_TY_LATE_BOUND.bits - | TypeFlags::HAS_CT_LATE_BOUND.bits; + const HAS_BOUND_VARS = TypeFlags::HAS_RE_BOUND.bits + | TypeFlags::HAS_TY_BOUND.bits + | TypeFlags::HAS_CT_BOUND.bits; /// Does this have any `ReErased` regions? const HAS_RE_ERASED = 1 << 19; diff --git a/src/tools/clippy/clippy_lints/src/eta_reduction.rs b/src/tools/clippy/clippy_lints/src/eta_reduction.rs index 150b1c777db1..02c53fafd696 100644 --- a/src/tools/clippy/clippy_lints/src/eta_reduction.rs +++ b/src/tools/clippy/clippy_lints/src/eta_reduction.rs @@ -290,7 +290,7 @@ fn has_late_bound_to_non_late_bound_regions(from_sig: FnSig<'_>, to_sig: FnSig<' .zip(to_tys) .any(|(from_ty, to_ty)| check_ty(from_ty, to_ty)) }, - _ => from_ty.has_late_bound_regions(), + _ => from_ty.has_bound_regions(), } } diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index 758aa40a2dd1..2ff979f2dcb3 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -1160,7 +1160,7 @@ pub fn make_normalized_projection<'tcx>( ) -> Option> { fn helper<'tcx>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: AliasTy<'tcx>) -> Option> { #[cfg(debug_assertions)] - if let Some((i, arg)) = ty.args.iter().enumerate().find(|(_, arg)| arg.has_late_bound_regions()) { + if let Some((i, arg)) = ty.args.iter().enumerate().find(|(_, arg)| arg.has_bound_regions()) { debug_assert!( false, "args contain late-bound region at index `{i}` which can't be normalized.\n\ @@ -1233,7 +1233,7 @@ pub fn make_normalized_projection_with_regions<'tcx>( ) -> Option> { fn helper<'tcx>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: AliasTy<'tcx>) -> Option> { #[cfg(debug_assertions)] - if let Some((i, arg)) = ty.args.iter().enumerate().find(|(_, arg)| arg.has_late_bound_regions()) { + if let Some((i, arg)) = ty.args.iter().enumerate().find(|(_, arg)| arg.has_bound_regions()) { debug_assert!( false, "args contain late-bound region at index `{i}` which can't be normalized.\n\ From 5d8d700fd3911b8219168b3a9bdac52691fd5a42 Mon Sep 17 00:00:00 2001 From: Augie Fackler Date: Mon, 13 Nov 2023 10:43:33 -0500 Subject: [PATCH 422/435] tests: update check for inferred nneg on zext This was broken by upstream llvm/llvm-project@dc6d0773960c664eee12a1ed871fad5c81a20a12. It's easy enough to use a regex match to support both, so we do that. r? @nikic @rustbot label: +llvm-main --- tests/codegen/unchecked_shifts.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/codegen/unchecked_shifts.rs b/tests/codegen/unchecked_shifts.rs index aca9bec77dfe..eded894c6d08 100644 --- a/tests/codegen/unchecked_shifts.rs +++ b/tests/codegen/unchecked_shifts.rs @@ -31,7 +31,7 @@ pub unsafe fn unchecked_shl_unsigned_smaller(a: u16, b: u32) -> u16 { #[no_mangle] pub unsafe fn unchecked_shl_unsigned_bigger(a: u64, b: u32) -> u64 { // CHECK-NOT: assume - // CHECK: %[[EXT:.+]] = zext i32 %b to i64 + // CHECK: %[[EXT:.+]] = zext{{( nneg)?}} i32 %b to i64 // CHECK: shl i64 %a, %[[EXT]] a.unchecked_shl(b) } @@ -63,7 +63,7 @@ pub unsafe fn unchecked_shr_signed_smaller(a: i16, b: u32) -> i16 { #[no_mangle] pub unsafe fn unchecked_shr_signed_bigger(a: i64, b: u32) -> i64 { // CHECK-NOT: assume - // CHECK: %[[EXT:.+]] = zext i32 %b to i64 + // CHECK: %[[EXT:.+]] = zext{{( nneg)?}} i32 %b to i64 // CHECK: ashr i64 %a, %[[EXT]] a.unchecked_shr(b) } From 855388e9a2de1ddb99e83004941fb78d5ec796e4 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Mon, 13 Nov 2023 11:04:53 -0800 Subject: [PATCH 423/435] Mention LLVM 64186 in a comment --- compiler/rustc_llvm/build.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_llvm/build.rs b/compiler/rustc_llvm/build.rs index 107f2b65171b..ba160ff28dce 100644 --- a/compiler/rustc_llvm/build.rs +++ b/compiler/rustc_llvm/build.rs @@ -242,6 +242,7 @@ fn main() { } // We need libkstat for getHostCPUName on SPARC builds. + // See also: https://github.com/llvm/llvm-project/issues/64186 if target.starts_with("sparcv9") && target.contains("solaris") { println!("cargo:rustc-link-lib=kstat"); } From 636a6f70b692966dc891e566c44e665b44057e95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Mon, 13 Nov 2023 15:27:44 +0200 Subject: [PATCH 424/435] Try Mode::ToolRustc --- src/bootstrap/src/core/build_steps/check.rs | 6 +++--- src/bootstrap/src/core/build_steps/test.rs | 4 ++-- src/bootstrap/src/core/build_steps/tool.rs | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/check.rs b/src/bootstrap/src/core/build_steps/check.rs index 121925b56a05..d36c41906b0c 100644 --- a/src/bootstrap/src/core/build_steps/check.rs +++ b/src/bootstrap/src/core/build_steps/check.rs @@ -376,12 +376,12 @@ impl Step for RustAnalyzer { let compiler = builder.compiler(builder.top_stage, builder.config.build); let target = self.target; - builder.ensure(Std::new(target)); + builder.ensure(Rustc::new(target, builder)); let mut cargo = prepare_tool_cargo( builder, compiler, - Mode::ToolStd, + Mode::ToolRustc, target, cargo_subcommand(builder.kind), "src/tools/rust-analyzer", @@ -414,7 +414,7 @@ impl Step for RustAnalyzer { /// Cargo's output path in a given stage, compiled by a particular /// compiler for the specified target. fn stamp(builder: &Builder<'_>, compiler: Compiler, target: TargetSelection) -> PathBuf { - builder.cargo_out(compiler, Mode::ToolStd, target).join(".rust-analyzer-check.stamp") + builder.cargo_out(compiler, Mode::ToolRustc, target).join(".rust-analyzer-check.stamp") } } } diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 39667d16b7b6..359e5c59111f 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -369,7 +369,7 @@ impl Step for RustAnalyzer { // We don't need to build the whole Rust Analyzer for the proc-macro-srv test suite, // but we do need the standard library to be present. - builder.ensure(compile::Std::new(compiler, host)); + builder.ensure(compile::Rustc::new(compiler, host)); let workspace_path = "src/tools/rust-analyzer"; // until the whole RA test suite runs on `i686`, we only run @@ -378,7 +378,7 @@ impl Step for RustAnalyzer { let mut cargo = tool::prepare_tool_cargo( builder, compiler, - Mode::ToolStd, + Mode::ToolRustc, host, "test", crate_path, diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index 9912681c781d..6a6438f9a931 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -635,7 +635,7 @@ impl Step for RustAnalyzer { compiler: self.compiler, target: self.target, tool: "rust-analyzer", - mode: Mode::ToolStd, + mode: Mode::ToolRustc, path: "src/tools/rust-analyzer", extra_features: vec!["rust-analyzer/in-rust-tree".to_owned()], is_optional_tool: false, From c2c065c3eab89a3828fc72d4fd45b70658ee08c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Mon, 13 Nov 2023 20:54:53 +0200 Subject: [PATCH 425/435] Add missing rustc_private features --- src/tools/rust-analyzer/crates/hir-ty/src/lib.rs | 1 + src/tools/rust-analyzer/crates/hir/Cargo.toml | 3 +++ src/tools/rust-analyzer/crates/hir/src/lib.rs | 1 + src/tools/rust-analyzer/crates/ide/src/lib.rs | 3 ++- src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml | 1 + 5 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs index 405bb001b5d1..c14339f6afe0 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs @@ -1,6 +1,7 @@ //! The type system. We currently use this to infer types for completion, hover //! information and various assists. #![warn(rust_2018_idioms, unused_lifetimes, semicolon_in_expressions_from_macros)] +#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))] #[allow(unused)] macro_rules! eprintln { diff --git a/src/tools/rust-analyzer/crates/hir/Cargo.toml b/src/tools/rust-analyzer/crates/hir/Cargo.toml index f860ee948452..09ab60dd549f 100644 --- a/src/tools/rust-analyzer/crates/hir/Cargo.toml +++ b/src/tools/rust-analyzer/crates/hir/Cargo.toml @@ -30,3 +30,6 @@ profile.workspace = true stdx.workspace = true syntax.workspace = true tt.workspace = true + +[features] +in-rust-tree = [] diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index 17ffb9acbd19..93859611668e 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -18,6 +18,7 @@ //! . #![warn(rust_2018_idioms, unused_lifetimes, semicolon_in_expressions_from_macros)] +#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))] #![recursion_limit = "512"] mod semantics; diff --git a/src/tools/rust-analyzer/crates/ide/src/lib.rs b/src/tools/rust-analyzer/crates/ide/src/lib.rs index aee03d218adf..2320c95b4a1a 100644 --- a/src/tools/rust-analyzer/crates/ide/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide/src/lib.rs @@ -8,8 +8,9 @@ //! in this crate. // For proving that RootDatabase is RefUnwindSafe. -#![recursion_limit = "128"] #![warn(rust_2018_idioms, unused_lifetimes, semicolon_in_expressions_from_macros)] +#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))] +#![recursion_limit = "128"] #[allow(unused)] macro_rules! eprintln { diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml index ee5df984b68e..c85b3e53cda2 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml +++ b/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml @@ -97,6 +97,7 @@ in-rust-tree = [ "syntax/in-rust-tree", "parser/in-rust-tree", "rustc-dependencies/in-rust-tree", + "hir/in-rust-tree", "hir-def/in-rust-tree", "hir-ty/in-rust-tree", ] From 5061c09c58948de2c09ea7d8f3b50b994608dd7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 13 Nov 2023 17:05:08 +0000 Subject: [PATCH 426/435] review comments: more targeted span setting approach --- compiler/rustc_hir_typeck/src/expr.rs | 26 +++++++++++++++++-- .../indexing/indexing-requires-a-uint.stderr | 2 ++ .../suggest-dereferencing-index.stderr | 2 ++ 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 7298e1e57022..f1987c29ddcc 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -21,7 +21,7 @@ use crate::{ TupleArgumentsFlag::DontTupleArguments, }; use rustc_ast as ast; -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{ pluralize, struct_span_err, AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder, @@ -2877,7 +2877,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // two-phase not needed because index_ty is never mutable self.demand_coerce(idx, idx_t, index_ty, None, AllowTwoPhase::No); self.select_obligations_where_possible(|errors| { - self.point_at_index(errors, idx.span) + self.point_at_index(errors, idx.span); }); element_ty } @@ -3037,7 +3037,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } fn point_at_index(&self, errors: &mut Vec>, span: Span) { + let mut seen_preds = FxHashSet::default(); + // We re-sort here so that the outer most root obligations comes first, as we have the + // subsequent weird logic to identify *every* relevant obligation for proper deduplication + // of diagnostics. + errors.sort_by_key(|error| error.root_obligation.recursion_depth); for error in errors { + match ( + error.root_obligation.predicate.kind().skip_binder(), + error.obligation.predicate.kind().skip_binder(), + ) { + (ty::PredicateKind::Clause(ty::ClauseKind::Trait(predicate)), _) + if self.tcx.lang_items().index_trait() == Some(predicate.trait_ref.def_id) => + { + seen_preds.insert(error.obligation.predicate.kind().skip_binder()); + } + (_, ty::PredicateKind::Clause(ty::ClauseKind::Trait(predicate))) + if self.tcx.is_diagnostic_item(sym::SliceIndex, predicate.trait_ref.def_id) => + { + seen_preds.insert(error.obligation.predicate.kind().skip_binder()); + } + (root, pred) if seen_preds.contains(&pred) || seen_preds.contains(&root) => {} + _ => continue, + } error.obligation.cause.span = span; } } diff --git a/tests/ui/indexing/indexing-requires-a-uint.stderr b/tests/ui/indexing/indexing-requires-a-uint.stderr index 6ea6bb600e94..3041c2c99a10 100644 --- a/tests/ui/indexing/indexing-requires-a-uint.stderr +++ b/tests/ui/indexing/indexing-requires-a-uint.stderr @@ -8,6 +8,8 @@ LL | [0][0u8]; = help: the trait `SliceIndex<[{integer}]>` is implemented for `usize` = help: for that trait implementation, expected `usize`, found `u8` = note: required for `[{integer}]` to implement `Index` + = note: 1 redundant requirement hidden + = note: required for `[{integer}; 1]` to implement `Index` error[E0308]: mismatched types --> $DIR/indexing-requires-a-uint.rs:12:18 diff --git a/tests/ui/suggestions/suggest-dereferencing-index.stderr b/tests/ui/suggestions/suggest-dereferencing-index.stderr index adf01339972e..23f6657f092a 100644 --- a/tests/ui/suggestions/suggest-dereferencing-index.stderr +++ b/tests/ui/suggestions/suggest-dereferencing-index.stderr @@ -8,6 +8,8 @@ LL | let one_item_please: i32 = [1, 2, 3][i]; = help: the trait `SliceIndex<[{integer}]>` is implemented for `usize` = help: for that trait implementation, expected `usize`, found `&usize` = note: required for `[{integer}]` to implement `Index<&usize>` + = note: 1 redundant requirement hidden + = note: required for `[{integer}; 3]` to implement `Index<&usize>` help: dereference this index | LL | let one_item_please: i32 = [1, 2, 3][*i]; From 614ddc969595c412d8db7657e21678283b664d42 Mon Sep 17 00:00:00 2001 From: sjwang05 <63834813+sjwang05@users.noreply.github.com> Date: Mon, 13 Nov 2023 13:07:30 -0800 Subject: [PATCH 427/435] Suggest lhs deref for binops --- .../src/fn_ctxt/suggestions.rs | 60 +++++++++++++------ tests/ui/binop/binary-op-suggest-deref.fixed | 8 +++ tests/ui/binop/binary-op-suggest-deref.rs | 8 +++ tests/ui/binop/binary-op-suggest-deref.stderr | 14 +++++ 4 files changed, 71 insertions(+), 19 deletions(-) create mode 100644 tests/ui/binop/binary-op-suggest-deref.fixed create mode 100644 tests/ui/binop/binary-op-suggest-deref.rs create mode 100644 tests/ui/binop/binary-op-suggest-deref.stderr diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index c43d4932fb9f..2e0ab1560f4b 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -2326,14 +2326,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { )); } - let needs_parens = match expr.kind { - // parenthesize if needed (Issue #46756) - hir::ExprKind::Cast(_, _) | hir::ExprKind::Binary(_, _, _) => true, - // parenthesize borrows of range literals (Issue #54505) - _ if is_range_literal(expr) => true, - _ => false, - }; - if let Some((sugg, msg)) = self.can_use_as_ref(expr) { return Some(( sugg, @@ -2361,18 +2353,48 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - let sugg = mutability.ref_prefix_str(); - let (sugg, verbose) = if needs_parens { - ( - vec![ - (sp.shrink_to_lo(), format!("{prefix}{sugg}(")), - (sp.shrink_to_hi(), ")".to_string()), - ], - false, - ) - } else { - (vec![(sp.shrink_to_lo(), format!("{prefix}{sugg}"))], true) + let make_sugg = |expr: &Expr<'_>, span: Span, sugg: &str| { + let needs_parens = match expr.kind { + // parenthesize if needed (Issue #46756) + hir::ExprKind::Cast(_, _) | hir::ExprKind::Binary(_, _, _) => true, + // parenthesize borrows of range literals (Issue #54505) + _ if is_range_literal(expr) => true, + _ => false, + }; + + if needs_parens { + ( + vec![ + (span.shrink_to_lo(), format!("{prefix}{sugg}(")), + (span.shrink_to_hi(), ")".to_string()), + ], + false, + ) + } else { + (vec![(span.shrink_to_lo(), format!("{prefix}{sugg}"))], true) + } }; + + // Suggest dereferencing the lhs for expressions such as `&T == T` + if let Some(hir::Node::Expr(hir::Expr { + kind: hir::ExprKind::Binary(_, lhs, ..), + .. + })) = self.tcx.hir().find_parent(expr.hir_id) + && let &ty::Ref(..) = self.check_expr(lhs).kind() + { + let (sugg, verbose) = make_sugg(lhs, lhs.span, "*"); + + return Some(( + sugg, + "consider dereferencing the borrow".to_string(), + Applicability::MachineApplicable, + verbose, + false, + )); + } + + let sugg = mutability.ref_prefix_str(); + let (sugg, verbose) = make_sugg(expr, sp, sugg); return Some(( sugg, format!("consider {}borrowing here", mutability.mutably_str()), diff --git a/tests/ui/binop/binary-op-suggest-deref.fixed b/tests/ui/binop/binary-op-suggest-deref.fixed new file mode 100644 index 000000000000..1ff3599137b1 --- /dev/null +++ b/tests/ui/binop/binary-op-suggest-deref.fixed @@ -0,0 +1,8 @@ +// Issue #52544 +// run-rustfix + +fn main() { + let i: &i64 = &1; + if *i < 0 {} + //~^ ERROR mismatched types [E0308] +} diff --git a/tests/ui/binop/binary-op-suggest-deref.rs b/tests/ui/binop/binary-op-suggest-deref.rs new file mode 100644 index 000000000000..12505a9ac27e --- /dev/null +++ b/tests/ui/binop/binary-op-suggest-deref.rs @@ -0,0 +1,8 @@ +// Issue #52544 +// run-rustfix + +fn main() { + let i: &i64 = &1; + if i < 0 {} + //~^ ERROR mismatched types [E0308] +} diff --git a/tests/ui/binop/binary-op-suggest-deref.stderr b/tests/ui/binop/binary-op-suggest-deref.stderr new file mode 100644 index 000000000000..1b7e45c77249 --- /dev/null +++ b/tests/ui/binop/binary-op-suggest-deref.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/binary-op-suggest-deref.rs:6:12 + | +LL | if i < 0 {} + | ^ expected `&i64`, found integer + | +help: consider dereferencing the borrow + | +LL | if *i < 0 {} + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. From 78da5776509f4e646a664de3ee7041f8008d5931 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Thu, 9 Nov 2023 00:00:00 +0000 Subject: [PATCH 428/435] Custom MIR: Support cleanup blocks Cleanup blocks are declared with `bb (cleanup) = { ... }`. `Call` and `Drop` terminators take an additional argument describing the unwind action, which is one of the following: * `UnwindContinue()` * `UnwindUnreachable()` * `UnwindTerminate(reason)`, where reason is `ReasonAbi` or `ReasonInCleanup` * `UnwindCleanup(block)` Also support unwind resume and unwind terminate terminators: * `UnwindResume()` * `UnwindTerminate(reason)` --- .../rustc_mir_build/src/build/custom/mod.rs | 13 +++ .../rustc_mir_build/src/build/custom/parse.rs | 48 +++++++--- .../src/build/custom/parse/instruction.rs | 83 ++++++++++++----- compiler/rustc_span/src/symbol.rs | 34 +++++++ library/core/src/intrinsics/mir.rs | 88 +++++++++++++++---- .../fail/function_calls/arg_inplace_mutate.rs | 2 +- .../arg_inplace_mutate.stack.stderr | 4 +- .../arg_inplace_mutate.tree.stderr | 4 +- .../arg_inplace_observe_after.rs | 2 +- .../arg_inplace_observe_during.none.stderr | 4 +- .../arg_inplace_observe_during.rs | 2 +- .../arg_inplace_observe_during.stack.stderr | 4 +- .../arg_inplace_observe_during.tree.stderr | 4 +- .../return_pointer_aliasing.none.stderr | 4 +- .../function_calls/return_pointer_aliasing.rs | 2 +- .../return_pointer_aliasing.stack.stderr | 4 +- .../return_pointer_aliasing.tree.stderr | 4 +- .../return_pointer_aliasing2.rs | 2 +- .../return_pointer_aliasing2.stack.stderr | 4 +- .../return_pointer_aliasing2.tree.stderr | 4 +- .../return_pointer_on_unwind.rs | 4 +- .../cast_fn_ptr_invalid_caller_arg.rs | 2 +- .../cast_fn_ptr_invalid_caller_arg.stderr | 4 +- .../function_calls/return_place_on_heap.rs | 2 +- tests/mir-opt/building/custom/terminators.rs | 8 +- .../mir-opt/building/custom/unwind_action.rs | 68 ++++++++++++++ .../building/custom/unwind_terminate.rs | 34 +++++++ tests/mir-opt/copy-prop/borrowed_local.rs | 4 +- tests/mir-opt/copy-prop/calls.rs | 2 +- tests/mir-opt/copy-prop/custom_move_arg.rs | 4 +- tests/mir-opt/copy-prop/move_projection.rs | 4 +- .../dead-store-elimination/call_arg_copy.rs | 2 +- tests/mir-opt/dead-store-elimination/cycle.rs | 4 +- tests/mir-opt/gvn.rs | 12 +-- tests/mir-opt/reference_prop.rs | 10 +-- tests/ui/mir/validate/noncleanup-cleanup.rs | 21 +++++ tests/ui/mir/validate/noncleanup-resume.rs | 17 ++++ tests/ui/mir/validate/noncleanup-terminate.rs | 17 ++++ 38 files changed, 428 insertions(+), 107 deletions(-) create mode 100644 tests/mir-opt/building/custom/unwind_action.rs create mode 100644 tests/mir-opt/building/custom/unwind_terminate.rs create mode 100644 tests/ui/mir/validate/noncleanup-cleanup.rs create mode 100644 tests/ui/mir/validate/noncleanup-resume.rs create mode 100644 tests/ui/mir/validate/noncleanup-terminate.rs diff --git a/compiler/rustc_mir_build/src/build/custom/mod.rs b/compiler/rustc_mir_build/src/build/custom/mod.rs index 3de2f45ad9a8..d302d538ad41 100644 --- a/compiler/rustc_mir_build/src/build/custom/mod.rs +++ b/compiler/rustc_mir_build/src/build/custom/mod.rs @@ -162,6 +162,19 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { expected: expected.to_string(), } } + + fn stmt_error(&self, stmt: StmtId, expected: &'static str) -> ParseError { + let stmt = &self.thir[stmt]; + let span = match stmt.kind { + StmtKind::Expr { expr, .. } => self.thir[expr].span, + StmtKind::Let { span, .. } => span, + }; + ParseError { + span, + item_description: format!("{:?}", stmt.kind), + expected: expected.to_string(), + } + } } type PResult = Result; diff --git a/compiler/rustc_mir_build/src/build/custom/parse.rs b/compiler/rustc_mir_build/src/build/custom/parse.rs index e2ab2cb90c72..a6f9caada2d1 100644 --- a/compiler/rustc_mir_build/src/build/custom/parse.rs +++ b/compiler/rustc_mir_build/src/build/custom/parse.rs @@ -27,10 +27,13 @@ macro_rules! parse_by_kind { $expr_name:pat, $expected:literal, $( - @call($name:literal, $args:ident) => $call_expr:expr, + @call($name:ident, $args:ident) => $call_expr:expr, )* $( - $pat:pat => $expr:expr, + @variant($adt:ident, $variant:ident) => $variant_expr:expr, + )* + $( + $pat:pat $(if $guard:expr)? => $expr:expr, )* ) => {{ let expr_id = $self.preparse($expr_id); @@ -42,14 +45,20 @@ macro_rules! parse_by_kind { ExprKind::Call { ty, fun: _, args: $args, .. } if { match ty.kind() { ty::FnDef(did, _) => { - $self.tcx.is_diagnostic_item(rustc_span::Symbol::intern($name), *did) + $self.tcx.is_diagnostic_item(rustc_span::sym::$name, *did) } _ => false, } } => $call_expr, )* $( - $pat => $expr, + ExprKind::Adt(box AdtExpr { adt_def, variant_index, .. }) if { + $self.tcx.is_diagnostic_item(rustc_span::sym::$adt, adt_def.did()) && + adt_def.variants()[*variant_index].name == rustc_span::sym::$variant + } => $variant_expr, + )* + $( + $pat $(if $guard)? => $expr, )* #[allow(unreachable_patterns)] _ => return Err($self.expr_error(expr_id, $expected)) @@ -172,7 +181,8 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { ExprKind::Block { block } => &self.thir[*block].stmts, ); for (i, block_def) in block_defs.iter().enumerate() { - let block = self.parse_block_def(self.statement_as_expr(*block_def)?)?; + let is_cleanup = self.body.basic_blocks_mut()[BasicBlock::from_usize(i)].is_cleanup; + let block = self.parse_block_def(self.statement_as_expr(*block_def)?, is_cleanup)?; self.body.basic_blocks_mut()[BasicBlock::from_usize(i)] = block; } @@ -181,15 +191,28 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { fn parse_block_decls(&mut self, stmts: impl Iterator) -> PResult<()> { for stmt in stmts { - let (var, _, _) = self.parse_let_statement(stmt)?; - let data = BasicBlockData::new(None); - let block = self.body.basic_blocks_mut().push(data); - self.block_map.insert(var, block); + self.parse_basic_block_decl(stmt)?; } - Ok(()) } + fn parse_basic_block_decl(&mut self, stmt: StmtId) -> PResult<()> { + match &self.thir[stmt].kind { + StmtKind::Let { pattern, initializer: Some(initializer), .. } => { + let (var, ..) = self.parse_var(pattern)?; + let mut data = BasicBlockData::new(None); + data.is_cleanup = parse_by_kind!(self, *initializer, _, "basic block declaration", + @variant(mir_basic_block, Normal) => false, + @variant(mir_basic_block, Cleanup) => true, + ); + let block = self.body.basic_blocks_mut().push(data); + self.block_map.insert(var, block); + Ok(()) + } + _ => Err(self.stmt_error(stmt, "let statement with an initializer")), + } + } + fn parse_local_decls(&mut self, mut stmts: impl Iterator) -> PResult<()> { let (ret_var, ..) = self.parse_let_statement(stmts.next().unwrap())?; self.local_map.insert(ret_var, Local::from_u32(0)); @@ -219,7 +242,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { }; let span = self.thir[expr].span; let (name, operand) = parse_by_kind!(self, expr, _, "debuginfo", - @call("mir_debuginfo", args) => { + @call(mir_debuginfo, args) => { (args[0], args[1]) }, ); @@ -281,12 +304,13 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { } } - fn parse_block_def(&self, expr_id: ExprId) -> PResult> { + fn parse_block_def(&self, expr_id: ExprId, is_cleanup: bool) -> PResult> { let block = parse_by_kind!(self, expr_id, _, "basic block", ExprKind::Block { block } => &self.thir[*block], ); let mut data = BasicBlockData::new(None); + data.is_cleanup = is_cleanup; for stmt_id in &*block.stmts { let stmt = self.statement_as_expr(*stmt_id)?; let span = self.thir[stmt].span; diff --git a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs index fd2c57a0a6f1..4ce7f831c871 100644 --- a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs +++ b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs @@ -13,19 +13,19 @@ use super::{parse_by_kind, PResult, ParseCtxt}; impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { pub fn parse_statement(&self, expr_id: ExprId) -> PResult> { parse_by_kind!(self, expr_id, _, "statement", - @call("mir_storage_live", args) => { + @call(mir_storage_live, args) => { Ok(StatementKind::StorageLive(self.parse_local(args[0])?)) }, - @call("mir_storage_dead", args) => { + @call(mir_storage_dead, args) => { Ok(StatementKind::StorageDead(self.parse_local(args[0])?)) }, - @call("mir_deinit", args) => { + @call(mir_deinit, args) => { Ok(StatementKind::Deinit(Box::new(self.parse_place(args[0])?))) }, - @call("mir_retag", args) => { + @call(mir_retag, args) => { Ok(StatementKind::Retag(RetagKind::Default, Box::new(self.parse_place(args[0])?))) }, - @call("mir_set_discriminant", args) => { + @call(mir_set_discriminant, args) => { let place = self.parse_place(args[0])?; let var = self.parse_integer_literal(args[1])? as u32; Ok(StatementKind::SetDiscriminant { @@ -43,24 +43,30 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { pub fn parse_terminator(&self, expr_id: ExprId) -> PResult> { parse_by_kind!(self, expr_id, expr, "terminator", - @call("mir_return", _args) => { + @call(mir_return, _args) => { Ok(TerminatorKind::Return) }, - @call("mir_goto", args) => { + @call(mir_goto, args) => { Ok(TerminatorKind::Goto { target: self.parse_block(args[0])? } ) }, - @call("mir_unreachable", _args) => { + @call(mir_unreachable, _args) => { Ok(TerminatorKind::Unreachable) }, - @call("mir_drop", args) => { + @call(mir_unwind_resume, _args) => { + Ok(TerminatorKind::UnwindResume) + }, + @call(mir_unwind_terminate, args) => { + Ok(TerminatorKind::UnwindTerminate(self.parse_unwind_terminate_reason(args[0])?)) + }, + @call(mir_drop, args) => { Ok(TerminatorKind::Drop { place: self.parse_place(args[0])?, target: self.parse_block(args[1])?, - unwind: UnwindAction::Continue, + unwind: self.parse_unwind_action(args[2])?, replace: false, }) }, - @call("mir_call", args) => { + @call(mir_call, args) => { self.parse_call(args) }, ExprKind::Match { scrutinee, arms, .. } => { @@ -70,6 +76,34 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { ) } + fn parse_unwind_terminate_reason(&self, expr_id: ExprId) -> PResult { + parse_by_kind!(self, expr_id, _, "unwind terminate reason", + @variant(mir_unwind_terminate_reason, Abi) => { + Ok(UnwindTerminateReason::Abi) + }, + @variant(mir_unwind_terminate_reason, InCleanup) => { + Ok(UnwindTerminateReason::InCleanup) + }, + ) + } + + fn parse_unwind_action(&self, expr_id: ExprId) -> PResult { + parse_by_kind!(self, expr_id, _, "unwind action", + @call(mir_unwind_continue, _args) => { + Ok(UnwindAction::Continue) + }, + @call(mir_unwind_unreachable, _args) => { + Ok(UnwindAction::Unreachable) + }, + @call(mir_unwind_terminate, args) => { + Ok(UnwindAction::Terminate(self.parse_unwind_terminate_reason(args[0])?)) + }, + @call(mir_unwind_cleanup, args) => { + Ok(UnwindAction::Cleanup(self.parse_block(args[0])?)) + }, + ) + } + fn parse_match(&self, arms: &[ArmId], span: Span) -> PResult { let Some((otherwise, rest)) = arms.split_last() else { return Err(ParseError { @@ -113,6 +147,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { ); let destination = self.parse_place(destination)?; let target = self.parse_block(args[1])?; + let unwind = self.parse_unwind_action(args[2])?; parse_by_kind!(self, call, _, "function call", ExprKind::Call { fun, args, from_hir_call, fn_span, .. } => { @@ -126,7 +161,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { args, destination, target: Some(target), - unwind: UnwindAction::Continue, + unwind, call_source: if *from_hir_call { CallSource::Normal } else { CallSource::OverloadedOperator }, @@ -138,25 +173,25 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { fn parse_rvalue(&self, expr_id: ExprId) -> PResult> { parse_by_kind!(self, expr_id, expr, "rvalue", - @call("mir_discriminant", args) => self.parse_place(args[0]).map(Rvalue::Discriminant), - @call("mir_cast_transmute", args) => { + @call(mir_discriminant, args) => self.parse_place(args[0]).map(Rvalue::Discriminant), + @call(mir_cast_transmute, args) => { let source = self.parse_operand(args[0])?; Ok(Rvalue::Cast(CastKind::Transmute, source, expr.ty)) }, - @call("mir_checked", args) => { + @call(mir_checked, args) => { parse_by_kind!(self, args[0], _, "binary op", ExprKind::Binary { op, lhs, rhs } => Ok(Rvalue::CheckedBinaryOp( *op, Box::new((self.parse_operand(*lhs)?, self.parse_operand(*rhs)?)) )), ) }, - @call("mir_offset", args) => { + @call(mir_offset, args) => { let ptr = self.parse_operand(args[0])?; let offset = self.parse_operand(args[1])?; Ok(Rvalue::BinaryOp(BinOp::Offset, Box::new((ptr, offset)))) }, - @call("mir_len", args) => Ok(Rvalue::Len(self.parse_place(args[0])?)), - @call("mir_copy_for_deref", args) => Ok(Rvalue::CopyForDeref(self.parse_place(args[0])?)), + @call(mir_len, args) => Ok(Rvalue::Len(self.parse_place(args[0])?)), + @call(mir_copy_for_deref, args) => Ok(Rvalue::CopyForDeref(self.parse_place(args[0])?)), ExprKind::Borrow { borrow_kind, arg } => Ok( Rvalue::Ref(self.tcx.lifetimes.re_erased, *borrow_kind, self.parse_place(*arg)?) ), @@ -206,9 +241,9 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { pub fn parse_operand(&self, expr_id: ExprId) -> PResult> { parse_by_kind!(self, expr_id, expr, "operand", - @call("mir_move", args) => self.parse_place(args[0]).map(Operand::Move), - @call("mir_static", args) => self.parse_static(args[0]), - @call("mir_static_mut", args) => self.parse_static(args[0]), + @call(mir_move, args) => self.parse_place(args[0]).map(Operand::Move), + @call(mir_static, args) => self.parse_static(args[0]), + @call(mir_static_mut, args) => self.parse_static(args[0]), ExprKind::Literal { .. } | ExprKind::NamedConst { .. } | ExprKind::NonHirLiteral { .. } @@ -229,7 +264,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { fn parse_place_inner(&self, expr_id: ExprId) -> PResult<(Place<'tcx>, PlaceTy<'tcx>)> { let (parent, proj) = parse_by_kind!(self, expr_id, expr, "place", - @call("mir_field", args) => { + @call(mir_field, args) => { let (parent, ty) = self.parse_place_inner(args[0])?; let field = FieldIdx::from_u32(self.parse_integer_literal(args[1])? as u32); let field_ty = ty.field_ty(self.tcx, field); @@ -237,7 +272,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { let place = parent.project_deeper(&[proj], self.tcx); return Ok((place, PlaceTy::from_ty(field_ty))); }, - @call("mir_variant", args) => { + @call(mir_variant, args) => { (args[0], PlaceElem::Downcast( None, VariantIdx::from_u32(self.parse_integer_literal(args[1])? as u32) @@ -245,7 +280,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { }, ExprKind::Deref { arg } => { parse_by_kind!(self, *arg, _, "does not matter", - @call("mir_make_place", args) => return self.parse_place_inner(args[0]), + @call(mir_make_place, args) => return self.parse_place_inner(args[0]), _ => (*arg, PlaceElem::Deref), ) }, diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index f287862cc23c..302be85a429f 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -124,6 +124,7 @@ symbols! { // There is currently no checking that all symbols are used; that would be // nice to have. Symbols { + Abi, AcqRel, Acquire, AddToDiagnostic, @@ -166,6 +167,7 @@ symbols! { CString, Capture, Center, + Cleanup, Clone, Command, ConstParamTy, @@ -215,6 +217,7 @@ symbols! { HashSet, Hasher, Implied, + InCleanup, IndexOutput, Input, Instant, @@ -258,6 +261,7 @@ symbols! { NonZeroU8, NonZeroUsize, None, + Normal, Ok, Option, Ord, @@ -1023,6 +1027,36 @@ symbols! { minnumf32, minnumf64, mips_target_feature, + mir_basic_block, + mir_call, + mir_cast_transmute, + mir_checked, + mir_copy_for_deref, + mir_debuginfo, + mir_deinit, + mir_discriminant, + mir_drop, + mir_field, + mir_goto, + mir_len, + mir_make_place, + mir_move, + mir_offset, + mir_retag, + mir_return, + mir_set_discriminant, + mir_static, + mir_static_mut, + mir_storage_dead, + mir_storage_live, + mir_unreachable, + mir_unwind_cleanup, + mir_unwind_continue, + mir_unwind_resume, + mir_unwind_terminate, + mir_unwind_terminate_reason, + mir_unwind_unreachable, + mir_variant, miri, misc, mmx_reg, diff --git a/library/core/src/intrinsics/mir.rs b/library/core/src/intrinsics/mir.rs index b26a17ec30e9..0d8a306ace5e 100644 --- a/library/core/src/intrinsics/mir.rs +++ b/library/core/src/intrinsics/mir.rs @@ -110,15 +110,15 @@ //! let popped; //! //! { -//! Call(_unused = Vec::push(v, value), pop) +//! Call(_unused = Vec::push(v, value), pop, UnwindContinue()) //! } //! //! pop = { -//! Call(popped = Vec::pop(v), drop) +//! Call(popped = Vec::pop(v), drop, UnwindContinue()) //! } //! //! drop = { -//! Drop(popped, ret) +//! Drop(popped, ret, UnwindContinue()) //! } //! //! ret = { @@ -238,10 +238,6 @@ //! //! #### Terminators //! -//! Custom MIR does not currently support cleanup blocks or non-trivial unwind paths. As such, there -//! are no resume and abort terminators, and terminators that might unwind do not have any way to -//! indicate the unwind block. -//! //! - [`Goto`], [`Return`], [`Unreachable`] and [`Drop`](Drop()) have associated functions. //! - `match some_int_operand` becomes a `SwitchInt`. Each arm should be `literal => basic_block` //! - The exception is the last arm, which must be `_ => basic_block` and corresponds to the @@ -260,7 +256,26 @@ /// Type representing basic blocks. /// /// All terminators will have this type as a return type. It helps achieve some type safety. -pub struct BasicBlock; +#[rustc_diagnostic_item = "mir_basic_block"] +pub enum BasicBlock { + /// A non-cleanup basic block. + Normal, + /// A basic block that lies on an unwind path. + Cleanup, +} + +/// The reason we are terminating the process during unwinding. +#[rustc_diagnostic_item = "mir_unwind_terminate_reason"] +pub enum UnwindTerminateReason { + /// Unwinding is just not possible given the ABI of this function. + Abi, + /// We were already cleaning up for an ongoing unwind, and a *second*, *nested* unwind was + /// triggered by the drop glue. + InCleanup, +} + +pub use UnwindTerminateReason::Abi as ReasonAbi; +pub use UnwindTerminateReason::InCleanup as ReasonInCleanup; macro_rules! define { ($name:literal, $( #[ $meta:meta ] )* fn $($sig:tt)*) => { @@ -271,11 +286,41 @@ macro_rules! define { } } +// Unwind actions +define!( + "mir_unwind_continue", + /// An unwind action that continues unwinding. + fn UnwindContinue() +); +define!( + "mir_unwind_unreachable", + /// An unwind action that triggers undefined behaviour. + fn UnwindUnreachable() -> BasicBlock +); +define!( + "mir_unwind_terminate", + /// An unwind action that terminates the execution. + /// + /// `UnwindTerminate` can also be used as a terminator. + fn UnwindTerminate(reason: UnwindTerminateReason) +); +define!( + "mir_unwind_cleanup", + /// An unwind action that continues execution in a given basic blok. + fn UnwindCleanup(goto: BasicBlock) +); + +// Terminators define!("mir_return", fn Return() -> BasicBlock); define!("mir_goto", fn Goto(destination: BasicBlock) -> BasicBlock); define!("mir_unreachable", fn Unreachable() -> BasicBlock); -define!("mir_drop", fn Drop(place: T, goto: BasicBlock)); -define!("mir_call", fn Call(call: (), goto: BasicBlock)); +define!("mir_drop", fn Drop(place: T, goto: BasicBlock, unwind_action: U)); +define!("mir_call", fn Call(call: (), goto: BasicBlock, unwind_action: U)); +define!("mir_unwind_resume", + /// A terminator that resumes the unwinding. + fn UnwindResume() +); + define!("mir_storage_live", fn StorageLive(local: T)); define!("mir_storage_dead", fn StorageDead(local: T)); define!("mir_deinit", fn Deinit(place: T)); @@ -382,16 +427,15 @@ pub macro mir { } $( - $block_name:ident = { + $block_name:ident $(($block_cleanup:ident))? = { $($block:tt)* } )* ) => {{ // First, we declare all basic blocks. - $( - let $block_name: ::core::intrinsics::mir::BasicBlock; - )* - + __internal_declare_basic_blocks!($( + $block_name $(($block_cleanup))? + )*); { // Now all locals #[allow(non_snake_case)] @@ -585,3 +629,17 @@ pub macro __internal_remove_let { } }, } + +/// Helper macro that declares the basic blocks. +#[doc(hidden)] +pub macro __internal_declare_basic_blocks { + () => {}, + ($name:ident (cleanup) $($rest:tt)*) => { + let $name = ::core::intrinsics::mir::BasicBlock::Cleanup; + __internal_declare_basic_blocks!($($rest)*) + }, + ($name:ident $($rest:tt)*) => { + let $name = ::core::intrinsics::mir::BasicBlock::Normal; + __internal_declare_basic_blocks!($($rest)*) + }, +} diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.rs b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.rs index d47af50d407e..e79bd70e915e 100644 --- a/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.rs +++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.rs @@ -14,7 +14,7 @@ fn main() { let ptr = std::ptr::addr_of_mut!(non_copy); // Inside `callee`, the first argument and `*ptr` are basically // aliasing places! - Call(_unit = callee(Move(*ptr), ptr), after_call) + Call(_unit = callee(Move(*ptr), ptr), after_call, UnwindContinue()) } after_call = { Return() diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.stack.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.stack.stderr index 381442e69b13..ccf9732ed079 100644 --- a/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.stack.stderr +++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.stack.stderr @@ -27,8 +27,8 @@ LL | unsafe { ptr.write(S(0)) }; note: inside `main` --> $DIR/arg_inplace_mutate.rs:LL:CC | -LL | Call(_unit = callee(Move(*ptr), ptr), after_call) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | Call(_unit = callee(Move(*ptr), ptr), after_call, UnwindContinue()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info) note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.tree.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.tree.stderr index 3d8ba68547bd..e7baf6e23db7 100644 --- a/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.tree.stderr +++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.tree.stderr @@ -35,8 +35,8 @@ LL | unsafe { ptr.write(S(0)) }; note: inside `main` --> $DIR/arg_inplace_mutate.rs:LL:CC | -LL | Call(_unit = callee(Move(*ptr), ptr), after_call) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | Call(_unit = callee(Move(*ptr), ptr), after_call, UnwindContinue()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info) note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_after.rs b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_after.rs index ea773048dd4e..e4c00fdd8456 100644 --- a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_after.rs +++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_after.rs @@ -11,7 +11,7 @@ fn main() { { let non_copy = S(42); // This could change `non_copy` in-place - Call(_unit = change_arg(Move(non_copy)), after_call) + Call(_unit = change_arg(Move(non_copy)), after_call, UnwindContinue()) } after_call = { // So now we must not be allowed to observe non-copy again. diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.none.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.none.stderr index cba23c21d12b..f8140d0236af 100644 --- a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.none.stderr +++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.none.stderr @@ -11,8 +11,8 @@ LL | unsafe { ptr.read() }; note: inside `main` --> $DIR/arg_inplace_observe_during.rs:LL:CC | -LL | Call(_unit = change_arg(Move(*ptr), ptr), after_call) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | Call(_unit = change_arg(Move(*ptr), ptr), after_call, UnwindContinue()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.rs b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.rs index 8c6a7df7a6dd..517abd733a9c 100644 --- a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.rs +++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.rs @@ -14,7 +14,7 @@ fn main() { let non_copy = S(42); let ptr = std::ptr::addr_of_mut!(non_copy); // This could change `non_copy` in-place - Call(_unit = change_arg(Move(*ptr), ptr), after_call) + Call(_unit = change_arg(Move(*ptr), ptr), after_call, UnwindContinue()) } after_call = { Return() diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.stack.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.stack.stderr index f8532186be20..c37e788e6b44 100644 --- a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.stack.stderr +++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.stack.stderr @@ -27,8 +27,8 @@ LL | x.0 = 0; note: inside `main` --> $DIR/arg_inplace_observe_during.rs:LL:CC | -LL | Call(_unit = change_arg(Move(*ptr), ptr), after_call) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | Call(_unit = change_arg(Move(*ptr), ptr), after_call, UnwindContinue()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info) note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.tree.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.tree.stderr index 7b1846a32dbc..7557d3710d18 100644 --- a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.tree.stderr +++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.tree.stderr @@ -35,8 +35,8 @@ LL | x.0 = 0; note: inside `main` --> $DIR/arg_inplace_observe_during.rs:LL:CC | -LL | Call(_unit = change_arg(Move(*ptr), ptr), after_call) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | Call(_unit = change_arg(Move(*ptr), ptr), after_call, UnwindContinue()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info) note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.none.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.none.stderr index 0a31adabf73d..dd951066c324 100644 --- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.none.stderr +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.none.stderr @@ -11,8 +11,8 @@ LL | unsafe { ptr.read() }; note: inside `main` --> $DIR/return_pointer_aliasing.rs:LL:CC | -LL | Call(*ptr = myfun(ptr), after_call) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | Call(*ptr = myfun(ptr), after_call, UnwindContinue()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.rs b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.rs index 3d560af3d5eb..23b1e38b99f7 100644 --- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.rs +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.rs @@ -15,7 +15,7 @@ pub fn main() { let ptr = &raw mut x; // We arrange for `myfun` to have a pointer that aliases // its return place. Even just reading from that pointer is UB. - Call(*ptr = myfun(ptr), after_call) + Call(*ptr = myfun(ptr), after_call, UnwindContinue()) } after_call = { diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.stack.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.stack.stderr index 875cc5edad98..cf13be6da012 100644 --- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.stack.stderr +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.stack.stderr @@ -27,8 +27,8 @@ LL | unsafe { ptr.read() }; note: inside `main` --> $DIR/return_pointer_aliasing.rs:LL:CC | -LL | Call(*ptr = myfun(ptr), after_call) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | Call(*ptr = myfun(ptr), after_call, UnwindContinue()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info) note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.tree.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.tree.stderr index deafbf020772..e16c4c0ebb67 100644 --- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.tree.stderr +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.tree.stderr @@ -35,8 +35,8 @@ LL | unsafe { ptr.read() }; note: inside `main` --> $DIR/return_pointer_aliasing.rs:LL:CC | -LL | Call(*ptr = myfun(ptr), after_call) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | Call(*ptr = myfun(ptr), after_call, UnwindContinue()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info) note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.rs b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.rs index c1bbc748e1a0..56706cdb63ba 100644 --- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.rs +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.rs @@ -15,7 +15,7 @@ pub fn main() { let ptr = &raw mut _x; // We arrange for `myfun` to have a pointer that aliases // its return place. Even just reading from that pointer is UB. - Call(_x = myfun(ptr), after_call) + Call(_x = myfun(ptr), after_call, UnwindContinue()) } after_call = { diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.stack.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.stack.stderr index 0666db34fec4..5d76d9eab67f 100644 --- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.stack.stderr +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.stack.stderr @@ -30,8 +30,8 @@ LL | unsafe { ptr.write(0) }; note: inside `main` --> $DIR/return_pointer_aliasing2.rs:LL:CC | -LL | Call(_x = myfun(ptr), after_call) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | Call(_x = myfun(ptr), after_call, UnwindContinue()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info) note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.tree.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.tree.stderr index e1b40a6bc183..e8165a73ff4f 100644 --- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.tree.stderr +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.tree.stderr @@ -35,8 +35,8 @@ LL | unsafe { ptr.write(0) }; note: inside `main` --> $DIR/return_pointer_aliasing2.rs:LL:CC | -LL | Call(_x = myfun(ptr), after_call) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | Call(_x = myfun(ptr), after_call, UnwindContinue()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info) note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.rs b/src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.rs index 79e29b79d6a2..923c59e74299 100644 --- a/src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.rs +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.rs @@ -14,7 +14,7 @@ struct S(i32, [u8; 128]); fn docall(out: &mut S) { mir! { { - Call(*out = callee(), after_call) + Call(*out = callee(), after_call, UnwindContinue()) } after_call = { @@ -37,7 +37,7 @@ fn callee() -> S { // become visible to the outside. In codegen we can see them // but Miri should detect this as UB! RET.0 = 42; - Call(_unit = startpanic(), after_call) + Call(_unit = startpanic(), after_call, UnwindContinue()) } after_call = { diff --git a/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.rs b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.rs index ee80186d4b50..9357b3725050 100644 --- a/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.rs +++ b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.rs @@ -20,7 +20,7 @@ fn call(f: fn(NonZeroU32)) { let tmp = ptr::addr_of!(c); let ptr = tmp as *const NonZeroU32; // The call site now is a NonZeroU32-to-u32 transmute. - Call(_res = f(*ptr), retblock) //~ERROR: expected something greater or equal to 1 + Call(_res = f(*ptr), retblock, UnwindContinue()) //~ERROR: expected something greater or equal to 1 } retblock = { Return() diff --git a/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.stderr b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.stderr index 234c28040086..b40d99f7bc95 100644 --- a/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.stderr +++ b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.stderr @@ -1,8 +1,8 @@ error: Undefined Behavior: constructing invalid value: encountered 0, but expected something greater or equal to 1 --> $DIR/cast_fn_ptr_invalid_caller_arg.rs:LL:CC | -LL | Call(_res = f(*ptr), retblock) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1 +LL | Call(_res = f(*ptr), retblock, UnwindContinue()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1 | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/src/tools/miri/tests/pass/function_calls/return_place_on_heap.rs b/src/tools/miri/tests/pass/function_calls/return_place_on_heap.rs index d410a875b1be..89ee689fabe1 100644 --- a/src/tools/miri/tests/pass/function_calls/return_place_on_heap.rs +++ b/src/tools/miri/tests/pass/function_calls/return_place_on_heap.rs @@ -11,7 +11,7 @@ pub fn main() { { let x = 0; let ptr = &raw mut x; - Call(*ptr = myfun(), after_call) + Call(*ptr = myfun(), after_call, UnwindContinue()) } after_call = { diff --git a/tests/mir-opt/building/custom/terminators.rs b/tests/mir-opt/building/custom/terminators.rs index 9e442e0f98a9..a83a6c07461f 100644 --- a/tests/mir-opt/building/custom/terminators.rs +++ b/tests/mir-opt/building/custom/terminators.rs @@ -13,7 +13,7 @@ fn ident(t: T) -> T { fn direct_call(x: i32) -> i32 { mir!( { - Call(RET = ident(x), retblock) + Call(RET = ident(x), retblock, UnwindContinue()) } retblock = { @@ -27,7 +27,7 @@ fn direct_call(x: i32) -> i32 { fn indirect_call(x: i32, f: fn(i32) -> i32) -> i32 { mir!( { - Call(RET = f(x), retblock) + Call(RET = f(x), retblock, UnwindContinue()) } retblock = { @@ -49,7 +49,7 @@ impl<'a> Drop for WriteOnDrop<'a> { fn drop_first<'a>(a: WriteOnDrop<'a>, b: WriteOnDrop<'a>) { mir!( { - Drop(a, retblock) + Drop(a, retblock, UnwindContinue()) } retblock = { @@ -64,7 +64,7 @@ fn drop_first<'a>(a: WriteOnDrop<'a>, b: WriteOnDrop<'a>) { fn drop_second<'a>(a: WriteOnDrop<'a>, b: WriteOnDrop<'a>) { mir!( { - Drop(b, retblock) + Drop(b, retblock, UnwindContinue()) } retblock = { diff --git a/tests/mir-opt/building/custom/unwind_action.rs b/tests/mir-opt/building/custom/unwind_action.rs new file mode 100644 index 000000000000..e3c4ffac358a --- /dev/null +++ b/tests/mir-opt/building/custom/unwind_action.rs @@ -0,0 +1,68 @@ +// compile-flags: --crate-type=lib +// edition:2021 +// needs-unwind +#![feature(custom_mir, core_intrinsics)] +use core::intrinsics::mir::*; + +// CHECK-LABEL: fn a() +// CHECK: bb0: { +// CHECK-NEXT: a() -> [return: bb1, unwind unreachable]; +#[custom_mir(dialect = "runtime", phase = "optimized")] +pub fn a() { + mir!( + { + Call(RET = a(), bb1, UnwindUnreachable()) + } + bb1 = { + Return() + } + ) +} + +// CHECK-LABEL: fn b() +// CHECK: bb0: { +// CHECK-NEXT: b() -> [return: bb1, unwind continue]; +#[custom_mir(dialect = "runtime", phase = "optimized")] +pub fn b() { + mir!( + { + Call(RET = b(), bb1, UnwindContinue()) + } + bb1 = { + Return() + } + ) +} + +// CHECK-LABEL: fn c() +// CHECK: bb0: { +// CHECK-NEXT: c() -> [return: bb1, unwind terminate(abi)]; +#[custom_mir(dialect = "runtime", phase = "optimized")] +pub fn c() { + mir!( + { + Call(RET = c(), bb1, UnwindTerminate(ReasonAbi)) + } + bb1 = { + Return() + } + ) +} + +// CHECK-LABEL: fn d() +// CHECK: bb0: { +// CHECK-NEXT: d() -> [return: bb1, unwind: bb2]; +#[custom_mir(dialect = "runtime", phase = "optimized")] +pub fn d() { + mir!( + { + Call(RET = d(), bb1, UnwindCleanup(bb2)) + } + bb1 = { + Return() + } + bb2 (cleanup) = { + UnwindResume() + } + ) +} diff --git a/tests/mir-opt/building/custom/unwind_terminate.rs b/tests/mir-opt/building/custom/unwind_terminate.rs new file mode 100644 index 000000000000..efdf2ddb1d02 --- /dev/null +++ b/tests/mir-opt/building/custom/unwind_terminate.rs @@ -0,0 +1,34 @@ +// compile-flags: --crate-type=lib +// edition:2021 +#![feature(custom_mir, core_intrinsics)] +use core::intrinsics::mir::*; + +// CHECK-LABEL: fn f() +// CHECK: bb1 (cleanup): { +// CHECK-NEXT: terminate(abi); +#[custom_mir(dialect = "runtime", phase = "optimized")] +pub fn f() { + mir!( + { + Return() + } + bb1(cleanup) = { + UnwindTerminate(ReasonAbi) + } + ) +} + +// CHECK-LABEL: fn g() +// CHECK: bb1 (cleanup): { +// CHECK-NEXT: terminate(cleanup); +#[custom_mir(dialect = "runtime", phase = "optimized")] +pub fn g() { + mir!( + { + Return() + } + bb1(cleanup) = { + UnwindTerminate(ReasonInCleanup) + } + ) +} diff --git a/tests/mir-opt/copy-prop/borrowed_local.rs b/tests/mir-opt/copy-prop/borrowed_local.rs index c6b8ad3571f3..a44e65164af0 100644 --- a/tests/mir-opt/copy-prop/borrowed_local.rs +++ b/tests/mir-opt/copy-prop/borrowed_local.rs @@ -22,11 +22,11 @@ fn f() -> bool { let b = a; // We cannot propagate the place `a`. let r2 = &b; - Call(RET = cmp_ref(r1, r2), next) + Call(RET = cmp_ref(r1, r2), next, UnwindContinue()) } next = { // But we can propagate the value `a`. - Call(RET = opaque(b), ret) + Call(RET = opaque(b), ret, UnwindContinue()) } ret = { Return() diff --git a/tests/mir-opt/copy-prop/calls.rs b/tests/mir-opt/copy-prop/calls.rs index 2970f5f0b8d4..bc6760707ccc 100644 --- a/tests/mir-opt/copy-prop/calls.rs +++ b/tests/mir-opt/copy-prop/calls.rs @@ -26,7 +26,7 @@ fn multiple_edges(t: bool) -> u8 { match t { true => bbt, _ => ret } } bbt = { - Call(x = dummy(13), ret) + Call(x = dummy(13), ret, UnwindContinue()) } ret = { // `x` is not assigned on the `bb0 -> ret` edge, diff --git a/tests/mir-opt/copy-prop/custom_move_arg.rs b/tests/mir-opt/copy-prop/custom_move_arg.rs index 2077874ee9a7..8593d9fa9aba 100644 --- a/tests/mir-opt/copy-prop/custom_move_arg.rs +++ b/tests/mir-opt/copy-prop/custom_move_arg.rs @@ -14,11 +14,11 @@ struct NotCopy(bool); fn f(_1: NotCopy) { mir!({ let _2 = _1; - Call(RET = opaque(Move(_1)), bb1) + Call(RET = opaque(Move(_1)), bb1, UnwindContinue()) } bb1 = { let _3 = Move(_2); - Call(RET = opaque(_3), bb2) + Call(RET = opaque(_3), bb2, UnwindContinue()) } bb2 = { Return() diff --git a/tests/mir-opt/copy-prop/move_projection.rs b/tests/mir-opt/copy-prop/move_projection.rs index 8629d535bcf7..438a90dddd0c 100644 --- a/tests/mir-opt/copy-prop/move_projection.rs +++ b/tests/mir-opt/copy-prop/move_projection.rs @@ -18,10 +18,10 @@ fn f(a: Foo) -> bool { let b = a; // This is a move out of a copy, so must become a copy of `a.0`. let c = Move(b.0); - Call(RET = opaque(Move(a)), bb1) + Call(RET = opaque(Move(a)), bb1, UnwindContinue()) } bb1 = { - Call(RET = opaque(Move(c)), ret) + Call(RET = opaque(Move(c)), ret, UnwindContinue()) } ret = { Return() diff --git a/tests/mir-opt/dead-store-elimination/call_arg_copy.rs b/tests/mir-opt/dead-store-elimination/call_arg_copy.rs index dcd15fb2b09e..b2eb64756f9a 100644 --- a/tests/mir-opt/dead-store-elimination/call_arg_copy.rs +++ b/tests/mir-opt/dead-store-elimination/call_arg_copy.rs @@ -28,7 +28,7 @@ struct Packed { fn move_packed(packed: Packed) { mir!( { - Call(RET = use_both(0, packed.y), ret) + Call(RET = use_both(0, packed.y), ret, UnwindContinue()) } ret = { Return() diff --git a/tests/mir-opt/dead-store-elimination/cycle.rs b/tests/mir-opt/dead-store-elimination/cycle.rs index 8896f5ff345b..c9ad06a9da26 100644 --- a/tests/mir-opt/dead-store-elimination/cycle.rs +++ b/tests/mir-opt/dead-store-elimination/cycle.rs @@ -20,7 +20,7 @@ fn cycle(mut x: i32, mut y: i32, mut z: i32) { mir!( let condition: bool; { - Call(condition = cond(), bb1) + Call(condition = cond(), bb1, UnwindContinue()) } bb1 = { match condition { true => bb2, _ => ret } @@ -30,7 +30,7 @@ fn cycle(mut x: i32, mut y: i32, mut z: i32) { z = y; y = x; x = temp; - Call(condition = cond(), bb1) + Call(condition = cond(), bb1, UnwindContinue()) } ret = { Return() diff --git a/tests/mir-opt/gvn.rs b/tests/mir-opt/gvn.rs index 10a66ced026e..6e082acdbd39 100644 --- a/tests/mir-opt/gvn.rs +++ b/tests/mir-opt/gvn.rs @@ -529,31 +529,31 @@ fn duplicate_slice() -> (bool, bool) { // CHECK: [[a:_.*]] = (const "a",); // CHECK: [[au:_.*]] = ([[a]].0: &str) as u128 (Transmute); let a = ("a",); - Call(au = transmute::<_, u128>(a.0), bb1) + Call(au = transmute::<_, u128>(a.0), bb1, UnwindContinue()) } bb1 = { // CHECK: [[c:_.*]] = identity::<&str>(([[a]].0: &str)) - Call(c = identity(a.0), bb2) + Call(c = identity(a.0), bb2, UnwindContinue()) } bb2 = { // CHECK: [[cu:_.*]] = [[c]] as u128 (Transmute); - Call(cu = transmute::<_, u128>(c), bb3) + Call(cu = transmute::<_, u128>(c), bb3, UnwindContinue()) } bb3 = { // This slice is different from `a.0`. Hence `bu` is not `au`. // CHECK: [[b:_.*]] = const "a"; // CHECK: [[bu:_.*]] = [[b]] as u128 (Transmute); let b = "a"; - Call(bu = transmute::<_, u128>(b), bb4) + Call(bu = transmute::<_, u128>(b), bb4, UnwindContinue()) } bb4 = { // This returns a copy of `b`, which is not `a`. // CHECK: [[d:_.*]] = identity::<&str>([[b]]) - Call(d = identity(b), bb5) + Call(d = identity(b), bb5, UnwindContinue()) } bb5 = { // CHECK: [[du:_.*]] = [[d]] as u128 (Transmute); - Call(du = transmute::<_, u128>(d), bb6) + Call(du = transmute::<_, u128>(d), bb6, UnwindContinue()) } bb6 = { // `direct` must not fold to `true`, as `indirect` will not. diff --git a/tests/mir-opt/reference_prop.rs b/tests/mir-opt/reference_prop.rs index 36134e019ad0..1b9c8fe15c25 100644 --- a/tests/mir-opt/reference_prop.rs +++ b/tests/mir-opt/reference_prop.rs @@ -695,7 +695,7 @@ fn multiple_storage() { // As there are multiple `StorageLive` statements for `x`, we cannot know if this `z`'s // pointer address is the address of `x`, so do nothing. let y = *z; - Call(RET = opaque(y), retblock) + Call(RET = opaque(y), retblock, UnwindContinue()) } retblock = { @@ -723,7 +723,7 @@ fn dominate_storage() { } bb1 = { let c = *r; - Call(RET = opaque(c), bb2) + Call(RET = opaque(c), bb2, UnwindContinue()) } bb2 = { StorageDead(x); @@ -759,18 +759,18 @@ fn maybe_dead(m: bool) { bb1 = { StorageDead(x); StorageDead(y); - Call(RET = opaque(u), bb2) + Call(RET = opaque(u), bb2, UnwindContinue()) } bb2 = { // As `x` may be `StorageDead`, `a` may be dangling, so we do nothing. let z = *a; - Call(RET = opaque(z), bb3) + Call(RET = opaque(z), bb3, UnwindContinue()) } bb3 = { // As `y` may be `StorageDead`, `b` may be dangling, so we do nothing. // This implies that we also do not substitute `b` in `bb0`. let t = *b; - Call(RET = opaque(t), retblock) + Call(RET = opaque(t), retblock, UnwindContinue()) } retblock = { Return() diff --git a/tests/ui/mir/validate/noncleanup-cleanup.rs b/tests/ui/mir/validate/noncleanup-cleanup.rs new file mode 100644 index 000000000000..0a1c4528aa6d --- /dev/null +++ b/tests/ui/mir/validate/noncleanup-cleanup.rs @@ -0,0 +1,21 @@ +// Check that validation rejects cleanup edge to a non-cleanup block. +// +// failure-status: 101 +// dont-check-compiler-stderr +// error-pattern: cleanuppad mismatch +#![feature(custom_mir, core_intrinsics)] +extern crate core; +use core::intrinsics::mir::*; + +#[custom_mir(dialect = "built")] +pub fn main() { + mir!( + { + Call(RET = main(), block, UnwindCleanup(block)) + } + block = { + Return() + } + ) + +} diff --git a/tests/ui/mir/validate/noncleanup-resume.rs b/tests/ui/mir/validate/noncleanup-resume.rs new file mode 100644 index 000000000000..e80d09bc90a5 --- /dev/null +++ b/tests/ui/mir/validate/noncleanup-resume.rs @@ -0,0 +1,17 @@ +// Check that validation rejects resume terminator in a non-cleanup block. +// +// failure-status: 101 +// dont-check-compiler-stderr +// error-pattern: resume on non-cleanup block +#![feature(custom_mir, core_intrinsics)] +extern crate core; +use core::intrinsics::mir::*; + +#[custom_mir(dialect = "built")] +pub fn main() { + mir!( + { + UnwindResume() + } + ) +} diff --git a/tests/ui/mir/validate/noncleanup-terminate.rs b/tests/ui/mir/validate/noncleanup-terminate.rs new file mode 100644 index 000000000000..2a74668370d4 --- /dev/null +++ b/tests/ui/mir/validate/noncleanup-terminate.rs @@ -0,0 +1,17 @@ +// Check that validation rejects terminate terminator in a non-cleanup block. +// +// failure-status: 101 +// dont-check-compiler-stderr +// error-pattern: terminate on non-cleanup block +#![feature(custom_mir, core_intrinsics)] +extern crate core; +use core::intrinsics::mir::*; + +#[custom_mir(dialect = "built")] +pub fn main() { + mir!( + { + UnwindTerminate(ReasonAbi) + } + ) +} From 8e2fcc4ca211021d929ca424055b59307a97a8f4 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Tue, 14 Nov 2023 12:06:30 +0100 Subject: [PATCH 429/435] Update to LLVM 17.0.5 --- src/llvm-project | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/llvm-project b/src/llvm-project index fef3d7b14ede..773829517804 160000 --- a/src/llvm-project +++ b/src/llvm-project @@ -1 +1 @@ -Subproject commit fef3d7b14ede45d051dc688aae0bb8c8b02a0566 +Subproject commit 7738295178045041669876bf32b0543ec8319a5c From a44a4edc0eb4361f998646891ba3728d3c9d9694 Mon Sep 17 00:00:00 2001 From: cui fliter Date: Tue, 14 Nov 2023 23:06:50 +0800 Subject: [PATCH 430/435] Fix some typos Signed-off-by: cui fliter --- compiler/rustc_codegen_llvm/src/callee.rs | 2 +- compiler/rustc_const_eval/src/interpret/discriminant.rs | 4 ++-- compiler/rustc_data_structures/src/sharded.rs | 6 +++--- compiler/rustc_data_structures/src/sync/lock.rs | 4 ++-- compiler/rustc_errors/src/markdown/parse.rs | 2 +- compiler/rustc_lint/src/reference_casting.rs | 2 +- compiler/rustc_parse/src/parser/ty.rs | 2 +- compiler/rustc_passes/src/dead.rs | 2 +- compiler/rustc_privacy/src/lib.rs | 2 +- 9 files changed, 13 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/callee.rs b/compiler/rustc_codegen_llvm/src/callee.rs index d5778757caae..0c9f7f195519 100644 --- a/compiler/rustc_codegen_llvm/src/callee.rs +++ b/compiler/rustc_codegen_llvm/src/callee.rs @@ -59,7 +59,7 @@ pub fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) -> // To avoid this, we set the Storage Class to "DllImport" so that // LLVM will prefix the name with `__imp_`. Ideally, we'd like the // existing logic below to set the Storage Class, but it has an - // exemption for MinGW for backwards compatability. + // exemption for MinGW for backwards compatibility. let llfn = cx.declare_fn( &common::i686_decorated_name( &dllimport, diff --git a/compiler/rustc_const_eval/src/interpret/discriminant.rs b/compiler/rustc_const_eval/src/interpret/discriminant.rs index fd1736703743..d9f583c1d1f6 100644 --- a/compiler/rustc_const_eval/src/interpret/discriminant.rs +++ b/compiler/rustc_const_eval/src/interpret/discriminant.rs @@ -119,7 +119,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { if matches!(ty.kind(), ty::Adt(def, ..) if def.variants().is_empty()) { throw_ub!(UninhabitedEnumVariantRead(index)) } - // For consisteny with `write_discriminant`, and to make sure that + // For consistency with `write_discriminant`, and to make sure that // `project_downcast` cannot fail due to strange layouts, we declare immediate UB // for uninhabited variants. if op.layout().for_variant(self, index).abi.is_uninhabited() { @@ -236,7 +236,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { variant } }; - // For consisteny with `write_discriminant`, and to make sure that `project_downcast` cannot fail due to strange layouts, we declare immediate UB for uninhabited variants. + // For consistency with `write_discriminant`, and to make sure that `project_downcast` cannot fail due to strange layouts, we declare immediate UB for uninhabited variants. if op.layout().for_variant(self, index).abi.is_uninhabited() { throw_ub!(UninhabitedEnumVariantRead(index)) } diff --git a/compiler/rustc_data_structures/src/sharded.rs b/compiler/rustc_data_structures/src/sharded.rs index 29516fffd6a6..639f05c9e524 100644 --- a/compiler/rustc_data_structures/src/sharded.rs +++ b/compiler/rustc_data_structures/src/sharded.rs @@ -79,7 +79,7 @@ impl Sharded { pub fn lock_shard_by_value(&self, _val: &K) -> LockGuard<'_, T> { match self { Self::Single(single) => { - // Syncronization is disabled so use the `lock_assume_no_sync` method optimized + // Synchronization is disabled so use the `lock_assume_no_sync` method optimized // for that case. // SAFETY: We know `is_dyn_thread_safe` was false when creating the lock thus @@ -102,7 +102,7 @@ impl Sharded { pub fn lock_shard_by_index(&self, _i: usize) -> LockGuard<'_, T> { match self { Self::Single(single) => { - // Syncronization is disabled so use the `lock_assume_no_sync` method optimized + // Synchronization is disabled so use the `lock_assume_no_sync` method optimized // for that case. // SAFETY: We know `is_dyn_thread_safe` was false when creating the lock thus @@ -111,7 +111,7 @@ impl Sharded { } #[cfg(parallel_compiler)] Self::Shards(shards) => { - // Syncronization is enabled so use the `lock_assume_sync` method optimized + // Synchronization is enabled so use the `lock_assume_sync` method optimized // for that case. // SAFETY (get_unchecked): The index gets ANDed with the shard mask, ensuring it is diff --git a/compiler/rustc_data_structures/src/sync/lock.rs b/compiler/rustc_data_structures/src/sync/lock.rs index 339aebbf81aa..040a8aa6b638 100644 --- a/compiler/rustc_data_structures/src/sync/lock.rs +++ b/compiler/rustc_data_structures/src/sync/lock.rs @@ -38,7 +38,7 @@ mod maybe_sync { lock: &'a Lock, marker: PhantomData<&'a mut T>, - /// The syncronization mode of the lock. This is explicitly passed to let LLVM relate it + /// The synchronization mode of the lock. This is explicitly passed to let LLVM relate it /// to the original lock operation. mode: Mode, } @@ -142,7 +142,7 @@ mod maybe_sync { .then(|| LockGuard { lock: self, marker: PhantomData, mode }) } - /// This acquires the lock assuming syncronization is in a specific mode. + /// This acquires the lock assuming synchronization is in a specific mode. /// /// Safety /// This method must only be called with `Mode::Sync` if `might_be_dyn_thread_safe` was diff --git a/compiler/rustc_errors/src/markdown/parse.rs b/compiler/rustc_errors/src/markdown/parse.rs index d3a08da62839..67e4963fddf7 100644 --- a/compiler/rustc_errors/src/markdown/parse.rs +++ b/compiler/rustc_errors/src/markdown/parse.rs @@ -329,7 +329,7 @@ fn parse_with_end_pat<'a>( end_sep: &[u8], ignore_esc: bool, ) -> Option<(&'a [u8], &'a [u8])> { - // Find positions that start with the end seperator + // Find positions that start with the end separator for idx in (0..buf.len()).filter(|idx| buf[*idx..].starts_with(end_sep)) { if !ignore_esc && idx > 0 && buf[idx - 1] == b'\\' { continue; diff --git a/compiler/rustc_lint/src/reference_casting.rs b/compiler/rustc_lint/src/reference_casting.rs index d44691b5e9ba..82483ac7dc0f 100644 --- a/compiler/rustc_lint/src/reference_casting.rs +++ b/compiler/rustc_lint/src/reference_casting.rs @@ -155,7 +155,7 @@ fn is_cast_from_const_to_mut<'tcx>( let start_ty = cx.typeck_results().node_type(e.hir_id); if let ty::Ref(_, inner_ty, Mutability::Not) = start_ty.kind() { - // If an UnsafeCell method is involved we need to additionaly check the + // If an UnsafeCell method is involved we need to additionally check the // inner type for the presence of the Freeze trait (ie does NOT contain // an UnsafeCell), since in that case we would incorrectly lint on valid casts. // diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index be2cbaf3020e..dc0f13965230 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -135,7 +135,7 @@ impl<'a> Parser<'a> { ) } - /// Parse a type suitable for a field defintion. + /// Parse a type suitable for a field definition. /// The difference from `parse_ty` is that this version /// allows anonymous structs and unions. pub fn parse_ty_for_field_def(&mut self) -> PResult<'a, P> { diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 2e8c58b0241f..6b2b842543a8 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -314,7 +314,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { // for the `#[expect]` case. // // Note that an item can and will be duplicated on the worklist with different - // `ComesFromAllowExpect`, particulary if it was added from the + // `ComesFromAllowExpect`, particularly if it was added from the // `effective_visibilities` query or from the `#[allow]`/`#[expect]` checks, // this "duplication" is essential as otherwise a function with `#[expect]` // called from a `pub fn` may be falsely reported as not live, falsely diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 4bb7e65747f7..4b3b82c59cfb 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -1756,7 +1756,7 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx, '_> { // fn from(_: Priv) -> Pub {...} // } // - // lints shouldn't be emmited even if `from` effective visibility + // lints shouldn't be emitted even if `from` effective visibility // is larger than `Priv` nominal visibility and if `Priv` can leak // in some scenarios due to type inference. let impl_ev = EffectiveVisibility::of_impl::( From 6ad73f5ee8bc25f89966b258400056d1f776760d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Tue, 14 Nov 2023 18:07:02 +0200 Subject: [PATCH 431/435] Depend on rustc_driver --- src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs index 9748990b7a3f..a7d0a0b0dfc4 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs @@ -3,6 +3,10 @@ //! Based on cli flags, either spawns an LSP server, or runs a batch analysis #![warn(rust_2018_idioms, unused_lifetimes, semicolon_in_expressions_from_macros)] +#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))] +#[cfg(feature = "in-rust-tree")] +#[allow(unused_extern_crates)] +extern crate rustc_driver; mod logger; mod rustc_wrapper; From 6873465600c7d9b4cdf80b5fcf4d06abd8c1e91e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Sun, 29 Oct 2023 00:00:00 +0000 Subject: [PATCH 432/435] Fix def-use check for call terminators --- compiler/rustc_codegen_ssa/src/mir/analyze.rs | 19 +++++-- compiler/rustc_middle/src/mir/mod.rs | 19 ++++++- compiler/rustc_mir_transform/src/ssa.rs | 55 +++++++++++-------- tests/ui/mir/ssa_call_ret.rs | 30 ++++++++++ 4 files changed, 93 insertions(+), 30 deletions(-) create mode 100644 tests/ui/mir/ssa_call_ret.rs diff --git a/compiler/rustc_codegen_ssa/src/mir/analyze.rs b/compiler/rustc_codegen_ssa/src/mir/analyze.rs index 2285e7f4e01e..ed859cb20de9 100644 --- a/compiler/rustc_codegen_ssa/src/mir/analyze.rs +++ b/compiler/rustc_codegen_ssa/src/mir/analyze.rs @@ -36,7 +36,7 @@ pub fn non_ssa_locals<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // Arguments get assigned to by means of the function being called for arg in mir.args_iter() { - analyzer.assign(arg, DefLocation::Argument); + analyzer.define(arg, DefLocation::Argument); } // If there exists a local definition that dominates all uses of that local, @@ -74,7 +74,7 @@ struct LocalAnalyzer<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { } impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'tcx, Bx> { - fn assign(&mut self, local: mir::Local, location: DefLocation) { + fn define(&mut self, local: mir::Local, location: DefLocation) { let kind = &mut self.locals[local]; match *kind { LocalKind::ZST => {} @@ -162,7 +162,7 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx> debug!("visit_assign(place={:?}, rvalue={:?})", place, rvalue); if let Some(local) = place.as_local() { - self.assign(local, DefLocation::Body(location)); + self.define(local, DefLocation::Assignment(location)); if self.locals[local] != LocalKind::Memory { let decl_span = self.fx.mir.local_decls[local].source_info.span; if !self.fx.rvalue_creates_operand(rvalue, decl_span) { @@ -183,9 +183,14 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx> fn visit_local(&mut self, local: mir::Local, context: PlaceContext, location: Location) { match context { - PlaceContext::MutatingUse(MutatingUseContext::Call) - | PlaceContext::MutatingUse(MutatingUseContext::Yield) => { - self.assign(local, DefLocation::Body(location)); + PlaceContext::MutatingUse(MutatingUseContext::Call) => { + let call = location.block; + let TerminatorKind::Call { target, .. } = + self.fx.mir.basic_blocks[call].terminator().kind + else { + bug!() + }; + self.define(local, DefLocation::CallReturn { call, target }); } PlaceContext::NonUse(_) @@ -237,6 +242,8 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx> } } } + + PlaceContext::MutatingUse(MutatingUseContext::Yield) => bug!(), } } } diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 7054cede2d87..874c997c23be 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -1611,14 +1611,29 @@ impl Location { #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum DefLocation { Argument, - Body(Location), + Assignment(Location), + CallReturn { call: BasicBlock, target: Option }, } impl DefLocation { pub fn dominates(self, location: Location, dominators: &Dominators) -> bool { match self { DefLocation::Argument => true, - DefLocation::Body(def) => def.successor_within_block().dominates(location, dominators), + DefLocation::Assignment(def) => { + def.successor_within_block().dominates(location, dominators) + } + DefLocation::CallReturn { target: None, .. } => false, + DefLocation::CallReturn { call, target: Some(target) } => { + // The definition occurs on the call -> target edge. The definition dominates a use + // if and only if the edge is on all paths from the entry to the use. + // + // Note that a call terminator has only one edge that can reach the target, so when + // the call strongly dominates the target, all paths from the entry to the target + // go through the call -> target edge. + call != target + && dominators.dominates(call, target) + && dominators.dominates(target, location.block) + } } } } diff --git a/compiler/rustc_mir_transform/src/ssa.rs b/compiler/rustc_mir_transform/src/ssa.rs index 1f59c790b4eb..3a6e1ef34883 100644 --- a/compiler/rustc_mir_transform/src/ssa.rs +++ b/compiler/rustc_mir_transform/src/ssa.rs @@ -40,7 +40,8 @@ impl SsaLocals { let dominators = body.basic_blocks.dominators(); let direct_uses = IndexVec::from_elem(0, &body.local_decls); - let mut visitor = SsaVisitor { assignments, assignment_order, dominators, direct_uses }; + let mut visitor = + SsaVisitor { body, assignments, assignment_order, dominators, direct_uses }; for local in body.args_iter() { visitor.assignments[local] = Set1::One(DefLocation::Argument); @@ -110,7 +111,7 @@ impl SsaLocals { body: &'a Body<'tcx>, ) -> impl Iterator, Location)> + 'a { self.assignment_order.iter().filter_map(|&local| { - if let Set1::One(DefLocation::Body(loc)) = self.assignments[local] { + if let Set1::One(DefLocation::Assignment(loc)) = self.assignments[local] { let stmt = body.stmt_at(loc).left()?; // `loc` must point to a direct assignment to `local`. let Some((target, rvalue)) = stmt.kind.as_assign() else { bug!() }; @@ -134,21 +135,21 @@ impl SsaLocals { AssignedValue::Arg, Location { block: START_BLOCK, statement_index: 0 }, ), - Set1::One(DefLocation::Body(loc)) => { + Set1::One(DefLocation::Assignment(loc)) => { let bb = &mut basic_blocks[loc.block]; - let value = if loc.statement_index < bb.statements.len() { - // `loc` must point to a direct assignment to `local`. - let stmt = &mut bb.statements[loc.statement_index]; - let StatementKind::Assign(box (target, ref mut rvalue)) = stmt.kind else { - bug!() - }; - assert_eq!(target.as_local(), Some(local)); - AssignedValue::Rvalue(rvalue) - } else { - let term = bb.terminator_mut(); - AssignedValue::Terminator(&mut term.kind) + // `loc` must point to a direct assignment to `local`. + let stmt = &mut bb.statements[loc.statement_index]; + let StatementKind::Assign(box (target, ref mut rvalue)) = stmt.kind else { + bug!() }; - f(local, value, loc) + assert_eq!(target.as_local(), Some(local)); + f(local, AssignedValue::Rvalue(rvalue), loc) + } + Set1::One(DefLocation::CallReturn { call, .. }) => { + let bb = &mut basic_blocks[call]; + let loc = Location { block: call, statement_index: bb.statements.len() }; + let term = bb.terminator_mut(); + f(local, AssignedValue::Terminator(&mut term.kind), loc) } _ => {} } @@ -201,14 +202,15 @@ impl SsaLocals { } } -struct SsaVisitor<'a> { +struct SsaVisitor<'tcx, 'a> { + body: &'a Body<'tcx>, dominators: &'a Dominators, assignments: IndexVec>, assignment_order: Vec, direct_uses: IndexVec, } -impl SsaVisitor<'_> { +impl SsaVisitor<'_, '_> { fn check_dominates(&mut self, local: Local, loc: Location) { let set = &mut self.assignments[local]; let assign_dominates = match *set { @@ -224,7 +226,7 @@ impl SsaVisitor<'_> { } } -impl<'tcx> Visitor<'tcx> for SsaVisitor<'_> { +impl<'tcx> Visitor<'tcx> for SsaVisitor<'tcx, '_> { fn visit_local(&mut self, local: Local, ctxt: PlaceContext, loc: Location) { match ctxt { PlaceContext::MutatingUse(MutatingUseContext::Projection) @@ -250,9 +252,18 @@ impl<'tcx> Visitor<'tcx> for SsaVisitor<'_> { fn visit_place(&mut self, place: &Place<'tcx>, ctxt: PlaceContext, loc: Location) { let location = match ctxt { - PlaceContext::MutatingUse( - MutatingUseContext::Store | MutatingUseContext::Call | MutatingUseContext::Yield, - ) => Some(DefLocation::Body(loc)), + PlaceContext::MutatingUse(MutatingUseContext::Store) => { + Some(DefLocation::Assignment(loc)) + } + PlaceContext::MutatingUse(MutatingUseContext::Call) => { + let call = loc.block; + let TerminatorKind::Call { target, .. } = + self.body.basic_blocks[call].terminator().kind + else { + bug!() + }; + Some(DefLocation::CallReturn { call, target }) + } _ => None, }; if let Some(location) = location @@ -359,7 +370,7 @@ impl StorageLiveLocals { for (statement_index, statement) in bbdata.statements.iter().enumerate() { if let StatementKind::StorageLive(local) = statement.kind { storage_live[local] - .insert(DefLocation::Body(Location { block, statement_index })); + .insert(DefLocation::Assignment(Location { block, statement_index })); } } } diff --git a/tests/ui/mir/ssa_call_ret.rs b/tests/ui/mir/ssa_call_ret.rs new file mode 100644 index 000000000000..6132a6691dea --- /dev/null +++ b/tests/ui/mir/ssa_call_ret.rs @@ -0,0 +1,30 @@ +// Regression test for issue #117331, where variable `a` was misidentified as +// being in SSA form (the definition occurs on the return edge only). +// +// edition:2021 +// compile-flags: --crate-type=lib +// build-pass +// needs-unwind +#![feature(custom_mir, core_intrinsics)] +use core::intrinsics::mir::*; + +#[custom_mir(dialect = "runtime", phase = "optimized")] +pub fn f() -> u32 { + mir!( + let a: u32; + { + Call(a = g(), bb1, UnwindCleanup(bb2)) + } + bb1 = { + RET = a; + Return() + } + bb2 (cleanup) = { + RET = a; + UnwindResume() + } + ) +} + +#[inline(never)] +pub fn g() -> u32 { 0 } From 7f10299d9b521e429b02636bde905943f6869b2a Mon Sep 17 00:00:00 2001 From: Slanterns Date: Wed, 15 Nov 2023 06:01:57 +0800 Subject: [PATCH 433/435] Add missing entries in 1.74 release notes --- RELEASES.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/RELEASES.md b/RELEASES.md index 3b764fd773b6..f43bb7cfd32e 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -12,6 +12,7 @@ Language - [Allow explicit `#[repr(Rust)]`](https://github.com/rust-lang/rust/pull/114201/) - [closure field capturing: don't depend on alignment of packed fields](https://github.com/rust-lang/rust/pull/115315/) - [Enable MIR-based drop-tracking for `async` blocks](https://github.com/rust-lang/rust/pull/107421/) +- [Stabilize `impl_trait_projections`](https://github.com/rust-lang/rust/pull/115659) @@ -101,6 +102,7 @@ Compatibility Notes - [make Cell::swap panic if the Cells partially overlap](https://github.com/rust-lang/rust/pull/114795/) - [Reject invalid crate names in `--extern`](https://github.com/rust-lang/rust/pull/116001/) - [Don't resolve generic impls that may be shadowed by dyn built-in impls](https://github.com/rust-lang/rust/pull/114941/) +- [The new `impl From<{&,&mut} [T; N]> for Vec` is known to cause some inference failures with overly-generic code.](https://github.com/rust-lang/rust/issues/117054) In those examples using the `tui` crate, the combination of `AsRef<_>` and `Into` leaves the middle type ambiguous, and the new `impl` adds another possibility, so it now requires an explicit type annotation. From 563d9753649453321c477ecfb61ce86b84bdfa97 Mon Sep 17 00:00:00 2001 From: Slanterns Date: Wed, 15 Nov 2023 08:56:00 +0800 Subject: [PATCH 434/435] tidy --- RELEASES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASES.md b/RELEASES.md index f43bb7cfd32e..a0f6b1203fca 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -7,7 +7,7 @@ Language -------- - [Codify that `std::mem::Discriminant` does not depend on any lifetimes in T](https://github.com/rust-lang/rust/pull/104299/) -- [Replace `private_in_public` lint with `private_interfaces` and `private_bounds` per RFC 2145](https://github.com/rust-lang/rust/pull/113126/) +- [Replace `private_in_public` lint with `private_interfaces` and `private_bounds` per RFC 2145.](https://github.com/rust-lang/rust/pull/113126/) Read more in [RFC 2145](https://rust-lang.github.io/rfcs/2145-type-privacy.html). - [Allow explicit `#[repr(Rust)]`](https://github.com/rust-lang/rust/pull/114201/) - [closure field capturing: don't depend on alignment of packed fields](https://github.com/rust-lang/rust/pull/115315/) From 39e142ffd53c81cabfb170c15d9c35b980f7ffd0 Mon Sep 17 00:00:00 2001 From: The Miri Conjob Bot Date: Wed, 15 Nov 2023 05:05:53 +0000 Subject: [PATCH 435/435] Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 2beb3bfef9e5..0d677d36e362 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -3aaa0f57b7b877ef58532a8de075d1e5a79142bf +6d069a0ac7a423db87d86320edd39974f9f0c492

    c8a{(mx;m;W|O?~`Ycuf4*W{@lZ= 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 OVDNPHb6Mw<&;$T5S^|Io literal 28772 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 F0szf{k4pdm diff --git a/src/doc/rustc/src/images/image3.png b/src/doc/rustc/src/images/image3.png index ef02c605ead8a217a6991f4e7c137ee73ac6c520..844a2fe67472d0225e0c3595816c6832a8323d87 100644 GIT binary patch literal 19936 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

    ` where `P` is one of possible receivers, // the vtable is exactly in the `[ptr_size..2*ptr_size]` bytes. So we can use it without branching on // the type. let first_arg = arg_bytes.clone().next().unwrap(); diff --git a/crates/rust-analyzer/src/handlers/request.rs b/crates/rust-analyzer/src/handlers/request.rs index 6c2f1ec3fede..06c27332d440 100644 --- a/crates/rust-analyzer/src/handlers/request.rs +++ b/crates/rust-analyzer/src/handlers/request.rs @@ -2000,7 +2000,7 @@ fn run_rustfmt( let workspace = CargoTargetSpec::for_file(&snap, file_id)?; let mut cmd = match workspace { Some(spec) => { - // approach: if the command name contains a path seperator, join it with the workspace root. + // approach: if the command name contains a path separator, join it with the workspace root. // however, if the path is absolute, joining will result in the absolute path being preserved. // as a fallback, rely on $PATH-based discovery. let cmd_path = diff --git a/crates/syntax/src/tests/sourcegen_ast.rs b/crates/syntax/src/tests/sourcegen_ast.rs index 56227fce9b5c..74798952a3ff 100644 --- a/crates/syntax/src/tests/sourcegen_ast.rs +++ b/crates/syntax/src/tests/sourcegen_ast.rs @@ -623,7 +623,7 @@ fn lower_enum(grammar: &Grammar, rule: &Rule) -> Option> { } fn lower_rule(acc: &mut Vec, grammar: &Grammar, label: Option<&String>, rule: &Rule) { - if lower_seperated_list(acc, grammar, label, rule) { + if lower_separated_list(acc, grammar, label, rule) { return; } @@ -689,7 +689,7 @@ fn lower_rule(acc: &mut Vec, grammar: &Grammar, label: Option<&String>, r } // (T (',' T)* ','?) -fn lower_seperated_list( +fn lower_separated_list( acc: &mut Vec, grammar: &Grammar, label: Option<&String>, From 03b24f275607672fce4577a6a3edbb18d9b1977d Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 30 Oct 2023 09:11:52 +0100 Subject: [PATCH 173/435] remove some dead code --- .../rustc_mir_build/src/thir/pattern/const_to_pat.rs | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index 53823c9226cd..a5e7cae69349 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -211,16 +211,6 @@ impl<'tcx> ConstToPat<'tcx> { } else if !self.saw_const_match_lint.get() { if let Some(mir_structural_match_violation) = mir_structural_match_violation { match non_sm_ty.kind() { - ty::RawPtr(pointee) - if pointee.ty.is_sized(self.tcx(), self.param_env) => {} - ty::FnPtr(..) | ty::RawPtr(..) => { - self.tcx().emit_spanned_lint( - lint::builtin::POINTER_STRUCTURAL_MATCH, - self.id, - self.span, - PointerPattern, - ); - } ty::Adt(..) if mir_structural_match_violation => { self.tcx().emit_spanned_lint( lint::builtin::INDIRECT_STRUCTURAL_MATCH, From 9a33f82140c6da6e5808253309c674554b93e9fe Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 30 Oct 2023 15:21:34 +0000 Subject: [PATCH 174/435] Remove inline asm support from the list of limitations #1403 extended support to all targets supported by cg_clif --- Readme.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/Readme.md b/Readme.md index 5664cbe7d4fa..1a2b2bbc5881 100644 --- a/Readme.md +++ b/Readme.md @@ -76,8 +76,6 @@ configuration options. ## Not yet supported -* Inline assembly ([no cranelift support](https://github.com/bytecodealliance/wasmtime/issues/1041)) - * On UNIX there is support for invoking an external assembler for `global_asm!` and `asm!`. * SIMD ([tracked here](https://github.com/rust-lang/rustc_codegen_cranelift/issues/171), `std::simd` fully works, `std::arch` is partially supported) * Unwinding on panics ([no cranelift support](https://github.com/bytecodealliance/wasmtime/issues/1677), `-Cpanic=abort` is enabled by default) From 9d290f1d4c45d4459b51f26c3df26025e23e21b1 Mon Sep 17 00:00:00 2001 From: Sarrus1 Date: Mon, 30 Oct 2023 19:40:24 +0100 Subject: [PATCH 175/435] chore: fix urls in guide.md --- docs/dev/guide.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/dev/guide.md b/docs/dev/guide.md index 56a68ef04379..a5f1811bf24a 100644 --- a/docs/dev/guide.md +++ b/docs/dev/guide.md @@ -272,7 +272,7 @@ several times, with different sets of `cfg`s enabled. The IDE-specific task of mapping source code into a semantic model is inherently imprecise for this reason and gets handled by the [`source_binder`]. -[`source_binder`]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/hir/src/source_binder.rs +[`source_binder`]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/source_binder.rs The semantic interface is declared in the [`code_model_api`] module. Each entity is identified by an integer ID and has a bunch of methods which take a salsa database @@ -280,8 +280,8 @@ as an argument and returns other entities (which are also IDs). Internally, thes methods invoke various queries on the database to build the model on demand. Here's [the list of queries]. -[`code_model_api`]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/hir/src/code_model_api.rs -[the list of queries]: https://github.com/rust-lang/rust-analyzer/blob/7e84440e25e19529e4ff8a66e521d1b06349c6ec/crates/hir/src/db.rs#L20-L106 +[`code_model_api`]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/code_model_api.rs +[the list of queries]: https://github.com/rust-lang/rust-analyzer/blob/7e84440e25e19529e4ff8a66e521d1b06349c6ec/crates/ra_hir/src/db.rs#L20-L106 The first step of building the model is parsing the source code. From ab8101d0196b6d1d0161b47fadff22bc82195fe5 Mon Sep 17 00:00:00 2001 From: SparrowLii Date: Tue, 31 Oct 2023 16:36:40 +0800 Subject: [PATCH 176/435] enable parallel rustc in nightly builds --- src/bootstrap/src/core/config/config.rs | 7 +++++-- src/ci/run.sh | 4 ++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index f56e46010f37..95d34aaf285d 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -1072,6 +1072,7 @@ impl Config { config.bindir = "bin".into(); config.dist_include_mingw_linker = true; config.dist_compression_profile = "fast".into(); + config.rustc_parallel = true; config.stdout_is_tty = std::io::stdout().is_terminal(); config.stderr_is_tty = std::io::stderr().is_terminal(); @@ -1111,7 +1112,7 @@ impl Config { fn parse_inner(args: &[String], get_toml: impl Fn(&Path) -> TomlConfig) -> Config { let mut flags = Flags::parse(&args); - let mut config = Config::default_opts(); + let mut config: Config = Config::default_opts(); // Set flags. config.paths = std::mem::take(&mut flags.paths); @@ -1429,7 +1430,9 @@ impl Config { set(&mut config.use_lld, rust.use_lld); set(&mut config.lld_enabled, rust.lld); set(&mut config.llvm_tools_enabled, rust.llvm_tools); - config.rustc_parallel = rust.parallel_compiler.unwrap_or(false); + config.rustc_parallel = rust + .parallel_compiler + .unwrap_or(config.channel == "dev" || config.channel == "nightly"); config.rustc_default_linker = rust.default_linker; config.musl_root = rust.musl_root.map(PathBuf::from); config.save_toolstates = rust.save_toolstates.map(PathBuf::from); diff --git a/src/ci/run.sh b/src/ci/run.sh index 9a63bb5c91c9..f67bfb7920ee 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -98,8 +98,8 @@ if [ "$DEPLOY$DEPLOY_ALT" = "1" ]; then if [ "$NO_LLVM_ASSERTIONS" = "1" ]; then RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --disable-llvm-assertions" elif [ "$DEPLOY_ALT" != "" ]; then - if [ "$NO_PARALLEL_COMPILER" = "" ]; then - RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set rust.parallel-compiler" + if [ "$ALT_PARALLEL_COMPILER" = "" ]; then + RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set rust.parallel-compiler=false" fi RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-llvm-assertions" RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set rust.verify-llvm-ir" From bf5fb7614b2d7fe6a3c2a9a2c922734c03e8dab6 Mon Sep 17 00:00:00 2001 From: SparrowLii Date: Tue, 31 Oct 2023 16:52:16 +0800 Subject: [PATCH 177/435] update bootstrap change history --- config.example.toml | 2 +- src/bootstrap/src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config.example.toml b/config.example.toml index 66fa91d4bad1..698e3d62ae41 100644 --- a/config.example.toml +++ b/config.example.toml @@ -30,7 +30,7 @@ # # If `change-id` does not match the version that is currently running, # `x.py` will prompt you to update it and check the related PR for more details. -change-id = 116998 +change-id = 117435 # ============================================================================= # Tweaking how LLVM is compiled diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index d7f49a6d11b9..80d6b77e96ba 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -77,7 +77,7 @@ const LLD_FILE_NAMES: &[&str] = &["ld.lld", "ld64.lld", "lld-link", "wasm-ld"]; /// /// If you make any major changes (such as adding new values or changing default values), please /// ensure that the associated PR ID is added to the end of this list. -pub const CONFIG_CHANGE_HISTORY: &[usize] = &[115898, 116998]; +pub const CONFIG_CHANGE_HISTORY: &[usize] = &[115898, 116998, 117435]; /// Extra --check-cfg to add when building /// (Mode restriction, config name, config values (if any)) From 248dd14fa590b55b237098ff377e702e4d336bd1 Mon Sep 17 00:00:00 2001 From: SparrowLii Date: Tue, 31 Oct 2023 17:30:41 +0800 Subject: [PATCH 178/435] update config.example.toml --- config.example.toml | 9 +++++---- src/bootstrap/src/core/config/config.rs | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/config.example.toml b/config.example.toml index 698e3d62ae41..4984cf8ba1e7 100644 --- a/config.example.toml +++ b/config.example.toml @@ -553,10 +553,11 @@ change-id = 117435 # Whether to always use incremental compilation when building rustc #incremental = false -# Build a multi-threaded rustc -# FIXME(#75760): Some UI tests fail when this option is enabled. -# NOTE: This option is NOT SUPPORTED. See #48685. -#parallel-compiler = false +# Build a multi-threaded rustc. This allows users to use parallel rustc +# via the unstable option `-Z threads=n`. +# Since stable/beta channels only allow using stable features, +# `parallel-compiler = false` should be set for these channels. +#parallel-compiler = true # The default linker that will be hard-coded into the generated # compiler for targets that don't specify a default linker explicitly diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 95d34aaf285d..a871399453e4 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -1112,7 +1112,7 @@ impl Config { fn parse_inner(args: &[String], get_toml: impl Fn(&Path) -> TomlConfig) -> Config { let mut flags = Flags::parse(&args); - let mut config: Config = Config::default_opts(); + let mut config = Config::default_opts(); // Set flags. config.paths = std::mem::take(&mut flags.paths); From a723acf3469e4585a3da2b230e67afe4683d92a2 Mon Sep 17 00:00:00 2001 From: Young-Flash <871946895@qq.com> Date: Tue, 31 Oct 2023 21:03:26 +0800 Subject: [PATCH 179/435] simplify the code --- crates/ide-db/src/imports/insert_use.rs | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/crates/ide-db/src/imports/insert_use.rs b/crates/ide-db/src/imports/insert_use.rs index 6caa6e3511cd..a0cfd3836ddf 100644 --- a/crates/ide-db/src/imports/insert_use.rs +++ b/crates/ide-db/src/imports/insert_use.rs @@ -9,7 +9,7 @@ use syntax::{ algo, ast::{ self, edit_in_place::Removable, make, AstNode, HasAttrs, HasModuleItem, HasVisibility, - PathSegmentKind, Rename, UseTree, + PathSegmentKind, UseTree, }, ted, Direction, NodeOrToken, SyntaxKind, SyntaxNode, }; @@ -163,16 +163,12 @@ pub fn insert_use(scope: &ImportScope, path: ast::Path, cfg: &InsertUseConfig) { pub fn insert_use_as_alias(scope: &ImportScope, path: ast::Path, cfg: &InsertUseConfig) { let text: &str = "use foo as _"; let parse = syntax::SourceFile::parse(text); - let node = match parse.tree().syntax().descendants().find_map(UseTree::cast) { - Some(it) => it, - None => { - panic!( - "Failed to make ast node `{}` from text {}", - std::any::type_name::(), - text - ) - } - }; + let node = parse + .tree() + .syntax() + .descendants() + .find_map(UseTree::cast) + .expect("Failed to make ast node `Rename`"); let alias = node.rename(); insert_use_with_alias_option(scope, path, cfg, alias); @@ -202,11 +198,8 @@ fn insert_use_with_alias_option( }; } - let use_item = if alias.is_some() { - make::use_(None, make::use_tree(path.clone(), None, alias, false)).clone_for_update() - } else { - make::use_(None, make::use_tree(path.clone(), None, None, false)).clone_for_update() - }; + let use_item = + make::use_(None, make::use_tree(path.clone(), None, alias, false)).clone_for_update(); // merge into existing imports if possible if let Some(mb) = mb { From 929544ef2886a0823868ac9b7011c516ce697476 Mon Sep 17 00:00:00 2001 From: Young-Flash <871946895@qq.com> Date: Tue, 31 Oct 2023 22:13:07 +0800 Subject: [PATCH 180/435] use `check_assist_by_label` to pick assist --- .../ide-assists/src/handlers/auto_import.rs | 220 +++++++++++++++++- 1 file changed, 213 insertions(+), 7 deletions(-) diff --git a/crates/ide-assists/src/handlers/auto_import.rs b/crates/ide-assists/src/handlers/auto_import.rs index a2efa4d10bd6..cafd57a97727 100644 --- a/crates/ide-assists/src/handlers/auto_import.rs +++ b/crates/ide-assists/src/handlers/auto_import.rs @@ -287,7 +287,8 @@ mod tests { }; use crate::tests::{ - check_assist, check_assist_not_applicable, check_assist_target, TEST_CONFIG, + check_assist, check_assist_by_label, check_assist_not_applicable, check_assist_target, + TEST_CONFIG, }; fn check_auto_import_order(before: &str, order: &[&str]) { @@ -739,7 +740,44 @@ fn main() { #[test] fn associated_trait_function() { - check_assist( + check_assist_by_label( + auto_import, + r" + mod test_mod { + pub trait TestTrait { + fn test_function(); + } + pub struct TestStruct {} + impl TestTrait for TestStruct { + fn test_function() {} + } + } + + fn main() { + test_mod::TestStruct::test_function$0 + } + ", + r" + use test_mod::TestTrait; + + mod test_mod { + pub trait TestTrait { + fn test_function(); + } + pub struct TestStruct {} + impl TestTrait for TestStruct { + fn test_function() {} + } + } + + fn main() { + test_mod::TestStruct::test_function + } + ", + "Import `test_mod::TestTrait`", + ); + + check_assist_by_label( auto_import, r" mod test_mod { @@ -773,6 +811,7 @@ fn main() { test_mod::TestStruct::test_function } ", + "Import `test_mod::TestTrait as _`", ); } @@ -810,7 +849,7 @@ fn main() { #[test] fn associated_trait_const() { - check_assist( + check_assist_by_label( auto_import, r" mod test_mod { @@ -844,6 +883,44 @@ fn main() { test_mod::TestStruct::TEST_CONST } ", + "Import `test_mod::TestTrait as _`", + ); + + check_assist_by_label( + auto_import, + r" + mod test_mod { + pub trait TestTrait { + const TEST_CONST: u8; + } + pub struct TestStruct {} + impl TestTrait for TestStruct { + const TEST_CONST: u8 = 42; + } + } + + fn main() { + test_mod::TestStruct::TEST_CONST$0 + } + ", + r" + use test_mod::TestTrait; + + mod test_mod { + pub trait TestTrait { + const TEST_CONST: u8; + } + pub struct TestStruct {} + impl TestTrait for TestStruct { + const TEST_CONST: u8 = 42; + } + } + + fn main() { + test_mod::TestStruct::TEST_CONST + } + ", + "Import `test_mod::TestTrait`", ); } @@ -881,7 +958,7 @@ fn main() { #[test] fn trait_method() { - check_assist( + check_assist_by_label( auto_import, r" mod test_mod { @@ -917,12 +994,52 @@ fn main() { test_struct.test_method() } ", + "Import `test_mod::TestTrait as _`", + ); + + check_assist_by_label( + auto_import, + r" + mod test_mod { + pub trait TestTrait { + fn test_method(&self); + } + pub struct TestStruct {} + impl TestTrait for TestStruct { + fn test_method(&self) {} + } + } + + fn main() { + let test_struct = test_mod::TestStruct {}; + test_struct.test_meth$0od() + } + ", + r" + use test_mod::TestTrait; + + mod test_mod { + pub trait TestTrait { + fn test_method(&self); + } + pub struct TestStruct {} + impl TestTrait for TestStruct { + fn test_method(&self) {} + } + } + + fn main() { + let test_struct = test_mod::TestStruct {}; + test_struct.test_method() + } + ", + "Import `test_mod::TestTrait`", ); } #[test] fn trait_method_cross_crate() { - check_assist( + check_assist_by_label( auto_import, r" //- /main.rs crate:main deps:dep @@ -949,12 +1066,43 @@ fn main() { test_struct.test_method() } ", + "Import `dep::test_mod::TestTrait as _`", + ); + + check_assist_by_label( + auto_import, + r" + //- /main.rs crate:main deps:dep + fn main() { + let test_struct = dep::test_mod::TestStruct {}; + test_struct.test_meth$0od() + } + //- /dep.rs crate:dep + pub mod test_mod { + pub trait TestTrait { + fn test_method(&self); + } + pub struct TestStruct {} + impl TestTrait for TestStruct { + fn test_method(&self) {} + } + } + ", + r" + use dep::test_mod::TestTrait; + + fn main() { + let test_struct = dep::test_mod::TestStruct {}; + test_struct.test_method() + } + ", + "Import `dep::test_mod::TestTrait`", ); } #[test] fn assoc_fn_cross_crate() { - check_assist( + check_assist_by_label( auto_import, r" //- /main.rs crate:main deps:dep @@ -979,12 +1127,41 @@ fn main() { dep::test_mod::TestStruct::test_function } ", + "Import `dep::test_mod::TestTrait as _`", + ); + + check_assist_by_label( + auto_import, + r" + //- /main.rs crate:main deps:dep + fn main() { + dep::test_mod::TestStruct::test_func$0tion + } + //- /dep.rs crate:dep + pub mod test_mod { + pub trait TestTrait { + fn test_function(); + } + pub struct TestStruct {} + impl TestTrait for TestStruct { + fn test_function() {} + } + } + ", + r" + use dep::test_mod::TestTrait; + + fn main() { + dep::test_mod::TestStruct::test_function + } + ", + "Import `dep::test_mod::TestTrait`", ); } #[test] fn assoc_const_cross_crate() { - check_assist( + check_assist_by_label( auto_import, r" //- /main.rs crate:main deps:dep @@ -1009,6 +1186,35 @@ fn main() { dep::test_mod::TestStruct::CONST } ", + "Import `dep::test_mod::TestTrait as _`", + ); + + check_assist_by_label( + auto_import, + r" + //- /main.rs crate:main deps:dep + fn main() { + dep::test_mod::TestStruct::CONST$0 + } + //- /dep.rs crate:dep + pub mod test_mod { + pub trait TestTrait { + const CONST: bool; + } + pub struct TestStruct {} + impl TestTrait for TestStruct { + const CONST: bool = true; + } + } + ", + r" + use dep::test_mod::TestTrait; + + fn main() { + dep::test_mod::TestStruct::CONST + } + ", + "Import `dep::test_mod::TestTrait`", ); } From 48ca2d9703742149aa33b3f84ae933d063213d19 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 31 Oct 2023 18:38:31 +0000 Subject: [PATCH 181/435] Implement llvm.fma.v* intrinsics cc #1405 --- src/intrinsics/llvm.rs | 15 +++++++++++++++ src/intrinsics/mod.rs | 29 +++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/src/intrinsics/llvm.rs b/src/intrinsics/llvm.rs index c16947609980..e9b7daf14924 100644 --- a/src/intrinsics/llvm.rs +++ b/src/intrinsics/llvm.rs @@ -51,6 +51,21 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>( }); } + _ if intrinsic.starts_with("llvm.fma.v") => { + intrinsic_args!(fx, args => (x,y,z); intrinsic); + + simd_trio_for_each_lane( + fx, + x, + y, + z, + ret, + &|fx, _lane_ty, _res_lane_ty, lane_x, lane_y, lane_z| { + fx.bcx.ins().fma(lane_x, lane_y, lane_z) + }, + ); + } + _ => { fx.tcx .sess diff --git a/src/intrinsics/mod.rs b/src/intrinsics/mod.rs index 83d5d53624eb..58b31a534328 100644 --- a/src/intrinsics/mod.rs +++ b/src/intrinsics/mod.rs @@ -132,6 +132,35 @@ fn simd_pair_for_each_lane<'tcx>( } } +fn simd_trio_for_each_lane<'tcx>( + fx: &mut FunctionCx<'_, '_, 'tcx>, + x: CValue<'tcx>, + y: CValue<'tcx>, + z: CValue<'tcx>, + ret: CPlace<'tcx>, + f: &dyn Fn(&mut FunctionCx<'_, '_, 'tcx>, Ty<'tcx>, Ty<'tcx>, Value, Value, Value) -> Value, +) { + assert_eq!(x.layout(), y.layout()); + let layout = x.layout(); + + let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx); + let lane_layout = fx.layout_of(lane_ty); + let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx); + let ret_lane_layout = fx.layout_of(ret_lane_ty); + assert_eq!(lane_count, ret_lane_count); + + for lane_idx in 0..lane_count { + let x_lane = x.value_lane(fx, lane_idx).load_scalar(fx); + let y_lane = y.value_lane(fx, lane_idx).load_scalar(fx); + let z_lane = z.value_lane(fx, lane_idx).load_scalar(fx); + + let res_lane = f(fx, lane_layout.ty, ret_lane_layout.ty, x_lane, y_lane, z_lane); + let res_lane = CValue::by_val(res_lane, ret_lane_layout); + + ret.place_lane(fx, lane_idx).write_cvalue(fx, res_lane); + } +} + fn simd_reduce<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, val: CValue<'tcx>, From 3d454707ab42dc663c33052b010976e6ada97e10 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Wed, 18 Oct 2023 17:19:51 +0000 Subject: [PATCH 182/435] FileCheck while_storage. --- tests/mir-opt/building/while_storage.rs | 60 ++++++++++++++++ ...hile_loop.PreCodegen.after.panic-abort.mir | 70 +++++++++++++++++++ ...ile_loop.PreCodegen.after.panic-unwind.mir | 70 +++++++++++++++++++ tests/mir-opt/while_storage.rs | 21 ------ ...hile_loop.PreCodegen.after.panic-abort.mir | 16 ----- ...ile_loop.PreCodegen.after.panic-unwind.mir | 16 ----- 6 files changed, 200 insertions(+), 53 deletions(-) create mode 100644 tests/mir-opt/building/while_storage.rs create mode 100644 tests/mir-opt/building/while_storage.while_loop.PreCodegen.after.panic-abort.mir create mode 100644 tests/mir-opt/building/while_storage.while_loop.PreCodegen.after.panic-unwind.mir delete mode 100644 tests/mir-opt/while_storage.rs delete mode 100644 tests/mir-opt/while_storage.while_loop.PreCodegen.after.panic-abort.mir delete mode 100644 tests/mir-opt/while_storage.while_loop.PreCodegen.after.panic-unwind.mir diff --git a/tests/mir-opt/building/while_storage.rs b/tests/mir-opt/building/while_storage.rs new file mode 100644 index 000000000000..b06c1639c3f3 --- /dev/null +++ b/tests/mir-opt/building/while_storage.rs @@ -0,0 +1,60 @@ +// EMIT_MIR_FOR_EACH_PANIC_STRATEGY +// Test that we correctly generate StorageDead statements for while loop +// conditions on all branches +// compile-flags: -Zmir-opt-level=0 + +fn get_bool(c: bool) -> bool { + c +} + +// EMIT_MIR while_storage.while_loop.PreCodegen.after.mir +fn while_loop(c: bool) { + // CHECK-LABEL: fn while_loop( + // CHECK: bb0: { + // CHECK-NEXT: goto -> bb1; + // CHECK: bb1: { + // CHECK-NEXT: StorageLive(_3); + // CHECK-NEXT: StorageLive(_2); + // CHECK-NEXT: _2 = _1; + // CHECK-NEXT: _3 = get_bool(move _2) -> [return: bb2, unwind + // CHECK: bb2: { + // CHECK-NEXT: switchInt(move _3) -> [0: bb3, otherwise: bb4]; + // CHECK: bb3: { + // CHECK-NEXT: StorageDead(_2); + // CHECK-NEXT: StorageLive(_9); + // CHECK-NEXT: _0 = const (); + // CHECK-NEXT: StorageDead(_9); + // CHECK-NEXT: goto -> bb8; + // CHECK: bb4: { + // CHECK-NEXT: StorageDead(_2); + // CHECK-NEXT: StorageLive(_5); + // CHECK-NEXT: StorageLive(_4); + // CHECK-NEXT: _4 = _1; + // CHECK-NEXT: _5 = get_bool(move _4) -> [return: bb5, unwind + // CHECK: bb5: { + // CHECK-NEXT: switchInt(move _5) -> [0: bb6, otherwise: bb7]; + // CHECK: bb6: { + // CHECK-NEXT: StorageDead(_4); + // CHECK-NEXT: _6 = const (); + // CHECK-NEXT: StorageDead(_5); + // CHECK-NEXT: StorageDead(_3); + // CHECK-NEXT: goto -> bb1; + // CHECK: bb7: { + // CHECK-NEXT: StorageDead(_4); + // CHECK-NEXT: _0 = const (); + // CHECK-NEXT: StorageDead(_5); + // CHECK-NEXT: goto -> bb8; + // CHECK: bb8: { + // CHECK-NEXT: StorageDead(_3); + // CHECK-NEXT: return; + + while get_bool(c) { + if get_bool(c) { + break; + } + } +} + +fn main() { + while_loop(false); +} diff --git a/tests/mir-opt/building/while_storage.while_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/building/while_storage.while_loop.PreCodegen.after.panic-abort.mir new file mode 100644 index 000000000000..26c82edf2d5f --- /dev/null +++ b/tests/mir-opt/building/while_storage.while_loop.PreCodegen.after.panic-abort.mir @@ -0,0 +1,70 @@ +// MIR for `while_loop` after PreCodegen + +fn while_loop(_1: bool) -> () { + debug c => _1; + let mut _0: (); + let mut _2: bool; + let mut _3: bool; + let mut _4: bool; + let mut _5: bool; + let mut _6: (); + let mut _7: !; + let mut _8: !; + let _9: (); + let mut _10: !; + + bb0: { + goto -> bb1; + } + + bb1: { + StorageLive(_3); + StorageLive(_2); + _2 = _1; + _3 = get_bool(move _2) -> [return: bb2, unwind unreachable]; + } + + bb2: { + switchInt(move _3) -> [0: bb3, otherwise: bb4]; + } + + bb3: { + StorageDead(_2); + StorageLive(_9); + _0 = const (); + StorageDead(_9); + goto -> bb8; + } + + bb4: { + StorageDead(_2); + StorageLive(_5); + StorageLive(_4); + _4 = _1; + _5 = get_bool(move _4) -> [return: bb5, unwind unreachable]; + } + + bb5: { + switchInt(move _5) -> [0: bb6, otherwise: bb7]; + } + + bb6: { + StorageDead(_4); + _6 = const (); + StorageDead(_5); + StorageDead(_3); + goto -> bb1; + } + + bb7: { + StorageDead(_4); + _0 = const (); + StorageDead(_5); + goto -> bb8; + } + + bb8: { + StorageDead(_3); + return; + } +} diff --git a/tests/mir-opt/building/while_storage.while_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/building/while_storage.while_loop.PreCodegen.after.panic-unwind.mir new file mode 100644 index 000000000000..1bb72074846e --- /dev/null +++ b/tests/mir-opt/building/while_storage.while_loop.PreCodegen.after.panic-unwind.mir @@ -0,0 +1,70 @@ +// MIR for `while_loop` after PreCodegen + +fn while_loop(_1: bool) -> () { + debug c => _1; + let mut _0: (); + let mut _2: bool; + let mut _3: bool; + let mut _4: bool; + let mut _5: bool; + let mut _6: (); + let mut _7: !; + let mut _8: !; + let _9: (); + let mut _10: !; + + bb0: { + goto -> bb1; + } + + bb1: { + StorageLive(_3); + StorageLive(_2); + _2 = _1; + _3 = get_bool(move _2) -> [return: bb2, unwind continue]; + } + + bb2: { + switchInt(move _3) -> [0: bb3, otherwise: bb4]; + } + + bb3: { + StorageDead(_2); + StorageLive(_9); + _0 = const (); + StorageDead(_9); + goto -> bb8; + } + + bb4: { + StorageDead(_2); + StorageLive(_5); + StorageLive(_4); + _4 = _1; + _5 = get_bool(move _4) -> [return: bb5, unwind continue]; + } + + bb5: { + switchInt(move _5) -> [0: bb6, otherwise: bb7]; + } + + bb6: { + StorageDead(_4); + _6 = const (); + StorageDead(_5); + StorageDead(_3); + goto -> bb1; + } + + bb7: { + StorageDead(_4); + _0 = const (); + StorageDead(_5); + goto -> bb8; + } + + bb8: { + StorageDead(_3); + return; + } +} diff --git a/tests/mir-opt/while_storage.rs b/tests/mir-opt/while_storage.rs deleted file mode 100644 index 3a3d451ee8d7..000000000000 --- a/tests/mir-opt/while_storage.rs +++ /dev/null @@ -1,21 +0,0 @@ -// skip-filecheck -// EMIT_MIR_FOR_EACH_PANIC_STRATEGY -// Test that we correctly generate StorageDead statements for while loop -// conditions on all branches - -fn get_bool(c: bool) -> bool { - c -} - -// EMIT_MIR while_storage.while_loop.PreCodegen.after.mir -fn while_loop(c: bool) { - while get_bool(c) { - if get_bool(c) { - break; - } - } -} - -fn main() { - while_loop(false); -} diff --git a/tests/mir-opt/while_storage.while_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/while_storage.while_loop.PreCodegen.after.panic-abort.mir deleted file mode 100644 index 21c4b92cf045..000000000000 --- a/tests/mir-opt/while_storage.while_loop.PreCodegen.after.panic-abort.mir +++ /dev/null @@ -1,16 +0,0 @@ -// MIR for `while_loop` after PreCodegen - -fn while_loop(_1: bool) -> () { - debug c => _1; - let mut _0: (); - scope 1 (inlined get_bool) { - debug c => _1; - } - scope 2 (inlined get_bool) { - debug c => _1; - } - - bb0: { - return; - } -} diff --git a/tests/mir-opt/while_storage.while_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/while_storage.while_loop.PreCodegen.after.panic-unwind.mir deleted file mode 100644 index 21c4b92cf045..000000000000 --- a/tests/mir-opt/while_storage.while_loop.PreCodegen.after.panic-unwind.mir +++ /dev/null @@ -1,16 +0,0 @@ -// MIR for `while_loop` after PreCodegen - -fn while_loop(_1: bool) -> () { - debug c => _1; - let mut _0: (); - scope 1 (inlined get_bool) { - debug c => _1; - } - scope 2 (inlined get_bool) { - debug c => _1; - } - - bb0: { - return; - } -} From e65ec7d8f1a01a5eec62fb71865f0a124aec1ead Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Wed, 18 Oct 2023 17:30:28 +0000 Subject: [PATCH 183/435] FileCheck const_debuginfo. --- .../const_debuginfo.main.ConstDebugInfo.diff | 91 +++++++++++-------- tests/mir-opt/const_debuginfo.rs | 17 +++- 2 files changed, 66 insertions(+), 42 deletions(-) diff --git a/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff b/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff index f5d822520a70..87c07279552f 100644 --- a/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff +++ b/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff @@ -4,6 +4,12 @@ fn main() -> () { let mut _0: (); let _1: u8; + let mut _5: u8; + let mut _6: u8; + let mut _7: u8; + let mut _8: u8; + let mut _14: u32; + let mut _15: u32; scope 1 { - debug x => _1; + debug x => const 1_u8; @@ -19,34 +25,23 @@ scope 4 { - debug sum => _4; + debug sum => const 6_u8; - let _5: &str; + let _9: &str; scope 5 { -- debug s => _5; +- debug s => _9; + debug s => const "hello, world!"; - let _8: bool; - let _9: bool; - let _10: u32; + let _10: (bool, bool, u32); scope 6 { -- debug ((f: (bool, bool, u32)).0: bool) => _8; -- debug ((f: (bool, bool, u32)).1: bool) => _9; -- debug ((f: (bool, bool, u32)).2: u32) => _10; -+ debug ((f: (bool, bool, u32)).0: bool) => const true; -+ debug ((f: (bool, bool, u32)).1: bool) => const false; -+ debug ((f: (bool, bool, u32)).2: u32) => const 123_u32; - let _6: std::option::Option; + debug f => _10; + let _11: std::option::Option; scope 7 { -- debug o => _6; -+ debug o => const Option::::Some(99_u16); - let _11: u32; - let _12: u32; + debug o => _11; + let _12: Point; scope 8 { -- debug ((p: Point).0: u32) => _11; -- debug ((p: Point).1: u32) => _12; -+ debug ((p: Point).0: u32) => const 32_u32; -+ debug ((p: Point).1: u32) => const 32_u32; - let _7: u32; +- debug p => _12; ++ debug p => const Point {{ x: 32_u32, y: 32_u32 }}; + let _13: u32; scope 9 { -- debug a => _7; +- debug a => _13; + debug a => const 64_u32; } } @@ -59,37 +54,57 @@ } bb0: { + StorageLive(_1); _1 = const 1_u8; + StorageLive(_2); _2 = const 2_u8; + StorageLive(_3); _3 = const 3_u8; StorageLive(_4); - _4 = const 6_u8; StorageLive(_5); - _5 = const "hello, world!"; - StorageLive(_8); - StorageLive(_9); - StorageLive(_10); - _8 = const true; - _9 = const false; - _10 = const 123_u32; StorageLive(_6); - _6 = const Option::::Some(99_u16); - _11 = const 32_u32; - _12 = const 32_u32; + _6 = const 1_u8; StorageLive(_7); - _7 = const 64_u32; + _7 = const 2_u8; + _5 = const 3_u8; StorageDead(_7); StorageDead(_6); + StorageLive(_8); + _8 = const 3_u8; + _4 = const 6_u8; StorageDead(_8); - StorageDead(_9); - StorageDead(_10); StorageDead(_5); + StorageLive(_9); + _9 = const "hello, world!"; + StorageLive(_10); + _10 = (const true, const false, const 123_u32); + StorageLive(_11); + _11 = Option::::Some(const 99_u16); + StorageLive(_12); + _12 = const Point {{ x: 32_u32, y: 32_u32 }}; + StorageLive(_13); + StorageLive(_14); + _14 = const 32_u32; + StorageLive(_15); + _15 = const 32_u32; + _13 = const 64_u32; + StorageDead(_15); + StorageDead(_14); + _0 = const (); + StorageDead(_13); + StorageDead(_12); + StorageDead(_11); + StorageDead(_10); + StorageDead(_9); StorageDead(_4); + StorageDead(_3); + StorageDead(_2); + StorageDead(_1); return; } } - ALLOC0 (size: 4, align: 2) { - 01 00 63 00 │ ..c. + ALLOC0 (size: 8, align: 4) { + 20 00 00 00 20 00 00 00 │ ... ... } diff --git a/tests/mir-opt/const_debuginfo.rs b/tests/mir-opt/const_debuginfo.rs index d8ae08a0723c..0e5ac4b8bd60 100644 --- a/tests/mir-opt/const_debuginfo.rs +++ b/tests/mir-opt/const_debuginfo.rs @@ -1,12 +1,23 @@ -// skip-filecheck -// compile-flags: -C overflow-checks=no -Zunsound-mir-opts +// unit-test: ConstDebugInfo +// compile-flags: -C overflow-checks=no -Zmir-enable-passes=+ConstProp struct Point { x: u32, y: u32, } +// EMIT_MIR const_debuginfo.main.ConstDebugInfo.diff fn main() { + // CHECK-LABEL: fn main( + // CHECK: debug x => const 1_u8; + // CHECK: debug y => const 2_u8; + // CHECK: debug z => const 3_u8; + // CHECK: debug sum => const 6_u8; + // CHECK: debug s => const "hello, world!"; + // CHECK: debug f => {{_.*}}; + // CHECK: debug o => {{_.*}}; + // CHECK: debug p => const Point + // CHECK: debug a => const 64_u32; let x = 1u8; let y = 2u8; let z = 3u8; @@ -21,5 +32,3 @@ fn main() { let p = Point { x: 32, y: 32 }; let a = p.x + p.y; } - -// EMIT_MIR const_debuginfo.main.ConstDebugInfo.diff From ac4d0965bb8cbab327cd26306ba4de2036d7d0fd Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Wed, 18 Oct 2023 17:40:14 +0000 Subject: [PATCH 184/435] FileCheck const_prop_miscompile. --- .../indirect_mutation.bar.ConstProp.diff} | 0 .../indirect_mutation.foo.ConstProp.diff} | 0 tests/mir-opt/const_prop/indirect_mutation.rs | 41 +++++++++++++++++++ tests/mir-opt/const_prop_miscompile.rs | 24 ----------- 4 files changed, 41 insertions(+), 24 deletions(-) rename tests/mir-opt/{const_prop_miscompile.bar.ConstProp.diff => const_prop/indirect_mutation.bar.ConstProp.diff} (100%) rename tests/mir-opt/{const_prop_miscompile.foo.ConstProp.diff => const_prop/indirect_mutation.foo.ConstProp.diff} (100%) create mode 100644 tests/mir-opt/const_prop/indirect_mutation.rs delete mode 100644 tests/mir-opt/const_prop_miscompile.rs diff --git a/tests/mir-opt/const_prop_miscompile.bar.ConstProp.diff b/tests/mir-opt/const_prop/indirect_mutation.bar.ConstProp.diff similarity index 100% rename from tests/mir-opt/const_prop_miscompile.bar.ConstProp.diff rename to tests/mir-opt/const_prop/indirect_mutation.bar.ConstProp.diff diff --git a/tests/mir-opt/const_prop_miscompile.foo.ConstProp.diff b/tests/mir-opt/const_prop/indirect_mutation.foo.ConstProp.diff similarity index 100% rename from tests/mir-opt/const_prop_miscompile.foo.ConstProp.diff rename to tests/mir-opt/const_prop/indirect_mutation.foo.ConstProp.diff diff --git a/tests/mir-opt/const_prop/indirect_mutation.rs b/tests/mir-opt/const_prop/indirect_mutation.rs new file mode 100644 index 000000000000..ec9da6e8e5c5 --- /dev/null +++ b/tests/mir-opt/const_prop/indirect_mutation.rs @@ -0,0 +1,41 @@ +// unit-test: ConstProp +// Check that we do not propagate past an indirect mutation. +#![feature(raw_ref_op)] + +// EMIT_MIR indirect_mutation.foo.ConstProp.diff +fn foo() { + // CHECK-LABEL: fn foo( + // CHECK: debug u => _1; + // CHECK: debug y => _3; + // CHECK: _1 = (const 1_i32,); + // CHECK: _2 = &mut (_1.0: i32); + // CHECK: (*_2) = const 5_i32; + // CHECK: _4 = (_1.0: i32); + // CHECK: _3 = Eq(move _4, const 5_i32); + + let mut u = (1,); + *&mut u.0 = 5; + let y = { u.0 } == 5; +} + +// EMIT_MIR indirect_mutation.bar.ConstProp.diff +fn bar() { + // CHECK-LABEL: fn bar( + // CHECK: debug v => _1; + // CHECK: debug y => _4; + // CHECK: _3 = &raw mut (_1.0: i32); + // CHECK: (*_3) = const 5_i32; + // CHECK: _5 = (_1.0: i32); + // CHECK: _4 = Eq(move _5, const 5_i32); + + let mut v = (1,); + unsafe { + *&raw mut v.0 = 5; + } + let y = { v.0 } == 5; +} + +fn main() { + foo(); + bar(); +} diff --git a/tests/mir-opt/const_prop_miscompile.rs b/tests/mir-opt/const_prop_miscompile.rs deleted file mode 100644 index 00696535ac15..000000000000 --- a/tests/mir-opt/const_prop_miscompile.rs +++ /dev/null @@ -1,24 +0,0 @@ -// skip-filecheck -// unit-test: ConstProp -#![feature(raw_ref_op)] - -// EMIT_MIR const_prop_miscompile.foo.ConstProp.diff -fn foo() { - let mut u = (1,); - *&mut u.0 = 5; - let y = { u.0 } == 5; -} - -// EMIT_MIR const_prop_miscompile.bar.ConstProp.diff -fn bar() { - let mut v = (1,); - unsafe { - *&raw mut v.0 = 5; - } - let y = { v.0 } == 5; -} - -fn main() { - foo(); - bar(); -} From 03c9acdd8fec7039c91c9523e4cfde761fb2a577 Mon Sep 17 00:00:00 2001 From: George Bateman Date: Tue, 15 Aug 2023 20:10:45 +0100 Subject: [PATCH 185/435] Support enum variants in offset_of! --- src/base.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/base.rs b/src/base.rs index 80e7c5bd9edb..91b1547cb6ea 100644 --- a/src/base.rs +++ b/src/base.rs @@ -766,7 +766,7 @@ fn codegen_stmt<'tcx>( NullOp::SizeOf => layout.size.bytes(), NullOp::AlignOf => layout.align.abi.bytes(), NullOp::OffsetOf(fields) => { - layout.offset_of_subfield(fx, fields.iter().map(|f| f.index())).bytes() + layout.offset_of_subfield(fx, fields.iter()).bytes() } }; let val = CValue::by_val( From 904aceec7d9595d49b1ce6e9e8a04f64f6a814fd Mon Sep 17 00:00:00 2001 From: clubby789 Date: Fri, 27 Oct 2023 19:51:51 +0000 Subject: [PATCH 186/435] Give a better diagnostic for missing parens in Fn* bounds --- compiler/rustc_parse/messages.ftl | 3 ++ compiler/rustc_parse/src/errors.rs | 28 +++++++++++++++++++ compiler/rustc_parse/src/parser/item.rs | 12 ++++++++ compiler/rustc_span/src/symbol.rs | 3 ++ .../issue-108109-fn-trait-missing-paren.fixed | 8 ++++++ .../issue-108109-fn-trait-missing-paren.rs | 8 ++++++ ...issue-108109-fn-trait-missing-paren.stderr | 11 ++++++++ 7 files changed, 73 insertions(+) create mode 100644 tests/ui/parser/issues/issue-108109-fn-trait-missing-paren.fixed create mode 100644 tests/ui/parser/issues/issue-108109-fn-trait-missing-paren.rs create mode 100644 tests/ui/parser/issues/issue-108109-fn-trait-missing-paren.stderr diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index e0778f72bfe6..8036c68f6181 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -270,6 +270,9 @@ parse_fn_ptr_with_generics = function pointer types may not have generic paramet *[false] a } `for` parameter list +parse_fn_trait_missing_paren = `Fn` bounds require arguments in parentheses + .add_paren = add the missing parentheses + parse_forgot_paren = perhaps you forgot parentheses? parse_found_expr_would_be_stmt = expected expression, found `{$token}` diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index aeb4fd0a304a..311d573d1fcf 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -1370,6 +1370,34 @@ pub(crate) struct FnPtrWithGenericsSugg { pub for_param_list_exists: bool, } +pub(crate) struct FnTraitMissingParen { + pub span: Span, + pub machine_applicable: bool, +} + +impl AddToDiagnostic for FnTraitMissingParen { + fn add_to_diagnostic_with(self, diag: &mut rustc_errors::Diagnostic, _: F) + where + F: Fn( + &mut rustc_errors::Diagnostic, + rustc_errors::SubdiagnosticMessage, + ) -> rustc_errors::SubdiagnosticMessage, + { + diag.span_label(self.span, crate::fluent_generated::parse_fn_trait_missing_paren); + let applicability = if self.machine_applicable { + Applicability::MachineApplicable + } else { + Applicability::MaybeIncorrect + }; + diag.span_suggestion_short( + self.span.shrink_to_hi(), + crate::fluent_generated::parse_add_paren, + "()", + applicability, + ); + } +} + #[derive(Diagnostic)] #[diag(parse_unexpected_if_with_if)] pub(crate) struct UnexpectedIfWithIf( diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 982f601c0d5a..aa06fd9df516 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -2278,6 +2278,18 @@ impl<'a> Parser<'a> { err.span_label(ident.span, "while parsing this `fn`"); err.emit(); } else { + // check for typo'd Fn* trait bounds such as + // fn foo() where F: FnOnce -> () {} + if self.token.kind == token::RArrow { + let machine_applicable = [sym::FnOnce, sym::FnMut, sym::Fn] + .into_iter() + .any(|s| self.prev_token.is_ident_named(s)); + + err.subdiagnostic(errors::FnTraitMissingParen { + span: self.prev_token.span, + machine_applicable, + }); + } return Err(err); } } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 88d9dab2ba56..8b33c1b825a1 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -193,6 +193,9 @@ symbols! { Error, File, FileType, + Fn, + FnMut, + FnOnce, FormatSpec, Formatter, From, diff --git a/tests/ui/parser/issues/issue-108109-fn-trait-missing-paren.fixed b/tests/ui/parser/issues/issue-108109-fn-trait-missing-paren.fixed new file mode 100644 index 000000000000..eaae288864a3 --- /dev/null +++ b/tests/ui/parser/issues/issue-108109-fn-trait-missing-paren.fixed @@ -0,0 +1,8 @@ +// run-rustfix + +pub fn func() where F: FnOnce() -> () {} +//~^ ERROR expected one of +//~| NOTE expected one of +//~| NOTE `Fn` bounds require arguments in parentheses + +fn main() {} diff --git a/tests/ui/parser/issues/issue-108109-fn-trait-missing-paren.rs b/tests/ui/parser/issues/issue-108109-fn-trait-missing-paren.rs new file mode 100644 index 000000000000..ea5c71150e83 --- /dev/null +++ b/tests/ui/parser/issues/issue-108109-fn-trait-missing-paren.rs @@ -0,0 +1,8 @@ +// run-rustfix + +pub fn func() where F: FnOnce -> () {} +//~^ ERROR expected one of +//~| NOTE expected one of +//~| NOTE `Fn` bounds require arguments in parentheses + +fn main() {} diff --git a/tests/ui/parser/issues/issue-108109-fn-trait-missing-paren.stderr b/tests/ui/parser/issues/issue-108109-fn-trait-missing-paren.stderr new file mode 100644 index 000000000000..7cda667570de --- /dev/null +++ b/tests/ui/parser/issues/issue-108109-fn-trait-missing-paren.stderr @@ -0,0 +1,11 @@ +error: expected one of `(`, `+`, `,`, `::`, `<`, or `{`, found `->` + --> $DIR/issue-108109-fn-trait-missing-paren.rs:3:34 + | +LL | pub fn func() where F: FnOnce -> () {} + | -------^^ expected one of `(`, `+`, `,`, `::`, `<`, or `{` + | | | + | | help: try adding parentheses + | `Fn` bounds require arguments in parentheses + +error: aborting due to previous error + From 740a864b7cd7b3f0981f2562519483b0350550a5 Mon Sep 17 00:00:00 2001 From: "luoyangze.ptrl" Date: Thu, 2 Nov 2023 00:27:11 +0800 Subject: [PATCH 187/435] feat: skip checking tt count for include macro call --- crates/hir-expand/src/db.rs | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/crates/hir-expand/src/db.rs b/crates/hir-expand/src/db.rs index 5292a5fa1b16..80450afc331a 100644 --- a/crates/hir-expand/src/db.rs +++ b/crates/hir-expand/src/db.rs @@ -614,9 +614,25 @@ fn macro_expand(db: &dyn ExpandDatabase, id: MacroCallId) -> ExpandResult { + if let Some(name_ref) = + ast_id.to_node(db).path().and_then(|p| p.segment()).and_then(|s| s.name_ref()) + { + name_ref.text() == "include" + } else { + false + } + } + _ => false, + }; + + if !skip_check_tt_count { + // Set a hard limit for the expanded tt + if let Err(value) = check_tt_count(&tt) { + return value; + } } ExpandResult { value: Arc::new(tt), err } From 029fbd67ef65dae50172678033c0762610041a38 Mon Sep 17 00:00:00 2001 From: Kornel Date: Mon, 9 Oct 2023 15:05:32 +0100 Subject: [PATCH 188/435] Hint optimizer about reserved capacity --- library/alloc/src/raw_vec.rs | 18 ++++++++++++++---- tests/codegen/vec-reserve-extend.rs | 14 ++++++++++++++ tests/ui/hygiene/panic-location.run.stderr | 2 +- 3 files changed, 29 insertions(+), 5 deletions(-) create mode 100644 tests/codegen/vec-reserve-extend.rs diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs index 625b67a79ad0..f5756da6a309 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs @@ -305,10 +305,13 @@ impl RawVec { /// The same as `reserve`, but returns on errors instead of panicking or aborting. pub fn try_reserve(&mut self, len: usize, additional: usize) -> Result<(), TryReserveError> { if self.needs_to_grow(len, additional) { - self.grow_amortized(len, additional) - } else { - Ok(()) + self.grow_amortized(len, additional)?; } + unsafe { + // Inform the optimizer that the reservation has succeeded or wasn't needed + core::intrinsics::assume(!self.needs_to_grow(len, additional)); + } + Ok(()) } /// Ensures that the buffer contains at least enough space to hold `len + @@ -339,7 +342,14 @@ impl RawVec { len: usize, additional: usize, ) -> Result<(), TryReserveError> { - if self.needs_to_grow(len, additional) { self.grow_exact(len, additional) } else { Ok(()) } + if self.needs_to_grow(len, additional) { + self.grow_exact(len, additional)?; + } + unsafe { + // Inform the optimizer that the reservation has succeeded or wasn't needed + core::intrinsics::assume(!self.needs_to_grow(len, additional)); + } + Ok(()) } /// Shrinks the buffer down to the specified capacity. If the given amount diff --git a/tests/codegen/vec-reserve-extend.rs b/tests/codegen/vec-reserve-extend.rs new file mode 100644 index 000000000000..d95220104c22 --- /dev/null +++ b/tests/codegen/vec-reserve-extend.rs @@ -0,0 +1,14 @@ +// compile-flags: -O + +#![crate_type = "lib"] + +// CHECK-LABEL: @should_reserve_once +#[no_mangle] +pub fn should_reserve_once(v: &mut Vec) { + // CHECK: tail call void @llvm.assume + v.try_reserve(3).unwrap(); + // CHECK-NOT: call {{.*}}reserve + // CHECK-NOT: call {{.*}}do_reserve_and_handle + // CHECK-NOT: call {{.*}}__rust_alloc( + v.extend([1, 2, 3]); +} diff --git a/tests/ui/hygiene/panic-location.run.stderr b/tests/ui/hygiene/panic-location.run.stderr index 1fd61084130a..e0dc13c0c95c 100644 --- a/tests/ui/hygiene/panic-location.run.stderr +++ b/tests/ui/hygiene/panic-location.run.stderr @@ -1,3 +1,3 @@ -thread 'main' panicked at library/alloc/src/raw_vec.rs:535:5: +thread 'main' panicked at library/alloc/src/raw_vec.rs:545:5: capacity overflow note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace From b76f2c8ee0d9bc5517e6d8a01d62f1add8b12c35 Mon Sep 17 00:00:00 2001 From: "luoyangze.ptrl" Date: Thu, 2 Nov 2023 10:14:54 +0800 Subject: [PATCH 189/435] fix: using name(include) instead of str --- crates/hir-expand/src/db.rs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/crates/hir-expand/src/db.rs b/crates/hir-expand/src/db.rs index 80450afc331a..204227e33873 100644 --- a/crates/hir-expand/src/db.rs +++ b/crates/hir-expand/src/db.rs @@ -12,11 +12,15 @@ use syntax::{ use triomphe::Arc; use crate::{ - ast_id_map::AstIdMap, builtin_attr_macro::pseudo_derive_attr_expansion, - builtin_fn_macro::EagerExpander, fixup, hygiene::HygieneFrame, tt, AstId, BuiltinAttrExpander, - BuiltinDeriveExpander, BuiltinFnLikeExpander, EagerCallInfo, ExpandError, ExpandResult, - ExpandTo, HirFileId, HirFileIdRepr, MacroCallId, MacroCallKind, MacroCallLoc, MacroDefId, - MacroDefKind, MacroFile, ProcMacroExpander, + ast_id_map::AstIdMap, + builtin_attr_macro::pseudo_derive_attr_expansion, + builtin_fn_macro::EagerExpander, + fixup, + hygiene::HygieneFrame, + name::{name, AsName}, + tt, AstId, BuiltinAttrExpander, BuiltinDeriveExpander, BuiltinFnLikeExpander, EagerCallInfo, + ExpandError, ExpandResult, ExpandTo, HirFileId, HirFileIdRepr, MacroCallId, MacroCallKind, + MacroCallLoc, MacroDefId, MacroDefKind, MacroFile, ProcMacroExpander, }; /// Total limit on the number of tokens produced by any macro invocation. @@ -620,7 +624,7 @@ fn macro_expand(db: &dyn ExpandDatabase, id: MacroCallId) -> ExpandResult Date: Sun, 29 Oct 2023 04:11:45 +0100 Subject: [PATCH 190/435] Reorder --- .../src/thir/pattern/check_match.rs | 299 +++++++++--------- 1 file changed, 151 insertions(+), 148 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 933653e708e9..136f4210fe4c 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -572,6 +572,111 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { } } +/// Check if a by-value binding is by-value. That is, check if the binding's type is not `Copy`. +/// Check that there are no borrow or move conflicts in `binding @ subpat` patterns. +/// +/// For example, this would reject: +/// - `ref x @ Some(ref mut y)`, +/// - `ref mut x @ Some(ref y)`, +/// - `ref mut x @ Some(ref mut y)`, +/// - `ref mut? x @ Some(y)`, and +/// - `x @ Some(ref mut? y)`. +/// +/// This analysis is *not* subsumed by NLL. +fn check_borrow_conflicts_in_at_patterns<'tcx>(cx: &MatchVisitor<'_, '_, 'tcx>, pat: &Pat<'tcx>) { + // Extract `sub` in `binding @ sub`. + let PatKind::Binding { name, mode, ty, subpattern: Some(box ref sub), .. } = pat.kind else { + return; + }; + + let is_binding_by_move = |ty: Ty<'tcx>| !ty.is_copy_modulo_regions(cx.tcx, cx.param_env); + + let sess = cx.tcx.sess; + + // Get the binding move, extract the mutability if by-ref. + let mut_outer = match mode { + BindingMode::ByValue if is_binding_by_move(ty) => { + // We have `x @ pat` where `x` is by-move. Reject all borrows in `pat`. + let mut conflicts_ref = Vec::new(); + sub.each_binding(|_, mode, _, span| match mode { + BindingMode::ByValue => {} + BindingMode::ByRef(_) => conflicts_ref.push(span), + }); + if !conflicts_ref.is_empty() { + sess.emit_err(BorrowOfMovedValue { + binding_span: pat.span, + conflicts_ref, + name, + ty, + suggest_borrowing: Some(pat.span.shrink_to_lo()), + }); + } + return; + } + BindingMode::ByValue => return, + BindingMode::ByRef(m) => m.mutability(), + }; + + // We now have `ref $mut_outer binding @ sub` (semantically). + // Recurse into each binding in `sub` and find mutability or move conflicts. + let mut conflicts_move = Vec::new(); + let mut conflicts_mut_mut = Vec::new(); + let mut conflicts_mut_ref = Vec::new(); + sub.each_binding(|name, mode, ty, span| { + match mode { + BindingMode::ByRef(mut_inner) => match (mut_outer, mut_inner.mutability()) { + // Both sides are `ref`. + (Mutability::Not, Mutability::Not) => {} + // 2x `ref mut`. + (Mutability::Mut, Mutability::Mut) => { + conflicts_mut_mut.push(Conflict::Mut { span, name }) + } + (Mutability::Not, Mutability::Mut) => { + conflicts_mut_ref.push(Conflict::Mut { span, name }) + } + (Mutability::Mut, Mutability::Not) => { + conflicts_mut_ref.push(Conflict::Ref { span, name }) + } + }, + BindingMode::ByValue if is_binding_by_move(ty) => { + conflicts_move.push(Conflict::Moved { span, name }) // `ref mut?` + by-move conflict. + } + BindingMode::ByValue => {} // `ref mut?` + by-copy is fine. + } + }); + + let report_mut_mut = !conflicts_mut_mut.is_empty(); + let report_mut_ref = !conflicts_mut_ref.is_empty(); + let report_move_conflict = !conflicts_move.is_empty(); + + let mut occurrences = match mut_outer { + Mutability::Mut => vec![Conflict::Mut { span: pat.span, name }], + Mutability::Not => vec![Conflict::Ref { span: pat.span, name }], + }; + occurrences.extend(conflicts_mut_mut); + occurrences.extend(conflicts_mut_ref); + occurrences.extend(conflicts_move); + + // Report errors if any. + if report_mut_mut { + // Report mutability conflicts for e.g. `ref mut x @ Some(ref mut y)`. + sess.emit_err(MultipleMutBorrows { span: pat.span, occurrences }); + } else if report_mut_ref { + // Report mutability conflicts for e.g. `ref x @ Some(ref mut y)` or the converse. + match mut_outer { + Mutability::Mut => { + sess.emit_err(AlreadyMutBorrowed { span: pat.span, occurrences }); + } + Mutability::Not => { + sess.emit_err(AlreadyBorrowed { span: pat.span, occurrences }); + } + }; + } else if report_move_conflict { + // Report by-ref and by-move conflicts, e.g. `ref x @ y`. + sess.emit_err(MovedWhileBorrowed { span: pat.span, occurrences }); + } +} + fn check_for_bindings_named_same_as_variants( cx: &MatchVisitor<'_, '_, '_>, pat: &Pat<'_>, @@ -616,25 +721,6 @@ fn check_for_bindings_named_same_as_variants( }); } -/// Checks for common cases of "catchall" patterns that may not be intended as such. -fn pat_is_catchall(pat: &DeconstructedPat<'_, '_>) -> bool { - use Constructor::*; - match pat.ctor() { - Wildcard => true, - Single => pat.iter_fields().all(|pat| pat_is_catchall(pat)), - _ => false, - } -} - -fn unreachable_pattern(tcx: TyCtxt<'_>, span: Span, id: HirId, catchall: Option) { - tcx.emit_spanned_lint( - UNREACHABLE_PATTERNS, - id, - span, - UnreachablePattern { span: if catchall.is_some() { Some(span) } else { None }, catchall }, - ); -} - fn irrefutable_let_patterns( tcx: TyCtxt<'_>, id: HirId, @@ -680,11 +766,23 @@ fn report_arm_reachability<'p, 'tcx>( cx: &MatchCheckCtxt<'p, 'tcx>, report: &UsefulnessReport<'p, 'tcx>, ) { + let report_unreachable_pattern = |span, hir_id, catchall: Option| { + cx.tcx.emit_spanned_lint( + UNREACHABLE_PATTERNS, + hir_id, + span, + UnreachablePattern { + span: if catchall.is_some() { Some(span) } else { None }, + catchall, + }, + ); + }; + use Reachability::*; let mut catchall = None; for (arm, is_useful) in report.arm_usefulness.iter() { match is_useful { - Unreachable => unreachable_pattern(cx.tcx, arm.pat.span(), arm.hir_id, catchall), + Unreachable => report_unreachable_pattern(arm.pat.span(), arm.hir_id, catchall), Reachable(unreachables) if unreachables.is_empty() => {} // The arm is reachable, but contains unreachable subpatterns (from or-patterns). Reachable(unreachables) => { @@ -692,7 +790,7 @@ fn report_arm_reachability<'p, 'tcx>( // Emit lints in the order in which they occur in the file. unreachables.sort_unstable(); for span in unreachables { - unreachable_pattern(cx.tcx, span, arm.hir_id, None); + report_unreachable_pattern(span, arm.hir_id, None); } } } @@ -702,22 +800,14 @@ fn report_arm_reachability<'p, 'tcx>( } } -fn collect_non_exhaustive_tys<'tcx>( - tcx: TyCtxt<'tcx>, - pat: &WitnessPat<'tcx>, - non_exhaustive_tys: &mut FxHashSet>, -) { - if matches!(pat.ctor(), Constructor::NonExhaustive) { - non_exhaustive_tys.insert(pat.ty()); +/// Checks for common cases of "catchall" patterns that may not be intended as such. +fn pat_is_catchall(pat: &DeconstructedPat<'_, '_>) -> bool { + use Constructor::*; + match pat.ctor() { + Wildcard => true, + Single => pat.iter_fields().all(|pat| pat_is_catchall(pat)), + _ => false, } - if let Constructor::IntRange(range) = pat.ctor() { - if range.is_beyond_boundaries(pat.ty(), tcx) { - // The range denotes the values before `isize::MIN` or the values after `usize::MAX`/`isize::MAX`. - non_exhaustive_tys.insert(pat.ty()); - } - } - pat.iter_fields() - .for_each(|field_pat| collect_non_exhaustive_tys(tcx, field_pat, non_exhaustive_tys)) } /// Report that a match is not exhaustive. @@ -755,7 +845,14 @@ fn non_exhaustive_match<'p, 'tcx>( sp, format!("non-exhaustive patterns: {joined_patterns} not covered"), ); - err.span_label(sp, pattern_not_covered_label(&witnesses, &joined_patterns)); + err.span_label( + sp, + format!( + "pattern{} {} not covered", + rustc_errors::pluralize!(witnesses.len()), + joined_patterns + ), + ); patterns_len = witnesses.len(); pattern = if witnesses.len() < 4 { witnesses @@ -910,7 +1007,7 @@ fn non_exhaustive_match<'p, 'tcx>( err.emit() } -pub(crate) fn joined_uncovered_patterns<'p, 'tcx>( +fn joined_uncovered_patterns<'p, 'tcx>( cx: &MatchCheckCtxt<'p, 'tcx>, witnesses: &[WitnessPat<'tcx>], ) -> String { @@ -931,11 +1028,22 @@ pub(crate) fn joined_uncovered_patterns<'p, 'tcx>( } } -pub(crate) fn pattern_not_covered_label( - witnesses: &[WitnessPat<'_>], - joined_patterns: &str, -) -> String { - format!("pattern{} {} not covered", rustc_errors::pluralize!(witnesses.len()), joined_patterns) +fn collect_non_exhaustive_tys<'tcx>( + tcx: TyCtxt<'tcx>, + pat: &WitnessPat<'tcx>, + non_exhaustive_tys: &mut FxHashSet>, +) { + if matches!(pat.ctor(), Constructor::NonExhaustive) { + non_exhaustive_tys.insert(pat.ty()); + } + if let Constructor::IntRange(range) = pat.ctor() { + if range.is_beyond_boundaries(pat.ty(), tcx) { + // The range denotes the values before `isize::MIN` or the values after `usize::MAX`/`isize::MAX`. + non_exhaustive_tys.insert(pat.ty()); + } + } + pat.iter_fields() + .for_each(|field_pat| collect_non_exhaustive_tys(tcx, field_pat, non_exhaustive_tys)) } /// Point at the definition of non-covered `enum` variants. @@ -997,108 +1105,3 @@ fn maybe_point_at_variant<'a, 'p: 'a, 'tcx: 'a>( } covered } - -/// Check if a by-value binding is by-value. That is, check if the binding's type is not `Copy`. -/// Check that there are no borrow or move conflicts in `binding @ subpat` patterns. -/// -/// For example, this would reject: -/// - `ref x @ Some(ref mut y)`, -/// - `ref mut x @ Some(ref y)`, -/// - `ref mut x @ Some(ref mut y)`, -/// - `ref mut? x @ Some(y)`, and -/// - `x @ Some(ref mut? y)`. -/// -/// This analysis is *not* subsumed by NLL. -fn check_borrow_conflicts_in_at_patterns<'tcx>(cx: &MatchVisitor<'_, '_, 'tcx>, pat: &Pat<'tcx>) { - // Extract `sub` in `binding @ sub`. - let PatKind::Binding { name, mode, ty, subpattern: Some(box ref sub), .. } = pat.kind else { - return; - }; - - let is_binding_by_move = |ty: Ty<'tcx>| !ty.is_copy_modulo_regions(cx.tcx, cx.param_env); - - let sess = cx.tcx.sess; - - // Get the binding move, extract the mutability if by-ref. - let mut_outer = match mode { - BindingMode::ByValue if is_binding_by_move(ty) => { - // We have `x @ pat` where `x` is by-move. Reject all borrows in `pat`. - let mut conflicts_ref = Vec::new(); - sub.each_binding(|_, mode, _, span| match mode { - BindingMode::ByValue => {} - BindingMode::ByRef(_) => conflicts_ref.push(span), - }); - if !conflicts_ref.is_empty() { - sess.emit_err(BorrowOfMovedValue { - binding_span: pat.span, - conflicts_ref, - name, - ty, - suggest_borrowing: Some(pat.span.shrink_to_lo()), - }); - } - return; - } - BindingMode::ByValue => return, - BindingMode::ByRef(m) => m.mutability(), - }; - - // We now have `ref $mut_outer binding @ sub` (semantically). - // Recurse into each binding in `sub` and find mutability or move conflicts. - let mut conflicts_move = Vec::new(); - let mut conflicts_mut_mut = Vec::new(); - let mut conflicts_mut_ref = Vec::new(); - sub.each_binding(|name, mode, ty, span| { - match mode { - BindingMode::ByRef(mut_inner) => match (mut_outer, mut_inner.mutability()) { - // Both sides are `ref`. - (Mutability::Not, Mutability::Not) => {} - // 2x `ref mut`. - (Mutability::Mut, Mutability::Mut) => { - conflicts_mut_mut.push(Conflict::Mut { span, name }) - } - (Mutability::Not, Mutability::Mut) => { - conflicts_mut_ref.push(Conflict::Mut { span, name }) - } - (Mutability::Mut, Mutability::Not) => { - conflicts_mut_ref.push(Conflict::Ref { span, name }) - } - }, - BindingMode::ByValue if is_binding_by_move(ty) => { - conflicts_move.push(Conflict::Moved { span, name }) // `ref mut?` + by-move conflict. - } - BindingMode::ByValue => {} // `ref mut?` + by-copy is fine. - } - }); - - let report_mut_mut = !conflicts_mut_mut.is_empty(); - let report_mut_ref = !conflicts_mut_ref.is_empty(); - let report_move_conflict = !conflicts_move.is_empty(); - - let mut occurrences = match mut_outer { - Mutability::Mut => vec![Conflict::Mut { span: pat.span, name }], - Mutability::Not => vec![Conflict::Ref { span: pat.span, name }], - }; - occurrences.extend(conflicts_mut_mut); - occurrences.extend(conflicts_mut_ref); - occurrences.extend(conflicts_move); - - // Report errors if any. - if report_mut_mut { - // Report mutability conflicts for e.g. `ref mut x @ Some(ref mut y)`. - sess.emit_err(MultipleMutBorrows { span: pat.span, occurrences }); - } else if report_mut_ref { - // Report mutability conflicts for e.g. `ref x @ Some(ref mut y)` or the converse. - match mut_outer { - Mutability::Mut => { - sess.emit_err(AlreadyMutBorrowed { span: pat.span, occurrences }); - } - Mutability::Not => { - sess.emit_err(AlreadyBorrowed { span: pat.span, occurrences }); - } - }; - } else if report_move_conflict { - // Report by-ref and by-move conflicts, e.g. `ref x @ y`. - sess.emit_err(MovedWhileBorrowed { span: pat.span, occurrences }); - } -} From 1f9a2f73e12b0bbfff21f78b220cf742e44e35b7 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sun, 29 Oct 2023 04:36:06 +0100 Subject: [PATCH 191/435] Uncomplicate check_let_chain --- .../src/thir/pattern/check_match.rs | 82 ++++++++----------- 1 file changed, 36 insertions(+), 46 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 136f4210fe4c..9cae42c43590 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -150,8 +150,8 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for MatchVisitor<'a, '_, 'tcx> { ExprKind::Let { box ref pat, expr } => { self.check_let(pat, expr, self.let_source, ex.span); } - ExprKind::LogicalOp { op: LogicalOp::And, lhs, rhs } => { - self.check_let_chain(self.let_source, ex.span, lhs, rhs); + ExprKind::LogicalOp { op: LogicalOp::And, .. } => { + self.check_let_chain(self.let_source, ex); } _ => {} }; @@ -326,71 +326,61 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { } #[instrument(level = "trace", skip(self))] - fn check_let_chain( - &mut self, - let_source: LetSource, - top_expr_span: Span, - mut lhs: ExprId, - rhs: ExprId, - ) { + fn check_let_chain(&mut self, let_source: LetSource, expr: &Expr<'tcx>) { if let LetSource::None = let_source { return; } - // Lint level enclosing the next `lhs`. - let mut cur_lint_level = self.lint_level; + let top_expr_span = expr.span; + + // Lint level enclosing `next_expr`. + let mut next_expr_lint_level = self.lint_level; // Obtain the refutabilities of all exprs in the chain, // and record chain members that aren't let exprs. let mut chain_refutabilities = Vec::new(); let mut error = Ok(()); - let mut add = |expr: ExprId, mut local_lint_level| { - // `local_lint_level` is the lint level enclosing the pattern inside `expr`. - let mut expr = &self.thir[expr]; - debug!(?expr, ?local_lint_level, "add"); - // Fast-forward through scopes. + let mut next_expr = Some(expr); + while let Some(mut expr) = next_expr { while let ExprKind::Scope { value, lint_level, .. } = expr.kind { if let LintLevel::Explicit(hir_id) = lint_level { - local_lint_level = hir_id + next_expr_lint_level = hir_id } expr = &self.thir[value]; } - debug!(?expr, ?local_lint_level, "after scopes"); - match expr.kind { + if let ExprKind::LogicalOp { op: LogicalOp::And, lhs, rhs } = expr.kind { + expr = &self.thir[rhs]; + // Let chains recurse on the left, so we recurse into the lhs. + next_expr = Some(&self.thir[lhs]); + } else { + next_expr = None; + } + + // Lint level enclosing `expr`. + let mut expr_lint_level = next_expr_lint_level; + // Fast-forward through scopes. + while let ExprKind::Scope { value, lint_level, .. } = expr.kind { + if let LintLevel::Explicit(hir_id) = lint_level { + expr_lint_level = hir_id + } + expr = &self.thir[value]; + } + let value = match expr.kind { ExprKind::Let { box ref pat, expr: _ } => { if let Err(err) = pat.pat_error_reported() { error = Err(err); - return None; + None + } else { + let mut ncx = self.new_cx(expr_lint_level, true); + let tpat = self.lower_pattern(&mut ncx, pat); + let refutable = !is_let_irrefutable(&mut ncx, expr_lint_level, tpat); + Some((expr.span, refutable)) } - let mut ncx = self.new_cx(local_lint_level, true); - let tpat = self.lower_pattern(&mut ncx, pat); - let refutable = !is_let_irrefutable(&mut ncx, local_lint_level, tpat); - Some((expr.span, refutable)) } _ => None, - } - }; - - // Let chains recurse on the left, so we start by adding the rightmost. - chain_refutabilities.push(add(rhs, cur_lint_level)); - - loop { - while let ExprKind::Scope { value, lint_level, .. } = self.thir[lhs].kind { - if let LintLevel::Explicit(hir_id) = lint_level { - cur_lint_level = hir_id - } - lhs = value; - } - if let ExprKind::LogicalOp { op: LogicalOp::And, lhs: new_lhs, rhs: expr } = - self.thir[lhs].kind - { - chain_refutabilities.push(add(expr, cur_lint_level)); - lhs = new_lhs; - } else { - chain_refutabilities.push(add(lhs, cur_lint_level)); - break; - } + }; + chain_refutabilities.push(value); } debug!(?chain_refutabilities); chain_refutabilities.reverse(); From 380c56c6b3260bf96bd7cfd98c2095455a621d2a Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sun, 29 Oct 2023 04:40:03 +0100 Subject: [PATCH 192/435] Check pattern error while lowering --- .../src/thir/pattern/check_match.rs | 71 ++++++++----------- 1 file changed, 29 insertions(+), 42 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 9cae42c43590..31e1b779bfd3 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -81,6 +81,9 @@ struct MatchVisitor<'a, 'p, 'tcx> { lint_level: HirId, let_source: LetSource, pattern_arena: &'p TypedArena>, + /// Tracks if we encountered an error while checking this body. That the first function to + /// report it stores it here. Some functions return `Result` to allow callers to short-circuit + /// on error, but callers don't need to store it here again. error: Result<(), ErrorGuaranteed>, } @@ -211,11 +214,16 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { } fn lower_pattern( - &self, - cx: &mut MatchCheckCtxt<'p, 'tcx>, + &mut self, + cx: &MatchCheckCtxt<'p, 'tcx>, pattern: &Pat<'tcx>, - ) -> &'p DeconstructedPat<'p, 'tcx> { - cx.pattern_arena.alloc(DeconstructedPat::from_pat(cx, &pattern)) + ) -> Result<&'p DeconstructedPat<'p, 'tcx>, ErrorGuaranteed> { + if let Err(err) = pattern.pat_error_reported() { + self.error = Err(err); + Err(err) + } else { + Ok(cx.pattern_arena.alloc(DeconstructedPat::from_pat(cx, pattern))) + } } fn new_cx(&self, hir_id: HirId, refutable: bool) -> MatchCheckCtxt<'p, 'tcx> { @@ -233,13 +241,9 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { if let LetSource::None = source { return; } - if let Err(err) = pat.pat_error_reported() { - self.error = Err(err); - return; - } self.check_patterns(pat, Refutable); let mut cx = self.new_cx(self.lint_level, true); - let tpat = self.lower_pattern(&mut cx, pat); + let Ok(tpat) = self.lower_pattern(&cx, pat) else { return }; self.check_let_reachability(&mut cx, self.lint_level, source, tpat, span); } @@ -252,31 +256,22 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { ) { let mut cx = self.new_cx(self.lint_level, true); + let mut tarms = Vec::with_capacity(arms.len()); for &arm in arms { // Check the arm for some things unrelated to exhaustiveness. let arm = &self.thir.arms[arm]; self.with_lint_level(arm.lint_level, |this| { this.check_patterns(&arm.pattern, Refutable); }); - if let Err(err) = arm.pattern.pat_error_reported() { - self.error = Err(err); - return; - } + let hir_id = match arm.lint_level { + LintLevel::Explicit(hir_id) => hir_id, + LintLevel::Inherited => self.lint_level, + }; + let Ok(pat) = self.lower_pattern(&mut cx, &arm.pattern) else { return }; + let arm = MatchArm { pat, hir_id, has_guard: arm.guard.is_some() }; + tarms.push(arm); } - let tarms: Vec<_> = arms - .iter() - .map(|&arm| { - let arm = &self.thir.arms[arm]; - let hir_id = match arm.lint_level { - LintLevel::Explicit(hir_id) => hir_id, - LintLevel::Inherited => self.lint_level, - }; - let pat = self.lower_pattern(&mut cx, &arm.pattern); - MatchArm { pat, hir_id, has_guard: arm.guard.is_some() } - }) - .collect(); - let scrut = &self.thir[scrut]; let scrut_ty = scrut.ty; let report = compute_match_usefulness(&cx, &tarms, self.lint_level, scrut_ty, scrut.span); @@ -340,7 +335,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { // and record chain members that aren't let exprs. let mut chain_refutabilities = Vec::new(); - let mut error = Ok(()); + let mut got_lowering_error = false; let mut next_expr = Some(expr); while let Some(mut expr) = next_expr { while let ExprKind::Scope { value, lint_level, .. } = expr.kind { @@ -368,14 +363,13 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { } let value = match expr.kind { ExprKind::Let { box ref pat, expr: _ } => { - if let Err(err) = pat.pat_error_reported() { - error = Err(err); - None - } else { - let mut ncx = self.new_cx(expr_lint_level, true); - let tpat = self.lower_pattern(&mut ncx, pat); + let mut ncx = self.new_cx(expr_lint_level, true); + if let Ok(tpat) = self.lower_pattern(&mut ncx, pat) { let refutable = !is_let_irrefutable(&mut ncx, expr_lint_level, tpat); Some((expr.span, refutable)) + } else { + got_lowering_error = true; + None } } _ => None, @@ -385,8 +379,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { debug!(?chain_refutabilities); chain_refutabilities.reverse(); - if error.is_err() { - self.error = error; + if got_lowering_error { return; } @@ -452,15 +445,9 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { #[instrument(level = "trace", skip(self))] fn check_irrefutable(&mut self, pat: &Pat<'tcx>, origin: &str, sp: Option) { - // If we got errors while lowering, don't emit anything more. - if let Err(err) = pat.pat_error_reported() { - self.error = Err(err); - return; - } - let mut cx = self.new_cx(self.lint_level, false); - let pattern = self.lower_pattern(&mut cx, pat); + let Ok(pattern) = self.lower_pattern(&mut cx, pat) else { return }; let pattern_ty = pattern.ty(); let arm = MatchArm { pat: pattern, hir_id: self.lint_level, has_guard: false }; let report = From d95f6a9532708e13d779e431384daa64b638703e Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sun, 29 Oct 2023 04:43:25 +0100 Subject: [PATCH 193/435] Tweak diagnostic for consistency --- .../src/thir/pattern/check_match.rs | 6 +- .../empty-match.exhaustive_patterns.stderr | 86 +++++++++++-------- .../usefulness/empty-match.normal.stderr | 86 +++++++++++-------- tests/ui/pattern/usefulness/empty-match.rs | 12 ++- .../ui/pattern/usefulness/issue-35609.stderr | 3 + .../non-exhaustive-pattern-witness.stderr | 15 +++- 6 files changed, 129 insertions(+), 79 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 31e1b779bfd3..0e218cd8788e 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -1033,10 +1033,8 @@ fn adt_defined_here<'p, 'tcx>( let ty = ty.peel_refs(); if let ty::Adt(def, _) = ty.kind() { let mut spans = vec![]; - if witnesses.len() < 5 { - for sp in maybe_point_at_variant(cx, *def, witnesses.iter()) { - spans.push(sp); - } + for sp in maybe_point_at_variant(cx, *def, witnesses.iter().take(5)) { + spans.push(sp); } let def_span = cx .tcx diff --git a/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr index 5b81a8c3d3c0..fce1d8d19280 100644 --- a/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr +++ b/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr @@ -1,5 +1,5 @@ error: unreachable pattern - --> $DIR/empty-match.rs:58:9 + --> $DIR/empty-match.rs:68:9 | LL | _ => {}, | ^ @@ -10,26 +10,26 @@ note: the lint level is defined here LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ -error: unreachable pattern - --> $DIR/empty-match.rs:61:9 - | -LL | _ if false => {}, - | ^ - -error: unreachable pattern - --> $DIR/empty-match.rs:68:9 - | -LL | _ => {}, - | ^ - error: unreachable pattern --> $DIR/empty-match.rs:71:9 | LL | _ if false => {}, | ^ +error: unreachable pattern + --> $DIR/empty-match.rs:78:9 + | +LL | _ => {}, + | ^ + +error: unreachable pattern + --> $DIR/empty-match.rs:81:9 + | +LL | _ if false => {}, + | ^ + error[E0005]: refutable pattern in local binding - --> $DIR/empty-match.rs:76:9 + --> $DIR/empty-match.rs:86:9 | LL | let None = x; | ^^^^ pattern `Some(_)` not covered @@ -44,19 +44,19 @@ LL | if let None = x { todo!() }; | ++ +++++++++++ error: unreachable pattern - --> $DIR/empty-match.rs:88:9 + --> $DIR/empty-match.rs:98:9 | LL | _ => {}, | ^ error: unreachable pattern - --> $DIR/empty-match.rs:91:9 + --> $DIR/empty-match.rs:101:9 | LL | _ if false => {}, | ^ error[E0004]: non-exhaustive patterns: type `u8` is non-empty - --> $DIR/empty-match.rs:109:20 + --> $DIR/empty-match.rs:119:20 | LL | match_no_arms!(0u8); | ^^^ @@ -65,7 +65,7 @@ LL | match_no_arms!(0u8); = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: type `NonEmptyStruct1` is non-empty - --> $DIR/empty-match.rs:111:20 + --> $DIR/empty-match.rs:121:20 | LL | match_no_arms!(NonEmptyStruct1); | ^^^^^^^^^^^^^^^ @@ -79,7 +79,7 @@ LL | struct NonEmptyStruct1; = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: type `NonEmptyStruct2` is non-empty - --> $DIR/empty-match.rs:113:20 + --> $DIR/empty-match.rs:123:20 | LL | match_no_arms!(NonEmptyStruct2(true)); | ^^^^^^^^^^^^^^^^^^^^^ @@ -93,7 +93,7 @@ LL | struct NonEmptyStruct2(bool); = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: type `NonEmptyUnion1` is non-empty - --> $DIR/empty-match.rs:115:20 + --> $DIR/empty-match.rs:125:20 | LL | match_no_arms!((NonEmptyUnion1 { foo: () })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -107,7 +107,7 @@ LL | union NonEmptyUnion1 { = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: type `NonEmptyUnion2` is non-empty - --> $DIR/empty-match.rs:117:20 + --> $DIR/empty-match.rs:127:20 | LL | match_no_arms!((NonEmptyUnion2 { foo: () })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -121,7 +121,7 @@ LL | union NonEmptyUnion2 { = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered - --> $DIR/empty-match.rs:119:20 + --> $DIR/empty-match.rs:129:20 | LL | match_no_arms!(NonEmptyEnum1::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered @@ -137,7 +137,7 @@ LL | Foo(bool), = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered - --> $DIR/empty-match.rs:122:20 + --> $DIR/empty-match.rs:132:20 | LL | match_no_arms!(NonEmptyEnum2::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered @@ -156,21 +156,28 @@ LL | Bar, = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered - --> $DIR/empty-match.rs:125:20 + --> $DIR/empty-match.rs:135:20 | LL | match_no_arms!(NonEmptyEnum5::V1); | ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered | note: `NonEmptyEnum5` defined here - --> $DIR/empty-match.rs:49:6 + --> $DIR/empty-match.rs:50:5 | LL | enum NonEmptyEnum5 { - | ^^^^^^^^^^^^^ + | ------------- +LL | V1, V2, V3, V4, V5, + | ^^ ^^ ^^ ^^ ^^ not covered + | | | | | + | | | | not covered + | | | not covered + | | not covered + | not covered = note: the matched value is of type `NonEmptyEnum5` = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms error[E0004]: non-exhaustive patterns: `_` not covered - --> $DIR/empty-match.rs:129:24 + --> $DIR/empty-match.rs:139:24 | LL | match_guarded_arm!(0u8); | ^^^ pattern `_` not covered @@ -184,7 +191,7 @@ LL + _ => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyStruct1` not covered - --> $DIR/empty-match.rs:134:24 + --> $DIR/empty-match.rs:144:24 | LL | match_guarded_arm!(NonEmptyStruct1); | ^^^^^^^^^^^^^^^ pattern `NonEmptyStruct1` not covered @@ -203,7 +210,7 @@ LL + NonEmptyStruct1 => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyStruct2(_)` not covered - --> $DIR/empty-match.rs:139:24 + --> $DIR/empty-match.rs:149:24 | LL | match_guarded_arm!(NonEmptyStruct2(true)); | ^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyStruct2(_)` not covered @@ -222,7 +229,7 @@ LL + NonEmptyStruct2(_) => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyUnion1 { .. }` not covered - --> $DIR/empty-match.rs:144:24 + --> $DIR/empty-match.rs:154:24 | LL | match_guarded_arm!((NonEmptyUnion1 { foo: () })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion1 { .. }` not covered @@ -241,7 +248,7 @@ LL + NonEmptyUnion1 { .. } => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyUnion2 { .. }` not covered - --> $DIR/empty-match.rs:149:24 + --> $DIR/empty-match.rs:159:24 | LL | match_guarded_arm!((NonEmptyUnion2 { foo: () })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion2 { .. }` not covered @@ -260,7 +267,7 @@ LL + NonEmptyUnion2 { .. } => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered - --> $DIR/empty-match.rs:154:24 + --> $DIR/empty-match.rs:164:24 | LL | match_guarded_arm!(NonEmptyEnum1::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered @@ -281,7 +288,7 @@ LL + NonEmptyEnum1::Foo(_) => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered - --> $DIR/empty-match.rs:159:24 + --> $DIR/empty-match.rs:169:24 | LL | match_guarded_arm!(NonEmptyEnum2::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered @@ -305,16 +312,23 @@ LL + NonEmptyEnum2::Foo(_) | NonEmptyEnum2::Bar => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered - --> $DIR/empty-match.rs:164:24 + --> $DIR/empty-match.rs:174:24 | LL | match_guarded_arm!(NonEmptyEnum5::V1); | ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered | note: `NonEmptyEnum5` defined here - --> $DIR/empty-match.rs:49:6 + --> $DIR/empty-match.rs:50:5 | LL | enum NonEmptyEnum5 { - | ^^^^^^^^^^^^^ + | ------------- +LL | V1, V2, V3, V4, V5, + | ^^ ^^ ^^ ^^ ^^ not covered + | | | | | + | | | | not covered + | | | not covered + | | not covered + | not covered = note: the matched value is of type `NonEmptyEnum5` = note: match arms with guards don't count towards exhaustivity help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms diff --git a/tests/ui/pattern/usefulness/empty-match.normal.stderr b/tests/ui/pattern/usefulness/empty-match.normal.stderr index 6d17455086be..97aac68c8d93 100644 --- a/tests/ui/pattern/usefulness/empty-match.normal.stderr +++ b/tests/ui/pattern/usefulness/empty-match.normal.stderr @@ -1,5 +1,5 @@ error: unreachable pattern - --> $DIR/empty-match.rs:58:9 + --> $DIR/empty-match.rs:68:9 | LL | _ => {}, | ^ @@ -10,26 +10,26 @@ note: the lint level is defined here LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ -error: unreachable pattern - --> $DIR/empty-match.rs:61:9 - | -LL | _ if false => {}, - | ^ - -error: unreachable pattern - --> $DIR/empty-match.rs:68:9 - | -LL | _ => {}, - | ^ - error: unreachable pattern --> $DIR/empty-match.rs:71:9 | LL | _ if false => {}, | ^ +error: unreachable pattern + --> $DIR/empty-match.rs:78:9 + | +LL | _ => {}, + | ^ + +error: unreachable pattern + --> $DIR/empty-match.rs:81:9 + | +LL | _ if false => {}, + | ^ + error[E0005]: refutable pattern in local binding - --> $DIR/empty-match.rs:76:9 + --> $DIR/empty-match.rs:86:9 | LL | let None = x; | ^^^^ pattern `Some(_)` not covered @@ -43,19 +43,19 @@ LL | if let None = x { todo!() }; | ++ +++++++++++ error: unreachable pattern - --> $DIR/empty-match.rs:88:9 + --> $DIR/empty-match.rs:98:9 | LL | _ => {}, | ^ error: unreachable pattern - --> $DIR/empty-match.rs:91:9 + --> $DIR/empty-match.rs:101:9 | LL | _ if false => {}, | ^ error[E0004]: non-exhaustive patterns: type `u8` is non-empty - --> $DIR/empty-match.rs:109:20 + --> $DIR/empty-match.rs:119:20 | LL | match_no_arms!(0u8); | ^^^ @@ -64,7 +64,7 @@ LL | match_no_arms!(0u8); = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: type `NonEmptyStruct1` is non-empty - --> $DIR/empty-match.rs:111:20 + --> $DIR/empty-match.rs:121:20 | LL | match_no_arms!(NonEmptyStruct1); | ^^^^^^^^^^^^^^^ @@ -78,7 +78,7 @@ LL | struct NonEmptyStruct1; = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: type `NonEmptyStruct2` is non-empty - --> $DIR/empty-match.rs:113:20 + --> $DIR/empty-match.rs:123:20 | LL | match_no_arms!(NonEmptyStruct2(true)); | ^^^^^^^^^^^^^^^^^^^^^ @@ -92,7 +92,7 @@ LL | struct NonEmptyStruct2(bool); = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: type `NonEmptyUnion1` is non-empty - --> $DIR/empty-match.rs:115:20 + --> $DIR/empty-match.rs:125:20 | LL | match_no_arms!((NonEmptyUnion1 { foo: () })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -106,7 +106,7 @@ LL | union NonEmptyUnion1 { = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: type `NonEmptyUnion2` is non-empty - --> $DIR/empty-match.rs:117:20 + --> $DIR/empty-match.rs:127:20 | LL | match_no_arms!((NonEmptyUnion2 { foo: () })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -120,7 +120,7 @@ LL | union NonEmptyUnion2 { = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered - --> $DIR/empty-match.rs:119:20 + --> $DIR/empty-match.rs:129:20 | LL | match_no_arms!(NonEmptyEnum1::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered @@ -136,7 +136,7 @@ LL | Foo(bool), = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered - --> $DIR/empty-match.rs:122:20 + --> $DIR/empty-match.rs:132:20 | LL | match_no_arms!(NonEmptyEnum2::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered @@ -155,21 +155,28 @@ LL | Bar, = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered - --> $DIR/empty-match.rs:125:20 + --> $DIR/empty-match.rs:135:20 | LL | match_no_arms!(NonEmptyEnum5::V1); | ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered | note: `NonEmptyEnum5` defined here - --> $DIR/empty-match.rs:49:6 + --> $DIR/empty-match.rs:50:5 | LL | enum NonEmptyEnum5 { - | ^^^^^^^^^^^^^ + | ------------- +LL | V1, V2, V3, V4, V5, + | ^^ ^^ ^^ ^^ ^^ not covered + | | | | | + | | | | not covered + | | | not covered + | | not covered + | not covered = note: the matched value is of type `NonEmptyEnum5` = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms error[E0004]: non-exhaustive patterns: `_` not covered - --> $DIR/empty-match.rs:129:24 + --> $DIR/empty-match.rs:139:24 | LL | match_guarded_arm!(0u8); | ^^^ pattern `_` not covered @@ -183,7 +190,7 @@ LL + _ => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyStruct1` not covered - --> $DIR/empty-match.rs:134:24 + --> $DIR/empty-match.rs:144:24 | LL | match_guarded_arm!(NonEmptyStruct1); | ^^^^^^^^^^^^^^^ pattern `NonEmptyStruct1` not covered @@ -202,7 +209,7 @@ LL + NonEmptyStruct1 => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyStruct2(_)` not covered - --> $DIR/empty-match.rs:139:24 + --> $DIR/empty-match.rs:149:24 | LL | match_guarded_arm!(NonEmptyStruct2(true)); | ^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyStruct2(_)` not covered @@ -221,7 +228,7 @@ LL + NonEmptyStruct2(_) => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyUnion1 { .. }` not covered - --> $DIR/empty-match.rs:144:24 + --> $DIR/empty-match.rs:154:24 | LL | match_guarded_arm!((NonEmptyUnion1 { foo: () })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion1 { .. }` not covered @@ -240,7 +247,7 @@ LL + NonEmptyUnion1 { .. } => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyUnion2 { .. }` not covered - --> $DIR/empty-match.rs:149:24 + --> $DIR/empty-match.rs:159:24 | LL | match_guarded_arm!((NonEmptyUnion2 { foo: () })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion2 { .. }` not covered @@ -259,7 +266,7 @@ LL + NonEmptyUnion2 { .. } => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered - --> $DIR/empty-match.rs:154:24 + --> $DIR/empty-match.rs:164:24 | LL | match_guarded_arm!(NonEmptyEnum1::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered @@ -280,7 +287,7 @@ LL + NonEmptyEnum1::Foo(_) => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered - --> $DIR/empty-match.rs:159:24 + --> $DIR/empty-match.rs:169:24 | LL | match_guarded_arm!(NonEmptyEnum2::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered @@ -304,16 +311,23 @@ LL + NonEmptyEnum2::Foo(_) | NonEmptyEnum2::Bar => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered - --> $DIR/empty-match.rs:164:24 + --> $DIR/empty-match.rs:174:24 | LL | match_guarded_arm!(NonEmptyEnum5::V1); | ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered | note: `NonEmptyEnum5` defined here - --> $DIR/empty-match.rs:49:6 + --> $DIR/empty-match.rs:50:5 | LL | enum NonEmptyEnum5 { - | ^^^^^^^^^^^^^ + | ------------- +LL | V1, V2, V3, V4, V5, + | ^^ ^^ ^^ ^^ ^^ not covered + | | | | | + | | | | not covered + | | | not covered + | | not covered + | not covered = note: the matched value is of type `NonEmptyEnum5` = note: match arms with guards don't count towards exhaustivity help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms diff --git a/tests/ui/pattern/usefulness/empty-match.rs b/tests/ui/pattern/usefulness/empty-match.rs index d56d2e3c817c..6551900bbc6c 100644 --- a/tests/ui/pattern/usefulness/empty-match.rs +++ b/tests/ui/pattern/usefulness/empty-match.rs @@ -47,9 +47,19 @@ enum NonEmptyEnum2 { //~| NOTE not covered } enum NonEmptyEnum5 { + V1, V2, V3, V4, V5, //~^ NOTE `NonEmptyEnum5` defined here //~| NOTE `NonEmptyEnum5` defined here - V1, V2, V3, V4, V5, + //~| NOTE not covered + //~| NOTE not covered + //~| NOTE not covered + //~| NOTE not covered + //~| NOTE not covered + //~| NOTE not covered + //~| NOTE not covered + //~| NOTE not covered + //~| NOTE not covered + //~| NOTE not covered } fn empty_enum(x: EmptyEnum) { diff --git a/tests/ui/pattern/usefulness/issue-35609.stderr b/tests/ui/pattern/usefulness/issue-35609.stderr index 6d5e2f410bc9..9feedfde4697 100644 --- a/tests/ui/pattern/usefulness/issue-35609.stderr +++ b/tests/ui/pattern/usefulness/issue-35609.stderr @@ -107,6 +107,9 @@ LL | match Some(A) { | note: `Option` defined here --> $SRC_DIR/core/src/option.rs:LL:COL + ::: $SRC_DIR/core/src/option.rs:LL:COL + | + = note: not covered = note: the matched value is of type `Option` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms | diff --git a/tests/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr b/tests/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr index f914b98d9231..c75c4ccdc875 100644 --- a/tests/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr +++ b/tests/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr @@ -68,10 +68,21 @@ LL | match ExcessiveEnum::First { | ^^^^^^^^^^^^^^^^^^^^ patterns `ExcessiveEnum::Second`, `ExcessiveEnum::Third`, `ExcessiveEnum::Fourth` and 8 more not covered | note: `ExcessiveEnum` defined here - --> $DIR/non-exhaustive-pattern-witness.rs:44:6 + --> $DIR/non-exhaustive-pattern-witness.rs:46:5 | LL | enum ExcessiveEnum { - | ^^^^^^^^^^^^^ + | ------------- +LL | First, +LL | Second, + | ^^^^^^ not covered +LL | Third, + | ^^^^^ not covered +LL | Fourth, + | ^^^^^^ not covered +LL | Fifth, + | ^^^^^ not covered +LL | Sixth, + | ^^^^^ not covered = note: the matched value is of type `ExcessiveEnum` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms | From b60f08a66d5a545d414a70a7047161cb191054b9 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sun, 29 Oct 2023 05:11:52 +0100 Subject: [PATCH 194/435] Add regression test for pattern checks --- .../usefulness/conflicting_bindings.rs | 22 ++++++++ .../usefulness/conflicting_bindings.stderr | 50 +++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 tests/ui/pattern/usefulness/conflicting_bindings.rs create mode 100644 tests/ui/pattern/usefulness/conflicting_bindings.stderr diff --git a/tests/ui/pattern/usefulness/conflicting_bindings.rs b/tests/ui/pattern/usefulness/conflicting_bindings.rs new file mode 100644 index 000000000000..1df4425c48bf --- /dev/null +++ b/tests/ui/pattern/usefulness/conflicting_bindings.rs @@ -0,0 +1,22 @@ +#![feature(if_let_guard, let_chains)] + +fn main() { + let mut x = Some(String::new()); + let ref mut y @ ref mut z = x; + //~^ ERROR: mutable more than once + let Some(ref mut y @ ref mut z) = x else { return }; + //~^ ERROR: mutable more than once + if let Some(ref mut y @ ref mut z) = x {} + //~^ ERROR: mutable more than once + if let Some(ref mut y @ ref mut z) = x && true {} + while let Some(ref mut y @ ref mut z) = x {} + //~^ ERROR: mutable more than once + while let Some(ref mut y @ ref mut z) = x && true {} + match x { + ref mut y @ ref mut z => {} //~ ERROR: mutable more than once + } + match () { + () if let Some(ref mut y @ ref mut z) = x => {} //~ ERROR: mutable more than once + _ => {} + } +} diff --git a/tests/ui/pattern/usefulness/conflicting_bindings.stderr b/tests/ui/pattern/usefulness/conflicting_bindings.stderr new file mode 100644 index 000000000000..af20eece20cf --- /dev/null +++ b/tests/ui/pattern/usefulness/conflicting_bindings.stderr @@ -0,0 +1,50 @@ +error: cannot borrow value as mutable more than once at a time + --> $DIR/conflicting_bindings.rs:5:9 + | +LL | let ref mut y @ ref mut z = x; + | ^^^^^^^^^ --------- value is mutably borrowed by `z` here + | | + | value is mutably borrowed by `y` here + +error: cannot borrow value as mutable more than once at a time + --> $DIR/conflicting_bindings.rs:7:14 + | +LL | let Some(ref mut y @ ref mut z) = x else { return }; + | ^^^^^^^^^ --------- value is mutably borrowed by `z` here + | | + | value is mutably borrowed by `y` here + +error: cannot borrow value as mutable more than once at a time + --> $DIR/conflicting_bindings.rs:9:17 + | +LL | if let Some(ref mut y @ ref mut z) = x {} + | ^^^^^^^^^ --------- value is mutably borrowed by `z` here + | | + | value is mutably borrowed by `y` here + +error: cannot borrow value as mutable more than once at a time + --> $DIR/conflicting_bindings.rs:12:20 + | +LL | while let Some(ref mut y @ ref mut z) = x {} + | ^^^^^^^^^ --------- value is mutably borrowed by `z` here + | | + | value is mutably borrowed by `y` here + +error: cannot borrow value as mutable more than once at a time + --> $DIR/conflicting_bindings.rs:16:9 + | +LL | ref mut y @ ref mut z => {} + | ^^^^^^^^^ --------- value is mutably borrowed by `z` here + | | + | value is mutably borrowed by `y` here + +error: cannot borrow value as mutable more than once at a time + --> $DIR/conflicting_bindings.rs:19:24 + | +LL | () if let Some(ref mut y @ ref mut z) = x => {} + | ^^^^^^^^^ --------- value is mutably borrowed by `z` here + | | + | value is mutably borrowed by `y` here + +error: aborting due to 6 previous errors + From c19856929dbbcc4b0b6103e8a566b7763b7ab117 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sun, 29 Oct 2023 05:15:36 +0100 Subject: [PATCH 195/435] Always do all the pattern checks --- .../src/thir/pattern/check_match.rs | 120 +++++++++--------- .../usefulness/conflicting_bindings.rs | 2 + .../usefulness/conflicting_bindings.stderr | 24 +++- 3 files changed, 82 insertions(+), 64 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 0e218cd8788e..c66a26123bc8 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -58,7 +58,7 @@ fn create_e0004( struct_span_err!(sess, sp, E0004, "{}", &error_message) } -#[derive(PartialEq)] +#[derive(Copy, Clone, PartialEq)] enum RefutableFlag { Irrefutable, Refutable, @@ -197,32 +197,36 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { self.let_source = old_let_source; } - fn with_lint_level(&mut self, new_lint_level: LintLevel, f: impl FnOnce(&mut Self)) { + fn with_lint_level( + &mut self, + new_lint_level: LintLevel, + f: impl FnOnce(&mut Self) -> T, + ) -> T { if let LintLevel::Explicit(hir_id) = new_lint_level { let old_lint_level = self.lint_level; self.lint_level = hir_id; - f(self); + let ret = f(self); self.lint_level = old_lint_level; + ret } else { - f(self); + f(self) } } - fn check_patterns(&self, pat: &Pat<'tcx>, rf: RefutableFlag) { - pat.walk_always(|pat| check_borrow_conflicts_in_at_patterns(self, pat)); - check_for_bindings_named_same_as_variants(self, pat, rf); - } - fn lower_pattern( &mut self, cx: &MatchCheckCtxt<'p, 'tcx>, - pattern: &Pat<'tcx>, + pat: &Pat<'tcx>, ) -> Result<&'p DeconstructedPat<'p, 'tcx>, ErrorGuaranteed> { - if let Err(err) = pattern.pat_error_reported() { + if let Err(err) = pat.pat_error_reported() { self.error = Err(err); Err(err) } else { - Ok(cx.pattern_arena.alloc(DeconstructedPat::from_pat(cx, pattern))) + // Check the pattern for some things unrelated to exhaustiveness. + let refutable = if cx.refutable { Refutable } else { Irrefutable }; + pat.walk_always(|pat| check_borrow_conflicts_in_at_patterns(self, pat)); + pat.walk_always(|pat| check_for_bindings_named_same_as_variants(self, pat, refutable)); + Ok(cx.pattern_arena.alloc(DeconstructedPat::from_pat(cx, pat))) } } @@ -241,7 +245,6 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { if let LetSource::None = source { return; } - self.check_patterns(pat, Refutable); let mut cx = self.new_cx(self.lint_level, true); let Ok(tpat) = self.lower_pattern(&cx, pat) else { return }; self.check_let_reachability(&mut cx, self.lint_level, source, tpat, span); @@ -258,18 +261,18 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { let mut tarms = Vec::with_capacity(arms.len()); for &arm in arms { - // Check the arm for some things unrelated to exhaustiveness. let arm = &self.thir.arms[arm]; - self.with_lint_level(arm.lint_level, |this| { - this.check_patterns(&arm.pattern, Refutable); + let got_error = self.with_lint_level(arm.lint_level, |this| { + let Ok(pat) = this.lower_pattern(&mut cx, &arm.pattern) else { + return true; + }; + let arm = MatchArm { pat, hir_id: this.lint_level, has_guard: arm.guard.is_some() }; + tarms.push(arm); + false }); - let hir_id = match arm.lint_level { - LintLevel::Explicit(hir_id) => hir_id, - LintLevel::Inherited => self.lint_level, - }; - let Ok(pat) = self.lower_pattern(&mut cx, &arm.pattern) else { return }; - let arm = MatchArm { pat, hir_id, has_guard: arm.guard.is_some() }; - tarms.push(arm); + if got_error { + return; + } } let scrut = &self.thir[scrut]; @@ -458,7 +461,6 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { let witnesses = report.non_exhaustiveness_witnesses; if witnesses.is_empty() { // The pattern is irrefutable. - self.check_patterns(pat, Irrefutable); return; } @@ -659,43 +661,41 @@ fn check_for_bindings_named_same_as_variants( pat: &Pat<'_>, rf: RefutableFlag, ) { - pat.walk_always(|p| { - if let PatKind::Binding { - name, - mode: BindingMode::ByValue, - mutability: Mutability::Not, - subpattern: None, - ty, - .. - } = p.kind - && let ty::Adt(edef, _) = ty.peel_refs().kind() - && edef.is_enum() - && edef - .variants() - .iter() - .any(|variant| variant.name == name && variant.ctor_kind() == Some(CtorKind::Const)) - { - let variant_count = edef.variants().len(); - let ty_path = with_no_trimmed_paths!(cx.tcx.def_path_str(edef.did())); - cx.tcx.emit_spanned_lint( - BINDINGS_WITH_VARIANT_NAME, - cx.lint_level, - p.span, - BindingsWithVariantName { - // If this is an irrefutable pattern, and there's > 1 variant, - // then we can't actually match on this. Applying the below - // suggestion would produce code that breaks on `check_irrefutable`. - suggestion: if rf == Refutable || variant_count == 1 { - Some(p.span) - } else { - None - }, - ty_path, - name, + if let PatKind::Binding { + name, + mode: BindingMode::ByValue, + mutability: Mutability::Not, + subpattern: None, + ty, + .. + } = pat.kind + && let ty::Adt(edef, _) = ty.peel_refs().kind() + && edef.is_enum() + && edef + .variants() + .iter() + .any(|variant| variant.name == name && variant.ctor_kind() == Some(CtorKind::Const)) + { + let variant_count = edef.variants().len(); + let ty_path = with_no_trimmed_paths!(cx.tcx.def_path_str(edef.did())); + cx.tcx.emit_spanned_lint( + BINDINGS_WITH_VARIANT_NAME, + cx.lint_level, + pat.span, + BindingsWithVariantName { + // If this is an irrefutable pattern, and there's > 1 variant, + // then we can't actually match on this. Applying the below + // suggestion would produce code that breaks on `check_irrefutable`. + suggestion: if rf == Refutable || variant_count == 1 { + Some(pat.span) + } else { + None }, - ) - } - }); + ty_path, + name, + }, + ) + } } fn irrefutable_let_patterns( diff --git a/tests/ui/pattern/usefulness/conflicting_bindings.rs b/tests/ui/pattern/usefulness/conflicting_bindings.rs index 1df4425c48bf..0b3e7ce9e9a0 100644 --- a/tests/ui/pattern/usefulness/conflicting_bindings.rs +++ b/tests/ui/pattern/usefulness/conflicting_bindings.rs @@ -9,9 +9,11 @@ fn main() { if let Some(ref mut y @ ref mut z) = x {} //~^ ERROR: mutable more than once if let Some(ref mut y @ ref mut z) = x && true {} + //~^ ERROR: mutable more than once while let Some(ref mut y @ ref mut z) = x {} //~^ ERROR: mutable more than once while let Some(ref mut y @ ref mut z) = x && true {} + //~^ ERROR: mutable more than once match x { ref mut y @ ref mut z => {} //~ ERROR: mutable more than once } diff --git a/tests/ui/pattern/usefulness/conflicting_bindings.stderr b/tests/ui/pattern/usefulness/conflicting_bindings.stderr index af20eece20cf..679fc83e7f56 100644 --- a/tests/ui/pattern/usefulness/conflicting_bindings.stderr +++ b/tests/ui/pattern/usefulness/conflicting_bindings.stderr @@ -23,7 +23,15 @@ LL | if let Some(ref mut y @ ref mut z) = x {} | value is mutably borrowed by `y` here error: cannot borrow value as mutable more than once at a time - --> $DIR/conflicting_bindings.rs:12:20 + --> $DIR/conflicting_bindings.rs:11:17 + | +LL | if let Some(ref mut y @ ref mut z) = x && true {} + | ^^^^^^^^^ --------- value is mutably borrowed by `z` here + | | + | value is mutably borrowed by `y` here + +error: cannot borrow value as mutable more than once at a time + --> $DIR/conflicting_bindings.rs:13:20 | LL | while let Some(ref mut y @ ref mut z) = x {} | ^^^^^^^^^ --------- value is mutably borrowed by `z` here @@ -31,7 +39,15 @@ LL | while let Some(ref mut y @ ref mut z) = x {} | value is mutably borrowed by `y` here error: cannot borrow value as mutable more than once at a time - --> $DIR/conflicting_bindings.rs:16:9 + --> $DIR/conflicting_bindings.rs:15:20 + | +LL | while let Some(ref mut y @ ref mut z) = x && true {} + | ^^^^^^^^^ --------- value is mutably borrowed by `z` here + | | + | value is mutably borrowed by `y` here + +error: cannot borrow value as mutable more than once at a time + --> $DIR/conflicting_bindings.rs:18:9 | LL | ref mut y @ ref mut z => {} | ^^^^^^^^^ --------- value is mutably borrowed by `z` here @@ -39,12 +55,12 @@ LL | ref mut y @ ref mut z => {} | value is mutably borrowed by `y` here error: cannot borrow value as mutable more than once at a time - --> $DIR/conflicting_bindings.rs:19:24 + --> $DIR/conflicting_bindings.rs:21:24 | LL | () if let Some(ref mut y @ ref mut z) = x => {} | ^^^^^^^^^ --------- value is mutably borrowed by `z` here | | | value is mutably borrowed by `y` here -error: aborting due to 6 previous errors +error: aborting due to 8 previous errors From fcd24fbd3c73e90ddb5416f644bf8e7337b17f87 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sun, 29 Oct 2023 05:35:03 +0100 Subject: [PATCH 196/435] Factor out pointing at ADT definition --- .../src/thir/pattern/check_match.rs | 83 +++++++++---------- 1 file changed, 40 insertions(+), 43 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index c66a26123bc8..694e4c07bd5d 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -9,9 +9,7 @@ use rustc_arena::TypedArena; use rustc_ast::Mutability; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::stack::ensure_sufficient_stack; -use rustc_errors::{ - struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan, -}; +use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, MultiSpan}; use rustc_hir as hir; use rustc_hir::def::*; use rustc_hir::def_id::LocalDefId; @@ -507,17 +505,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { }); }; - let adt_defined_here = try { - let ty = pattern_ty.peel_refs(); - let ty::Adt(def, _) = ty.kind() else { None? }; - let adt_def_span = cx.tcx.hir().get_if_local(def.did())?.ident()?.span; - let mut variants = vec![]; - - for span in maybe_point_at_variant(&cx, *def, witnesses.iter().take(5)) { - variants.push(Variant { span }); - } - AdtDefinedHere { adt_def_span, ty, variants } - }; + let adt_defined_here = report_adt_defined_here(self.tcx, pattern_ty, &witnesses, false); // Emit an extra note if the first uncovered witness would be uninhabited // if we disregard visibility. @@ -842,7 +830,22 @@ fn non_exhaustive_match<'p, 'tcx>( }; }; - adt_defined_here(cx, &mut err, scrut_ty, &witnesses); + // Point at the definition of non-covered `enum` variants. + if let Some(AdtDefinedHere { adt_def_span, ty, variants }) = + report_adt_defined_here(cx.tcx, scrut_ty, &witnesses, true) + { + let mut multi_span = if variants.is_empty() { + MultiSpan::from_span(adt_def_span) + } else { + MultiSpan::from_spans(variants.iter().map(|Variant { span }| *span).collect()) + }; + + multi_span.push_span_label(adt_def_span, ""); + for Variant { span } in variants { + multi_span.push_span_label(span, "not covered"); + } + err.span_note(multi_span, format!("`{ty}` defined here")); + } err.note(format!("the matched value is of type `{}`", scrut_ty)); if !is_empty_match { @@ -1023,39 +1026,33 @@ fn collect_non_exhaustive_tys<'tcx>( .for_each(|field_pat| collect_non_exhaustive_tys(tcx, field_pat, non_exhaustive_tys)) } -/// Point at the definition of non-covered `enum` variants. -fn adt_defined_here<'p, 'tcx>( - cx: &MatchCheckCtxt<'p, 'tcx>, - err: &mut Diagnostic, +fn report_adt_defined_here<'tcx>( + tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, witnesses: &[WitnessPat<'tcx>], -) { + point_at_non_local_ty: bool, +) -> Option> { let ty = ty.peel_refs(); - if let ty::Adt(def, _) = ty.kind() { - let mut spans = vec![]; - for sp in maybe_point_at_variant(cx, *def, witnesses.iter().take(5)) { - spans.push(sp); - } - let def_span = cx - .tcx - .hir() - .get_if_local(def.did()) - .and_then(|node| node.ident()) - .map(|ident| ident.span) - .unwrap_or_else(|| cx.tcx.def_span(def.did())); - let mut span: MultiSpan = - if spans.is_empty() { def_span.into() } else { spans.clone().into() }; + let ty::Adt(def, _) = ty.kind() else { + return None; + }; + let adt_def_span = + tcx.hir().get_if_local(def.did()).and_then(|node| node.ident()).map(|ident| ident.span); + let adt_def_span = if point_at_non_local_ty { + adt_def_span.unwrap_or_else(|| tcx.def_span(def.did())) + } else { + adt_def_span? + }; - span.push_span_label(def_span, ""); - for pat in spans { - span.push_span_label(pat, "not covered"); - } - err.span_note(span, format!("`{ty}` defined here")); + let mut variants = vec![]; + for span in maybe_point_at_variant(tcx, *def, witnesses.iter().take(5)) { + variants.push(Variant { span }); } + Some(AdtDefinedHere { adt_def_span, ty, variants }) } -fn maybe_point_at_variant<'a, 'p: 'a, 'tcx: 'a>( - cx: &MatchCheckCtxt<'p, 'tcx>, +fn maybe_point_at_variant<'a, 'tcx: 'a>( + tcx: TyCtxt<'tcx>, def: AdtDef<'tcx>, patterns: impl Iterator>, ) -> Vec { @@ -1068,7 +1065,7 @@ fn maybe_point_at_variant<'a, 'p: 'a, 'tcx: 'a>( { continue; } - let sp = def.variant(*variant_index).ident(cx.tcx).span; + let sp = def.variant(*variant_index).ident(tcx).span; if covered.contains(&sp) { // Don't point at variants that have already been covered due to other patterns to avoid // visual clutter. @@ -1076,7 +1073,7 @@ fn maybe_point_at_variant<'a, 'p: 'a, 'tcx: 'a>( } covered.push(sp); } - covered.extend(maybe_point_at_variant(cx, def, pattern.iter_fields())); + covered.extend(maybe_point_at_variant(tcx, def, pattern.iter_fields())); } covered } From 3760d919d86b1f4ad464ee1370ba6389e161a7a2 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sun, 29 Oct 2023 05:37:59 +0100 Subject: [PATCH 197/435] Cleanup check_match code paths --- .../src/thir/pattern/check_match.rs | 214 +++++++++--------- 1 file changed, 104 insertions(+), 110 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 694e4c07bd5d..eadd7a310b71 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -42,7 +42,7 @@ pub(crate) fn check_match(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), Err for param in thir.params.iter() { if let Some(box ref pattern) = param.pat { - visitor.check_irrefutable(pattern, "function argument", None); + visitor.check_binding_is_irrefutable(pattern, "function argument", None); } } visitor.error @@ -66,16 +66,17 @@ use RefutableFlag::*; #[derive(Clone, Copy, Debug, PartialEq, Eq)] enum LetSource { None, + PlainLet, IfLet, IfLetGuard, LetElse, WhileLet, } -struct MatchVisitor<'a, 'p, 'tcx> { +struct MatchVisitor<'thir, 'p, 'tcx> { tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, - thir: &'a Thir<'tcx>, + thir: &'thir Thir<'tcx>, lint_level: HirId, let_source: LetSource, pattern_arena: &'p TypedArena>, @@ -85,8 +86,10 @@ struct MatchVisitor<'a, 'p, 'tcx> { error: Result<(), ErrorGuaranteed>, } -impl<'a, 'tcx> Visitor<'a, 'tcx> for MatchVisitor<'a, '_, 'tcx> { - fn thir(&self) -> &'a Thir<'tcx> { +// Visitor for a thir body. This calls `check_match`, `check_let` and `check_let_chain` as +// appropriate. +impl<'thir, 'tcx> Visitor<'thir, 'tcx> for MatchVisitor<'thir, '_, 'tcx> { + fn thir(&self) -> &'thir Thir<'tcx> { self.thir } @@ -101,7 +104,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for MatchVisitor<'a, '_, 'tcx> { } Some(Guard::IfLet(ref pat, expr)) => { this.with_let_source(LetSource::IfLetGuard, |this| { - this.check_let(pat, expr, LetSource::IfLetGuard, pat.span); + this.check_let(pat, Some(expr), pat.span); this.visit_pat(pat); this.visit_expr(&this.thir[expr]); }); @@ -148,45 +151,43 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for MatchVisitor<'a, '_, 'tcx> { }; self.check_match(scrutinee, arms, source, ex.span); } - ExprKind::Let { box ref pat, expr } => { - self.check_let(pat, expr, self.let_source, ex.span); + ExprKind::Let { box ref pat, expr } if !matches!(self.let_source, LetSource::None) => { + self.check_let(pat, Some(expr), ex.span); } - ExprKind::LogicalOp { op: LogicalOp::And, .. } => { - self.check_let_chain(self.let_source, ex); + ExprKind::LogicalOp { op: LogicalOp::And, .. } + if !matches!(self.let_source, LetSource::None) => + { + self.check_let_chain(ex); } _ => {} }; + // If we got e.g. `let pat1 = x1 && let pat2 = x2` above, we will now traverse the two + // `let`s. In order not to check them twice we set `LetSource::None`. self.with_let_source(LetSource::None, |this| visit::walk_expr(this, ex)); } fn visit_stmt(&mut self, stmt: &Stmt<'tcx>) { - let old_lint_level = self.lint_level; match stmt.kind { StmtKind::Let { box ref pattern, initializer, else_block, lint_level, span, .. } => { - if let LintLevel::Explicit(lint_level) = lint_level { - self.lint_level = lint_level; - } - - if let Some(initializer) = initializer - && else_block.is_some() - { - self.check_let(pattern, initializer, LetSource::LetElse, span); - } - - if else_block.is_none() { - self.check_irrefutable(pattern, "local binding", Some(span)); - } + self.with_lint_level(lint_level, |this| { + let let_source = + if else_block.is_some() { LetSource::LetElse } else { LetSource::PlainLet }; + this.with_let_source(let_source, |this| { + this.check_let(pattern, initializer, span) + }); + visit::walk_stmt(this, stmt); + }); + } + StmtKind::Expr { .. } => { + visit::walk_stmt(self, stmt); } - _ => {} } - visit::walk_stmt(self, stmt); - self.lint_level = old_lint_level; } } -impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { +impl<'thir, 'p, 'tcx> MatchVisitor<'thir, 'p, 'tcx> { #[instrument(level = "trace", skip(self, f))] fn with_let_source(&mut self, let_source: LetSource, f: impl FnOnce(&mut Self)) { let old_let_source = self.let_source; @@ -228,24 +229,37 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { } } - fn new_cx(&self, hir_id: HirId, refutable: bool) -> MatchCheckCtxt<'p, 'tcx> { + fn new_cx(&self, refutability: RefutableFlag) -> MatchCheckCtxt<'p, 'tcx> { + let refutable = match refutability { + Irrefutable => false, + Refutable => true, + }; MatchCheckCtxt { tcx: self.tcx, param_env: self.param_env, - module: self.tcx.parent_module(hir_id).to_def_id(), + module: self.tcx.parent_module(self.lint_level).to_def_id(), pattern_arena: &self.pattern_arena, refutable, } } #[instrument(level = "trace", skip(self))] - fn check_let(&mut self, pat: &Pat<'tcx>, scrutinee: ExprId, source: LetSource, span: Span) { - if let LetSource::None = source { - return; + fn check_let(&mut self, pat: &Pat<'tcx>, scrutinee: Option, span: Span) { + assert!(self.let_source != LetSource::None); + if let LetSource::PlainLet = self.let_source { + self.check_binding_is_irrefutable(pat, "local binding", Some(span)) + } else { + let Ok(irrefutable) = self.is_let_irrefutable(pat) else { return }; + if irrefutable { + report_irrefutable_let_patterns( + self.tcx, + self.lint_level, + self.let_source, + 1, + span, + ); + } } - let mut cx = self.new_cx(self.lint_level, true); - let Ok(tpat) = self.lower_pattern(&cx, pat) else { return }; - self.check_let_reachability(&mut cx, self.lint_level, source, tpat, span); } fn check_match( @@ -255,15 +269,13 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { source: hir::MatchSource, expr_span: Span, ) { - let mut cx = self.new_cx(self.lint_level, true); + let cx = self.new_cx(Refutable); let mut tarms = Vec::with_capacity(arms.len()); for &arm in arms { let arm = &self.thir.arms[arm]; let got_error = self.with_lint_level(arm.lint_level, |this| { - let Ok(pat) = this.lower_pattern(&mut cx, &arm.pattern) else { - return true; - }; + let Ok(pat) = this.lower_pattern(&cx, &arm.pattern) else { return true }; let arm = MatchArm { pat, hir_id: this.lint_level, has_guard: arm.guard.is_some() }; tarms.push(arm); false @@ -299,34 +311,18 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { debug_assert_eq!(pat.span.desugaring_kind(), Some(DesugaringKind::ForLoop)); let PatKind::Variant { ref subpatterns, .. } = pat.kind else { bug!() }; let [pat_field] = &subpatterns[..] else { bug!() }; - self.check_irrefutable(&pat_field.pattern, "`for` loop binding", None); + self.check_binding_is_irrefutable(&pat_field.pattern, "`for` loop binding", None); } else { - self.error = Err(non_exhaustive_match( + self.error = Err(report_non_exhaustive_match( &cx, self.thir, scrut_ty, scrut.span, witnesses, arms, expr_span, )); } } } - fn check_let_reachability( - &mut self, - cx: &mut MatchCheckCtxt<'p, 'tcx>, - pat_id: HirId, - source: LetSource, - pat: &'p DeconstructedPat<'p, 'tcx>, - span: Span, - ) { - if is_let_irrefutable(cx, pat_id, pat) { - irrefutable_let_patterns(cx.tcx, pat_id, source, 1, span); - } - } - #[instrument(level = "trace", skip(self))] - fn check_let_chain(&mut self, let_source: LetSource, expr: &Expr<'tcx>) { - if let LetSource::None = let_source { - return; - } - + fn check_let_chain(&mut self, expr: &Expr<'tcx>) { + assert!(self.let_source != LetSource::None); let top_expr_span = expr.span; // Lint level enclosing `next_expr`. @@ -336,7 +332,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { // and record chain members that aren't let exprs. let mut chain_refutabilities = Vec::new(); - let mut got_lowering_error = false; + let mut got_error = false; let mut next_expr = Some(expr); while let Some(mut expr) = next_expr { while let ExprKind::Scope { value, lint_level, .. } = expr.kind { @@ -364,14 +360,15 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { } let value = match expr.kind { ExprKind::Let { box ref pat, expr: _ } => { - let mut ncx = self.new_cx(expr_lint_level, true); - if let Ok(tpat) = self.lower_pattern(&mut ncx, pat) { - let refutable = !is_let_irrefutable(&mut ncx, expr_lint_level, tpat); - Some((expr.span, refutable)) - } else { - got_lowering_error = true; - None - } + self.with_lint_level(LintLevel::Explicit(expr_lint_level), |this| { + match this.is_let_irrefutable(pat) { + Ok(irrefutable) => Some((expr.span, !irrefutable)), + Err(_) => { + got_error = true; + None + } + } + }) } _ => None, }; @@ -380,17 +377,17 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { debug!(?chain_refutabilities); chain_refutabilities.reverse(); - if got_lowering_error { + if got_error { return; } - // Third, emit the actual warnings. + // Emit the actual warnings. if chain_refutabilities.iter().all(|r| matches!(*r, Some((_, false)))) { // The entire chain is made up of irrefutable `let` statements - irrefutable_let_patterns( + report_irrefutable_let_patterns( self.tcx, self.lint_level, - let_source, + self.let_source, chain_refutabilities.len(), top_expr_span, ); @@ -409,7 +406,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { // so can't always be moved out. // FIXME: Add checking whether the bindings are actually used in the prefix, // and lint if they are not. - if !matches!(let_source, LetSource::WhileLet | LetSource::IfLetGuard) { + if !matches!(self.let_source, LetSource::WhileLet | LetSource::IfLetGuard) { // Emit the lint let prefix = &chain_refutabilities[..until]; let span_start = prefix[0].unwrap().0; @@ -444,18 +441,33 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { } } + fn analyze_binding( + &mut self, + pat: &Pat<'tcx>, + refutability: RefutableFlag, + ) -> Result<(MatchCheckCtxt<'p, 'tcx>, UsefulnessReport<'p, 'tcx>), ErrorGuaranteed> { + let cx = self.new_cx(refutability); + let pat = self.lower_pattern(&cx, pat)?; + let arms = [MatchArm { pat, hir_id: self.lint_level, has_guard: false }]; + let report = compute_match_usefulness(&cx, &arms, self.lint_level, pat.ty(), pat.span()); + Ok((cx, report)) + } + + fn is_let_irrefutable(&mut self, pat: &Pat<'tcx>) -> Result { + let (cx, report) = self.analyze_binding(pat, Refutable)?; + // Report if the pattern is unreachable, which can only occur when the type is + // uninhabited. This also reports unreachable sub-patterns. + report_arm_reachability(&cx, &report); + // If the list of witnesses is empty, the match is exhaustive, + // i.e. the `if let` pattern is irrefutable. + Ok(report.non_exhaustiveness_witnesses.is_empty()) + } + #[instrument(level = "trace", skip(self))] - fn check_irrefutable(&mut self, pat: &Pat<'tcx>, origin: &str, sp: Option) { - let mut cx = self.new_cx(self.lint_level, false); + fn check_binding_is_irrefutable(&mut self, pat: &Pat<'tcx>, origin: &str, sp: Option) { + let pattern_ty = pat.ty; - let Ok(pattern) = self.lower_pattern(&mut cx, pat) else { return }; - let pattern_ty = pattern.ty(); - let arm = MatchArm { pat: pattern, hir_id: self.lint_level, has_guard: false }; - let report = - compute_match_usefulness(&cx, &[arm], self.lint_level, pattern_ty, pattern.span()); - - // Note: we ignore whether the pattern is unreachable (i.e. whether the type is empty). We - // only care about exhaustiveness here. + let Ok((cx, report)) = self.analyze_binding(pat, Irrefutable) else { return }; let witnesses = report.non_exhaustiveness_witnesses; if witnesses.is_empty() { // The pattern is irrefutable. @@ -509,16 +521,16 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { // Emit an extra note if the first uncovered witness would be uninhabited // if we disregard visibility. - let witness_1_is_privately_uninhabited = if cx.tcx.features().exhaustive_patterns + let witness_1_is_privately_uninhabited = if self.tcx.features().exhaustive_patterns && let Some(witness_1) = witnesses.get(0) && let ty::Adt(adt, args) = witness_1.ty().kind() && adt.is_enum() && let Constructor::Variant(variant_index) = witness_1.ctor() { let variant = adt.variant(*variant_index); - let inhabited = variant.inhabited_predicate(cx.tcx, *adt).instantiate(cx.tcx, args); - assert!(inhabited.apply(cx.tcx, cx.param_env, cx.module)); - !inhabited.apply_ignore_module(cx.tcx, cx.param_env) + let inhabited = variant.inhabited_predicate(self.tcx, *adt).instantiate(self.tcx, args); + assert!(inhabited.apply(self.tcx, cx.param_env, cx.module)); + !inhabited.apply_ignore_module(self.tcx, cx.param_env) } else { false }; @@ -673,7 +685,7 @@ fn check_for_bindings_named_same_as_variants( BindingsWithVariantName { // If this is an irrefutable pattern, and there's > 1 variant, // then we can't actually match on this. Applying the below - // suggestion would produce code that breaks on `check_irrefutable`. + // suggestion would produce code that breaks on `check_binding_is_irrefutable`. suggestion: if rf == Refutable || variant_count == 1 { Some(pat.span) } else { @@ -686,7 +698,7 @@ fn check_for_bindings_named_same_as_variants( } } -fn irrefutable_let_patterns( +fn report_irrefutable_let_patterns( tcx: TyCtxt<'_>, id: HirId, source: LetSource, @@ -700,7 +712,7 @@ fn irrefutable_let_patterns( } match source { - LetSource::None => bug!(), + LetSource::None | LetSource::PlainLet => bug!(), LetSource::IfLet => emit_diag!(IrrefutableLetPatternsIfLet), LetSource::IfLetGuard => emit_diag!(IrrefutableLetPatternsIfLetGuard), LetSource::LetElse => emit_diag!(IrrefutableLetPatternsLetElse), @@ -708,24 +720,6 @@ fn irrefutable_let_patterns( } } -fn is_let_irrefutable<'p, 'tcx>( - cx: &mut MatchCheckCtxt<'p, 'tcx>, - pat_id: HirId, - pat: &'p DeconstructedPat<'p, 'tcx>, -) -> bool { - let arms = [MatchArm { pat, hir_id: pat_id, has_guard: false }]; - let report = compute_match_usefulness(&cx, &arms, pat_id, pat.ty(), pat.span()); - - // Report if the pattern is unreachable, which can only occur when the type is uninhabited. - // This also reports unreachable sub-patterns though, so we can't just replace it with an - // `is_uninhabited` check. - report_arm_reachability(&cx, &report); - - // If the list of witnesses is empty, the match is exhaustive, - // i.e. the `if let` pattern is irrefutable. - report.non_exhaustiveness_witnesses.is_empty() -} - /// Report unreachable arms, if any. fn report_arm_reachability<'p, 'tcx>( cx: &MatchCheckCtxt<'p, 'tcx>, @@ -776,7 +770,7 @@ fn pat_is_catchall(pat: &DeconstructedPat<'_, '_>) -> bool { } /// Report that a match is not exhaustive. -fn non_exhaustive_match<'p, 'tcx>( +fn report_non_exhaustive_match<'p, 'tcx>( cx: &MatchCheckCtxt<'p, 'tcx>, thir: &Thir<'tcx>, scrut_ty: Ty<'tcx>, From 04f1024ecb8716e3f23b580af48d50428b05ad6a Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 2 Nov 2023 09:44:36 +0000 Subject: [PATCH 198/435] Rustup to rustc 1.75.0-nightly (75b064d26 2023-11-01) --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index 7e3eaacf8ef0..54683e1ebb18 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2023-10-29" +channel = "nightly-2023-11-02" components = ["rust-src", "rustc-dev", "llvm-tools"] From c04ceb4342b7362e9f7620f956f1098bdab24128 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 2 Nov 2023 09:52:21 +0000 Subject: [PATCH 199/435] Fix workaround for the `int $$0x29` issue to not crash on empty inline asm --- src/inline_asm.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/inline_asm.rs b/src/inline_asm.rs index 331649b2ec24..78212e8a4cc0 100644 --- a/src/inline_asm.rs +++ b/src/inline_asm.rs @@ -47,7 +47,9 @@ pub(crate) fn codegen_inline_asm<'tcx>( // Used by panic_abort on Windows, but uses a syntax which only happens to work with // asm!() by accident and breaks with the GNU assembler as well as global_asm!() for // the LLVM backend. - if template[0] == InlineAsmTemplatePiece::String("int $$0x29".to_string()) { + if template.len() == 1 + && template[0] == InlineAsmTemplatePiece::String("int $$0x29".to_string()) + { fx.bcx.ins().trap(TrapCode::User(1)); return; } From ef3703694ff6b19d38aff83477bb2ad38f5a58d8 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 2 Nov 2023 10:27:56 +0000 Subject: [PATCH 200/435] Disable a couple of rustc tests which are broken due to a rustc bug --- scripts/test_rustc_tests.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/scripts/test_rustc_tests.sh b/scripts/test_rustc_tests.sh index b485f2571cc7..dcc8c7f43560 100755 --- a/scripts/test_rustc_tests.sh +++ b/scripts/test_rustc_tests.sh @@ -147,6 +147,11 @@ rm tests/ui/process/nofile-limit.rs # TODO some AArch64 linking issue rm tests/ui/stdio-is-blocking.rs # really slow with unoptimized libstd +# rustc bugs +# ========== +# https://github.com/rust-lang/rust/pull/116447#issuecomment-1790451463 +rm tests/ui/coroutine/gen_block_*.rs + cp ../dist/bin/rustdoc-clif ../dist/bin/rustdoc # some tests expect bin/rustdoc to exist # prevent $(RUSTDOC) from picking up the sysroot built by x.py. It conflicts with the one used by From 384f7382ba595092169569e4e16aaeb7dbd32f7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Wed, 25 Oct 2023 23:19:34 +0200 Subject: [PATCH 201/435] add test for #113381 Fixes #113381 r? fee1-dead --- .../const_closure-const_trait_impl-ice-113381.rs | 15 +++++++++++++++ ...nst_closure-const_trait_impl-ice-113381.stderr | 11 +++++++++++ 2 files changed, 26 insertions(+) create mode 100644 tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const_closure-const_trait_impl-ice-113381.rs create mode 100644 tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const_closure-const_trait_impl-ice-113381.stderr diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const_closure-const_trait_impl-ice-113381.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const_closure-const_trait_impl-ice-113381.rs new file mode 100644 index 000000000000..6598d1da0f86 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const_closure-const_trait_impl-ice-113381.rs @@ -0,0 +1,15 @@ +#![feature(const_closures, const_trait_impl, effects)] +#![allow(incomplete_features)] + +trait Foo { + fn foo(&self); +} + +impl Foo for () { + fn foo(&self) {} +} + +fn main() { + (const || { (()).foo() })(); + //~^ ERROR: cannot call non-const fn +} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const_closure-const_trait_impl-ice-113381.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const_closure-const_trait_impl-ice-113381.stderr new file mode 100644 index 000000000000..002d586ac64f --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const_closure-const_trait_impl-ice-113381.stderr @@ -0,0 +1,11 @@ +error[E0015]: cannot call non-const fn `<() as Foo>::foo` in constant functions + --> $DIR/const_closure-const_trait_impl-ice-113381.rs:13:22 + | +LL | (const || { (()).foo() })(); + | ^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0015`. From 666cad9a5f86c9e69e6ef0f75d85a34ad30f11d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Thu, 2 Nov 2023 16:15:33 +0100 Subject: [PATCH 202/435] add test for #113375 Fixes #113375 --- .../ice-113375-index-out-of-bounds-generics.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 tests/ui/rfcs/rfc-2632-const-trait-impl/effects/ice-113375-index-out-of-bounds-generics.rs diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/ice-113375-index-out-of-bounds-generics.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/ice-113375-index-out-of-bounds-generics.rs new file mode 100644 index 000000000000..1954d2942e0b --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/ice-113375-index-out-of-bounds-generics.rs @@ -0,0 +1,18 @@ +// check-pass + +// effects ice https://github.com/rust-lang/rust/issues/113375 index out of bounds + +#![allow(incomplete_features, unused)] +#![feature(effects, adt_const_params)] + +struct Bar(T); + +impl Bar { + const fn value() -> usize { + 42 + } +} + +struct Foo::value()]>; + +pub fn main() {} From 909513ef74d790b29d9c79eab775b1fca62ecd04 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 2 Nov 2023 15:32:44 +0000 Subject: [PATCH 203/435] Use Value instead of CValue in CInlineAsmOperand --- src/inline_asm.rs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/inline_asm.rs b/src/inline_asm.rs index 78212e8a4cc0..ee7d5bcc9f7c 100644 --- a/src/inline_asm.rs +++ b/src/inline_asm.rs @@ -13,7 +13,7 @@ use crate::prelude::*; enum CInlineAsmOperand<'tcx> { In { reg: InlineAsmRegOrRegClass, - value: CValue<'tcx>, + value: Value, }, Out { reg: InlineAsmRegOrRegClass, @@ -23,7 +23,7 @@ enum CInlineAsmOperand<'tcx> { InOut { reg: InlineAsmRegOrRegClass, _late: bool, - in_value: CValue<'tcx>, + in_value: Value, out_place: Option>, }, Const { @@ -57,9 +57,10 @@ pub(crate) fn codegen_inline_asm<'tcx>( let operands = operands .into_iter() .map(|operand| match *operand { - InlineAsmOperand::In { reg, ref value } => { - CInlineAsmOperand::In { reg, value: crate::base::codegen_operand(fx, value) } - } + InlineAsmOperand::In { reg, ref value } => CInlineAsmOperand::In { + reg, + value: crate::base::codegen_operand(fx, value).load_scalar(fx), + }, InlineAsmOperand::Out { reg, late, ref place } => CInlineAsmOperand::Out { reg, late, @@ -69,7 +70,7 @@ pub(crate) fn codegen_inline_asm<'tcx>( CInlineAsmOperand::InOut { reg, _late: late, - in_value: crate::base::codegen_operand(fx, in_value), + in_value: crate::base::codegen_operand(fx, in_value).load_scalar(fx), out_place: out_place.map(|place| crate::base::codegen_place(fx, place)), } } @@ -167,7 +168,7 @@ pub(crate) fn codegen_inline_asm<'tcx>( for (i, operand) in operands.iter().enumerate() { match operand { CInlineAsmOperand::In { reg: _, value } => { - inputs.push((asm_gen.stack_slots_input[i].unwrap(), value.load_scalar(fx))); + inputs.push((asm_gen.stack_slots_input[i].unwrap(), *value)); } CInlineAsmOperand::Out { reg: _, late: _, place } => { if let Some(place) = place { @@ -175,7 +176,7 @@ pub(crate) fn codegen_inline_asm<'tcx>( } } CInlineAsmOperand::InOut { reg: _, _late: _, in_value, out_place } => { - inputs.push((asm_gen.stack_slots_input[i].unwrap(), in_value.load_scalar(fx))); + inputs.push((asm_gen.stack_slots_input[i].unwrap(), *in_value)); if let Some(out_place) = out_place { outputs.push((asm_gen.stack_slots_output[i].unwrap(), *out_place)); } From f6a8c3afb5b2c0cb1be044b9dc4368bfc8403991 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 2 Nov 2023 16:03:26 +0000 Subject: [PATCH 204/435] Add real implementation of _xgetbv() --- src/inline_asm.rs | 80 ++++++++++++++++++++++++++++++++++++++ src/intrinsics/llvm_x86.rs | 11 ++---- 2 files changed, 83 insertions(+), 8 deletions(-) diff --git a/src/inline_asm.rs b/src/inline_asm.rs index ee7d5bcc9f7c..ce0eecca8a8b 100644 --- a/src/inline_asm.rs +++ b/src/inline_asm.rs @@ -729,3 +729,83 @@ fn call_inline_asm<'tcx>( place.write_cvalue(fx, CValue::by_val(value, place.layout())); } } + +pub(crate) fn codegen_xgetbv<'tcx>( + fx: &mut FunctionCx<'_, '_, 'tcx>, + xcr_no: Value, + ret: CPlace<'tcx>, +) { + // FIXME add .eh_frame unwind info directives + + let operands = vec![ + CInlineAsmOperand::In { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::cx)), + value: xcr_no, + }, + CInlineAsmOperand::Out { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::ax)), + late: true, + place: Some(ret), + }, + CInlineAsmOperand::Out { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::dx)), + late: true, + place: None, + }, + ]; + let options = InlineAsmOptions::NOSTACK | InlineAsmOptions::PURE | InlineAsmOptions::NOMEM; + + let mut inputs = Vec::new(); + let mut outputs = Vec::new(); + + let mut asm_gen = InlineAssemblyGenerator { + tcx: fx.tcx, + arch: fx.tcx.sess.asm_arch.unwrap(), + enclosing_def_id: fx.instance.def_id(), + template: &[InlineAsmTemplatePiece::String( + " + xgetbv + // out = rdx << 32 | rax + shl rdx, 32 + or rax, rdx + " + .to_string(), + )], + operands: &operands, + options, + registers: Vec::new(), + stack_slots_clobber: Vec::new(), + stack_slots_input: Vec::new(), + stack_slots_output: Vec::new(), + stack_slot_size: Size::from_bytes(0), + }; + asm_gen.allocate_registers(); + asm_gen.allocate_stack_slots(); + + let inline_asm_index = fx.cx.inline_asm_index.get(); + fx.cx.inline_asm_index.set(inline_asm_index + 1); + let asm_name = format!( + "__inline_asm_{}_n{}", + fx.cx.cgu_name.as_str().replace('.', "__").replace('-', "_"), + inline_asm_index + ); + + let generated_asm = asm_gen.generate_asm_wrapper(&asm_name); + fx.cx.global_asm.push_str(&generated_asm); + + for (i, operand) in operands.iter().enumerate() { + match operand { + CInlineAsmOperand::In { reg: _, value } => { + inputs.push((asm_gen.stack_slots_input[i].unwrap(), *value)); + } + CInlineAsmOperand::Out { reg: _, late: _, place } => { + if let Some(place) = place { + outputs.push((asm_gen.stack_slots_output[i].unwrap(), *place)); + } + } + _ => unreachable!(), + } + } + + call_inline_asm(fx, &asm_name, asm_gen.stack_slot_size, inputs, outputs); +} diff --git a/src/intrinsics/llvm_x86.rs b/src/intrinsics/llvm_x86.rs index ea5997a14bb7..6fd85ab8bf1d 100644 --- a/src/intrinsics/llvm_x86.rs +++ b/src/intrinsics/llvm_x86.rs @@ -20,16 +20,11 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( // Used by is_x86_feature_detected!(); "llvm.x86.xgetbv" => { - // FIXME use the actual xgetbv instruction - intrinsic_args!(fx, args => (v); intrinsic); + intrinsic_args!(fx, args => (xcr_no); intrinsic); - let v = v.load_scalar(fx); + let xcr_no = xcr_no.load_scalar(fx); - // As of writing on XCR0 exists - fx.bcx.ins().trapnz(v, TrapCode::UnreachableCodeReached); - - let res = fx.bcx.ins().iconst(types::I64, 1 /* bit 0 must be set */); - ret.write_cvalue(fx, CValue::by_val(res, fx.layout_of(fx.tcx.types.i64))); + crate::inline_asm::codegen_xgetbv(fx, xcr_no, ret); } "llvm.x86.sse.cmp.ps" | "llvm.x86.sse2.cmp.pd" => { From 1b7bb9a7bd8c1f0d7f8a889001ba5b3141522764 Mon Sep 17 00:00:00 2001 From: Peter Tripp Date: Thu, 2 Nov 2023 15:53:33 -0400 Subject: [PATCH 205/435] VSCode search: 'category:formatters rust' metadata. --- editors/code/package.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/editors/code/package.json b/editors/code/package.json index 2dde66c97006..b3e4a9ff5135 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -17,6 +17,8 @@ "rust" ], "categories": [ + "Formatters", + "Linters", "Programming Languages" ], "capabilities": { From 274a6f3d0dd938b908ac3f5fd84b703f223c47db Mon Sep 17 00:00:00 2001 From: Alejandro Martinez Ruiz Date: Thu, 2 Nov 2023 17:43:10 +0100 Subject: [PATCH 206/435] bootstrap/setup: create hooks directory if non-existing --- src/bootstrap/src/core/build_steps/setup.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/src/core/build_steps/setup.rs b/src/bootstrap/src/core/build_steps/setup.rs index 435ebb6df90d..b4540641bfa2 100644 --- a/src/bootstrap/src/core/build_steps/setup.rs +++ b/src/bootstrap/src/core/build_steps/setup.rs @@ -469,7 +469,8 @@ fn install_git_hook_maybe(config: &Config) -> io::Result<()> { assert!(output.status.success(), "failed to run `git`"); PathBuf::from(t!(String::from_utf8(output.stdout)).trim()) })); - let dst = git.join("hooks").join("pre-push"); + let hooks_dir = git.join("hooks"); + let dst = hooks_dir.join("pre-push"); if dst.exists() { // The git hook has already been set up, or the user already has a custom hook. return Ok(()); @@ -486,6 +487,10 @@ undesirable, simply delete the `pre-push` file from .git/hooks." println!("Ok, skipping installation!"); return Ok(()); } + if !hooks_dir.exists() { + // We need to (try to) create the hooks directory first. + let _ = fs::create_dir(hooks_dir); + } let src = config.src.join("src").join("etc").join("pre-push.sh"); match fs::hard_link(src, &dst) { Err(e) => { From fccdde63c9764d6332721c06247b4fc78a847d37 Mon Sep 17 00:00:00 2001 From: Peter Tripp Date: Thu, 2 Nov 2023 18:21:31 -0400 Subject: [PATCH 207/435] Maybe not a linter. --- editors/code/package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/editors/code/package.json b/editors/code/package.json index b3e4a9ff5135..c7b877b2897c 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -18,7 +18,6 @@ ], "categories": [ "Formatters", - "Linters", "Programming Languages" ], "capabilities": { From 075409ddd9bf30602c7654e37127e1dbbb460871 Mon Sep 17 00:00:00 2001 From: ltdk Date: Fri, 8 Sep 2023 23:57:15 -0400 Subject: [PATCH 208/435] Move RandomState and DefaultHasher into std::hash, but don't export for now --- library/std/src/collections/hash/map.rs | 151 +--------------- library/std/src/collections/hash/map/tests.rs | 2 +- library/std/src/collections/hash/set.rs | 4 +- library/std/src/collections/hash/set/tests.rs | 2 +- library/std/src/collections/mod.rs | 5 + library/std/src/hash/mod.rs | 91 ++++++++++ library/std/src/hash/random.rs | 161 ++++++++++++++++++ library/std/src/lib.rs | 5 +- library/std/src/path/tests.rs | 6 +- library/std/tests/common/mod.rs | 4 +- library/test/src/helpers/shuffle.rs | 3 +- library/test/src/lib.rs | 6 +- 12 files changed, 272 insertions(+), 168 deletions(-) create mode 100644 library/std/src/hash/mod.rs create mode 100644 library/std/src/hash/random.rs diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index 4d109285d164..ba808fb010bc 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -6,16 +6,13 @@ use self::Entry::*; use hashbrown::hash_map as base; use crate::borrow::Borrow; -use crate::cell::Cell; use crate::collections::TryReserveError; use crate::collections::TryReserveErrorKind; use crate::error::Error; use crate::fmt::{self, Debug}; -#[allow(deprecated)] -use crate::hash::{BuildHasher, Hash, Hasher, SipHasher13}; +use crate::hash::{BuildHasher, Hash, RandomState}; use crate::iter::FusedIterator; use crate::ops::Index; -use crate::sys; /// A [hash map] implemented with quadratic probing and SIMD lookup. /// @@ -3072,152 +3069,6 @@ where } } -/// `RandomState` is the default state for [`HashMap`] types. -/// -/// A particular instance `RandomState` will create the same instances of -/// [`Hasher`], but the hashers created by two different `RandomState` -/// instances are unlikely to produce the same result for the same values. -/// -/// # Examples -/// -/// ``` -/// use std::collections::HashMap; -/// use std::collections::hash_map::RandomState; -/// -/// let s = RandomState::new(); -/// let mut map = HashMap::with_hasher(s); -/// map.insert(1, 2); -/// ``` -#[derive(Clone)] -#[stable(feature = "hashmap_build_hasher", since = "1.7.0")] -pub struct RandomState { - k0: u64, - k1: u64, -} - -impl RandomState { - /// Constructs a new `RandomState` that is initialized with random keys. - /// - /// # Examples - /// - /// ``` - /// use std::collections::hash_map::RandomState; - /// - /// let s = RandomState::new(); - /// ``` - #[inline] - #[allow(deprecated)] - // rand - #[must_use] - #[stable(feature = "hashmap_build_hasher", since = "1.7.0")] - pub fn new() -> RandomState { - // Historically this function did not cache keys from the OS and instead - // simply always called `rand::thread_rng().gen()` twice. In #31356 it - // was discovered, however, that because we re-seed the thread-local RNG - // from the OS periodically that this can cause excessive slowdown when - // many hash maps are created on a thread. To solve this performance - // trap we cache the first set of randomly generated keys per-thread. - // - // Later in #36481 it was discovered that exposing a deterministic - // iteration order allows a form of DOS attack. To counter that we - // increment one of the seeds on every RandomState creation, giving - // every corresponding HashMap a different iteration order. - thread_local!(static KEYS: Cell<(u64, u64)> = { - Cell::new(sys::hashmap_random_keys()) - }); - - KEYS.with(|keys| { - let (k0, k1) = keys.get(); - keys.set((k0.wrapping_add(1), k1)); - RandomState { k0, k1 } - }) - } -} - -#[stable(feature = "hashmap_build_hasher", since = "1.7.0")] -impl BuildHasher for RandomState { - type Hasher = DefaultHasher; - #[inline] - #[allow(deprecated)] - fn build_hasher(&self) -> DefaultHasher { - DefaultHasher(SipHasher13::new_with_keys(self.k0, self.k1)) - } -} - -/// The default [`Hasher`] used by [`RandomState`]. -/// -/// The internal algorithm is not specified, and so it and its hashes should -/// not be relied upon over releases. -#[stable(feature = "hashmap_default_hasher", since = "1.13.0")] -#[allow(deprecated)] -#[derive(Clone, Debug)] -pub struct DefaultHasher(SipHasher13); - -impl DefaultHasher { - /// Creates a new `DefaultHasher`. - /// - /// This hasher is not guaranteed to be the same as all other - /// `DefaultHasher` instances, but is the same as all other `DefaultHasher` - /// instances created through `new` or `default`. - #[stable(feature = "hashmap_default_hasher", since = "1.13.0")] - #[inline] - #[allow(deprecated)] - #[rustc_const_unstable(feature = "const_hash", issue = "104061")] - #[must_use] - pub const fn new() -> DefaultHasher { - DefaultHasher(SipHasher13::new_with_keys(0, 0)) - } -} - -#[stable(feature = "hashmap_default_hasher", since = "1.13.0")] -impl Default for DefaultHasher { - /// Creates a new `DefaultHasher` using [`new`]. - /// See its documentation for more. - /// - /// [`new`]: DefaultHasher::new - #[inline] - fn default() -> DefaultHasher { - DefaultHasher::new() - } -} - -#[stable(feature = "hashmap_default_hasher", since = "1.13.0")] -impl Hasher for DefaultHasher { - // The underlying `SipHasher13` doesn't override the other - // `write_*` methods, so it's ok not to forward them here. - - #[inline] - fn write(&mut self, msg: &[u8]) { - self.0.write(msg) - } - - #[inline] - fn write_str(&mut self, s: &str) { - self.0.write_str(s); - } - - #[inline] - fn finish(&self) -> u64 { - self.0.finish() - } -} - -#[stable(feature = "hashmap_build_hasher", since = "1.7.0")] -impl Default for RandomState { - /// Constructs a new `RandomState`. - #[inline] - fn default() -> RandomState { - RandomState::new() - } -} - -#[stable(feature = "std_debug", since = "1.16.0")] -impl fmt::Debug for RandomState { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("RandomState").finish_non_exhaustive() - } -} - #[inline] fn map_entry<'a, K: 'a, V: 'a>(raw: base::RustcEntry<'a, K, V>) -> Entry<'a, K, V> { match raw { diff --git a/library/std/src/collections/hash/map/tests.rs b/library/std/src/collections/hash/map/tests.rs index 91a3776e7be8..8585376abc18 100644 --- a/library/std/src/collections/hash/map/tests.rs +++ b/library/std/src/collections/hash/map/tests.rs @@ -1,8 +1,8 @@ use super::Entry::{Occupied, Vacant}; use super::HashMap; -use super::RandomState; use crate::assert_matches::assert_matches; use crate::cell::RefCell; +use crate::hash::RandomState; use crate::test_helpers::test_rng; use rand::Rng; use realstd::collections::TryReserveErrorKind::*; diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs index 6a87f6e5f2dc..ffc4521d0ae0 100644 --- a/library/std/src/collections/hash/set.rs +++ b/library/std/src/collections/hash/set.rs @@ -6,11 +6,11 @@ use hashbrown::hash_set as base; use crate::borrow::Borrow; use crate::collections::TryReserveError; use crate::fmt; -use crate::hash::{BuildHasher, Hash}; +use crate::hash::{BuildHasher, Hash, RandomState}; use crate::iter::{Chain, FusedIterator}; use crate::ops::{BitAnd, BitOr, BitXor, Sub}; -use super::map::{map_try_reserve_error, RandomState}; +use super::map::map_try_reserve_error; /// A [hash set] implemented as a `HashMap` where the value is `()`. /// diff --git a/library/std/src/collections/hash/set/tests.rs b/library/std/src/collections/hash/set/tests.rs index e0cd80b44f8e..208f61e755c5 100644 --- a/library/std/src/collections/hash/set/tests.rs +++ b/library/std/src/collections/hash/set/tests.rs @@ -1,6 +1,6 @@ -use super::super::map::RandomState; use super::HashSet; +use crate::hash::RandomState; use crate::panic::{catch_unwind, AssertUnwindSafe}; use crate::sync::atomic::{AtomicU32, Ordering}; use crate::sync::Arc; diff --git a/library/std/src/collections/mod.rs b/library/std/src/collections/mod.rs index 42f738acb9f7..1389d24a8c51 100644 --- a/library/std/src/collections/mod.rs +++ b/library/std/src/collections/mod.rs @@ -439,6 +439,11 @@ pub mod hash_map { //! A hash map implemented with quadratic probing and SIMD lookup. #[stable(feature = "rust1", since = "1.0.0")] pub use super::hash::map::*; + + #[stable(feature = "hashmap_build_hasher", since = "1.7.0")] + pub use crate::hash::random::DefaultHasher; + #[stable(feature = "hashmap_build_hasher", since = "1.7.0")] + pub use crate::hash::random::RandomState; } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/std/src/hash/mod.rs b/library/std/src/hash/mod.rs new file mode 100644 index 000000000000..63abed3ce742 --- /dev/null +++ b/library/std/src/hash/mod.rs @@ -0,0 +1,91 @@ +//! Generic hashing support. +//! +//! This module provides a generic way to compute the [hash] of a value. +//! Hashes are most commonly used with [`HashMap`] and [`HashSet`]. +//! +//! [hash]: https://en.wikipedia.org/wiki/Hash_function +//! [`HashMap`]: ../../std/collections/struct.HashMap.html +//! [`HashSet`]: ../../std/collections/struct.HashSet.html +//! +//! The simplest way to make a type hashable is to use `#[derive(Hash)]`: +//! +//! # Examples +//! +//! ```rust +//! use std::hash::{DefaultHasher, Hash, Hasher}; +//! +//! #[derive(Hash)] +//! struct Person { +//! id: u32, +//! name: String, +//! phone: u64, +//! } +//! +//! let person1 = Person { +//! id: 5, +//! name: "Janet".to_string(), +//! phone: 555_666_7777, +//! }; +//! let person2 = Person { +//! id: 5, +//! name: "Bob".to_string(), +//! phone: 555_666_7777, +//! }; +//! +//! assert!(calculate_hash(&person1) != calculate_hash(&person2)); +//! +//! fn calculate_hash(t: &T) -> u64 { +//! let mut s = DefaultHasher::new(); +//! t.hash(&mut s); +//! s.finish() +//! } +//! ``` +//! +//! If you need more control over how a value is hashed, you need to implement +//! the [`Hash`] trait: +//! +//! ```rust +//! use std::hash::{DefaultHasher, Hash, Hasher}; +//! +//! struct Person { +//! id: u32, +//! # #[allow(dead_code)] +//! name: String, +//! phone: u64, +//! } +//! +//! impl Hash for Person { +//! fn hash(&self, state: &mut H) { +//! self.id.hash(state); +//! self.phone.hash(state); +//! } +//! } +//! +//! let person1 = Person { +//! id: 5, +//! name: "Janet".to_string(), +//! phone: 555_666_7777, +//! }; +//! let person2 = Person { +//! id: 5, +//! name: "Bob".to_string(), +//! phone: 555_666_7777, +//! }; +//! +//! assert_eq!(calculate_hash(&person1), calculate_hash(&person2)); +//! +//! fn calculate_hash(t: &T) -> u64 { +//! let mut s = DefaultHasher::new(); +//! t.hash(&mut s); +//! s.finish() +//! } +//! ``` +#![stable(feature = "rust1", since = "1.0.0")] + +pub(crate) mod random; + +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::hash::*; + +// #[stable(feature = "std_hash_exports", since = "CURRENT_RUSTC_VERSION")] +pub(crate) use self::random::{DefaultHasher, RandomState}; diff --git a/library/std/src/hash/random.rs b/library/std/src/hash/random.rs new file mode 100644 index 000000000000..a1ccbb25369b --- /dev/null +++ b/library/std/src/hash/random.rs @@ -0,0 +1,161 @@ +//! This module exists to isolate [`RandomState`] and [`DefaultHasher`] outside of the +//! [`collections`] module without actually publicly exporting them, so that parts of that +//! implementation can more easily be moved to the [`alloc`] crate. +//! +//! Although its items are public and contain stability attributes, they can't actually be accessed +//! outside this crate. +//! +//! [`collections`]: crate::collections +#[allow(deprecated)] +use super::{BuildHasher, Hasher, SipHasher13}; +use crate::cell::Cell; +use crate::fmt; +use crate::sys; + +/// `RandomState` is the default state for [`HashMap`] types. +/// +/// A particular instance `RandomState` will create the same instances of +/// [`Hasher`], but the hashers created by two different `RandomState` +/// instances are unlikely to produce the same result for the same values. +/// +/// [`HashMap`]: crate::collections::HashMap +/// +/// # Examples +/// +/// ``` +/// use std::collections::HashMap; +/// use std::hash::RandomState; +/// +/// let s = RandomState::new(); +/// let mut map = HashMap::with_hasher(s); +/// map.insert(1, 2); +/// ``` +#[stable(feature = "hashmap_build_hasher", since = "1.7.0")] +#[derive(Clone)] +pub struct RandomState { + k0: u64, + k1: u64, +} + +impl RandomState { + /// Constructs a new `RandomState` that is initialized with random keys. + /// + /// # Examples + /// + /// ``` + /// use std::hash::RandomState; + /// + /// let s = RandomState::new(); + /// ``` + #[inline] + #[allow(deprecated)] + // rand + #[must_use] + #[stable(feature = "hashmap_build_hasher", since = "1.7.0")] + pub fn new() -> RandomState { + // Historically this function did not cache keys from the OS and instead + // simply always called `rand::thread_rng().gen()` twice. In #31356 it + // was discovered, however, that because we re-seed the thread-local RNG + // from the OS periodically that this can cause excessive slowdown when + // many hash maps are created on a thread. To solve this performance + // trap we cache the first set of randomly generated keys per-thread. + // + // Later in #36481 it was discovered that exposing a deterministic + // iteration order allows a form of DOS attack. To counter that we + // increment one of the seeds on every RandomState creation, giving + // every corresponding HashMap a different iteration order. + thread_local!(static KEYS: Cell<(u64, u64)> = { + Cell::new(sys::hashmap_random_keys()) + }); + + KEYS.with(|keys| { + let (k0, k1) = keys.get(); + keys.set((k0.wrapping_add(1), k1)); + RandomState { k0, k1 } + }) + } +} + +#[stable(feature = "hashmap_build_hasher", since = "1.7.0")] +impl BuildHasher for RandomState { + type Hasher = DefaultHasher; + #[inline] + #[allow(deprecated)] + fn build_hasher(&self) -> DefaultHasher { + DefaultHasher(SipHasher13::new_with_keys(self.k0, self.k1)) + } +} + +/// The default [`Hasher`] used by [`RandomState`]. +/// +/// The internal algorithm is not specified, and so it and its hashes should +/// not be relied upon over releases. +#[allow(deprecated)] +#[derive(Clone, Debug)] +#[stable(feature = "hashmap_build_hasher", since = "1.7.0")] +pub struct DefaultHasher(SipHasher13); + +impl DefaultHasher { + /// Creates a new `DefaultHasher`. + /// + /// This hasher is not guaranteed to be the same as all other + /// `DefaultHasher` instances, but is the same as all other `DefaultHasher` + /// instances created through `new` or `default`. + #[stable(feature = "hashmap_default_hasher", since = "1.13.0")] + #[inline] + #[allow(deprecated)] + #[rustc_const_unstable(feature = "const_hash", issue = "104061")] + #[must_use] + pub const fn new() -> DefaultHasher { + DefaultHasher(SipHasher13::new_with_keys(0, 0)) + } +} + +#[stable(feature = "hashmap_default_hasher", since = "1.13.0")] +impl Default for DefaultHasher { + /// Creates a new `DefaultHasher` using [`new`]. + /// See its documentation for more. + /// + /// [`new`]: DefaultHasher::new + #[inline] + fn default() -> DefaultHasher { + DefaultHasher::new() + } +} + +#[stable(feature = "hashmap_default_hasher", since = "1.13.0")] +impl Hasher for DefaultHasher { + // The underlying `SipHasher13` doesn't override the other + // `write_*` methods, so it's ok not to forward them here. + + #[inline] + fn write(&mut self, msg: &[u8]) { + self.0.write(msg) + } + + #[inline] + fn write_str(&mut self, s: &str) { + self.0.write_str(s); + } + + #[inline] + fn finish(&self) -> u64 { + self.0.finish() + } +} + +#[stable(feature = "hashmap_build_hasher", since = "1.7.0")] +impl Default for RandomState { + /// Constructs a new `RandomState`. + #[inline] + fn default() -> RandomState { + RandomState::new() + } +} + +#[stable(feature = "std_debug", since = "1.16.0")] +impl fmt::Debug for RandomState { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("RandomState").finish_non_exhaustive() + } +} diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index f57c8d4e7e28..f564fcf620a6 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -493,8 +493,6 @@ pub use core::convert; pub use core::default; #[stable(feature = "futures_api", since = "1.36.0")] pub use core::future; -#[stable(feature = "rust1", since = "1.0.0")] -pub use core::hash; #[stable(feature = "core_hint", since = "1.27.0")] pub use core::hint; #[stable(feature = "i128", since = "1.26.0")] @@ -564,6 +562,7 @@ pub mod env; pub mod error; pub mod ffi; pub mod fs; +pub mod hash; pub mod io; pub mod net; pub mod num; @@ -715,7 +714,7 @@ pub(crate) mod test_helpers { #[track_caller] pub(crate) fn test_rng() -> rand_xorshift::XorShiftRng { use core::hash::{BuildHasher, Hash, Hasher}; - let mut hasher = crate::collections::hash_map::RandomState::new().build_hasher(); + let mut hasher = crate::hash::RandomState::new().build_hasher(); core::panic::Location::caller().hash(&mut hasher); let hc64 = hasher.finish(); let seed_vec = hc64.to_le_bytes().into_iter().chain(0u8..8).collect::>(); diff --git a/library/std/src/path/tests.rs b/library/std/src/path/tests.rs index f12ffbf2e016..dbc0f7d9df35 100644 --- a/library/std/src/path/tests.rs +++ b/library/std/src/path/tests.rs @@ -1,8 +1,7 @@ use super::*; -use crate::collections::hash_map::DefaultHasher; use crate::collections::{BTreeSet, HashSet}; -use crate::hash::Hasher; +use crate::hash::{DefaultHasher, Hasher}; use crate::rc::Rc; use crate::sync::Arc; use core::hint::black_box; @@ -1461,8 +1460,7 @@ fn test_eq_receivers() { #[test] pub fn test_compare() { - use crate::collections::hash_map::DefaultHasher; - use crate::hash::{Hash, Hasher}; + use crate::hash::{DefaultHasher, Hash, Hasher}; fn hash(t: T) -> u64 { let mut s = DefaultHasher::new(); diff --git a/library/std/tests/common/mod.rs b/library/std/tests/common/mod.rs index 358c2c3f9b2f..1aad6549e76c 100644 --- a/library/std/tests/common/mod.rs +++ b/library/std/tests/common/mod.rs @@ -1,17 +1,17 @@ #![allow(unused)] +use rand::RngCore; use std::env; use std::fs; use std::path::{Path, PathBuf}; use std::thread; -use rand::RngCore; /// Copied from `std::test_helpers::test_rng`, since these tests rely on the /// seed not being the same for every RNG invocation too. #[track_caller] pub(crate) fn test_rng() -> rand_xorshift::XorShiftRng { use core::hash::{BuildHasher, Hash, Hasher}; - let mut hasher = std::collections::hash_map::RandomState::new().build_hasher(); + let mut hasher = std::hash::RandomState::new().build_hasher(); core::panic::Location::caller().hash(&mut hasher); let hc64 = hasher.finish(); let seed_vec = hc64.to_le_bytes().into_iter().chain(0u8..8).collect::>(); diff --git a/library/test/src/helpers/shuffle.rs b/library/test/src/helpers/shuffle.rs index ca503106c556..2ac3bfbd4d6f 100644 --- a/library/test/src/helpers/shuffle.rs +++ b/library/test/src/helpers/shuffle.rs @@ -1,7 +1,6 @@ use crate::cli::TestOpts; use crate::types::{TestDescAndFn, TestId, TestName}; -use std::collections::hash_map::DefaultHasher; -use std::hash::Hasher; +use std::hash::{DefaultHasher, Hasher}; use std::time::{SystemTime, UNIX_EPOCH}; pub fn get_shuffle_seed(opts: &TestOpts) -> Option { diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs index bddf75dffbb6..9cea375fd38f 100644 --- a/library/test/src/lib.rs +++ b/library/test/src/lib.rs @@ -264,8 +264,8 @@ pub fn run_tests( where F: FnMut(TestEvent) -> io::Result<()>, { - use std::collections::{self, HashMap}; - use std::hash::BuildHasherDefault; + use std::collections::HashMap; + use std::hash::{DefaultHasher, BuildHasherDefault}; use std::sync::mpsc::RecvTimeoutError; struct RunningTest { @@ -287,7 +287,7 @@ where // Use a deterministic hasher type TestMap = - HashMap>; + HashMap>; struct TimeoutEntry { id: TestId, From 8337e86b28b9cdab7250e39710a1c81b99aeeb8d Mon Sep 17 00:00:00 2001 From: ltdk Date: Fri, 13 Oct 2023 02:44:19 -0400 Subject: [PATCH 209/435] Add insta-stable std::hash::{DefaultHasher, RandomState} exports --- compiler/rustc_middle/src/ty/error.rs | 3 +- compiler/rustc_session/src/config.rs | 3 +- compiler/rustc_session/src/options.rs | 3 +- compiler/rustc_target/src/spec/mod.rs | 2 +- library/alloc/src/lib.rs | 2 +- library/alloc/src/vec/mod.rs | 2 +- library/alloc/tests/lib.rs | 3 +- library/core/src/array/mod.rs | 2 +- library/core/src/hash/mod.rs | 29 +++++++------------ library/core/src/hash/sip.rs | 26 +++++------------ library/core/src/ptr/mod.rs | 3 +- library/core/tests/hash/mod.rs | 2 +- library/core/tests/lib.rs | 2 +- library/std/src/collections/hash/map.rs | 6 ++-- library/std/src/collections/hash/set.rs | 6 ++-- library/std/src/hash/mod.rs | 4 +-- library/test/src/lib.rs | 5 ++-- src/tools/compiletest/src/runtest.rs | 3 +- .../import-trait-for-method-call.rs | 2 +- 19 files changed, 40 insertions(+), 68 deletions(-) diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index 738bb5e8b195..b26f98769c14 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -7,8 +7,7 @@ use rustc_hir::def_id::DefId; use rustc_span::symbol::Symbol; use rustc_target::spec::abi; use std::borrow::Cow; -use std::collections::hash_map::DefaultHasher; -use std::hash::{Hash, Hasher}; +use std::hash::{DefaultHasher, Hash, Hasher}; use std::path::PathBuf; #[derive(Clone, Copy, Debug, PartialEq, Eq, TypeFoldable, TypeVisitable)] diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 715a7f9cb631..9477754c3401 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -3179,9 +3179,8 @@ pub(crate) mod dep_tracking { use rustc_target::spec::{ RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TargetTriple, TlsModel, }; - use std::collections::hash_map::DefaultHasher; use std::collections::BTreeMap; - use std::hash::Hash; + use std::hash::{DefaultHasher, Hash}; use std::num::NonZeroUsize; use std::path::PathBuf; diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 7510a41485af..5a779728ec31 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -19,8 +19,7 @@ use rustc_span::SourceFileHashAlgorithm; use std::collections::BTreeMap; -use std::collections::hash_map::DefaultHasher; -use std::hash::Hasher; +use std::hash::{DefaultHasher, Hasher}; use std::num::{IntErrorKind, NonZeroUsize}; use std::path::PathBuf; use std::str; diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 48ca5fcf3ad0..19b7ea5d5789 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -3537,7 +3537,7 @@ impl TargetTriple { /// If this target is a path, a hash of the path is appended to the triple returned /// by `triple()`. pub fn debug_triple(&self) -> String { - use std::collections::hash_map::DefaultHasher; + use std::hash::DefaultHasher; match self { TargetTriple::TargetTriple(triple) => triple.to_owned(), diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 4f0a02da4407..2fb6eac96852 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -271,7 +271,7 @@ pub(crate) mod test_helpers { /// seed not being the same for every RNG invocation too. pub(crate) fn test_rng() -> rand_xorshift::XorShiftRng { use std::hash::{BuildHasher, Hash, Hasher}; - let mut hasher = std::collections::hash_map::RandomState::new().build_hasher(); + let mut hasher = std::hash::RandomState::new().build_hasher(); std::panic::Location::caller().hash(&mut hasher); let hc64 = hasher.finish(); let seed_vec = diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 6c78d65f1c94..ea7d6f6f4a64 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -2706,7 +2706,7 @@ impl Clone for Vec { /// ``` /// use std::hash::BuildHasher; /// -/// let b = std::collections::hash_map::RandomState::new(); +/// let b = std::hash::RandomState::new(); /// let v: Vec = vec![0xa8, 0x3c, 0x09]; /// let s: &[u8] = &[0xa8, 0x3c, 0x09]; /// assert_eq!(b.hash_one(v), b.hash_one(s)); diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index aa7a331b368b..6d5c17ef0230 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -43,8 +43,7 @@ #![deny(fuzzy_provenance_casts)] #![deny(unsafe_op_in_unsafe_fn)] -use std::collections::hash_map::DefaultHasher; -use std::hash::{Hash, Hasher}; +use std::hash::{DefaultHasher, Hash, Hasher}; mod arc; mod autotraits; diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index ebd4a8c05fe3..9c8d7bbd9997 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -297,7 +297,7 @@ impl<'a, T, const N: usize> TryFrom<&'a mut [T]> for &'a mut [T; N] { /// ``` /// use std::hash::BuildHasher; /// -/// let b = std::collections::hash_map::RandomState::new(); +/// let b = std::hash::RandomState::new(); /// let a: [u8; 3] = [0xa8, 0x3c, 0x09]; /// let s: &[u8] = &[0xa8, 0x3c, 0x09]; /// assert_eq!(b.hash_one(a), b.hash_one(s)); diff --git a/library/core/src/hash/mod.rs b/library/core/src/hash/mod.rs index 35b757dc1ee0..153971a59c5c 100644 --- a/library/core/src/hash/mod.rs +++ b/library/core/src/hash/mod.rs @@ -12,8 +12,7 @@ //! # Examples //! //! ```rust -//! use std::collections::hash_map::DefaultHasher; -//! use std::hash::{Hash, Hasher}; +//! use std::hash::{DefaultHasher, Hash, Hasher}; //! //! #[derive(Hash)] //! struct Person { @@ -46,8 +45,7 @@ //! the [`Hash`] trait: //! //! ```rust -//! use std::collections::hash_map::DefaultHasher; -//! use std::hash::{Hash, Hasher}; +//! use std::hash::{DefaultHasher, Hash, Hasher}; //! //! struct Person { //! id: u32, @@ -194,8 +192,7 @@ pub trait Hash { /// # Examples /// /// ``` - /// use std::collections::hash_map::DefaultHasher; - /// use std::hash::{Hash, Hasher}; + /// use std::hash::{DefaultHasher, Hash, Hasher}; /// /// let mut hasher = DefaultHasher::new(); /// 7920.hash(&mut hasher); @@ -224,8 +221,7 @@ pub trait Hash { /// # Examples /// /// ``` - /// use std::collections::hash_map::DefaultHasher; - /// use std::hash::{Hash, Hasher}; + /// use std::hash::{DefaultHasher, Hash, Hasher}; /// /// let mut hasher = DefaultHasher::new(); /// let numbers = [6, 28, 496, 8128]; @@ -300,8 +296,7 @@ pub use macros::Hash; /// # Examples /// /// ``` -/// use std::collections::hash_map::DefaultHasher; -/// use std::hash::Hasher; +/// use std::hash::{DefaultHasher, Hasher}; /// /// let mut hasher = DefaultHasher::new(); /// @@ -329,8 +324,7 @@ pub trait Hasher { /// # Examples /// /// ``` - /// use std::collections::hash_map::DefaultHasher; - /// use std::hash::Hasher; + /// use std::hash::{DefaultHasher, Hasher}; /// /// let mut hasher = DefaultHasher::new(); /// hasher.write(b"Cool!"); @@ -347,8 +341,7 @@ pub trait Hasher { /// # Examples /// /// ``` - /// use std::collections::hash_map::DefaultHasher; - /// use std::hash::Hasher; + /// use std::hash::{DefaultHasher, Hasher}; /// /// let mut hasher = DefaultHasher::new(); /// let data = [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef]; @@ -627,8 +620,7 @@ impl Hasher for &mut H { /// # Examples /// /// ``` -/// use std::collections::hash_map::RandomState; -/// use std::hash::{BuildHasher, Hasher}; +/// use std::hash::{BuildHasher, Hasher, RandomState}; /// /// let s = RandomState::new(); /// let mut hasher_1 = s.build_hasher(); @@ -656,8 +648,7 @@ pub trait BuildHasher { /// # Examples /// /// ``` - /// use std::collections::hash_map::RandomState; - /// use std::hash::BuildHasher; + /// use std::hash::{BuildHasher, RandomState}; /// /// let s = RandomState::new(); /// let new_s = s.build_hasher(); @@ -690,7 +681,7 @@ pub trait BuildHasher { /// } /// /// // Then later, in a `#[test]` for the type... - /// let bh = std::collections::hash_map::RandomState::new(); + /// let bh = std::hash::RandomState::new(); /// assert_eq!( /// bh.hash_one(OrderAmbivalentPair(1, 2)), /// bh.hash_one(OrderAmbivalentPair(2, 1)) diff --git a/library/core/src/hash/sip.rs b/library/core/src/hash/sip.rs index 6b9f2e84257d..78a232faaf88 100644 --- a/library/core/src/hash/sip.rs +++ b/library/core/src/hash/sip.rs @@ -14,7 +14,7 @@ use crate::ptr; /// /// See: #[unstable(feature = "hashmap_internals", issue = "none")] -#[deprecated(since = "1.13.0", note = "use `std::collections::hash_map::DefaultHasher` instead")] +#[deprecated(since = "1.13.0", note = "use `std::hash::DefaultHasher` instead")] #[derive(Debug, Clone, Default)] #[doc(hidden)] pub struct SipHasher13 { @@ -25,7 +25,7 @@ pub struct SipHasher13 { /// /// See: #[unstable(feature = "hashmap_internals", issue = "none")] -#[deprecated(since = "1.13.0", note = "use `std::collections::hash_map::DefaultHasher` instead")] +#[deprecated(since = "1.13.0", note = "use `std::hash::DefaultHasher` instead")] #[derive(Debug, Clone, Default)] struct SipHasher24 { hasher: Hasher, @@ -44,7 +44,7 @@ struct SipHasher24 { /// it is not intended for cryptographic purposes. As such, all /// cryptographic uses of this implementation are _strongly discouraged_. #[stable(feature = "rust1", since = "1.0.0")] -#[deprecated(since = "1.13.0", note = "use `std::collections::hash_map::DefaultHasher` instead")] +#[deprecated(since = "1.13.0", note = "use `std::hash::DefaultHasher` instead")] #[derive(Debug, Clone, Default)] pub struct SipHasher(SipHasher24); @@ -147,10 +147,7 @@ impl SipHasher { /// Creates a new `SipHasher` with the two initial keys set to 0. #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[deprecated( - since = "1.13.0", - note = "use `std::collections::hash_map::DefaultHasher` instead" - )] + #[deprecated(since = "1.13.0", note = "use `std::hash::DefaultHasher` instead")] #[rustc_const_unstable(feature = "const_hash", issue = "104061")] #[must_use] pub const fn new() -> SipHasher { @@ -160,10 +157,7 @@ impl SipHasher { /// Creates a `SipHasher` that is keyed off the provided keys. #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[deprecated( - since = "1.13.0", - note = "use `std::collections::hash_map::DefaultHasher` instead" - )] + #[deprecated(since = "1.13.0", note = "use `std::hash::DefaultHasher` instead")] #[rustc_const_unstable(feature = "const_hash", issue = "104061")] #[must_use] pub const fn new_with_keys(key0: u64, key1: u64) -> SipHasher { @@ -175,10 +169,7 @@ impl SipHasher13 { /// Creates a new `SipHasher13` with the two initial keys set to 0. #[inline] #[unstable(feature = "hashmap_internals", issue = "none")] - #[deprecated( - since = "1.13.0", - note = "use `std::collections::hash_map::DefaultHasher` instead" - )] + #[deprecated(since = "1.13.0", note = "use `std::hash::DefaultHasher` instead")] #[rustc_const_unstable(feature = "const_hash", issue = "104061")] pub const fn new() -> SipHasher13 { SipHasher13::new_with_keys(0, 0) @@ -187,10 +178,7 @@ impl SipHasher13 { /// Creates a `SipHasher13` that is keyed off the provided keys. #[inline] #[unstable(feature = "hashmap_internals", issue = "none")] - #[deprecated( - since = "1.13.0", - note = "use `std::collections::hash_map::DefaultHasher` instead" - )] + #[deprecated(since = "1.13.0", note = "use `std::hash::DefaultHasher` instead")] #[rustc_const_unstable(feature = "const_hash", issue = "104061")] pub const fn new_with_keys(key0: u64, key1: u64) -> SipHasher13 { SipHasher13 { hasher: Hasher::new_with_keys(key0, key1) } diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 84b179df8c19..998ea52904ff 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -1911,8 +1911,7 @@ pub fn addr_eq(p: *const T, q: *const U) -> bool { /// # Examples /// /// ``` -/// use std::collections::hash_map::DefaultHasher; -/// use std::hash::{Hash, Hasher}; +/// use std::hash::{DefaultHasher, Hash, Hasher}; /// use std::ptr; /// /// let five = 5; diff --git a/library/core/tests/hash/mod.rs b/library/core/tests/hash/mod.rs index 033bd1ed6ed9..5268f32c0319 100644 --- a/library/core/tests/hash/mod.rs +++ b/library/core/tests/hash/mod.rs @@ -167,7 +167,7 @@ fn test_indirect_hasher() { #[test] fn test_build_hasher_object_safe() { - use std::collections::hash_map::{DefaultHasher, RandomState}; + use std::hash::{DefaultHasher, RandomState}; let _: &dyn BuildHasher = &RandomState::new(); } diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index df7b34ce73b4..45c102638b48 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -167,7 +167,7 @@ mod waker; #[allow(dead_code)] // Not used in all configurations. pub(crate) fn test_rng() -> rand_xorshift::XorShiftRng { use core::hash::{BuildHasher, Hash, Hasher}; - let mut hasher = std::collections::hash_map::RandomState::new().build_hasher(); + let mut hasher = std::hash::RandomState::new().build_hasher(); core::panic::Location::caller().hash(&mut hasher); let hc64 = hasher.finish(); let seed_vec = hc64.to_le_bytes().into_iter().chain(0u8..8).collect::>(); diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index ba808fb010bc..39e94902cfe5 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -271,7 +271,7 @@ impl HashMap { /// /// ``` /// use std::collections::HashMap; - /// use std::collections::hash_map::RandomState; + /// use std::hash::RandomState; /// /// let s = RandomState::new(); /// let mut map = HashMap::with_hasher(s); @@ -303,7 +303,7 @@ impl HashMap { /// /// ``` /// use std::collections::HashMap; - /// use std::collections::hash_map::RandomState; + /// use std::hash::RandomState; /// /// let s = RandomState::new(); /// let mut map = HashMap::with_capacity_and_hasher(10, s); @@ -714,7 +714,7 @@ impl HashMap { /// /// ``` /// use std::collections::HashMap; - /// use std::collections::hash_map::RandomState; + /// use std::hash::RandomState; /// /// let hasher = RandomState::new(); /// let map: HashMap = HashMap::with_hasher(hasher); diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs index ffc4521d0ae0..8bc596082906 100644 --- a/library/std/src/collections/hash/set.rs +++ b/library/std/src/collections/hash/set.rs @@ -361,7 +361,7 @@ impl HashSet { /// /// ``` /// use std::collections::HashSet; - /// use std::collections::hash_map::RandomState; + /// use std::hash::RandomState; /// /// let s = RandomState::new(); /// let mut set = HashSet::with_hasher(s); @@ -393,7 +393,7 @@ impl HashSet { /// /// ``` /// use std::collections::HashSet; - /// use std::collections::hash_map::RandomState; + /// use std::hash::RandomState; /// /// let s = RandomState::new(); /// let mut set = HashSet::with_capacity_and_hasher(10, s); @@ -411,7 +411,7 @@ impl HashSet { /// /// ``` /// use std::collections::HashSet; - /// use std::collections::hash_map::RandomState; + /// use std::hash::RandomState; /// /// let hasher = RandomState::new(); /// let set: HashSet = HashSet::with_hasher(hasher); diff --git a/library/std/src/hash/mod.rs b/library/std/src/hash/mod.rs index 63abed3ce742..bd9bbf298752 100644 --- a/library/std/src/hash/mod.rs +++ b/library/std/src/hash/mod.rs @@ -87,5 +87,5 @@ pub(crate) mod random; #[stable(feature = "rust1", since = "1.0.0")] pub use core::hash::*; -// #[stable(feature = "std_hash_exports", since = "CURRENT_RUSTC_VERSION")] -pub(crate) use self::random::{DefaultHasher, RandomState}; +#[stable(feature = "std_hash_exports", since = "CURRENT_RUSTC_VERSION")] +pub use self::random::{DefaultHasher, RandomState}; diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs index 9cea375fd38f..f92ffa94e99f 100644 --- a/library/test/src/lib.rs +++ b/library/test/src/lib.rs @@ -265,7 +265,7 @@ where F: FnMut(TestEvent) -> io::Result<()>, { use std::collections::HashMap; - use std::hash::{DefaultHasher, BuildHasherDefault}; + use std::hash::{BuildHasherDefault, DefaultHasher}; use std::sync::mpsc::RecvTimeoutError; struct RunningTest { @@ -286,8 +286,7 @@ where } // Use a deterministic hasher - type TestMap = - HashMap>; + type TestMap = HashMap>; struct TimeoutEntry { id: TestId, diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index e74d66a85992..f5d60177a16d 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -20,12 +20,11 @@ use regex::{Captures, Regex}; use rustfix::{apply_suggestions, get_suggestions_from_json, Filter}; use std::borrow::Cow; -use std::collections::hash_map::DefaultHasher; use std::collections::{HashMap, HashSet}; use std::env; use std::ffi::{OsStr, OsString}; use std::fs::{self, create_dir_all, File, OpenOptions}; -use std::hash::{Hash, Hasher}; +use std::hash::{DefaultHasher, Hash, Hasher}; use std::io::prelude::*; use std::io::{self, BufReader}; use std::iter; diff --git a/tests/ui/suggestions/import-trait-for-method-call.rs b/tests/ui/suggestions/import-trait-for-method-call.rs index 4dbadbdf9820..feb2c7e84f1d 100644 --- a/tests/ui/suggestions/import-trait-for-method-call.rs +++ b/tests/ui/suggestions/import-trait-for-method-call.rs @@ -1,7 +1,7 @@ use std::hash::BuildHasher; fn next_u64() -> u64 { - let bh = std::collections::hash_map::RandomState::new(); + let bh = std::hash::RandomState::new(); let h = bh.build_hasher(); h.finish() //~ ERROR no method named `finish` found for struct `DefaultHasher` } From 654288bbb7a923658fbafc3f25b93091ed0f61c1 Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Wed, 1 Nov 2023 18:43:04 -0700 Subject: [PATCH 210/435] Remove obsolete support for linking unwinder on Android Linking libgcc is no longer supported (see #103673), so remove the related link attributes and the check in unwind's build.rs. The check was the last remaining significant piece of logic in build.rs, so remove build.rs as well. --- Cargo.lock | 1 - library/unwind/Cargo.toml | 3 --- library/unwind/build.rs | 25 ------------------------- library/unwind/src/lib.rs | 6 +----- 4 files changed, 1 insertion(+), 34 deletions(-) delete mode 100644 library/unwind/build.rs diff --git a/Cargo.lock b/Cargo.lock index 938455782932..7f195422f6da 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5929,7 +5929,6 @@ dependencies = [ name = "unwind" version = "0.0.0" dependencies = [ - "cc", "cfg-if", "compiler_builtins", "core", diff --git a/library/unwind/Cargo.toml b/library/unwind/Cargo.toml index eab2717c4523..9aa552ed81ab 100644 --- a/library/unwind/Cargo.toml +++ b/library/unwind/Cargo.toml @@ -19,9 +19,6 @@ libc = { version = "0.2.79", features = ['rustc-dep-of-std'], default-features = compiler_builtins = "0.1.0" cfg-if = "1.0" -[build-dependencies] -cc = "1.0.76" - [features] # Only applies for Linux and Fuchsia targets diff --git a/library/unwind/build.rs b/library/unwind/build.rs deleted file mode 100644 index 5c3c02fb6ada..000000000000 --- a/library/unwind/build.rs +++ /dev/null @@ -1,25 +0,0 @@ -use std::env; - -fn main() { - println!("cargo:rerun-if-changed=build.rs"); - println!("cargo:rerun-if-env-changed=CARGO_CFG_MIRI"); - - if env::var_os("CARGO_CFG_MIRI").is_some() { - // Miri doesn't need the linker flags or a libunwind build. - return; - } - - let target = env::var("TARGET").expect("TARGET was not set"); - if target.contains("android") { - let build = cc::Build::new(); - - // Since ndk r23 beta 3 `libgcc` was replaced with `libunwind` thus - // check if we have `libunwind` available and if so use it. Otherwise - // fall back to `libgcc` to support older ndk versions. - let has_unwind = build.is_flag_supported("-lunwind").expect("Unable to invoke compiler"); - - if has_unwind { - println!("cargo:rustc-cfg=feature=\"system-llvm-libunwind\""); - } - } -} diff --git a/library/unwind/src/lib.rs b/library/unwind/src/lib.rs index e86408a9ed2b..335bded71c16 100644 --- a/library/unwind/src/lib.rs +++ b/library/unwind/src/lib.rs @@ -76,14 +76,10 @@ cfg_if::cfg_if! { cfg_if::cfg_if! { if #[cfg(feature = "llvm-libunwind")] { compile_error!("`llvm-libunwind` is not supported for Android targets"); - } else if #[cfg(feature = "system-llvm-libunwind")] { + } else { #[link(name = "unwind", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static"))] #[link(name = "unwind", cfg(not(target_feature = "crt-static")))] extern "C" {} - } else { - #[link(name = "gcc", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static"))] - #[link(name = "gcc", cfg(not(target_feature = "crt-static")))] - extern "C" {} } } // Android's unwinding library depends on dl_iterate_phdr in `libdl`. From 4b3ece475d6e77465a30c8b53d7e1e9e861e4b79 Mon Sep 17 00:00:00 2001 From: Gurinder Singh Date: Fri, 3 Nov 2023 07:32:10 +0530 Subject: [PATCH 211/435] Emit explanatory note for move errors in packed struct derives Derive expansions for packed structs cause move errors because they prefer copying over borrowing since borrowing the fields of a packed struct can result in unaligned access and therefore undefined behaviour. This underlying cause of the errors, however, is not apparent to the user. We add a diagnostic note here to remedy that. --- .../src/diagnostics/move_errors.rs | 20 +- .../deriving-with-repr-packed-move-errors.rs | 96 ++++++++++ ...riving-with-repr-packed-move-errors.stderr | 174 ++++++++++++++++++ .../derives/deriving-with-repr-packed.stderr | 1 + 4 files changed, 290 insertions(+), 1 deletion(-) create mode 100644 tests/ui/derives/deriving-with-repr-packed-move-errors.rs create mode 100644 tests/ui/derives/deriving-with-repr-packed-move-errors.stderr diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index 695ac6980cd7..41d6b98d7cfa 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -2,7 +2,7 @@ use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed use rustc_middle::mir::*; use rustc_middle::ty::{self, Ty}; use rustc_mir_dataflow::move_paths::{LookupResult, MovePathIndex}; -use rustc_span::{BytePos, Span}; +use rustc_span::{BytePos, ExpnKind, MacroKind, Span}; use crate::diagnostics::CapturedMessageOpt; use crate::diagnostics::{DescribePlaceOpt, UseSpans}; @@ -488,6 +488,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { args_span, } }); + + self.add_note_for_packed_struct_derive(err, original_path.local); } } } @@ -594,4 +596,20 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { ); } } + + /// Adds an explanatory note if the move error occurs in a derive macro + /// expansion of a packed struct. + /// Such errors happen because derive macro expansions shy away from taking + /// references to the struct's fields since doing so would be undefined behaviour + fn add_note_for_packed_struct_derive(&self, err: &mut Diagnostic, local: Local) { + let local_place: PlaceRef<'tcx> = local.into(); + let local_ty = local_place.ty(self.body.local_decls(), self.infcx.tcx).ty.peel_refs(); + + if let Some(adt) = local_ty.ty_adt_def() + && adt.repr().packed() + && let ExpnKind::Macro(MacroKind::Derive, name) = self.body.span.ctxt().outer_expn_data().kind + { + err.note(format!("`#[derive({name})]` triggers a move because taking references to the fields of a packed struct is undefined behaviour")); + } + } } diff --git a/tests/ui/derives/deriving-with-repr-packed-move-errors.rs b/tests/ui/derives/deriving-with-repr-packed-move-errors.rs new file mode 100644 index 000000000000..ffeb02d78b84 --- /dev/null +++ b/tests/ui/derives/deriving-with-repr-packed-move-errors.rs @@ -0,0 +1,96 @@ +// Check that deriving builtin traits for a packed struct with +// non-Copy fields emits move errors along with an additional +// diagnostic note explaining the reason +// See issue #117406 + +use std::fmt::{Debug, Formatter, Result}; +use std::cmp::Ordering; + +// Packed + derives: additional diagnostic should be emitted +// for each of Debug, PartialEq and PartialOrd +#[repr(packed)] +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)] +struct StructA(String); +//~^ ERROR: cannot move out of `self` which is behind a shared reference +//~| ERROR: cannot move out of `self` which is behind a shared reference +//~| ERROR: cannot move out of `other` which is behind a shared reference +//~| ERROR: cannot move out of `self` which is behind a shared reference +//~| ERROR: cannot move out of `other` which is behind a shared reference +//~| ERROR: cannot move out of `self` which is behind a shared reference +//~| ERROR: cannot move out of `other` which is behind a shared reference +//~| ERROR: cannot move out of `self` which is behind a shared reference +//~| ERROR: cannot move out of `self` which is behind a shared reference + + +// Unrelated impl: additinal diagnostic should NOT be emitted +impl StructA { + fn fmt(&self) -> String { + self.0 //~ ERROR: cannot move out of `self` which is behind a shared reference + } +} + +// Packed + manual impls: additional diagnostic should NOT be emitted +#[repr(packed)] +struct StructB(String); + +impl Debug for StructB { + fn fmt(&self, f: &mut Formatter) -> Result { + let x = &{ self.0 }; //~ ERROR: cannot move out of `self` which is behind a shared reference + write!(f, "{}", x) + } +} + +impl PartialEq for StructB { + fn eq(&self, other: &StructB) -> bool { + ({ self.0 }) == ({ other.0 }) + //~^ ERROR: cannot move out of `self` which is behind a shared reference + //~| ERROR: cannot move out of `other` which is behind a shared reference + } +} + +impl PartialOrd for StructB { + fn partial_cmp(&self, other: &StructB) -> Option { + PartialOrd::partial_cmp(&{ self.0 }, &{ other.0 }) + //~^ ERROR: cannot move out of `self` which is behind a shared reference + //~| ERROR: cannot move out of `other` which is behind a shared reference + } +} + +// NOT packed + derives: additinal diagnostic should NOT be emitted +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)] +struct StructC(String); + +// NOT packed + manual impls: additinal dignostic should NOT be emitted +struct StructD(String); + +impl Debug for StructD { + fn fmt(&self, f: &mut Formatter) -> Result { + let x = &{ self.0 }; //~ ERROR: cannot move out of `self` which is behind a shared reference + write!(f, "{}", x) + } +} + +impl PartialEq for StructD { + fn eq(&self, other: &StructD) -> bool { + ({ self.0 }) == ({ other.0 }) + //~^ ERROR: cannot move out of `self` which is behind a shared reference + //~| ERROR: cannot move out of `other` which is behind a shared reference + } +} + +impl PartialOrd for StructD { + fn partial_cmp(&self, other: &StructD) -> Option { + PartialOrd::partial_cmp(&{ self.0 }, &{ other.0 }) + //~^ ERROR: cannot move out of `self` which is behind a shared reference + //~| ERROR: cannot move out of `other` which is behind a shared reference + } +} + +// Packed + derives but the move is outside of a derive +// expansion: additinal diagnostic should NOT be emitted +fn func(arg: &StructA) -> String { + arg.0 //~ ERROR: cannot move out of `arg` which is behind a shared reference +} + +fn main(){ +} diff --git a/tests/ui/derives/deriving-with-repr-packed-move-errors.stderr b/tests/ui/derives/deriving-with-repr-packed-move-errors.stderr new file mode 100644 index 000000000000..c538061b365e --- /dev/null +++ b/tests/ui/derives/deriving-with-repr-packed-move-errors.stderr @@ -0,0 +1,174 @@ +error[E0507]: cannot move out of `self` which is behind a shared reference + --> $DIR/deriving-with-repr-packed-move-errors.rs:13:16 + | +LL | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)] + | ----- in this derive macro expansion +LL | struct StructA(String); + | ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait + | + = note: `#[derive(Debug)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour + = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0507]: cannot move out of `self` which is behind a shared reference + --> $DIR/deriving-with-repr-packed-move-errors.rs:13:16 + | +LL | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)] + | --------- in this derive macro expansion +LL | struct StructA(String); + | ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait + | + = note: `#[derive(PartialEq)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour + = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0507]: cannot move out of `other` which is behind a shared reference + --> $DIR/deriving-with-repr-packed-move-errors.rs:13:16 + | +LL | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)] + | --------- in this derive macro expansion +LL | struct StructA(String); + | ^^^^^^ move occurs because `other.0` has type `String`, which does not implement the `Copy` trait + | + = note: `#[derive(PartialEq)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour + = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0507]: cannot move out of `self` which is behind a shared reference + --> $DIR/deriving-with-repr-packed-move-errors.rs:13:16 + | +LL | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)] + | ---------- in this derive macro expansion +LL | struct StructA(String); + | ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait + | + = note: `#[derive(PartialOrd)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour + = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0507]: cannot move out of `other` which is behind a shared reference + --> $DIR/deriving-with-repr-packed-move-errors.rs:13:16 + | +LL | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)] + | ---------- in this derive macro expansion +LL | struct StructA(String); + | ^^^^^^ move occurs because `other.0` has type `String`, which does not implement the `Copy` trait + | + = note: `#[derive(PartialOrd)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour + = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0507]: cannot move out of `self` which is behind a shared reference + --> $DIR/deriving-with-repr-packed-move-errors.rs:13:16 + | +LL | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)] + | --- in this derive macro expansion +LL | struct StructA(String); + | ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait + | + = note: `#[derive(Ord)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour + = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0507]: cannot move out of `other` which is behind a shared reference + --> $DIR/deriving-with-repr-packed-move-errors.rs:13:16 + | +LL | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)] + | --- in this derive macro expansion +LL | struct StructA(String); + | ^^^^^^ move occurs because `other.0` has type `String`, which does not implement the `Copy` trait + | + = note: `#[derive(Ord)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour + = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0507]: cannot move out of `self` which is behind a shared reference + --> $DIR/deriving-with-repr-packed-move-errors.rs:13:16 + | +LL | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)] + | ---- in this derive macro expansion +LL | struct StructA(String); + | ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait + | + = note: `#[derive(Hash)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour + = note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0507]: cannot move out of `self` which is behind a shared reference + --> $DIR/deriving-with-repr-packed-move-errors.rs:13:16 + | +LL | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)] + | ----- in this derive macro expansion +LL | struct StructA(String); + | ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait + | + = note: `#[derive(Clone)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour + = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0507]: cannot move out of `self` which is behind a shared reference + --> $DIR/deriving-with-repr-packed-move-errors.rs:28:9 + | +LL | self.0 + | ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of `self` which is behind a shared reference + --> $DIR/deriving-with-repr-packed-move-errors.rs:38:20 + | +LL | let x = &{ self.0 }; + | ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of `self` which is behind a shared reference + --> $DIR/deriving-with-repr-packed-move-errors.rs:45:12 + | +LL | ({ self.0 }) == ({ other.0 }) + | ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of `other` which is behind a shared reference + --> $DIR/deriving-with-repr-packed-move-errors.rs:45:28 + | +LL | ({ self.0 }) == ({ other.0 }) + | ^^^^^^^ move occurs because `other.0` has type `String`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of `self` which is behind a shared reference + --> $DIR/deriving-with-repr-packed-move-errors.rs:53:36 + | +LL | PartialOrd::partial_cmp(&{ self.0 }, &{ other.0 }) + | ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of `other` which is behind a shared reference + --> $DIR/deriving-with-repr-packed-move-errors.rs:53:49 + | +LL | PartialOrd::partial_cmp(&{ self.0 }, &{ other.0 }) + | ^^^^^^^ move occurs because `other.0` has type `String`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of `self` which is behind a shared reference + --> $DIR/deriving-with-repr-packed-move-errors.rs:68:20 + | +LL | let x = &{ self.0 }; + | ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of `self` which is behind a shared reference + --> $DIR/deriving-with-repr-packed-move-errors.rs:75:12 + | +LL | ({ self.0 }) == ({ other.0 }) + | ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of `other` which is behind a shared reference + --> $DIR/deriving-with-repr-packed-move-errors.rs:75:28 + | +LL | ({ self.0 }) == ({ other.0 }) + | ^^^^^^^ move occurs because `other.0` has type `String`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of `self` which is behind a shared reference + --> $DIR/deriving-with-repr-packed-move-errors.rs:83:36 + | +LL | PartialOrd::partial_cmp(&{ self.0 }, &{ other.0 }) + | ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of `other` which is behind a shared reference + --> $DIR/deriving-with-repr-packed-move-errors.rs:83:49 + | +LL | PartialOrd::partial_cmp(&{ self.0 }, &{ other.0 }) + | ^^^^^^^ move occurs because `other.0` has type `String`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of `arg` which is behind a shared reference + --> $DIR/deriving-with-repr-packed-move-errors.rs:92:5 + | +LL | arg.0 + | ^^^^^ move occurs because `arg.0` has type `String`, which does not implement the `Copy` trait + +error: aborting due to 21 previous errors + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/derives/deriving-with-repr-packed.stderr b/tests/ui/derives/deriving-with-repr-packed.stderr index 0cfe03869af1..bb1fab343a3e 100644 --- a/tests/ui/derives/deriving-with-repr-packed.stderr +++ b/tests/ui/derives/deriving-with-repr-packed.stderr @@ -36,6 +36,7 @@ LL | #[repr(packed)] LL | struct X(Y); | ^ move occurs because `self.0` has type `Y`, which does not implement the `Copy` trait | + = note: `#[derive(Debug)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error; 2 warnings emitted From 57f570bb3304402038c906fd6bc79d0f42cfab26 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 3 Nov 2023 07:23:24 +0100 Subject: [PATCH 212/435] clarify that the str invariant is a safety, not validity, invariant --- library/core/src/primitive_docs.rs | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index f3695d16d7a6..a0caa6c8216c 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -291,7 +291,7 @@ mod prim_never {} /// Surrogate code points, used by UTF-16, are in the range 0xD800 to 0xDFFF. /// /// No `char` may be constructed, whether as a literal or at runtime, that is not a -/// Unicode scalar value: +/// Unicode scalar value. Violating this rule causes Undefined Behavior. /// /// ```compile_fail /// // Each of these is a compiler error @@ -308,9 +308,10 @@ mod prim_never {} /// let _ = unsafe { char::from_u32_unchecked(0x110000) }; /// ``` /// -/// USVs are also the exact set of values that may be encoded in UTF-8. Because -/// `char` values are USVs and `str` values are valid UTF-8, it is safe to store -/// any `char` in a `str` or read any character from a `str` as a `char`. +/// USVs are also the exact set of values that may be encoded in UTF-8. Because `char` values are +/// USVs and functions may assume [incoming `str` values are valid +/// UTF-8](primitive.str.html#invariant), it is safe to store any `char` in a `str` or read any +/// character from a `str` as a `char`. /// /// The gap in valid `char` values is understood by the compiler, so in the /// below example the two ranges are understood to cover the whole range of @@ -887,8 +888,6 @@ mod prim_slice {} /// type. It is usually seen in its borrowed form, `&str`. It is also the type /// of string literals, `&'static str`. /// -/// String slices are always valid UTF-8. -/// /// # Basic Usage /// /// String literals are string slices: @@ -942,6 +941,14 @@ mod prim_slice {} /// Note: This example shows the internals of `&str`. `unsafe` should not be /// used to get a string slice under normal circumstances. Use `as_str` /// instead. +/// +/// # Invariant +/// +/// Rust libraries may assume that string slices are always valid UTF-8. +/// +/// Constructing a non-UTF-8 string slice is not immediate Undefined Behavior, but any function +/// called on a string slice may assume that it is valid UTF-8, which means that a non-UTF-8 string +/// slice can lead to Undefined Behaviior down the road. #[stable(feature = "rust1", since = "1.0.0")] mod prim_str {} From 7c09b99ebb2e04b6f37ef30a9030e423438b182b Mon Sep 17 00:00:00 2001 From: George Bateman Date: Fri, 3 Nov 2023 13:16:47 +0000 Subject: [PATCH 213/435] Feature gate enums in offset_of --- compiler/rustc_feature/src/unstable.rs | 2 + compiler/rustc_hir_typeck/src/expr.rs | 9 +++++ compiler/rustc_span/src/symbol.rs | 1 + library/core/src/mem/mod.rs | 2 +- tests/mir-opt/const_prop/offset_of.rs | 2 +- .../feature-gate-offset-of-enum.rs | 15 ++++++++ .../feature-gate-offset-of-enum.stderr | 37 +++++++++++++++++++ tests/ui/offset-of/offset-of-enum.rs | 2 +- tests/ui/offset-of/offset-of-private.rs | 2 +- 9 files changed, 68 insertions(+), 4 deletions(-) create mode 100644 tests/ui/feature-gates/feature-gate-offset-of-enum.rs create mode 100644 tests/ui/feature-gates/feature-gate-offset-of-enum.stderr diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 72100863bb52..fdef9e7f4edf 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -526,6 +526,8 @@ declare_features! ( /// In that case, `dyn Trait: Trait` does not hold. Moreover, coercions and /// casts in safe Rust to `dyn Trait` for such a `Trait` is also forbidden. (unstable, object_safe_for_dispatch, "1.40.0", Some(43561), None), + /// Allows using enums in offset_of! + (unstable, offset_of_enum, "CURRENT_RUSTC_VERSION", Some(106655), None), /// Allows using `#[optimize(X)]`. (unstable, optimize_attribute, "1.34.0", Some(54882), None), /// Allows using `#![plugin(myplugin)]`. diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index bdac886bf9e7..23a8cc4e8ecc 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -3118,6 +3118,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let (ident, _def_scope) = self.tcx.adjust_ident_and_get_scope(field, container_def.did(), block); + if !self.tcx.features().offset_of_enum { + rustc_session::parse::feature_err( + &self.tcx.sess.parse_sess, + sym::offset_of_enum, + ident.span, + "using enums in offset_of is experimental", + ).emit(); + } + let Some((index, variant)) = container_def.variants() .iter_enumerated() .find(|(_, v)| v.ident(self.tcx).normalize_to_macros_2_0() == ident) else { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 6a131c0d78b1..ac8a359dbe7b 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1114,6 +1114,7 @@ symbols! { off, offset, offset_of, + offset_of_enum, omit_gdb_pretty_printer_section, on, on_unimplemented, diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index c88d71f8e548..5559e593f0bd 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -1355,7 +1355,7 @@ impl SizedTypeProperties for T {} /// # Examples /// /// ``` -/// #![feature(offset_of)] +/// #![feature(offset_of, offset_of_enum)] /// /// use std::mem; /// #[repr(C)] diff --git a/tests/mir-opt/const_prop/offset_of.rs b/tests/mir-opt/const_prop/offset_of.rs index 8a5289d58991..2571c3856f46 100644 --- a/tests/mir-opt/const_prop/offset_of.rs +++ b/tests/mir-opt/const_prop/offset_of.rs @@ -2,7 +2,7 @@ // unit-test: ConstProp // EMIT_MIR_FOR_EACH_PANIC_STRATEGY -#![feature(offset_of)] +#![feature(offset_of, offset_of_enum)] use std::marker::PhantomData; use std::mem::offset_of; diff --git a/tests/ui/feature-gates/feature-gate-offset-of-enum.rs b/tests/ui/feature-gates/feature-gate-offset-of-enum.rs new file mode 100644 index 000000000000..e19dcf9f6a54 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-offset-of-enum.rs @@ -0,0 +1,15 @@ +#![feature(offset_of)] + +use std::mem::offset_of; + +enum Alpha { + One(u8), + Two(u8), +} + +fn main() { + offset_of!(Alpha::One, 0); //~ ERROR expected type, found variant `Alpha::One` + offset_of!(Alpha, One); //~ ERROR `One` is an enum variant; expected field at end of `offset_of` + //~| ERROR using enums in offset_of is experimental + offset_of!(Alpha, Two.0); //~ ERROR using enums in offset_of is experimental +} diff --git a/tests/ui/feature-gates/feature-gate-offset-of-enum.stderr b/tests/ui/feature-gates/feature-gate-offset-of-enum.stderr new file mode 100644 index 000000000000..893f78702375 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-offset-of-enum.stderr @@ -0,0 +1,37 @@ +error[E0573]: expected type, found variant `Alpha::One` + --> $DIR/feature-gate-offset-of-enum.rs:11:16 + | +LL | offset_of!(Alpha::One, 0); + | ^^^^^^^^^^ + | | + | not a type + | help: try using the variant's enum: `Alpha` + +error[E0658]: using enums in offset_of is experimental + --> $DIR/feature-gate-offset-of-enum.rs:12:23 + | +LL | offset_of!(Alpha, One); + | ^^^ + | + = note: see issue #106655 for more information + = help: add `#![feature(offset_of_enum)]` to the crate attributes to enable + +error[E0795]: `One` is an enum variant; expected field at end of `offset_of` + --> $DIR/feature-gate-offset-of-enum.rs:12:23 + | +LL | offset_of!(Alpha, One); + | ^^^ enum variant + +error[E0658]: using enums in offset_of is experimental + --> $DIR/feature-gate-offset-of-enum.rs:14:23 + | +LL | offset_of!(Alpha, Two.0); + | ^^^ + | + = note: see issue #106655 for more information + = help: add `#![feature(offset_of_enum)]` to the crate attributes to enable + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0573, E0658, E0795. +For more information about an error, try `rustc --explain E0573`. diff --git a/tests/ui/offset-of/offset-of-enum.rs b/tests/ui/offset-of/offset-of-enum.rs index e8b5a08377bd..a2d6aace47da 100644 --- a/tests/ui/offset-of/offset-of-enum.rs +++ b/tests/ui/offset-of/offset-of-enum.rs @@ -1,4 +1,4 @@ -#![feature(offset_of)] +#![feature(offset_of, offset_of_enum)] use std::mem::offset_of; diff --git a/tests/ui/offset-of/offset-of-private.rs b/tests/ui/offset-of/offset-of-private.rs index 6fa30d63fb86..b7affdb79439 100644 --- a/tests/ui/offset-of/offset-of-private.rs +++ b/tests/ui/offset-of/offset-of-private.rs @@ -1,4 +1,4 @@ -#![feature(offset_of)] +#![feature(offset_of, offset_of_enum)] use std::mem::offset_of; From a723b01ae2d73a43efd445b054a65c75afa5fcba Mon Sep 17 00:00:00 2001 From: George Bateman Date: Fri, 3 Nov 2023 14:58:02 +0000 Subject: [PATCH 214/435] cfg_attr offset_of_enum feature in doctest --- library/core/src/mem/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index 5559e593f0bd..913c446c0782 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -1355,7 +1355,8 @@ impl SizedTypeProperties for T {} /// # Examples /// /// ``` -/// #![feature(offset_of, offset_of_enum)] +/// #![feature(offset_of)] +/// # #![cfg_attr(not(bootstrap), feature(offset_of_enum))] /// /// use std::mem; /// #[repr(C)] From 3984914affa48bb6a65a68844a0ddff498c30512 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 3 Nov 2023 09:17:16 -0700 Subject: [PATCH 215/435] Use `filter_map` in `try_par_for_each_in` This simplifies the expression, especially for the rayon part, and also lets us drop the `E: Copy` constraint. --- compiler/rustc_data_structures/src/sync/parallel.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_data_structures/src/sync/parallel.rs b/compiler/rustc_data_structures/src/sync/parallel.rs index 39dddb595691..5695d839d3eb 100644 --- a/compiler/rustc_data_structures/src/sync/parallel.rs +++ b/compiler/rustc_data_structures/src/sync/parallel.rs @@ -77,12 +77,12 @@ mod disabled { }) } - pub fn try_par_for_each_in( + pub fn try_par_for_each_in( t: T, mut for_each: impl FnMut(T::Item) -> Result<(), E>, ) -> Result<(), E> { parallel_guard(|guard| { - t.into_iter().fold(Ok(()), |ret, i| guard.run(|| for_each(i)).unwrap_or(ret).and(ret)) + t.into_iter().filter_map(|i| guard.run(|| for_each(i))).fold(Ok(()), Result::and) }) } @@ -178,7 +178,7 @@ mod enabled { pub fn try_par_for_each_in< T: IntoIterator + IntoParallelIterator::Item>, - E: Copy + Send, + E: Send, >( t: T, for_each: impl Fn(::Item) -> Result<(), E> + DynSync + DynSend, @@ -187,11 +187,10 @@ mod enabled { if mode::is_dyn_thread_safe() { let for_each = FromDyn::from(for_each); t.into_par_iter() - .fold_with(Ok(()), |ret, i| guard.run(|| for_each(i)).unwrap_or(ret).and(ret)) - .reduce(|| Ok(()), |a, b| a.and(b)) + .filter_map(|i| guard.run(|| for_each(i))) + .reduce(|| Ok(()), Result::and) } else { - t.into_iter() - .fold(Ok(()), |ret, i| guard.run(|| for_each(i)).unwrap_or(ret).and(ret)) + t.into_iter().filter_map(|i| guard.run(|| for_each(i))).fold(Ok(()), Result::and) } }) } From ee3a729cc440e5dbc589acc4c19e92d6e0f305c9 Mon Sep 17 00:00:00 2001 From: George Bateman Date: Fri, 3 Nov 2023 17:08:32 +0000 Subject: [PATCH 216/435] enable feature gate in E0795.md --- compiler/rustc_error_codes/src/error_codes/E0795.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0795.md b/compiler/rustc_error_codes/src/error_codes/E0795.md index 8b4b2dc87fd7..20f51441c291 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0795.md +++ b/compiler/rustc_error_codes/src/error_codes/E0795.md @@ -3,7 +3,7 @@ Invalid argument for the `offset_of!` macro. Erroneous code example: ```compile_fail,E0795 -#![feature(offset_of)] +#![feature(offset_of, offset_of_enum)] let x = std::mem::offset_of!(Option, Some); ``` @@ -16,7 +16,7 @@ The offset of the contained `u8` in the `Option` can be found by specifying the field name `0`: ``` -#![feature(offset_of)] +#![feature(offset_of, offset_of_enum)] let x: usize = std::mem::offset_of!(Option, Some.0); ``` From 335156ca732ec32fc3fb82b44516f8fa25d19576 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sun, 29 Oct 2023 09:20:15 +0100 Subject: [PATCH 217/435] Accumulate let chains alongside the visit --- .../src/thir/pattern/check_match.rs | 154 +++++++++--------- 1 file changed, 78 insertions(+), 76 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index eadd7a310b71..d94272bcc796 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -56,7 +56,7 @@ fn create_e0004( struct_span_err!(sess, sp, E0004, "{}", &error_message) } -#[derive(Copy, Clone, PartialEq)] +#[derive(Debug, Copy, Clone, PartialEq)] enum RefutableFlag { Irrefutable, Refutable, @@ -151,18 +151,22 @@ impl<'thir, 'tcx> Visitor<'thir, 'tcx> for MatchVisitor<'thir, '_, 'tcx> { }; self.check_match(scrutinee, arms, source, ex.span); } - ExprKind::Let { box ref pat, expr } if !matches!(self.let_source, LetSource::None) => { + ExprKind::Let { box ref pat, expr } => { self.check_let(pat, Some(expr), ex.span); } ExprKind::LogicalOp { op: LogicalOp::And, .. } if !matches!(self.let_source, LetSource::None) => { - self.check_let_chain(ex); + let mut chain_refutabilities = Vec::new(); + let Ok(()) = self.visit_land(ex, &mut chain_refutabilities) else { return }; + // If at least one of the operands is a `let ... = ...`. + if chain_refutabilities.iter().any(|x| x.is_some()) { + self.check_let_chain(chain_refutabilities, ex.span); + } + return; } _ => {} }; - // If we got e.g. `let pat1 = x1 && let pat2 = x2` above, we will now traverse the two - // `let`s. In order not to check them twice we set `LetSource::None`. self.with_let_source(LetSource::None, |this| visit::walk_expr(this, ex)); } @@ -212,6 +216,58 @@ impl<'thir, 'p, 'tcx> MatchVisitor<'thir, 'p, 'tcx> { } } + /// Visit a nested chain of `&&`. Used for if-let chains. This must call `visit_expr` on the + /// subexpressions we are not handling ourselves. + fn visit_land( + &mut self, + ex: &Expr<'tcx>, + accumulator: &mut Vec>, + ) -> Result<(), ErrorGuaranteed> { + match ex.kind { + ExprKind::Scope { value, lint_level, .. } => self.with_lint_level(lint_level, |this| { + this.visit_land(&this.thir[value], accumulator) + }), + ExprKind::LogicalOp { op: LogicalOp::And, lhs, rhs } => { + // We recurse into the lhs only, because `&&` chains associate to the left. + let res_lhs = self.visit_land(&self.thir[lhs], accumulator); + let res_rhs = self.visit_land_rhs(&self.thir[rhs])?; + accumulator.push(res_rhs); + res_lhs + } + _ => { + let res = self.visit_land_rhs(ex)?; + accumulator.push(res); + Ok(()) + } + } + } + + /// Visit the right-hand-side of a `&&`. Used for if-let chains. Returns `Some` if the + /// expression was ultimately a `let ... = ...`, and `None` if it was a normal boolean + /// expression. This must call `visit_expr` on the subexpressions we are not handling ourselves. + fn visit_land_rhs( + &mut self, + ex: &Expr<'tcx>, + ) -> Result, ErrorGuaranteed> { + match ex.kind { + ExprKind::Scope { value, lint_level, .. } => { + self.with_lint_level(lint_level, |this| this.visit_land_rhs(&this.thir[value])) + } + ExprKind::Let { box ref pat, expr } => { + self.with_let_source(LetSource::None, |this| { + this.visit_expr(&this.thir()[expr]); + }); + Ok(Some((ex.span, self.is_let_irrefutable(pat)?))) + } + _ => { + self.with_let_source(LetSource::None, |this| { + this.visit_expr(ex); + }); + Ok(None) + } + } + } + fn lower_pattern( &mut self, cx: &MatchCheckCtxt<'p, 'tcx>, @@ -249,8 +305,8 @@ impl<'thir, 'p, 'tcx> MatchVisitor<'thir, 'p, 'tcx> { if let LetSource::PlainLet = self.let_source { self.check_binding_is_irrefutable(pat, "local binding", Some(span)) } else { - let Ok(irrefutable) = self.is_let_irrefutable(pat) else { return }; - if irrefutable { + let Ok(refutability) = self.is_let_irrefutable(pat) else { return }; + if matches!(refutability, Irrefutable) { report_irrefutable_let_patterns( self.tcx, self.lint_level, @@ -321,81 +377,27 @@ impl<'thir, 'p, 'tcx> MatchVisitor<'thir, 'p, 'tcx> { } #[instrument(level = "trace", skip(self))] - fn check_let_chain(&mut self, expr: &Expr<'tcx>) { + fn check_let_chain( + &mut self, + chain_refutabilities: Vec>, + whole_chain_span: Span, + ) { assert!(self.let_source != LetSource::None); - let top_expr_span = expr.span; - // Lint level enclosing `next_expr`. - let mut next_expr_lint_level = self.lint_level; - - // Obtain the refutabilities of all exprs in the chain, - // and record chain members that aren't let exprs. - let mut chain_refutabilities = Vec::new(); - - let mut got_error = false; - let mut next_expr = Some(expr); - while let Some(mut expr) = next_expr { - while let ExprKind::Scope { value, lint_level, .. } = expr.kind { - if let LintLevel::Explicit(hir_id) = lint_level { - next_expr_lint_level = hir_id - } - expr = &self.thir[value]; - } - if let ExprKind::LogicalOp { op: LogicalOp::And, lhs, rhs } = expr.kind { - expr = &self.thir[rhs]; - // Let chains recurse on the left, so we recurse into the lhs. - next_expr = Some(&self.thir[lhs]); - } else { - next_expr = None; - } - - // Lint level enclosing `expr`. - let mut expr_lint_level = next_expr_lint_level; - // Fast-forward through scopes. - while let ExprKind::Scope { value, lint_level, .. } = expr.kind { - if let LintLevel::Explicit(hir_id) = lint_level { - expr_lint_level = hir_id - } - expr = &self.thir[value]; - } - let value = match expr.kind { - ExprKind::Let { box ref pat, expr: _ } => { - self.with_lint_level(LintLevel::Explicit(expr_lint_level), |this| { - match this.is_let_irrefutable(pat) { - Ok(irrefutable) => Some((expr.span, !irrefutable)), - Err(_) => { - got_error = true; - None - } - } - }) - } - _ => None, - }; - chain_refutabilities.push(value); - } - debug!(?chain_refutabilities); - chain_refutabilities.reverse(); - - if got_error { - return; - } - - // Emit the actual warnings. - if chain_refutabilities.iter().all(|r| matches!(*r, Some((_, false)))) { + if chain_refutabilities.iter().all(|r| matches!(*r, Some((_, Irrefutable)))) { // The entire chain is made up of irrefutable `let` statements report_irrefutable_let_patterns( self.tcx, self.lint_level, self.let_source, chain_refutabilities.len(), - top_expr_span, + whole_chain_span, ); return; } if let Some(until) = - chain_refutabilities.iter().position(|r| !matches!(*r, Some((_, false)))) + chain_refutabilities.iter().position(|r| !matches!(*r, Some((_, Irrefutable)))) && until > 0 { // The chain has a non-zero prefix of irrefutable `let` statements. @@ -423,7 +425,7 @@ impl<'thir, 'p, 'tcx> MatchVisitor<'thir, 'p, 'tcx> { } if let Some(from) = - chain_refutabilities.iter().rposition(|r| !matches!(*r, Some((_, false)))) + chain_refutabilities.iter().rposition(|r| !matches!(*r, Some((_, Irrefutable)))) && from != (chain_refutabilities.len() - 1) { // The chain has a non-empty suffix of irrefutable `let` statements @@ -453,14 +455,14 @@ impl<'thir, 'p, 'tcx> MatchVisitor<'thir, 'p, 'tcx> { Ok((cx, report)) } - fn is_let_irrefutable(&mut self, pat: &Pat<'tcx>) -> Result { + fn is_let_irrefutable(&mut self, pat: &Pat<'tcx>) -> Result { let (cx, report) = self.analyze_binding(pat, Refutable)?; - // Report if the pattern is unreachable, which can only occur when the type is - // uninhabited. This also reports unreachable sub-patterns. + // Report if the pattern is unreachable, which can only occur when the type is uninhabited. + // This also reports unreachable sub-patterns. report_arm_reachability(&cx, &report); - // If the list of witnesses is empty, the match is exhaustive, - // i.e. the `if let` pattern is irrefutable. - Ok(report.non_exhaustiveness_witnesses.is_empty()) + // If the list of witnesses is empty, the match is exhaustive, i.e. the `if let` pattern is + // irrefutable. + Ok(if report.non_exhaustiveness_witnesses.is_empty() { Irrefutable } else { Refutable }) } #[instrument(level = "trace", skip(self))] From 746197c08a737828353a5ace272b0fa92dcd578a Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sun, 29 Oct 2023 06:50:59 +0100 Subject: [PATCH 218/435] Tweak spans for "adt defined here" note --- .../src/thir/pattern/check_match.rs | 7 +-- .../match/non-exhaustive-match.stderr | 4 +- tests/ui/error-codes/E0004.stderr | 6 +-- ...on_exhaustive_omitted_patterns_lint.stderr | 6 +-- tests/ui/match/match_non_exhaustive.stderr | 4 +- tests/ui/pattern/issue-94866.stderr | 4 +- .../doc-hidden-non-exhaustive.stderr | 18 +++---- .../empty-match.exhaustive_patterns.stderr | 46 +++++++++------- .../usefulness/empty-match.normal.stderr | 46 +++++++++------- tests/ui/pattern/usefulness/empty-match.rs | 12 ++--- .../ui/pattern/usefulness/issue-39362.stderr | 6 +-- .../ui/pattern/usefulness/issue-40221.stderr | 6 +-- .../ui/pattern/usefulness/issue-56379.stderr | 10 ++-- .../usefulness/non-exhaustive-defined-here.rs | 18 ++++--- .../non-exhaustive-defined-here.stderr | 54 +++++++++---------- .../non-exhaustive-match-nested.stderr | 4 +- .../usefulness/non-exhaustive-match.stderr | 8 +-- .../non-exhaustive-pattern-witness.stderr | 36 ++++++------- .../usefulness/stable-gated-patterns.stderr | 6 +-- .../struct-like-enum-nonexhaustive.stderr | 6 +-- .../usefulness/unstable-gated-patterns.stderr | 6 +-- .../enum_same_crate_empty_match.stderr | 20 +++---- .../uninhabited/match.stderr | 8 +-- .../uninhabited/match_same_crate.stderr | 8 +-- .../match_with_exhaustive_patterns.stderr | 8 +-- 25 files changed, 183 insertions(+), 174 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index d94272bcc796..165d3f37111e 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -830,12 +830,7 @@ fn report_non_exhaustive_match<'p, 'tcx>( if let Some(AdtDefinedHere { adt_def_span, ty, variants }) = report_adt_defined_here(cx.tcx, scrut_ty, &witnesses, true) { - let mut multi_span = if variants.is_empty() { - MultiSpan::from_span(adt_def_span) - } else { - MultiSpan::from_spans(variants.iter().map(|Variant { span }| *span).collect()) - }; - + let mut multi_span = MultiSpan::from_span(adt_def_span); multi_span.push_span_label(adt_def_span, ""); for Variant { span } in variants { multi_span.push_span_label(span, "not covered"); diff --git a/tests/ui/closures/2229_closure_analysis/match/non-exhaustive-match.stderr b/tests/ui/closures/2229_closure_analysis/match/non-exhaustive-match.stderr index 0807f4590298..85426dd9a5ea 100644 --- a/tests/ui/closures/2229_closure_analysis/match/non-exhaustive-match.stderr +++ b/tests/ui/closures/2229_closure_analysis/match/non-exhaustive-match.stderr @@ -5,10 +5,10 @@ LL | let _b = || { match l1 { L1::A => () } }; | ^^ pattern `L1::B` not covered | note: `L1` defined here - --> $DIR/non-exhaustive-match.rs:12:14 + --> $DIR/non-exhaustive-match.rs:12:6 | LL | enum L1 { A, B } - | -- ^ not covered + | ^^ - not covered = note: the matched value is of type `L1` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | diff --git a/tests/ui/error-codes/E0004.stderr b/tests/ui/error-codes/E0004.stderr index 603bc5237ea2..ced478d65eae 100644 --- a/tests/ui/error-codes/E0004.stderr +++ b/tests/ui/error-codes/E0004.stderr @@ -5,12 +5,12 @@ LL | match x { | ^ pattern `Terminator::HastaLaVistaBaby` not covered | note: `Terminator` defined here - --> $DIR/E0004.rs:2:5 + --> $DIR/E0004.rs:1:6 | LL | enum Terminator { - | ---------- + | ^^^^^^^^^^ LL | HastaLaVistaBaby, - | ^^^^^^^^^^^^^^^^ not covered + | ---------------- not covered = note: the matched value is of type `Terminator` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | diff --git a/tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr b/tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr index eb61c4cf159a..8af0eedc82b1 100644 --- a/tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr +++ b/tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr @@ -134,13 +134,13 @@ LL | match Foo::A { | ^^^^^^ pattern `Foo::C` not covered | note: `Foo` defined here - --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:16:9 + --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:13:10 | LL | enum Foo { - | --- + | ^^^ ... LL | C, - | ^ not covered + | - not covered = note: the matched value is of type `Foo` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | diff --git a/tests/ui/match/match_non_exhaustive.stderr b/tests/ui/match/match_non_exhaustive.stderr index 7b8bdfe0053a..40be39ec0774 100644 --- a/tests/ui/match/match_non_exhaustive.stderr +++ b/tests/ui/match/match_non_exhaustive.stderr @@ -5,10 +5,10 @@ LL | match l { L::A => () }; | ^ pattern `L::B` not covered | note: `L` defined here - --> $DIR/match_non_exhaustive.rs:10:13 + --> $DIR/match_non_exhaustive.rs:10:6 | LL | enum L { A, B } - | - ^ not covered + | ^ - not covered = note: the matched value is of type `L` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | diff --git a/tests/ui/pattern/issue-94866.stderr b/tests/ui/pattern/issue-94866.stderr index b3c17ce8974d..dee4b3f557c7 100644 --- a/tests/ui/pattern/issue-94866.stderr +++ b/tests/ui/pattern/issue-94866.stderr @@ -5,10 +5,10 @@ LL | match Enum::A { | ^^^^^^^ pattern `Enum::B` not covered | note: `Enum` defined here - --> $DIR/issue-94866.rs:7:16 + --> $DIR/issue-94866.rs:7:6 | LL | enum Enum { A, B } - | ---- ^ not covered + | ^^^^ - not covered = note: the matched value is of type `Enum` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | diff --git a/tests/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr b/tests/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr index ff29de03d6b3..24f3eaa5230d 100644 --- a/tests/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr +++ b/tests/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr @@ -23,13 +23,13 @@ LL | match HiddenEnum::A { | ^^^^^^^^^^^^^ pattern `HiddenEnum::B` not covered | note: `HiddenEnum` defined here - --> $DIR/auxiliary/hidden.rs:3:5 + --> $DIR/auxiliary/hidden.rs:1:1 | LL | pub enum HiddenEnum { - | ------------------- + | ^^^^^^^^^^^^^^^^^^^ LL | A, LL | B, - | ^ not covered + | - not covered = note: the matched value is of type `HiddenEnum` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | @@ -44,13 +44,13 @@ LL | match HiddenEnum::A { | ^^^^^^^^^^^^^ patterns `HiddenEnum::B` and `_` not covered | note: `HiddenEnum` defined here - --> $DIR/auxiliary/hidden.rs:3:5 + --> $DIR/auxiliary/hidden.rs:1:1 | LL | pub enum HiddenEnum { - | ------------------- + | ^^^^^^^^^^^^^^^^^^^ LL | A, LL | B, - | ^ not covered + | - not covered = note: the matched value is of type `HiddenEnum` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | @@ -83,13 +83,13 @@ LL | match InCrate::A { | ^^^^^^^^^^ pattern `InCrate::C` not covered | note: `InCrate` defined here - --> $DIR/doc-hidden-non-exhaustive.rs:11:5 + --> $DIR/doc-hidden-non-exhaustive.rs:7:6 | LL | enum InCrate { - | ------- + | ^^^^^^^ ... LL | C, - | ^ not covered + | - not covered = note: the matched value is of type `InCrate` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | diff --git a/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr index fce1d8d19280..8f9bd5bde89a 100644 --- a/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr +++ b/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr @@ -127,12 +127,13 @@ LL | match_no_arms!(NonEmptyEnum1::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered | note: `NonEmptyEnum1` defined here - --> $DIR/empty-match.rs:33:5 + --> $DIR/empty-match.rs:32:6 | LL | enum NonEmptyEnum1 { - | ------------- + | ^^^^^^^^^^^^^ +... LL | Foo(bool), - | ^^^ not covered + | --- not covered = note: the matched value is of type `NonEmptyEnum1` = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern @@ -143,15 +144,16 @@ LL | match_no_arms!(NonEmptyEnum2::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered | note: `NonEmptyEnum2` defined here - --> $DIR/empty-match.rs:40:5 + --> $DIR/empty-match.rs:39:6 | LL | enum NonEmptyEnum2 { - | ------------- + | ^^^^^^^^^^^^^ +... LL | Foo(bool), - | ^^^ not covered + | --- not covered ... LL | Bar, - | ^^^ not covered + | --- not covered = note: the matched value is of type `NonEmptyEnum2` = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms @@ -162,12 +164,13 @@ LL | match_no_arms!(NonEmptyEnum5::V1); | ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered | note: `NonEmptyEnum5` defined here - --> $DIR/empty-match.rs:50:5 + --> $DIR/empty-match.rs:49:6 | LL | enum NonEmptyEnum5 { - | ------------- + | ^^^^^^^^^^^^^ +... LL | V1, V2, V3, V4, V5, - | ^^ ^^ ^^ ^^ ^^ not covered + | -- -- -- -- -- not covered | | | | | | | | | not covered | | | not covered @@ -273,12 +276,13 @@ LL | match_guarded_arm!(NonEmptyEnum1::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered | note: `NonEmptyEnum1` defined here - --> $DIR/empty-match.rs:33:5 + --> $DIR/empty-match.rs:32:6 | LL | enum NonEmptyEnum1 { - | ------------- + | ^^^^^^^^^^^^^ +... LL | Foo(bool), - | ^^^ not covered + | --- not covered = note: the matched value is of type `NonEmptyEnum1` = note: match arms with guards don't count towards exhaustivity help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown @@ -294,15 +298,16 @@ LL | match_guarded_arm!(NonEmptyEnum2::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered | note: `NonEmptyEnum2` defined here - --> $DIR/empty-match.rs:40:5 + --> $DIR/empty-match.rs:39:6 | LL | enum NonEmptyEnum2 { - | ------------- + | ^^^^^^^^^^^^^ +... LL | Foo(bool), - | ^^^ not covered + | --- not covered ... LL | Bar, - | ^^^ not covered + | --- not covered = note: the matched value is of type `NonEmptyEnum2` = note: match arms with guards don't count towards exhaustivity help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms @@ -318,12 +323,13 @@ LL | match_guarded_arm!(NonEmptyEnum5::V1); | ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered | note: `NonEmptyEnum5` defined here - --> $DIR/empty-match.rs:50:5 + --> $DIR/empty-match.rs:49:6 | LL | enum NonEmptyEnum5 { - | ------------- + | ^^^^^^^^^^^^^ +... LL | V1, V2, V3, V4, V5, - | ^^ ^^ ^^ ^^ ^^ not covered + | -- -- -- -- -- not covered | | | | | | | | | not covered | | | not covered diff --git a/tests/ui/pattern/usefulness/empty-match.normal.stderr b/tests/ui/pattern/usefulness/empty-match.normal.stderr index 97aac68c8d93..7f0389f40e23 100644 --- a/tests/ui/pattern/usefulness/empty-match.normal.stderr +++ b/tests/ui/pattern/usefulness/empty-match.normal.stderr @@ -126,12 +126,13 @@ LL | match_no_arms!(NonEmptyEnum1::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered | note: `NonEmptyEnum1` defined here - --> $DIR/empty-match.rs:33:5 + --> $DIR/empty-match.rs:32:6 | LL | enum NonEmptyEnum1 { - | ------------- + | ^^^^^^^^^^^^^ +... LL | Foo(bool), - | ^^^ not covered + | --- not covered = note: the matched value is of type `NonEmptyEnum1` = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern @@ -142,15 +143,16 @@ LL | match_no_arms!(NonEmptyEnum2::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered | note: `NonEmptyEnum2` defined here - --> $DIR/empty-match.rs:40:5 + --> $DIR/empty-match.rs:39:6 | LL | enum NonEmptyEnum2 { - | ------------- + | ^^^^^^^^^^^^^ +... LL | Foo(bool), - | ^^^ not covered + | --- not covered ... LL | Bar, - | ^^^ not covered + | --- not covered = note: the matched value is of type `NonEmptyEnum2` = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms @@ -161,12 +163,13 @@ LL | match_no_arms!(NonEmptyEnum5::V1); | ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered | note: `NonEmptyEnum5` defined here - --> $DIR/empty-match.rs:50:5 + --> $DIR/empty-match.rs:49:6 | LL | enum NonEmptyEnum5 { - | ------------- + | ^^^^^^^^^^^^^ +... LL | V1, V2, V3, V4, V5, - | ^^ ^^ ^^ ^^ ^^ not covered + | -- -- -- -- -- not covered | | | | | | | | | not covered | | | not covered @@ -272,12 +275,13 @@ LL | match_guarded_arm!(NonEmptyEnum1::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered | note: `NonEmptyEnum1` defined here - --> $DIR/empty-match.rs:33:5 + --> $DIR/empty-match.rs:32:6 | LL | enum NonEmptyEnum1 { - | ------------- + | ^^^^^^^^^^^^^ +... LL | Foo(bool), - | ^^^ not covered + | --- not covered = note: the matched value is of type `NonEmptyEnum1` = note: match arms with guards don't count towards exhaustivity help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown @@ -293,15 +297,16 @@ LL | match_guarded_arm!(NonEmptyEnum2::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered | note: `NonEmptyEnum2` defined here - --> $DIR/empty-match.rs:40:5 + --> $DIR/empty-match.rs:39:6 | LL | enum NonEmptyEnum2 { - | ------------- + | ^^^^^^^^^^^^^ +... LL | Foo(bool), - | ^^^ not covered + | --- not covered ... LL | Bar, - | ^^^ not covered + | --- not covered = note: the matched value is of type `NonEmptyEnum2` = note: match arms with guards don't count towards exhaustivity help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms @@ -317,12 +322,13 @@ LL | match_guarded_arm!(NonEmptyEnum5::V1); | ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered | note: `NonEmptyEnum5` defined here - --> $DIR/empty-match.rs:50:5 + --> $DIR/empty-match.rs:49:6 | LL | enum NonEmptyEnum5 { - | ------------- + | ^^^^^^^^^^^^^ +... LL | V1, V2, V3, V4, V5, - | ^^ ^^ ^^ ^^ ^^ not covered + | -- -- -- -- -- not covered | | | | | | | | | not covered | | | not covered diff --git a/tests/ui/pattern/usefulness/empty-match.rs b/tests/ui/pattern/usefulness/empty-match.rs index 6551900bbc6c..fe5d0bce14fe 100644 --- a/tests/ui/pattern/usefulness/empty-match.rs +++ b/tests/ui/pattern/usefulness/empty-match.rs @@ -30,27 +30,27 @@ union NonEmptyUnion2 { bar: (), } enum NonEmptyEnum1 { - Foo(bool), //~^ NOTE `NonEmptyEnum1` defined here //~| NOTE `NonEmptyEnum1` defined here - //~| NOTE not covered + Foo(bool), + //~^ NOTE not covered //~| NOTE not covered } enum NonEmptyEnum2 { - Foo(bool), //~^ NOTE `NonEmptyEnum2` defined here //~| NOTE `NonEmptyEnum2` defined here - //~| NOTE not covered + Foo(bool), + //~^ NOTE not covered //~| NOTE not covered Bar, //~^ NOTE not covered //~| NOTE not covered } enum NonEmptyEnum5 { - V1, V2, V3, V4, V5, //~^ NOTE `NonEmptyEnum5` defined here //~| NOTE `NonEmptyEnum5` defined here - //~| NOTE not covered + V1, V2, V3, V4, V5, + //~^ NOTE not covered //~| NOTE not covered //~| NOTE not covered //~| NOTE not covered diff --git a/tests/ui/pattern/usefulness/issue-39362.stderr b/tests/ui/pattern/usefulness/issue-39362.stderr index b8b17918aef8..8dc534916061 100644 --- a/tests/ui/pattern/usefulness/issue-39362.stderr +++ b/tests/ui/pattern/usefulness/issue-39362.stderr @@ -5,12 +5,12 @@ LL | match f { | ^ patterns `Foo::Bar { bar: Bar::C, .. }`, `Foo::Bar { bar: Bar::D, .. }`, `Foo::Bar { bar: Bar::E, .. }` and 1 more not covered | note: `Foo` defined here - --> $DIR/issue-39362.rs:2:5 + --> $DIR/issue-39362.rs:1:6 | LL | enum Foo { - | --- + | ^^^ LL | Bar { bar: Bar, id: usize } - | ^^^ not covered + | --- not covered = note: the matched value is of type `Foo` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms | diff --git a/tests/ui/pattern/usefulness/issue-40221.stderr b/tests/ui/pattern/usefulness/issue-40221.stderr index 4973e42b0544..40b42af26b34 100644 --- a/tests/ui/pattern/usefulness/issue-40221.stderr +++ b/tests/ui/pattern/usefulness/issue-40221.stderr @@ -5,12 +5,12 @@ LL | match proto { | ^^^^^ pattern `P::C(PC::QA)` not covered | note: `P` defined here - --> $DIR/issue-40221.rs:2:5 + --> $DIR/issue-40221.rs:1:6 | LL | enum P { - | - + | ^ LL | C(PC), - | ^ not covered + | - not covered = note: the matched value is of type `P` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | diff --git a/tests/ui/pattern/usefulness/issue-56379.stderr b/tests/ui/pattern/usefulness/issue-56379.stderr index b3e40b992399..50e13bdfdfed 100644 --- a/tests/ui/pattern/usefulness/issue-56379.stderr +++ b/tests/ui/pattern/usefulness/issue-56379.stderr @@ -5,16 +5,16 @@ LL | match Foo::A(true) { | ^^^^^^^^^^^^ patterns `Foo::A(false)`, `Foo::B(false)` and `Foo::C(false)` not covered | note: `Foo` defined here - --> $DIR/issue-56379.rs:2:5 + --> $DIR/issue-56379.rs:1:6 | LL | enum Foo { - | --- + | ^^^ LL | A(bool), - | ^ not covered + | - not covered LL | B(bool), - | ^ not covered + | - not covered LL | C(bool), - | ^ not covered + | - not covered = note: the matched value is of type `Foo` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | diff --git a/tests/ui/pattern/usefulness/non-exhaustive-defined-here.rs b/tests/ui/pattern/usefulness/non-exhaustive-defined-here.rs index 5145f769075d..1d1ea8e49646 100644 --- a/tests/ui/pattern/usefulness/non-exhaustive-defined-here.rs +++ b/tests/ui/pattern/usefulness/non-exhaustive-defined-here.rs @@ -1,10 +1,15 @@ +#![feature(custom_inner_attributes)] +#![rustfmt::skip] // Test the "defined here" and "not covered" diagnostic hints. // We also make sure that references are peeled off from the scrutinee type // so that the diagnostics work better with default binding modes. #[derive(Clone)] enum E { - //~^ NOTE + //~^ NOTE `E` defined here + //~| NOTE `E` defined here + //~| NOTE `E` defined here + //~| NOTE //~| NOTE //~| NOTE //~| NOTE @@ -12,10 +17,7 @@ enum E { //~| NOTE A, B, - //~^ NOTE `E` defined here - //~| NOTE `E` defined here - //~| NOTE `E` defined here - //~| NOTE not covered + //~^ NOTE not covered //~| NOTE not covered //~| NOTE not covered //~| NOTE not covered @@ -79,12 +81,12 @@ fn by_ref_thrice(e: & &mut &E) { } enum Opt { - //~^ NOTE + //~^ NOTE `Opt` defined here + //~| NOTE //~| NOTE Some(u8), None, - //~^ NOTE `Opt` defined here - //~| NOTE not covered + //~^ NOTE not covered //~| NOTE not covered } diff --git a/tests/ui/pattern/usefulness/non-exhaustive-defined-here.stderr b/tests/ui/pattern/usefulness/non-exhaustive-defined-here.stderr index 8489e2f14b87..a9e55fa53a68 100644 --- a/tests/ui/pattern/usefulness/non-exhaustive-defined-here.stderr +++ b/tests/ui/pattern/usefulness/non-exhaustive-defined-here.stderr @@ -1,20 +1,20 @@ error[E0004]: non-exhaustive patterns: `E::B` and `E::C` not covered - --> $DIR/non-exhaustive-defined-here.rs:35:11 + --> $DIR/non-exhaustive-defined-here.rs:37:11 | LL | match e1 { | ^^ patterns `E::B` and `E::C` not covered | note: `E` defined here - --> $DIR/non-exhaustive-defined-here.rs:14:5 + --> $DIR/non-exhaustive-defined-here.rs:8:6 | LL | enum E { - | - + | ^ ... LL | B, - | ^ not covered + | - not covered ... LL | C - | ^ not covered + | - not covered = note: the matched value is of type `E` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | @@ -23,7 +23,7 @@ LL + E::B | E::C => todo!() | error[E0005]: refutable pattern in local binding - --> $DIR/non-exhaustive-defined-here.rs:41:9 + --> $DIR/non-exhaustive-defined-here.rs:43:9 | LL | let E::A = e; | ^^^^ patterns `E::B` and `E::C` not covered @@ -31,7 +31,7 @@ LL | let E::A = e; = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html note: `E` defined here - --> $DIR/non-exhaustive-defined-here.rs:6:6 + --> $DIR/non-exhaustive-defined-here.rs:8:6 | LL | enum E { | ^ @@ -48,22 +48,22 @@ LL | if let E::A = e { todo!() }; | ++ +++++++++++ error[E0004]: non-exhaustive patterns: `&E::B` and `&E::C` not covered - --> $DIR/non-exhaustive-defined-here.rs:50:11 + --> $DIR/non-exhaustive-defined-here.rs:52:11 | LL | match e { | ^ patterns `&E::B` and `&E::C` not covered | note: `E` defined here - --> $DIR/non-exhaustive-defined-here.rs:14:5 + --> $DIR/non-exhaustive-defined-here.rs:8:6 | LL | enum E { - | - + | ^ ... LL | B, - | ^ not covered + | - not covered ... LL | C - | ^ not covered + | - not covered = note: the matched value is of type `&E` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | @@ -72,7 +72,7 @@ LL + &E::B | &E::C => todo!() | error[E0005]: refutable pattern in local binding - --> $DIR/non-exhaustive-defined-here.rs:57:9 + --> $DIR/non-exhaustive-defined-here.rs:59:9 | LL | let E::A = e; | ^^^^ patterns `&E::B` and `&E::C` not covered @@ -80,7 +80,7 @@ LL | let E::A = e; = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html note: `E` defined here - --> $DIR/non-exhaustive-defined-here.rs:6:6 + --> $DIR/non-exhaustive-defined-here.rs:8:6 | LL | enum E { | ^ @@ -97,22 +97,22 @@ LL | if let E::A = e { todo!() }; | ++ +++++++++++ error[E0004]: non-exhaustive patterns: `&&mut &E::B` and `&&mut &E::C` not covered - --> $DIR/non-exhaustive-defined-here.rs:66:11 + --> $DIR/non-exhaustive-defined-here.rs:68:11 | LL | match e { | ^ patterns `&&mut &E::B` and `&&mut &E::C` not covered | note: `E` defined here - --> $DIR/non-exhaustive-defined-here.rs:14:5 + --> $DIR/non-exhaustive-defined-here.rs:8:6 | LL | enum E { - | - + | ^ ... LL | B, - | ^ not covered + | - not covered ... LL | C - | ^ not covered + | - not covered = note: the matched value is of type `&&mut &E` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | @@ -121,7 +121,7 @@ LL + &&mut &E::B | &&mut &E::C => todo!() | error[E0005]: refutable pattern in local binding - --> $DIR/non-exhaustive-defined-here.rs:73:9 + --> $DIR/non-exhaustive-defined-here.rs:75:9 | LL | let E::A = e; | ^^^^ patterns `&&mut &E::B` and `&&mut &E::C` not covered @@ -129,7 +129,7 @@ LL | let E::A = e; = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html note: `E` defined here - --> $DIR/non-exhaustive-defined-here.rs:6:6 + --> $DIR/non-exhaustive-defined-here.rs:8:6 | LL | enum E { | ^ @@ -146,19 +146,19 @@ LL | if let E::A = e { todo!() }; | ++ +++++++++++ error[E0004]: non-exhaustive patterns: `Opt::None` not covered - --> $DIR/non-exhaustive-defined-here.rs:92:11 + --> $DIR/non-exhaustive-defined-here.rs:94:11 | LL | match e { | ^ pattern `Opt::None` not covered | note: `Opt` defined here - --> $DIR/non-exhaustive-defined-here.rs:85:5 + --> $DIR/non-exhaustive-defined-here.rs:83:6 | LL | enum Opt { - | --- + | ^^^ ... LL | None, - | ^^^^ not covered + | ---- not covered = note: the matched value is of type `Opt` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | @@ -167,7 +167,7 @@ LL + Opt::None => todo!() | error[E0005]: refutable pattern in local binding - --> $DIR/non-exhaustive-defined-here.rs:99:9 + --> $DIR/non-exhaustive-defined-here.rs:101:9 | LL | let Opt::Some(ref _x) = e; | ^^^^^^^^^^^^^^^^^ pattern `Opt::None` not covered @@ -175,7 +175,7 @@ LL | let Opt::Some(ref _x) = e; = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html note: `Opt` defined here - --> $DIR/non-exhaustive-defined-here.rs:81:6 + --> $DIR/non-exhaustive-defined-here.rs:83:6 | LL | enum Opt { | ^^^ diff --git a/tests/ui/pattern/usefulness/non-exhaustive-match-nested.stderr b/tests/ui/pattern/usefulness/non-exhaustive-match-nested.stderr index 98e417a17f86..310049fe13ec 100644 --- a/tests/ui/pattern/usefulness/non-exhaustive-match-nested.stderr +++ b/tests/ui/pattern/usefulness/non-exhaustive-match-nested.stderr @@ -18,10 +18,10 @@ LL | match x { | ^ pattern `T::A(U::C)` not covered | note: `T` defined here - --> $DIR/non-exhaustive-match-nested.rs:1:10 + --> $DIR/non-exhaustive-match-nested.rs:1:6 | LL | enum T { A(U), B } - | - ^ not covered + | ^ - not covered = note: the matched value is of type `T` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | diff --git a/tests/ui/pattern/usefulness/non-exhaustive-match.stderr b/tests/ui/pattern/usefulness/non-exhaustive-match.stderr index e59e8885e1a4..4bebd3cbbefd 100644 --- a/tests/ui/pattern/usefulness/non-exhaustive-match.stderr +++ b/tests/ui/pattern/usefulness/non-exhaustive-match.stderr @@ -5,10 +5,10 @@ LL | match x { T::B => { } } | ^ pattern `T::A` not covered | note: `T` defined here - --> $DIR/non-exhaustive-match.rs:3:10 + --> $DIR/non-exhaustive-match.rs:3:6 | LL | enum T { A, B } - | - ^ not covered + | ^ - not covered = note: the matched value is of type `T` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | @@ -79,10 +79,10 @@ LL | match T::A { | ^^^^ pattern `T::B` not covered | note: `T` defined here - --> $DIR/non-exhaustive-match.rs:3:13 + --> $DIR/non-exhaustive-match.rs:3:6 | LL | enum T { A, B } - | - ^ not covered + | ^ - not covered = note: the matched value is of type `T` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | diff --git a/tests/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr b/tests/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr index c75c4ccdc875..cceb1d8f65dd 100644 --- a/tests/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr +++ b/tests/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr @@ -23,12 +23,12 @@ LL | match Color::Red { | ^^^^^^^^^^ pattern `Color::Red` not covered | note: `Color` defined here - --> $DIR/non-exhaustive-pattern-witness.rs:17:5 + --> $DIR/non-exhaustive-pattern-witness.rs:16:6 | LL | enum Color { - | ----- + | ^^^^^ LL | Red, - | ^^^ not covered + | --- not covered = note: the matched value is of type `Color` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | @@ -43,17 +43,17 @@ LL | match Direction::North { | ^^^^^^^^^^^^^^^^ patterns `Direction::East`, `Direction::South` and `Direction::West` not covered | note: `Direction` defined here - --> $DIR/non-exhaustive-pattern-witness.rs:32:5 + --> $DIR/non-exhaustive-pattern-witness.rs:30:6 | LL | enum Direction { - | --------- + | ^^^^^^^^^ LL | North, LL | East, - | ^^^^ not covered + | ---- not covered LL | South, - | ^^^^^ not covered + | ----- not covered LL | West, - | ^^^^ not covered + | ---- not covered = note: the matched value is of type `Direction` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | @@ -68,21 +68,21 @@ LL | match ExcessiveEnum::First { | ^^^^^^^^^^^^^^^^^^^^ patterns `ExcessiveEnum::Second`, `ExcessiveEnum::Third`, `ExcessiveEnum::Fourth` and 8 more not covered | note: `ExcessiveEnum` defined here - --> $DIR/non-exhaustive-pattern-witness.rs:46:5 + --> $DIR/non-exhaustive-pattern-witness.rs:44:6 | LL | enum ExcessiveEnum { - | ------------- + | ^^^^^^^^^^^^^ LL | First, LL | Second, - | ^^^^^^ not covered + | ------ not covered LL | Third, - | ^^^^^ not covered + | ----- not covered LL | Fourth, - | ^^^^^^ not covered + | ------ not covered LL | Fifth, - | ^^^^^ not covered + | ----- not covered LL | Sixth, - | ^^^^^ not covered + | ----- not covered = note: the matched value is of type `ExcessiveEnum` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms | @@ -97,13 +97,13 @@ LL | match Color::Red { | ^^^^^^^^^^ pattern `Color::CustomRGBA { a: true, .. }` not covered | note: `Color` defined here - --> $DIR/non-exhaustive-pattern-witness.rs:19:5 + --> $DIR/non-exhaustive-pattern-witness.rs:16:6 | LL | enum Color { - | ----- + | ^^^^^ ... LL | CustomRGBA { a: bool, r: u8, g: u8, b: u8 }, - | ^^^^^^^^^^ not covered + | ---------- not covered = note: the matched value is of type `Color` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | diff --git a/tests/ui/pattern/usefulness/stable-gated-patterns.stderr b/tests/ui/pattern/usefulness/stable-gated-patterns.stderr index f944c25a905c..f75517fb7910 100644 --- a/tests/ui/pattern/usefulness/stable-gated-patterns.stderr +++ b/tests/ui/pattern/usefulness/stable-gated-patterns.stderr @@ -5,13 +5,13 @@ LL | match UnstableEnum::Stable { | ^^^^^^^^^^^^^^^^^^^^ patterns `UnstableEnum::Stable2` and `_` not covered | note: `UnstableEnum` defined here - --> $DIR/auxiliary/unstable.rs:9:5 + --> $DIR/auxiliary/unstable.rs:5:1 | LL | pub enum UnstableEnum { - | --------------------- + | ^^^^^^^^^^^^^^^^^^^^^ ... LL | Stable2, - | ^^^^^^^ not covered + | ------- not covered = note: the matched value is of type `UnstableEnum` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | diff --git a/tests/ui/pattern/usefulness/struct-like-enum-nonexhaustive.stderr b/tests/ui/pattern/usefulness/struct-like-enum-nonexhaustive.stderr index 22425aa0dd4d..3d2b540a9f57 100644 --- a/tests/ui/pattern/usefulness/struct-like-enum-nonexhaustive.stderr +++ b/tests/ui/pattern/usefulness/struct-like-enum-nonexhaustive.stderr @@ -5,12 +5,12 @@ LL | match x { | ^ pattern `A::B { x: Some(_) }` not covered | note: `A` defined here - --> $DIR/struct-like-enum-nonexhaustive.rs:2:5 + --> $DIR/struct-like-enum-nonexhaustive.rs:1:6 | LL | enum A { - | - + | ^ LL | B { x: Option }, - | ^ not covered + | - not covered = note: the matched value is of type `A` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | diff --git a/tests/ui/pattern/usefulness/unstable-gated-patterns.stderr b/tests/ui/pattern/usefulness/unstable-gated-patterns.stderr index d776249b2318..4a4945156f73 100644 --- a/tests/ui/pattern/usefulness/unstable-gated-patterns.stderr +++ b/tests/ui/pattern/usefulness/unstable-gated-patterns.stderr @@ -5,13 +5,13 @@ LL | match UnstableEnum::Stable { | ^^^^^^^^^^^^^^^^^^^^ pattern `UnstableEnum::Unstable` not covered | note: `UnstableEnum` defined here - --> $DIR/auxiliary/unstable.rs:11:5 + --> $DIR/auxiliary/unstable.rs:5:1 | LL | pub enum UnstableEnum { - | --------------------- + | ^^^^^^^^^^^^^^^^^^^^^ ... LL | Unstable, - | ^^^^^^^^ not covered + | -------- not covered = note: the matched value is of type `UnstableEnum` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr index de1bf8be8854..7386f10a6fb2 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr @@ -17,18 +17,18 @@ LL | match NonExhaustiveEnum::Unit {} | ^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonExhaustiveEnum::Unit`, `NonExhaustiveEnum::Tuple(_)` and `NonExhaustiveEnum::Struct { .. }` not covered | note: `NonExhaustiveEnum` defined here - --> $DIR/enum_same_crate_empty_match.rs:5:5 + --> $DIR/enum_same_crate_empty_match.rs:4:10 | LL | pub enum NonExhaustiveEnum { - | ----------------- + | ^^^^^^^^^^^^^^^^^ LL | Unit, - | ^^^^ not covered + | ---- not covered LL | LL | Tuple(u32), - | ^^^^^ not covered + | ----- not covered LL | LL | Struct { field: u32 } - | ^^^^^^ not covered + | ------ not covered = note: the matched value is of type `NonExhaustiveEnum` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | @@ -44,18 +44,18 @@ LL | match NormalEnum::Unit {} | ^^^^^^^^^^^^^^^^ patterns `NormalEnum::Unit`, `NormalEnum::Tuple(_)` and `NormalEnum::Struct { .. }` not covered | note: `NormalEnum` defined here - --> $DIR/enum_same_crate_empty_match.rs:14:5 + --> $DIR/enum_same_crate_empty_match.rs:13:10 | LL | pub enum NormalEnum { - | ---------- + | ^^^^^^^^^^ LL | Unit, - | ^^^^ not covered + | ---- not covered LL | LL | Tuple(u32), - | ^^^^^ not covered + | ----- not covered LL | LL | Struct { field: u32 } - | ^^^^^^ not covered + | ------ not covered = note: the matched value is of type `NormalEnum` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match.stderr index a9c54af0418a..c125756a646d 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match.stderr +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match.stderr @@ -62,14 +62,14 @@ LL | match x {} | ^ patterns `UninhabitedVariants::Tuple(_)` and `UninhabitedVariants::Struct { .. }` not covered | note: `UninhabitedVariants` defined here - --> $DIR/auxiliary/uninhabited.rs:17:23 + --> $DIR/auxiliary/uninhabited.rs:16:1 | LL | pub enum UninhabitedVariants { - | ---------------------------- + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ LL | #[non_exhaustive] Tuple(!), - | ^^^^^ not covered + | ----- not covered LL | #[non_exhaustive] Struct { x: ! } - | ^^^^^^ not covered + | ------ not covered = note: the matched value is of type `UninhabitedVariants` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_same_crate.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_same_crate.stderr index ec2a2f6f0553..7a12aca8520d 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_same_crate.stderr +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_same_crate.stderr @@ -43,14 +43,14 @@ LL | match x {} | ^ patterns `UninhabitedVariants::Tuple(_)` and `UninhabitedVariants::Struct { .. }` not covered | note: `UninhabitedVariants` defined here - --> $DIR/match_same_crate.rs:16:23 + --> $DIR/match_same_crate.rs:15:10 | LL | pub enum UninhabitedVariants { - | ------------------- + | ^^^^^^^^^^^^^^^^^^^ LL | #[non_exhaustive] Tuple(!), - | ^^^^^ not covered + | ----- not covered LL | #[non_exhaustive] Struct { x: ! } - | ^^^^^^ not covered + | ------ not covered = note: the matched value is of type `UninhabitedVariants` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr index b6b777ec56c4..19e2546b0da8 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr @@ -62,14 +62,14 @@ LL | match x {} | ^ patterns `UninhabitedVariants::Tuple(_)` and `UninhabitedVariants::Struct { .. }` not covered | note: `UninhabitedVariants` defined here - --> $DIR/auxiliary/uninhabited.rs:17:23 + --> $DIR/auxiliary/uninhabited.rs:16:1 | LL | pub enum UninhabitedVariants { - | ---------------------------- + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ LL | #[non_exhaustive] Tuple(!), - | ^^^^^ not covered + | ----- not covered LL | #[non_exhaustive] Struct { x: ! } - | ^^^^^^ not covered + | ------ not covered = note: the matched value is of type `UninhabitedVariants` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | From ff1858e2aa4c7ff60ae72ec7d90973a7a14b94f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Fri, 3 Nov 2023 10:56:30 +0100 Subject: [PATCH 219/435] Make `FatalErrorMarker` lower priority than other panics --- compiler/rustc_data_structures/src/lib.rs | 3 ++ .../src/sync/parallel.rs | 39 ++++++++++++------- compiler/rustc_span/src/fatal_error.rs | 2 +- 3 files changed, 30 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index 5d7f385c6e4a..d09c026c4b4e 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -127,6 +127,9 @@ impl Drop for OnDrop { } } +/// This is a marker for a fatal compiler error used with `resume_unwind`. +pub struct FatalErrorMarker; + /// Turns a closure that takes an `&mut Formatter` into something that can be display-formatted. pub fn make_display(f: impl Fn(&mut fmt::Formatter<'_>) -> fmt::Result) -> impl fmt::Display { struct Printer { diff --git a/compiler/rustc_data_structures/src/sync/parallel.rs b/compiler/rustc_data_structures/src/sync/parallel.rs index 39dddb595691..ec7012d79cf6 100644 --- a/compiler/rustc_data_structures/src/sync/parallel.rs +++ b/compiler/rustc_data_structures/src/sync/parallel.rs @@ -3,6 +3,8 @@ #![allow(dead_code)] +use crate::sync::IntoDynSyncSend; +use crate::FatalErrorMarker; use parking_lot::Mutex; use std::any::Any; use std::panic::{catch_unwind, resume_unwind, AssertUnwindSafe}; @@ -18,14 +20,17 @@ pub use enabled::*; /// continuing with unwinding. It's also used for the non-parallel code to ensure error message /// output match the parallel compiler for testing purposes. pub struct ParallelGuard { - panic: Mutex>>, + panic: Mutex>>>, } impl ParallelGuard { pub fn run(&self, f: impl FnOnce() -> R) -> Option { catch_unwind(AssertUnwindSafe(f)) .map_err(|err| { - *self.panic.lock() = Some(err); + let mut panic = self.panic.lock(); + if panic.is_none() || !(*err).is::() { + *panic = Some(IntoDynSyncSend(err)); + } }) .ok() } @@ -37,7 +42,7 @@ impl ParallelGuard { pub fn parallel_guard(f: impl FnOnce(&ParallelGuard) -> R) -> R { let guard = ParallelGuard { panic: Mutex::new(None) }; let ret = f(&guard); - if let Some(panic) = guard.panic.into_inner() { + if let Some(IntoDynSyncSend(panic)) = guard.panic.into_inner() { resume_unwind(panic); } ret @@ -106,14 +111,20 @@ mod enabled { parallel!(impl $fblock [$block, $($c,)*] [$($rest),*]) }; (impl $fblock:block [$($blocks:expr,)*] []) => { - ::rustc_data_structures::sync::scope(|s| { - $(let block = rustc_data_structures::sync::FromDyn::from(|| $blocks); - s.spawn(move |_| block.into_inner()());)* - (|| $fblock)(); + $crate::sync::parallel_guard(|guard| { + $crate::sync::scope(|s| { + $( + let block = $crate::sync::FromDyn::from(|| $blocks); + s.spawn(move |_| { + guard.run(move || block.into_inner()()); + }); + )* + guard.run(|| $fblock); + }); }); }; ($fblock:block, $($blocks:block),*) => { - if rustc_data_structures::sync::is_dyn_thread_safe() { + if $crate::sync::is_dyn_thread_safe() { // Reverse the order of the later blocks since Rayon executes them in reverse order // when using a single thread. This ensures the execution order matches that // of a single threaded rustc. @@ -146,11 +157,13 @@ mod enabled { if mode::is_dyn_thread_safe() { let oper_a = FromDyn::from(oper_a); let oper_b = FromDyn::from(oper_b); - let (a, b) = rayon::join( - move || FromDyn::from(oper_a.into_inner()()), - move || FromDyn::from(oper_b.into_inner()()), - ); - (a.into_inner(), b.into_inner()) + let (a, b) = parallel_guard(|guard| { + rayon::join( + move || guard.run(move || FromDyn::from(oper_a.into_inner()())), + move || guard.run(move || FromDyn::from(oper_b.into_inner()())), + ) + }); + (a.unwrap().into_inner(), b.unwrap().into_inner()) } else { super::disabled::join(oper_a, oper_b) } diff --git a/compiler/rustc_span/src/fatal_error.rs b/compiler/rustc_span/src/fatal_error.rs index fa84c486df51..f53e0b10b34c 100644 --- a/compiler/rustc_span/src/fatal_error.rs +++ b/compiler/rustc_span/src/fatal_error.rs @@ -5,7 +5,7 @@ #[must_use] pub struct FatalError; -pub struct FatalErrorMarker; +pub use rustc_data_structures::FatalErrorMarker; // Don't implement Send on FatalError. This makes it impossible to panic!(FatalError). // We don't want to invoke the panic handler and print a backtrace for fatal errors. From f8daa7d4f6c13ca12f3074ee2ba4f9866a6f8bee Mon Sep 17 00:00:00 2001 From: Augie Fackler Date: Fri, 3 Nov 2023 14:24:23 -0400 Subject: [PATCH 220/435] consts: remove dead code around `i1` constant values `LLVMConstZext` recently got deleted, and it turns out (thanks to @nikic for knowing!) that this is dead code. Tests all pass for me without this logic, and per nikic: > We always generate constants in "relocatable bag of bytes" > representation, so you're never going to get a plain bool. So this should be a safe thing to do. r? @nikic @rustbot label: +llvm-main --- compiler/rustc_codegen_llvm/src/consts.rs | 10 +--------- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 1 - 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index 73821b1685df..307c1264dc1b 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -374,15 +374,7 @@ impl<'ll> StaticMethods for CodegenCx<'ll, '_> { let g = self.get_static(def_id); - // boolean SSA values are i1, but they have to be stored in i8 slots, - // otherwise some LLVM optimization passes don't work as expected - let mut val_llty = self.val_ty(v); - let v = if val_llty == self.type_i1() { - val_llty = self.type_i8(); - llvm::LLVMConstZExt(v, val_llty) - } else { - v - }; + let val_llty = self.val_ty(v); let instance = Instance::mono(self.tcx, def_id); let ty = instance.ty(self.tcx, ty::ParamEnv::reveal_all()); diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index a038b3af03dd..7fc02a95be0a 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -969,7 +969,6 @@ extern "C" { ConstantIndices: *const &'a Value, NumIndices: c_uint, ) -> &'a Value; - pub fn LLVMConstZExt<'a>(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value; pub fn LLVMConstPtrToInt<'a>(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value; pub fn LLVMConstIntToPtr<'a>(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value; pub fn LLVMConstBitCast<'a>(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value; From 8eca01f4b6e09946baa26435894251e4d441b794 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 3 Oct 2023 13:54:17 +1100 Subject: [PATCH 221/435] Remove support for compiler plugins. They've been deprecated for four years. This commit includes the following changes. - It eliminates the `rustc_plugin_impl` crate. - It changes the language used for lints in `compiler/rustc_driver_impl/src/lib.rs` and `compiler/rustc_lint/src/context.rs`. External lints are now called "loaded" lints, rather than "plugins" to avoid confusion with the old plugins. This only has a tiny effect on the output of `-W help`. - E0457 and E0498 are no longer used. - E0463 is narrowed, now only relating to unfound crates, not plugins. - The `plugin` feature was moved from "active" to "removed". - It removes the entire plugins chapter from the unstable book. - It removes quite a few tests, mostly all of those in `tests/ui-fulldeps/plugin/`. Closes #29597. --- scripts/test_rustc_tests.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/test_rustc_tests.sh b/scripts/test_rustc_tests.sh index b485f2571cc7..a299b6de6b1c 100755 --- a/scripts/test_rustc_tests.sh +++ b/scripts/test_rustc_tests.sh @@ -68,7 +68,6 @@ rm -r tests/run-make/split-debuginfo # same rm -r tests/run-make/symbols-include-type-name # --emit=asm not supported rm -r tests/run-make/target-specs # i686 not supported by Cranelift rm -r tests/run-make/mismatching-target-triples # same -rm -r tests/run-make/use-extern-for-plugins # same rm tests/ui/asm/x86_64/issue-82869.rs # vector regs in inline asm not yet supported rm tests/ui/asm/x86_64/issue-96797.rs # const and sym inline asm operands don't work entirely correctly From de7a8305ae2b6eef11133de783f5089a94928f79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Sat, 4 Nov 2023 00:55:27 +0000 Subject: [PATCH 222/435] traverse region graph instead of SCCs to compute polonius loan scopes By using SCC for better performance, we also have to take into account SCCs whose representative is an existential region but also contains a placeholder. By only checking the representative, we may miss that the loan escapes the function. This can be fixed by picking a better representative, or removing placeholders from the main path. This is the simplest fix: forgo efficiency and traverse the region graph instead of the SCCs. --- compiler/rustc_borrowck/src/dataflow.rs | 6 +++--- .../rustc_borrowck/src/region_infer/mod.rs | 21 ++++++++++--------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs index 16814950b0d9..8676d2ba7c4c 100644 --- a/compiler/rustc_borrowck/src/dataflow.rs +++ b/compiler/rustc_borrowck/src/dataflow.rs @@ -273,11 +273,10 @@ impl<'tcx> PoloniusOutOfScopePrecomputer<'_, 'tcx> { ) { let sccs = self.regioncx.constraint_sccs(); let universal_regions = self.regioncx.universal_regions(); - let issuing_region_scc = sccs.scc(issuing_region); // We first handle the cases where the loan doesn't go out of scope, depending on the issuing // region's successors. - for scc in sccs.depth_first_search(issuing_region_scc) { + for successor in self.regioncx.region_graph().depth_first_search(issuing_region) { // 1. Via applied member constraints // // The issuing region can flow into the choice regions, and they are either: @@ -290,6 +289,7 @@ impl<'tcx> PoloniusOutOfScopePrecomputer<'_, 'tcx> { // For additional insurance via fuzzing and crater, we verify that the constraint's min // choice indeed escapes the function. In the future, we could e.g. turn this check into // a debug assert and early return as an optimization. + let scc = sccs.scc(successor); for constraint in self.regioncx.applied_member_constraints(scc) { if universal_regions.is_universal_region(constraint.min_choice) { return; @@ -300,7 +300,7 @@ impl<'tcx> PoloniusOutOfScopePrecomputer<'_, 'tcx> { // // If the issuing region outlives such a region, its loan escapes the function and // cannot go out of scope. We can early return. - if self.regioncx.scc_is_live_at_all_points(scc) { + if self.regioncx.is_region_live_at_all_points(successor) { return; } } diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 05c2cbd49692..b1f91a056282 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -22,11 +22,10 @@ use rustc_middle::traits::ObligationCauseCode; use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, TypeVisitableExt}; use rustc_span::Span; +use crate::constraints::graph::{self, NormalConstraintGraph, RegionGraph}; use crate::dataflow::BorrowIndex; use crate::{ - constraints::{ - graph::NormalConstraintGraph, ConstraintSccIndex, OutlivesConstraint, OutlivesConstraintSet, - }, + constraints::{ConstraintSccIndex, OutlivesConstraint, OutlivesConstraintSet}, diagnostics::{RegionErrorKind, RegionErrors, UniverseInfo}, member_constraints::{MemberConstraintSet, NllMemberConstraintIndex}, nll::PoloniusOutput, @@ -2293,19 +2292,21 @@ impl<'tcx> RegionInferenceContext<'tcx> { self.constraint_sccs.as_ref() } - /// Returns whether the given SCC is live at all points: whether the representative is a + /// Access to the region graph, built from the outlives constraints. + pub(crate) fn region_graph(&self) -> RegionGraph<'_, 'tcx, graph::Normal> { + self.constraint_graph.region_graph(&self.constraints, self.universal_regions.fr_static) + } + + /// Returns whether the given region is considered live at all points: whether it is a /// placeholder or a free region. - pub(crate) fn scc_is_live_at_all_points(&self, scc: ConstraintSccIndex) -> bool { + pub(crate) fn is_region_live_at_all_points(&self, region: RegionVid) -> bool { // FIXME: there must be a cleaner way to find this information. At least, when // higher-ranked subtyping is abstracted away from the borrowck main path, we'll only // need to check whether this is a universal region. - let representative = self.scc_representatives[scc]; - let origin = self.var_infos[representative].origin; + let origin = self.region_definition(region).origin; let live_at_all_points = matches!( origin, - RegionVariableOrigin::Nll( - NllRegionVariableOrigin::Placeholder(_) | NllRegionVariableOrigin::FreeRegion - ) + NllRegionVariableOrigin::Placeholder(_) | NllRegionVariableOrigin::FreeRegion ); live_at_all_points } From 2dff90dc233dd30244191af6a71e3b2d85a551eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Sat, 4 Nov 2023 01:03:49 +0000 Subject: [PATCH 223/435] add test for issue 117146 --- ...insensitive-scopes-issue-117146.nll.stderr | 40 +++++++++++++++++++ ...sitive-scopes-issue-117146.polonius.stderr | 40 +++++++++++++++++++ ...ocation-insensitive-scopes-issue-117146.rs | 20 ++++++++++ 3 files changed, 100 insertions(+) create mode 100644 tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.nll.stderr create mode 100644 tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.polonius.stderr create mode 100644 tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.rs diff --git a/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.nll.stderr b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.nll.stderr new file mode 100644 index 000000000000..5227ca8ec17d --- /dev/null +++ b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.nll.stderr @@ -0,0 +1,40 @@ +error[E0597]: `a` does not live long enough + --> $DIR/location-insensitive-scopes-issue-117146.rs:10:18 + | +LL | let b = |_| &a; + | --- -^ + | | || + | | |borrowed value does not live long enough + | | returning this value requires that `a` is borrowed for `'static` + | value captured here +... +LL | } + | - `a` dropped here while still borrowed + | +note: due to current limitations in the borrow checker, this implies a `'static` lifetime + --> $DIR/location-insensitive-scopes-issue-117146.rs:20:22 + | +LL | fn bad &()>(_: F) {} + | ^^^ + +error: implementation of `Fn` is not general enough + --> $DIR/location-insensitive-scopes-issue-117146.rs:13:5 + | +LL | bad(&b); + | ^^^^^^^ implementation of `Fn` is not general enough + | + = note: closure with signature `fn(&'2 ()) -> &()` must implement `Fn<(&'1 (),)>`, for any lifetime `'1`... + = note: ...but it actually implements `Fn<(&'2 (),)>`, for some specific lifetime `'2` + +error: implementation of `FnOnce` is not general enough + --> $DIR/location-insensitive-scopes-issue-117146.rs:13:5 + | +LL | bad(&b); + | ^^^^^^^ implementation of `FnOnce` is not general enough + | + = note: closure with signature `fn(&'2 ()) -> &()` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... + = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.polonius.stderr b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.polonius.stderr new file mode 100644 index 000000000000..5227ca8ec17d --- /dev/null +++ b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.polonius.stderr @@ -0,0 +1,40 @@ +error[E0597]: `a` does not live long enough + --> $DIR/location-insensitive-scopes-issue-117146.rs:10:18 + | +LL | let b = |_| &a; + | --- -^ + | | || + | | |borrowed value does not live long enough + | | returning this value requires that `a` is borrowed for `'static` + | value captured here +... +LL | } + | - `a` dropped here while still borrowed + | +note: due to current limitations in the borrow checker, this implies a `'static` lifetime + --> $DIR/location-insensitive-scopes-issue-117146.rs:20:22 + | +LL | fn bad &()>(_: F) {} + | ^^^ + +error: implementation of `Fn` is not general enough + --> $DIR/location-insensitive-scopes-issue-117146.rs:13:5 + | +LL | bad(&b); + | ^^^^^^^ implementation of `Fn` is not general enough + | + = note: closure with signature `fn(&'2 ()) -> &()` must implement `Fn<(&'1 (),)>`, for any lifetime `'1`... + = note: ...but it actually implements `Fn<(&'2 (),)>`, for some specific lifetime `'2` + +error: implementation of `FnOnce` is not general enough + --> $DIR/location-insensitive-scopes-issue-117146.rs:13:5 + | +LL | bad(&b); + | ^^^^^^^ implementation of `FnOnce` is not general enough + | + = note: closure with signature `fn(&'2 ()) -> &()` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... + = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.rs b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.rs new file mode 100644 index 000000000000..c165e7a1d1a5 --- /dev/null +++ b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.rs @@ -0,0 +1,20 @@ +// This is a non-regression test for issue #117146, where NLL and `-Zpolonius=next` computed +// different loan scopes when a region flowed into an SCC whose representative was an existential +// region. + +// revisions: nll polonius +// [polonius] compile-flags: -Zpolonius=next + +fn main() { + let a = (); + let b = |_| &a; + //[nll]~^ ERROR `a` does not live long enough + //[polonius]~^^ ERROR `a` does not live long enough + bad(&b); + //[nll]~^ ERROR implementation of `Fn` + //[nll]~| ERROR implementation of `FnOnce` + //[polonius]~^^^ ERROR implementation of `Fn` + //[polonius]~| ERROR implementation of `FnOnce` +} + +fn bad &()>(_: F) {} From a745f9249719c0de309bd4307a0583b82f713021 Mon Sep 17 00:00:00 2001 From: Peter Jaszkowiak Date: Fri, 3 Nov 2023 20:40:21 -0600 Subject: [PATCH 224/435] triagebot no-merges: exclude different case "Subtree update" as well --- triagebot.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/triagebot.toml b/triagebot.toml index b419727bcfdd..b846edca98b3 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -415,7 +415,7 @@ Issue #{number} "{title}" has been added. """ [no-merges] -exclude_titles = ["Rollup of", "subtree update"] +exclude_titles = ["Rollup of", "subtree update", "Subtree update"] labels = ["has-merge-commits", "S-waiting-on-author"] [github-releases] From f3587204c82b61a69c85f2e1c9f03613e550dc59 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Sat, 4 Nov 2023 00:02:21 -0400 Subject: [PATCH 225/435] Update cargo Remove license exception of `byteyarn` as it is no longer used --- src/tools/cargo | 2 +- src/tools/tidy/src/deps.rs | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/tools/cargo b/src/tools/cargo index b4d18d4bd3db..65e297d1ec0d 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit b4d18d4bd3db6d872892f6c87c51a02999b80802 +Subproject commit 65e297d1ec0dee1a74800efe600b8dc163bcf5db diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 4b12e9172af7..f0b541940c69 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -59,7 +59,6 @@ const EXCEPTIONS_CARGO: &[(&str, &str)] = &[ // tidy-alphabetical-start ("bitmaps", "MPL-2.0+"), ("bytesize", "Apache-2.0"), - ("byteyarn", "Apache-2.0"), ("ciborium", "Apache-2.0"), ("ciborium-io", "Apache-2.0"), ("ciborium-ll", "Apache-2.0"), From 0550ba5f7743e2d2a979ff41f098283f5ad68000 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 3 Nov 2023 07:58:03 +0100 Subject: [PATCH 226/435] avoid acronyms when we don't really need them --- library/core/src/primitive_docs.rs | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index a0caa6c8216c..8c7c44ca8d48 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -291,7 +291,7 @@ mod prim_never {} /// Surrogate code points, used by UTF-16, are in the range 0xD800 to 0xDFFF. /// /// No `char` may be constructed, whether as a literal or at runtime, that is not a -/// Unicode scalar value. Violating this rule causes Undefined Behavior. +/// Unicode scalar value. Violating this rule causes undefined behavior. /// /// ```compile_fail /// // Each of these is a compiler error @@ -308,10 +308,10 @@ mod prim_never {} /// let _ = unsafe { char::from_u32_unchecked(0x110000) }; /// ``` /// -/// USVs are also the exact set of values that may be encoded in UTF-8. Because `char` values are -/// USVs and functions may assume [incoming `str` values are valid -/// UTF-8](primitive.str.html#invariant), it is safe to store any `char` in a `str` or read any -/// character from a `str` as a `char`. +/// Unicode scalar values are also the exact set of values that may be encoded in UTF-8. Because +/// `char` values are Unicode scalar values and functions may assume [incoming `str` values are +/// valid UTF-8](primitive.str.html#invariant), it is safe to store any `char` in a `str` or read +/// any character from a `str` as a `char`. /// /// The gap in valid `char` values is understood by the compiler, so in the /// below example the two ranges are understood to cover the whole range of @@ -325,11 +325,10 @@ mod prim_never {} /// }; /// ``` /// -/// All USVs are valid `char` values, but not all of them represent a real -/// character. Many USVs are not currently assigned to a character, but may be -/// in the future ("reserved"); some will never be a character -/// ("noncharacters"); and some may be given different meanings by different -/// users ("private use"). +/// All Unicode scalar values are valid `char` values, but not all of them represent a real +/// character. Many Unicode scalar values are not currently assigned to a character, but may be in +/// the future ("reserved"); some will never be a character ("noncharacters"); and some may be given +/// different meanings by different users ("private use"). /// /// [Unicode code point]: https://www.unicode.org/glossary/#code_point /// [Unicode scalar value]: https://www.unicode.org/glossary/#unicode_scalar_value @@ -946,9 +945,9 @@ mod prim_slice {} /// /// Rust libraries may assume that string slices are always valid UTF-8. /// -/// Constructing a non-UTF-8 string slice is not immediate Undefined Behavior, but any function +/// Constructing a non-UTF-8 string slice is not immediate undefined behavior, but any function /// called on a string slice may assume that it is valid UTF-8, which means that a non-UTF-8 string -/// slice can lead to Undefined Behaviior down the road. +/// slice can lead to undefined behavior down the road. #[stable(feature = "rust1", since = "1.0.0")] mod prim_str {} From 19bf0da9d7b35327972683ad317cb405b2e2a2e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Sat, 4 Nov 2023 13:33:19 +0200 Subject: [PATCH 227/435] Fix docs path for derive macros --- crates/ide/src/doc_links.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/crates/ide/src/doc_links.rs b/crates/ide/src/doc_links.rs index 37a177622162..ac15b6aba618 100644 --- a/crates/ide/src/doc_links.rs +++ b/crates/ide/src/doc_links.rs @@ -602,7 +602,17 @@ fn filename_and_frag_for_def( } Definition::Const(c) => format!("const.{}.html", c.name(db)?.display(db.upcast())), Definition::Static(s) => format!("static.{}.html", s.name(db).display(db.upcast())), - Definition::Macro(mac) => format!("macro.{}.html", mac.name(db).display(db.upcast())), + Definition::Macro(mac) => match mac.kind(db) { + hir::MacroKind::Declarative + | hir::MacroKind::BuiltIn + | hir::MacroKind::Attr + | hir::MacroKind::ProcMacro => { + format!("macro.{}.html", mac.name(db).display(db.upcast())) + } + hir::MacroKind::Derive => { + format!("derive.{}.html", mac.name(db).display(db.upcast())) + } + }, Definition::Field(field) => { let def = match field.parent_def(db) { hir::VariantDef::Struct(it) => Definition::Adt(it.into()), From 5e2de479fa07a365d89bacac473f241960970b21 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Sat, 4 Nov 2023 15:01:34 +0300 Subject: [PATCH 228/435] Ensure compiler crate paths are generated before linking Signed-off-by: onur-ozkan --- src/bootstrap/src/core/build_steps/doc.rs | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs index 628a4ece8e90..b74f6f26feaa 100644 --- a/src/bootstrap/src/core/build_steps/doc.rs +++ b/src/bootstrap/src/core/build_steps/doc.rs @@ -685,18 +685,7 @@ impl Step for Rustc { target, ); - // This uses a shared directory so that librustdoc documentation gets - // correctly built and merged with the rustc documentation. This is - // needed because rustdoc is built in a different directory from - // rustc. rustdoc needs to be able to see everything, for example when - // merging the search index, or generating local (relative) links. let out_dir = builder.stage_out(compiler, Mode::Rustc).join(target.triple).join("doc"); - t!(fs::create_dir_all(out_dir.parent().unwrap())); - symlink_dir_force(&builder.config, &out, &out_dir); - // Cargo puts proc macros in `target/doc` even if you pass `--target` - // explicitly (https://github.com/rust-lang/cargo/issues/7677). - let proc_macro_out_dir = builder.stage_out(compiler, Mode::Rustc).join("doc"); - symlink_dir_force(&builder.config, &out, &proc_macro_out_dir); // Build cargo command. let mut cargo = builder.cargo(compiler, Mode::Rustc, SourceType::InTree, target, "doc"); @@ -736,6 +725,18 @@ impl Step for Rustc { } } + // This uses a shared directory so that librustdoc documentation gets + // correctly built and merged with the rustc documentation. + // + // This is needed because rustdoc is built in a different directory from + // rustc. rustdoc needs to be able to see everything, for example when + // merging the search index, or generating local (relative) links. + symlink_dir_force(&builder.config, &out, &out_dir); + // Cargo puts proc macros in `target/doc` even if you pass `--target` + // explicitly (https://github.com/rust-lang/cargo/issues/7677). + let proc_macro_out_dir = builder.stage_out(compiler, Mode::Rustc).join("doc"); + symlink_dir_force(&builder.config, &out, &proc_macro_out_dir); + builder.run(&mut cargo.into()); if builder.paths.iter().any(|path| path.ends_with("compiler")) { From fda009c858fe2039f981be56ce4b177da1fb8703 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Sat, 4 Nov 2023 15:02:38 +0300 Subject: [PATCH 229/435] add sanity check for compiler crate docs Signed-off-by: onur-ozkan --- src/bootstrap/src/core/build_steps/doc.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs index b74f6f26feaa..99440482adc0 100644 --- a/src/bootstrap/src/core/build_steps/doc.rs +++ b/src/bootstrap/src/core/build_steps/doc.rs @@ -739,6 +739,14 @@ impl Step for Rustc { builder.run(&mut cargo.into()); + if !builder.config.dry_run() { + // Sanity check on linked compiler crates + for krate in &*self.crates { + let dir_name = krate.replace("-", "_"); + assert!(out.join(&*dir_name).exists()); + } + } + if builder.paths.iter().any(|path| path.ends_with("compiler")) { // For `x.py doc compiler --open`, open `rustc_middle` by default. let index = out.join("rustc_middle").join("index.html"); From d82fdb6616207dff00af563508c6e6cc5aaa4ca3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Sat, 28 Oct 2023 19:00:49 +0000 Subject: [PATCH 230/435] pass `CODEGEN_BACKENDS` to docker --- src/ci/docker/run.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh index a2891ef95634..cedbc0390f8f 100755 --- a/src/ci/docker/run.sh +++ b/src/ci/docker/run.sh @@ -302,6 +302,7 @@ docker \ --env DIST_TRY_BUILD \ --env PR_CI_JOB \ --env OBJDIR_ON_HOST="$objdir" \ + --env CODEGEN_BACKENDS \ --init \ --rm \ rust-ci \ From a9913ebed0befb09ed21725e1e30cdbd6a9c33ea Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sat, 28 Oct 2023 19:11:51 +0000 Subject: [PATCH 231/435] Ensure the rustc-codegen-cranelift-preview component is never empty Either generate it with the actual codegen backend dylib or omit it entirely when the cranelift backend is disabled for this build. --- src/bootstrap/src/core/build_steps/dist.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index b578c5ec2950..197ce78d8859 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -1305,6 +1305,10 @@ impl Step for CodegenBackend { return None; } + if !builder.config.rust_codegen_backends.contains(&self.backend) { + return None; + } + if self.backend == "cranelift" { if !target_supports_cranelift_backend(self.compiler.host) { builder.info("target not supported by rustc_codegen_cranelift. skipping"); @@ -1343,12 +1347,15 @@ impl Step for CodegenBackend { let backends_dst = PathBuf::from("lib").join(&backends_rel); let backend_name = format!("rustc_codegen_{}", backend); + let mut found_backend = false; for backend in fs::read_dir(&backends_src).unwrap() { let file_name = backend.unwrap().file_name(); if file_name.to_str().unwrap().contains(&backend_name) { tarball.add_file(backends_src.join(file_name), &backends_dst, 0o644); + found_backend = true; } } + assert!(found_backend); Some(tarball.generate()) } From 451778b5517a7017eda2fea79ebb5078f11da3fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Sun, 29 Oct 2023 13:12:02 +0000 Subject: [PATCH 232/435] handle dry runs in `dist::CodegenBackend` self.number_of_times_dry_runs_have_caused_issues += 1; --- src/bootstrap/src/core/build_steps/dist.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index 197ce78d8859..6e80c55c8ce3 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -1298,6 +1298,10 @@ impl Step for CodegenBackend { } fn run(self, builder: &Builder<'_>) -> Option { + if builder.config.dry_run() { + return None; + } + // This prevents rustc_codegen_cranelift from being built for "dist" // or "install" on the stable/beta channels. It is not yet stable and // should not be included. From 55b49455e79bf43ad07e3d1f1482b07ca8cf3bdf Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Sat, 4 Nov 2023 15:43:09 +0300 Subject: [PATCH 233/435] ensure doc directory is not empty Signed-off-by: onur-ozkan --- src/bootstrap/src/core/build_steps/doc.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs index 99440482adc0..1ef481408f95 100644 --- a/src/bootstrap/src/core/build_steps/doc.rs +++ b/src/bootstrap/src/core/build_steps/doc.rs @@ -743,7 +743,8 @@ impl Step for Rustc { // Sanity check on linked compiler crates for krate in &*self.crates { let dir_name = krate.replace("-", "_"); - assert!(out.join(&*dir_name).exists()); + // Making sure the directory exists and is not empty. + assert!(out.join(&*dir_name).read_dir().unwrap().next().is_some()); } } From 7b19fb88bedccb58dfcce15d1c1c604f3635babf Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Mon, 23 Oct 2023 18:27:33 +0200 Subject: [PATCH 234/435] Add tests --- ...tted-patterns-dont-lint-on-arm.lint.stderr | 30 +++++++++++ ...ed-patterns-dont-lint-on-arm.normal.stderr | 16 ++++++ .../omitted-patterns-dont-lint-on-arm.rs | 50 +++++++++++++++++++ 3 files changed, 96 insertions(+) create mode 100644 tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.lint.stderr create mode 100644 tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.normal.stderr create mode 100644 tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.rs diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.lint.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.lint.stderr new file mode 100644 index 000000000000..c58b07d1aef2 --- /dev/null +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.lint.stderr @@ -0,0 +1,30 @@ +error: some variants are not matched explicitly + --> $DIR/omitted-patterns-dont-lint-on-arm.rs:15:11 + | +LL | match val { + | ^^^ pattern `NonExhaustiveEnum::Struct { .. }` not covered + | + = help: ensure that all variants are matched explicitly by adding the suggested match arms + = note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found +note: the lint level is defined here + --> $DIR/omitted-patterns-dont-lint-on-arm.rs:14:12 + | +LL | #[deny(non_exhaustive_omitted_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: some variants are not matched explicitly + --> $DIR/omitted-patterns-dont-lint-on-arm.rs:23:11 + | +LL | match val { + | ^^^ pattern `NonExhaustiveEnum::Struct { .. }` not covered + | + = help: ensure that all variants are matched explicitly by adding the suggested match arms + = note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found +note: the lint level is defined here + --> $DIR/omitted-patterns-dont-lint-on-arm.rs:22:27 + | +LL | #[cfg_attr(lint, deny(non_exhaustive_omitted_patterns))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.normal.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.normal.stderr new file mode 100644 index 000000000000..2d94a09de634 --- /dev/null +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.normal.stderr @@ -0,0 +1,16 @@ +error: some variants are not matched explicitly + --> $DIR/omitted-patterns-dont-lint-on-arm.rs:15:11 + | +LL | match val { + | ^^^ pattern `NonExhaustiveEnum::Struct { .. }` not covered + | + = help: ensure that all variants are matched explicitly by adding the suggested match arms + = note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found +note: the lint level is defined here + --> $DIR/omitted-patterns-dont-lint-on-arm.rs:14:12 + | +LL | #[deny(non_exhaustive_omitted_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.rs new file mode 100644 index 000000000000..9411d8f085bb --- /dev/null +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.rs @@ -0,0 +1,50 @@ +// revisions: normal lint +// Test that putting the lint level on a match arm emits a warning, as this was previously +// meaningful and is no longer. +#![feature(non_exhaustive_omitted_patterns_lint)] + +// aux-build:enums.rs +extern crate enums; + +use enums::NonExhaustiveEnum; + +fn main() { + let val = NonExhaustiveEnum::Unit; + + #[deny(non_exhaustive_omitted_patterns)] + match val { + //~^ ERROR some variants are not matched explicitly + NonExhaustiveEnum::Unit => {} + NonExhaustiveEnum::Tuple(_) => {} + _ => {} + } + + #[cfg_attr(lint, deny(non_exhaustive_omitted_patterns))] + match val { + //[lint]~^ ERROR some variants are not matched explicitly + NonExhaustiveEnum::Unit => {} + NonExhaustiveEnum::Tuple(_) => {} + _ => {} + } + + match val { + NonExhaustiveEnum::Unit => {} + NonExhaustiveEnum::Tuple(_) => {} + #[deny(non_exhaustive_omitted_patterns)] + _ => {} + } + + match val { + NonExhaustiveEnum::Unit => {} + NonExhaustiveEnum::Tuple(_) => {} + #[cfg_attr(lint, deny(non_exhaustive_omitted_patterns))] + _ => {} + } + + match val { + NonExhaustiveEnum::Unit => {} + NonExhaustiveEnum::Tuple(_) => {} + #[cfg_attr(lint, warn(non_exhaustive_omitted_patterns))] + _ => {} + } +} From 61d0fc7cf5f1ae6c9b7f1321376f251ce8139ef7 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Mon, 23 Oct 2023 18:55:04 +0200 Subject: [PATCH 235/435] Warn when lint level is set on a match arm --- compiler/rustc_mir_build/messages.ftl | 3 + compiler/rustc_mir_build/src/errors.rs | 5 ++ .../src/thir/pattern/usefulness.rs | 62 ++++++++++++------- .../ui/match_same_arms_non_exhaustive.rs | 2 +- ...tted-patterns-dont-lint-on-arm.lint.stderr | 41 +++++++++++- ...ed-patterns-dont-lint-on-arm.normal.stderr | 15 ++++- .../omitted-patterns-dont-lint-on-arm.rs | 6 +- 7 files changed, 107 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl index 32711c23dc4e..ed16d41a7433 100644 --- a/compiler/rustc_mir_build/messages.ftl +++ b/compiler/rustc_mir_build/messages.ftl @@ -221,6 +221,9 @@ mir_build_non_exhaustive_omitted_pattern = some variants are not matched explici .help = ensure that all variants are matched explicitly by adding the suggested match arms .note = the matched value is of type `{$scrut_ty}` and the `non_exhaustive_omitted_patterns` attribute was found +mir_build_non_exhaustive_omitted_pattern_lint_on_arm = the `non_exhaustive_omitted_pattern` lint level must be set on the whole match + .help = it used to make sense to set the lint level on an individual match arm, but that is no longer the case + mir_build_non_exhaustive_patterns_type_not_empty = non-exhaustive patterns: type `{$ty}` is non-empty .def_note = `{$peeled_ty}` defined here .type_note = the matched value is of type `{$ty}` diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 5bfce3ab5100..378a957df0fb 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -789,6 +789,11 @@ pub(crate) struct NonExhaustiveOmittedPattern<'tcx> { pub uncovered: Uncovered<'tcx>, } +#[derive(LintDiagnostic)] +#[diag(mir_build_non_exhaustive_omitted_pattern_lint_on_arm)] +#[help] +pub(crate) struct NonExhaustiveOmittedPatternLintOnArm; + #[derive(Subdiagnostic)] #[label(mir_build_uncovered)] pub(crate) struct Uncovered<'tcx> { diff --git a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs index 1eb1dd72a61d..233b911bfee1 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs @@ -311,7 +311,10 @@ use super::deconstruct_pat::{ Constructor, ConstructorSet, DeconstructedPat, IntRange, MaybeInfiniteInt, SplitConstructorSet, WitnessPat, }; -use crate::errors::{NonExhaustiveOmittedPattern, Overlap, OverlappingRangeEndpoints, Uncovered}; +use crate::errors::{ + NonExhaustiveOmittedPattern, NonExhaustiveOmittedPatternLintOnArm, Overlap, + OverlappingRangeEndpoints, Uncovered, +}; use rustc_data_structures::captures::Captures; @@ -1149,28 +1152,45 @@ pub(crate) fn compute_match_usefulness<'p, 'tcx>( // Run the non_exhaustive_omitted_patterns lint. Only run on refutable patterns to avoid hitting // `if let`s. Only run if the match is exhaustive otherwise the error is redundant. - if cx.refutable - && non_exhaustiveness_witnesses.is_empty() - && !matches!( + if cx.refutable && non_exhaustiveness_witnesses.is_empty() { + if !matches!( cx.tcx.lint_level_at_node(NON_EXHAUSTIVE_OMITTED_PATTERNS, lint_root).0, rustc_session::lint::Level::Allow - ) - { - let witnesses = collect_nonexhaustive_missing_variants(cx, &pat_column); - if !witnesses.is_empty() { - // Report that a match of a `non_exhaustive` enum marked with `non_exhaustive_omitted_patterns` - // is not exhaustive enough. - // - // NB: The partner lint for structs lives in `compiler/rustc_hir_analysis/src/check/pat.rs`. - cx.tcx.emit_spanned_lint( - NON_EXHAUSTIVE_OMITTED_PATTERNS, - lint_root, - scrut_span, - NonExhaustiveOmittedPattern { - scrut_ty, - uncovered: Uncovered::new(scrut_span, cx, witnesses), - }, - ); + ) { + let witnesses = collect_nonexhaustive_missing_variants(cx, &pat_column); + + if !witnesses.is_empty() { + // Report that a match of a `non_exhaustive` enum marked with `non_exhaustive_omitted_patterns` + // is not exhaustive enough. + // + // NB: The partner lint for structs lives in `compiler/rustc_hir_analysis/src/check/pat.rs`. + cx.tcx.emit_spanned_lint( + NON_EXHAUSTIVE_OMITTED_PATTERNS, + lint_root, + scrut_span, + NonExhaustiveOmittedPattern { + scrut_ty, + uncovered: Uncovered::new(scrut_span, cx, witnesses), + }, + ); + } + } else { + // We used to allow putting the `#[allow(non_exhaustive_omitted_patterns)]` on a match + // arm. This no longer makes sense so we warn users, to avoid silently breaking their + // usage of the lint. + for arm in arms { + if !matches!( + cx.tcx.lint_level_at_node(NON_EXHAUSTIVE_OMITTED_PATTERNS, arm.hir_id).0, + rustc_session::lint::Level::Allow + ) { + cx.tcx.emit_spanned_lint( + NON_EXHAUSTIVE_OMITTED_PATTERNS, + arm.hir_id, + arm.pat.span(), + NonExhaustiveOmittedPatternLintOnArm, + ); + } + } } } diff --git a/src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.rs b/src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.rs index e1b95aa57760..5c277f925a8f 100644 --- a/src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.rs +++ b/src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.rs @@ -9,12 +9,12 @@ fn repeat() -> ! { } pub fn f(x: Ordering) { + #[deny(non_exhaustive_omitted_patterns)] match x { Ordering::Relaxed => println!("relaxed"), Ordering::Release => println!("release"), Ordering::Acquire => println!("acquire"), Ordering::AcqRel | Ordering::SeqCst => repeat(), - #[deny(non_exhaustive_omitted_patterns)] _ => repeat(), } } diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.lint.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.lint.stderr index c58b07d1aef2..b0629c6de1a4 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.lint.stderr +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.lint.stderr @@ -26,5 +26,44 @@ note: the lint level is defined here LL | #[cfg_attr(lint, deny(non_exhaustive_omitted_patterns))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error: the `non_exhaustive_omitted_pattern` lint level must be set on the whole match + --> $DIR/omitted-patterns-dont-lint-on-arm.rs:34:9 + | +LL | _ => {} + | ^ + | + = help: it used to make sense to set the lint level on an individual match arm, but that is no longer the case +note: the lint level is defined here + --> $DIR/omitted-patterns-dont-lint-on-arm.rs:33:16 + | +LL | #[deny(non_exhaustive_omitted_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: the `non_exhaustive_omitted_pattern` lint level must be set on the whole match + --> $DIR/omitted-patterns-dont-lint-on-arm.rs:41:9 + | +LL | _ => {} + | ^ + | + = help: it used to make sense to set the lint level on an individual match arm, but that is no longer the case +note: the lint level is defined here + --> $DIR/omitted-patterns-dont-lint-on-arm.rs:40:31 + | +LL | #[cfg_attr(lint, deny(non_exhaustive_omitted_patterns))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: the `non_exhaustive_omitted_pattern` lint level must be set on the whole match + --> $DIR/omitted-patterns-dont-lint-on-arm.rs:48:9 + | +LL | _ => {} + | ^ + | + = help: it used to make sense to set the lint level on an individual match arm, but that is no longer the case +note: the lint level is defined here + --> $DIR/omitted-patterns-dont-lint-on-arm.rs:47:31 + | +LL | #[cfg_attr(lint, warn(non_exhaustive_omitted_patterns))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors; 1 warning emitted diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.normal.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.normal.stderr index 2d94a09de634..a7a2ad3a5f0d 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.normal.stderr +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.normal.stderr @@ -12,5 +12,18 @@ note: the lint level is defined here LL | #[deny(non_exhaustive_omitted_patterns)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: the `non_exhaustive_omitted_pattern` lint level must be set on the whole match + --> $DIR/omitted-patterns-dont-lint-on-arm.rs:34:9 + | +LL | _ => {} + | ^ + | + = help: it used to make sense to set the lint level on an individual match arm, but that is no longer the case +note: the lint level is defined here + --> $DIR/omitted-patterns-dont-lint-on-arm.rs:33:16 + | +LL | #[deny(non_exhaustive_omitted_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.rs index 9411d8f085bb..ac7b7cd93fd1 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.rs +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.rs @@ -31,20 +31,20 @@ fn main() { NonExhaustiveEnum::Unit => {} NonExhaustiveEnum::Tuple(_) => {} #[deny(non_exhaustive_omitted_patterns)] - _ => {} + _ => {} //~ ERROR lint level must be set on the whole match } match val { NonExhaustiveEnum::Unit => {} NonExhaustiveEnum::Tuple(_) => {} #[cfg_attr(lint, deny(non_exhaustive_omitted_patterns))] - _ => {} + _ => {} //[lint]~ ERROR lint level must be set on the whole match } match val { NonExhaustiveEnum::Unit => {} NonExhaustiveEnum::Tuple(_) => {} #[cfg_attr(lint, warn(non_exhaustive_omitted_patterns))] - _ => {} + _ => {} //[lint]~ WARN lint level must be set on the whole match } } From f0e83308791698b47a738c8fe0a762624c88a2e0 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Thu, 2 Nov 2023 06:21:08 +0100 Subject: [PATCH 236/435] Suggest to set lint level on whole match --- compiler/rustc_mir_build/messages.ftl | 6 +- compiler/rustc_mir_build/src/errors.rs | 9 ++- .../src/thir/pattern/check_match.rs | 11 +++- .../src/thir/pattern/usefulness.rs | 27 +++++---- ...tted-patterns-dont-lint-on-arm.lint.stderr | 58 ++++++++++--------- ...ed-patterns-dont-lint-on-arm.normal.stderr | 16 ++--- .../omitted-patterns-dont-lint-on-arm.rs | 9 ++- 7 files changed, 84 insertions(+), 52 deletions(-) diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl index ed16d41a7433..563851f712c6 100644 --- a/compiler/rustc_mir_build/messages.ftl +++ b/compiler/rustc_mir_build/messages.ftl @@ -221,8 +221,10 @@ mir_build_non_exhaustive_omitted_pattern = some variants are not matched explici .help = ensure that all variants are matched explicitly by adding the suggested match arms .note = the matched value is of type `{$scrut_ty}` and the `non_exhaustive_omitted_patterns` attribute was found -mir_build_non_exhaustive_omitted_pattern_lint_on_arm = the `non_exhaustive_omitted_pattern` lint level must be set on the whole match - .help = it used to make sense to set the lint level on an individual match arm, but that is no longer the case +mir_build_non_exhaustive_omitted_pattern_lint_on_arm = the lint level must be set on the whole match + .help = it no longer has any effect to set the lint level on an individual match arm + .label = remove this attribute + .suggestion = set the lint level on the whole match mir_build_non_exhaustive_patterns_type_not_empty = non-exhaustive patterns: type `{$ty}` is non-empty .def_note = `{$peeled_ty}` defined here diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 378a957df0fb..c4eed5532ee6 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -792,7 +792,14 @@ pub(crate) struct NonExhaustiveOmittedPattern<'tcx> { #[derive(LintDiagnostic)] #[diag(mir_build_non_exhaustive_omitted_pattern_lint_on_arm)] #[help] -pub(crate) struct NonExhaustiveOmittedPatternLintOnArm; +pub(crate) struct NonExhaustiveOmittedPatternLintOnArm { + #[label] + pub lint_span: Span, + #[suggestion(code = "#[{lint_level}({lint_name})]\n", applicability = "maybe-incorrect")] + pub suggest_lint_on_match: Option, + pub lint_level: &'static str, + pub lint_name: &'static str, +} #[derive(Subdiagnostic)] #[label(mir_build_uncovered)] diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 165d3f37111e..8c3d09c19a15 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -285,7 +285,11 @@ impl<'thir, 'p, 'tcx> MatchVisitor<'thir, 'p, 'tcx> { } } - fn new_cx(&self, refutability: RefutableFlag) -> MatchCheckCtxt<'p, 'tcx> { + fn new_cx( + &self, + refutability: RefutableFlag, + match_span: Option, + ) -> MatchCheckCtxt<'p, 'tcx> { let refutable = match refutability { Irrefutable => false, Refutable => true, @@ -295,6 +299,7 @@ impl<'thir, 'p, 'tcx> MatchVisitor<'thir, 'p, 'tcx> { param_env: self.param_env, module: self.tcx.parent_module(self.lint_level).to_def_id(), pattern_arena: &self.pattern_arena, + match_span, refutable, } } @@ -325,7 +330,7 @@ impl<'thir, 'p, 'tcx> MatchVisitor<'thir, 'p, 'tcx> { source: hir::MatchSource, expr_span: Span, ) { - let cx = self.new_cx(Refutable); + let cx = self.new_cx(Refutable, Some(expr_span)); let mut tarms = Vec::with_capacity(arms.len()); for &arm in arms { @@ -448,7 +453,7 @@ impl<'thir, 'p, 'tcx> MatchVisitor<'thir, 'p, 'tcx> { pat: &Pat<'tcx>, refutability: RefutableFlag, ) -> Result<(MatchCheckCtxt<'p, 'tcx>, UsefulnessReport<'p, 'tcx>), ErrorGuaranteed> { - let cx = self.new_cx(refutability); + let cx = self.new_cx(refutability, None); let pat = self.lower_pattern(&cx, pat)?; let arms = [MatchArm { pat, hir_id: self.lint_level, has_guard: false }]; let report = compute_match_usefulness(&cx, &arms, self.lint_level, pat.ty(), pat.span()); diff --git a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs index 233b911bfee1..da7b6587a722 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs @@ -340,6 +340,8 @@ pub(crate) struct MatchCheckCtxt<'p, 'tcx> { pub(crate) module: DefId, pub(crate) param_env: ty::ParamEnv<'tcx>, pub(crate) pattern_arena: &'p TypedArena>, + /// The span of the whole match, if applicable. + pub(crate) match_span: Option, /// Only produce `NON_EXHAUSTIVE_OMITTED_PATTERNS` lint on refutable patterns. pub(crate) refutable: bool, } @@ -1179,16 +1181,21 @@ pub(crate) fn compute_match_usefulness<'p, 'tcx>( // arm. This no longer makes sense so we warn users, to avoid silently breaking their // usage of the lint. for arm in arms { - if !matches!( - cx.tcx.lint_level_at_node(NON_EXHAUSTIVE_OMITTED_PATTERNS, arm.hir_id).0, - rustc_session::lint::Level::Allow - ) { - cx.tcx.emit_spanned_lint( - NON_EXHAUSTIVE_OMITTED_PATTERNS, - arm.hir_id, - arm.pat.span(), - NonExhaustiveOmittedPatternLintOnArm, - ); + let (lint_level, lint_level_source) = + cx.tcx.lint_level_at_node(NON_EXHAUSTIVE_OMITTED_PATTERNS, arm.hir_id); + if !matches!(lint_level, rustc_session::lint::Level::Allow) { + let decorator = NonExhaustiveOmittedPatternLintOnArm { + lint_span: lint_level_source.span(), + suggest_lint_on_match: cx.match_span.map(|span| span.shrink_to_lo()), + lint_level: lint_level.as_str(), + lint_name: "non_exhaustive_omitted_patterns", + }; + + use rustc_errors::DecorateLint; + let mut err = cx.tcx.sess.struct_span_warn(arm.pat.span(), ""); + err.set_primary_message(decorator.msg()); + decorator.decorate_lint(&mut err); + err.emit(); } } } diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.lint.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.lint.stderr index b0629c6de1a4..9192c66143cc 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.lint.stderr +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.lint.stderr @@ -26,44 +26,50 @@ note: the lint level is defined here LL | #[cfg_attr(lint, deny(non_exhaustive_omitted_patterns))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: the `non_exhaustive_omitted_pattern` lint level must be set on the whole match +warning: the lint level must be set on the whole match --> $DIR/omitted-patterns-dont-lint-on-arm.rs:34:9 | -LL | _ => {} - | ^ - | - = help: it used to make sense to set the lint level on an individual match arm, but that is no longer the case -note: the lint level is defined here - --> $DIR/omitted-patterns-dont-lint-on-arm.rs:33:16 - | LL | #[deny(non_exhaustive_omitted_patterns)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: the `non_exhaustive_omitted_pattern` lint level must be set on the whole match - --> $DIR/omitted-patterns-dont-lint-on-arm.rs:41:9 - | + | ------------------------------- remove this attribute LL | _ => {} | ^ | - = help: it used to make sense to set the lint level on an individual match arm, but that is no longer the case -note: the lint level is defined here - --> $DIR/omitted-patterns-dont-lint-on-arm.rs:40:31 + = help: it no longer has any effect to set the lint level on an individual match arm +help: set the lint level on the whole match + | +LL + #[deny(non_exhaustive_omitted_patterns)] +LL | match val { + | + +warning: the lint level must be set on the whole match + --> $DIR/omitted-patterns-dont-lint-on-arm.rs:42:9 | LL | #[cfg_attr(lint, deny(non_exhaustive_omitted_patterns))] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -warning: the `non_exhaustive_omitted_pattern` lint level must be set on the whole match - --> $DIR/omitted-patterns-dont-lint-on-arm.rs:48:9 - | + | ------------------------------- remove this attribute LL | _ => {} | ^ | - = help: it used to make sense to set the lint level on an individual match arm, but that is no longer the case -note: the lint level is defined here - --> $DIR/omitted-patterns-dont-lint-on-arm.rs:47:31 + = help: it no longer has any effect to set the lint level on an individual match arm +help: set the lint level on the whole match + | +LL + #[deny(non_exhaustive_omitted_patterns)] +LL | match val { + | + +warning: the lint level must be set on the whole match + --> $DIR/omitted-patterns-dont-lint-on-arm.rs:50:9 | LL | #[cfg_attr(lint, warn(non_exhaustive_omitted_patterns))] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ------------------------------- remove this attribute +LL | _ => {} + | ^ + | + = help: it no longer has any effect to set the lint level on an individual match arm +help: set the lint level on the whole match + | +LL + #[warn(non_exhaustive_omitted_patterns)] +LL | match val { + | -error: aborting due to 4 previous errors; 1 warning emitted +error: aborting due to 2 previous errors; 3 warnings emitted diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.normal.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.normal.stderr index a7a2ad3a5f0d..46093eb9fb35 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.normal.stderr +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.normal.stderr @@ -12,18 +12,20 @@ note: the lint level is defined here LL | #[deny(non_exhaustive_omitted_patterns)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: the `non_exhaustive_omitted_pattern` lint level must be set on the whole match +warning: the lint level must be set on the whole match --> $DIR/omitted-patterns-dont-lint-on-arm.rs:34:9 | +LL | #[deny(non_exhaustive_omitted_patterns)] + | ------------------------------- remove this attribute LL | _ => {} | ^ | - = help: it used to make sense to set the lint level on an individual match arm, but that is no longer the case -note: the lint level is defined here - --> $DIR/omitted-patterns-dont-lint-on-arm.rs:33:16 + = help: it no longer has any effect to set the lint level on an individual match arm +help: set the lint level on the whole match + | +LL + #[deny(non_exhaustive_omitted_patterns)] +LL | match val { | -LL | #[deny(non_exhaustive_omitted_patterns)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to previous error; 1 warning emitted diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.rs index ac7b7cd93fd1..33f9f56a5bbc 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.rs +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.rs @@ -31,20 +31,23 @@ fn main() { NonExhaustiveEnum::Unit => {} NonExhaustiveEnum::Tuple(_) => {} #[deny(non_exhaustive_omitted_patterns)] - _ => {} //~ ERROR lint level must be set on the whole match + _ => {} } + //~^^ WARN lint level must be set on the whole match match val { NonExhaustiveEnum::Unit => {} NonExhaustiveEnum::Tuple(_) => {} #[cfg_attr(lint, deny(non_exhaustive_omitted_patterns))] - _ => {} //[lint]~ ERROR lint level must be set on the whole match + _ => {} } + //[lint]~^^ WARN lint level must be set on the whole match match val { NonExhaustiveEnum::Unit => {} NonExhaustiveEnum::Tuple(_) => {} #[cfg_attr(lint, warn(non_exhaustive_omitted_patterns))] - _ => {} //[lint]~ WARN lint level must be set on the whole match + _ => {} } + //[lint]~^^ WARN lint level must be set on the whole match } From 52933e0bd2006b948f174a256cca65197d2ff4a6 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sat, 4 Nov 2023 16:49:10 +0300 Subject: [PATCH 237/435] Don't disable inline asm usage in compiler-builtins when the cranelift backend is enabled This was a leftover from when inline asm wasn't universally supported by the cranelift backend yet. It would cause the optimized inline asm intrinsics to be avoided for the standard library distributed with rustup now that we build the cranelift backend by default on nightly for several tier 1 targets. --- src/bootstrap/src/core/build_steps/compile.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 1eed534150bb..8ab0ef61c502 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -413,11 +413,6 @@ pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, car let mut features = String::new(); - // Cranelift doesn't support `asm`. - if stage != 0 && builder.config.default_codegen_backend().unwrap_or_default() == "cranelift" { - features += " compiler-builtins-no-asm"; - } - if builder.no_std(target) == Some(true) { features += " compiler-builtins-mem"; if !target.starts_with("bpf") { From a4768fea3545a799b9c19e65777f6fee7b50a561 Mon Sep 17 00:00:00 2001 From: bohan Date: Sat, 4 Nov 2023 17:00:33 +0800 Subject: [PATCH 238/435] fallback for `construct_generic_bound_failure` --- .../src/infer/error_reporting/mod.rs | 20 +++++++++++-------- .../impl-trait/in-trait/async-and-ret-ref.rs | 11 ++++++++++ .../in-trait/async-and-ret-ref.stderr | 14 +++++++++++++ 3 files changed, 37 insertions(+), 8 deletions(-) create mode 100644 tests/ui/impl-trait/in-trait/async-and-ret-ref.rs create mode 100644 tests/ui/impl-trait/in-trait/async-and-ret-ref.stderr diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index e4be435fded3..26d071a01397 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -2444,18 +2444,22 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { let suggestion = if has_lifetimes { format!(" + {lt_name}") } else { format!(": {lt_name}") }; suggs.push((sp, suggestion)) - } else { - let generics = self.tcx.hir().get_generics(suggestion_scope).unwrap(); + } else if let Some(generics) = self.tcx.hir().get_generics(suggestion_scope) { let pred = format!("{bound_kind}: {lt_name}"); - let suggestion = format!("{} {}", generics.add_where_or_trailing_comma(), pred,); + let suggestion = format!("{} {}", generics.add_where_or_trailing_comma(), pred); suggs.push((generics.tail_span_for_predicate_suggestion(), suggestion)) + } else { + let consider = format!("{msg} `{bound_kind}: {sub}`..."); + err.help(consider); } - err.multipart_suggestion_verbose( - format!("{msg}"), - suggs, - Applicability::MaybeIncorrect, // Issue #41966 - ); + if !suggs.is_empty() { + err.multipart_suggestion_verbose( + format!("{msg}"), + suggs, + Applicability::MaybeIncorrect, // Issue #41966 + ); + } } err diff --git a/tests/ui/impl-trait/in-trait/async-and-ret-ref.rs b/tests/ui/impl-trait/in-trait/async-and-ret-ref.rs new file mode 100644 index 000000000000..af6ffe833945 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/async-and-ret-ref.rs @@ -0,0 +1,11 @@ +// edition:2021 +// https://github.com/rust-lang/rust/issues/117547 + +trait T {} + +trait MyTrait { + async fn foo() -> &'static impl T; + //~^ ERROR the associated type `::{opaque#0}` may not live long enough +} + +fn main() {} diff --git a/tests/ui/impl-trait/in-trait/async-and-ret-ref.stderr b/tests/ui/impl-trait/in-trait/async-and-ret-ref.stderr new file mode 100644 index 000000000000..7c9028a8cd53 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/async-and-ret-ref.stderr @@ -0,0 +1,14 @@ +error[E0310]: the associated type `::{opaque#0}` may not live long enough + --> $DIR/async-and-ret-ref.rs:7:5 + | +LL | async fn foo() -> &'static impl T; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | the associated type `::{opaque#0}` must be valid for the static lifetime... + | ...so that the reference type `&'static impl T` does not outlive the data it points at + | + = help: consider adding an explicit lifetime bound `::{opaque#0}: 'static`... + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0310`. From 8d8f06b277a12e19189d6b08dbd9893db3283e9d Mon Sep 17 00:00:00 2001 From: The 8472 Date: Sat, 4 Nov 2023 12:07:10 +0100 Subject: [PATCH 239/435] avoid excessive initialization when copying to a Vec It now keeps track of initialized bytes to avoid reinitialization. It also keeps track of read sizes to avoid initializing more bytes than the reader needs. This is important when passing a huge vector to a Read that only has a few bytes to offer and doesn't implement read_buf(). --- library/std/src/io/copy.rs | 64 ++++++++++++++++++++++++++++---------- 1 file changed, 47 insertions(+), 17 deletions(-) diff --git a/library/std/src/io/copy.rs b/library/std/src/io/copy.rs index 57d226a3771e..e05ec9bde243 100644 --- a/library/std/src/io/copy.rs +++ b/library/std/src/io/copy.rs @@ -1,6 +1,7 @@ use super::{BorrowedBuf, BufReader, BufWriter, Read, Result, Write, DEFAULT_BUF_SIZE}; use crate::alloc::Allocator; use crate::cmp; +use crate::cmp::min; use crate::collections::VecDeque; use crate::io::IoSlice; use crate::mem::MaybeUninit; @@ -271,28 +272,57 @@ impl BufferedWriterSpec for Vec { } } + // don't immediately offer the vec's whole spare capacity, otherwise + // we might have to fully initialize it if the reader doesn't have a custom read_buf() impl + let mut max_read_size = DEFAULT_BUF_SIZE; + loop { self.reserve(DEFAULT_BUF_SIZE); - let mut buf: BorrowedBuf<'_> = self.spare_capacity_mut().into(); - match reader.read_buf(buf.unfilled()) { - Ok(()) => {} - Err(e) if e.is_interrupted() => continue, - Err(e) => return Err(e), - }; + let mut initialized_spare_capacity = 0; - let read = buf.filled().len(); - if read == 0 { - break; + loop { + let buf = self.spare_capacity_mut(); + let read_size = min(max_read_size, buf.len()); + let mut buf = BorrowedBuf::from(&mut buf[..read_size]); + // SAFETY: init is either 0 or the init_len from the previous iteration. + unsafe { + buf.set_init(initialized_spare_capacity); + } + match reader.read_buf(buf.unfilled()) { + Ok(()) => { + let bytes_read = buf.len(); + + // EOF + if bytes_read == 0 { + return Ok(bytes); + } + + // the reader is returning short reads but it doesn't call ensure_init() + if buf.init_len() < buf.capacity() { + max_read_size = usize::MAX; + } + // the reader hasn't returned short reads so far + if bytes_read == buf.capacity() { + max_read_size *= 2; + } + + initialized_spare_capacity = buf.init_len() - bytes_read; + bytes += bytes_read as u64; + // SAFETY: BorrowedBuf guarantees all of its filled bytes are init + // and the number of read bytes can't exceed the spare capacity since + // that's what the buffer is borrowing from. + unsafe { self.set_len(self.len() + bytes_read) }; + + // spare capacity full, reserve more + if self.len() == self.capacity() { + break; + } + } + Err(e) if e.is_interrupted() => continue, + Err(e) => return Err(e), + } } - - // SAFETY: BorrowedBuf guarantees all of its filled bytes are init - // and the number of read bytes can't exceed the spare capacity since - // that's what the buffer is borrowing from. - unsafe { self.set_len(self.len() + read) }; - bytes += read as u64; } - - Ok(bytes) } } From 78aa5e511c0b205a742edffd48533670579ec247 Mon Sep 17 00:00:00 2001 From: The 8472 Date: Sat, 4 Nov 2023 12:09:27 +0100 Subject: [PATCH 240/435] detect EOF earlier The initial probe-for-empty-source by stack_buffer_copy only detected EOF if the source was empty but not when it was merely small which lead to additional calls to read() after Ok(0) had already been returned in the stack copy routine --- library/std/src/io/copy.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/library/std/src/io/copy.rs b/library/std/src/io/copy.rs index e05ec9bde243..4d51a719f6ca 100644 --- a/library/std/src/io/copy.rs +++ b/library/std/src/io/copy.rs @@ -264,11 +264,13 @@ impl BufferedWriterSpec for Vec { fn copy_from(&mut self, reader: &mut R) -> Result { let mut bytes = 0; - // avoid allocating before we have determined that there's anything to read - if self.capacity() == 0 { - bytes = stack_buffer_copy(&mut reader.take(DEFAULT_BUF_SIZE as u64), self)?; - if bytes == 0 { - return Ok(0); + // avoid inflating empty/small vecs before we have determined that there's anything to read + if self.capacity() < DEFAULT_BUF_SIZE { + let stack_read_limit = DEFAULT_BUF_SIZE as u64; + bytes = stack_buffer_copy(&mut reader.take(stack_read_limit), self)?; + // fewer bytes than requested -> EOF reached + if bytes < stack_read_limit { + return Ok(bytes); } } From bee7b5889e5f3544d7a197c52c9ca5dbc929be97 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 4 Nov 2023 16:24:30 +0000 Subject: [PATCH 241/435] Derive TyEncodable/TyDecodable implementations that are parameterized over interner --- compiler/rustc_macros/src/serialize.rs | 30 ++-- compiler/rustc_type_ir/src/canonical.rs | 29 +-- compiler/rustc_type_ir/src/const_kind.rs | 68 +------ compiler/rustc_type_ir/src/lib.rs | 2 + compiler/rustc_type_ir/src/predicate_kind.rs | 139 +-------------- compiler/rustc_type_ir/src/region_kind.rs | 73 +------- compiler/rustc_type_ir/src/ty_kind.rs | 176 +------------------ 7 files changed, 31 insertions(+), 486 deletions(-) diff --git a/compiler/rustc_macros/src/serialize.rs b/compiler/rustc_macros/src/serialize.rs index ba75517d7a66..047066ac6815 100644 --- a/compiler/rustc_macros/src/serialize.rs +++ b/compiler/rustc_macros/src/serialize.rs @@ -5,11 +5,16 @@ use syn::spanned::Spanned; pub fn type_decodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { let decoder_ty = quote! { __D }; - if !s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") { - s.add_impl_generic(parse_quote! { 'tcx }); - } - s.add_impl_generic(parse_quote! {#decoder_ty: ::rustc_type_ir::codec::TyDecoder>}); - s.add_bounds(synstructure::AddBounds::Generics); + let bound = if s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") { + quote! { > } + } else if s.ast().generics.type_params().any(|ty| ty.ident == "I") { + quote! { } + } else { + quote! {} + }; + + s.add_impl_generic(parse_quote! {#decoder_ty: ::rustc_type_ir::codec::TyDecoder #bound }); + s.add_bounds(synstructure::AddBounds::Fields); decodable_body(s, decoder_ty) } @@ -97,12 +102,17 @@ fn decode_field(field: &syn::Field) -> proc_macro2::TokenStream { } pub fn type_encodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { - if !s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") { - s.add_impl_generic(parse_quote! {'tcx}); - } + let bound = if s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") { + quote! { > } + } else if s.ast().generics.type_params().any(|ty| ty.ident == "I") { + quote! { } + } else { + quote! {} + }; + let encoder_ty = quote! { __E }; - s.add_impl_generic(parse_quote! {#encoder_ty: ::rustc_type_ir::codec::TyEncoder>}); - s.add_bounds(synstructure::AddBounds::Generics); + s.add_impl_generic(parse_quote! {#encoder_ty: ::rustc_type_ir::codec::TyEncoder #bound }); + s.add_bounds(synstructure::AddBounds::Fields); encodable_body(s, encoder_ty, false) } diff --git a/compiler/rustc_type_ir/src/canonical.rs b/compiler/rustc_type_ir/src/canonical.rs index c8e730b585ad..ace9eade7f69 100644 --- a/compiler/rustc_type_ir/src/canonical.rs +++ b/compiler/rustc_type_ir/src/canonical.rs @@ -3,18 +3,17 @@ use std::hash::Hash; use std::ops::ControlFlow; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; -use rustc_serialize::{Decodable, Encodable}; use crate::fold::{FallibleTypeFolder, TypeFoldable}; use crate::visit::{TypeVisitable, TypeVisitor}; -use crate::TyDecoder; -use crate::{HashStableContext, Interner, TyEncoder, UniverseIndex}; +use crate::{HashStableContext, Interner, UniverseIndex}; /// A "canonicalized" type `V` is one where all free inference /// variables have been rewritten to "canonical vars". These are /// numbered starting from 0 in order of first appearance. #[derive(derivative::Derivative)] #[derivative(Clone(bound = "V: Clone"), Hash(bound = "V: Hash"))] +#[derive(TyEncodable, TyDecodable)] pub struct Canonical { pub value: V, pub max_universe: UniverseIndex, @@ -127,27 +126,3 @@ where self.variables.visit_with(folder) } } - -impl, V: Encodable> Encodable for Canonical -where - I::CanonicalVars: Encodable, -{ - fn encode(&self, s: &mut E) { - self.value.encode(s); - self.max_universe.encode(s); - self.variables.encode(s); - } -} - -impl, V: Decodable> Decodable for Canonical -where - I::CanonicalVars: Decodable, -{ - fn decode(d: &mut D) -> Self { - Canonical { - value: Decodable::decode(d), - max_universe: Decodable::decode(d), - variables: Decodable::decode(d), - } - } -} diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs index cf67ba0b21a1..33782b13ca8f 100644 --- a/compiler/rustc_type_ir/src/const_kind.rs +++ b/compiler/rustc_type_ir/src/const_kind.rs @@ -1,12 +1,8 @@ use rustc_data_structures::stable_hasher::HashStable; use rustc_data_structures::stable_hasher::StableHasher; -use rustc_serialize::{Decodable, Decoder, Encodable}; use std::fmt; -use crate::{ - DebruijnIndex, DebugWithInfcx, HashStableContext, InferCtxtLike, Interner, TyDecoder, - TyEncoder, WithInfcx, -}; +use crate::{DebruijnIndex, DebugWithInfcx, HashStableContext, InferCtxtLike, Interner, WithInfcx}; use self::ConstKind::*; @@ -20,6 +16,7 @@ use self::ConstKind::*; Ord = "feature_allow_slow_enum", Hash(bound = "") )] +#[derive(TyEncodable, TyDecodable)] pub enum ConstKind { /// A const generic parameter. Param(I::ParamConst), @@ -92,67 +89,6 @@ where } } -impl> Decodable for ConstKind -where - I::ParamConst: Decodable, - I::InferConst: Decodable, - I::BoundConst: Decodable, - I::PlaceholderConst: Decodable, - I::AliasConst: Decodable, - I::ValueConst: Decodable, - I::ErrorGuaranteed: Decodable, - I::ExprConst: Decodable, -{ - fn decode(d: &mut D) -> Self { - match Decoder::read_usize(d) { - 0 => Param(Decodable::decode(d)), - 1 => Infer(Decodable::decode(d)), - 2 => Bound(Decodable::decode(d), Decodable::decode(d)), - 3 => Placeholder(Decodable::decode(d)), - 4 => Unevaluated(Decodable::decode(d)), - 5 => Value(Decodable::decode(d)), - 6 => Error(Decodable::decode(d)), - 7 => Expr(Decodable::decode(d)), - _ => panic!( - "{}", - format!( - "invalid enum variant tag while decoding `{}`, expected 0..{}", - "ConstKind", 8, - ) - ), - } - } -} - -impl> Encodable for ConstKind -where - I::ParamConst: Encodable, - I::InferConst: Encodable, - I::BoundConst: Encodable, - I::PlaceholderConst: Encodable, - I::AliasConst: Encodable, - I::ValueConst: Encodable, - I::ErrorGuaranteed: Encodable, - I::ExprConst: Encodable, -{ - fn encode(&self, e: &mut E) { - let disc = const_kind_discriminant(self); - match self { - Param(p) => e.emit_enum_variant(disc, |e| p.encode(e)), - Infer(i) => e.emit_enum_variant(disc, |e| i.encode(e)), - Bound(d, b) => e.emit_enum_variant(disc, |e| { - d.encode(e); - b.encode(e); - }), - Placeholder(p) => e.emit_enum_variant(disc, |e| p.encode(e)), - Unevaluated(u) => e.emit_enum_variant(disc, |e| u.encode(e)), - Value(v) => e.emit_enum_variant(disc, |e| v.encode(e)), - Error(er) => e.emit_enum_variant(disc, |e| er.encode(e)), - Expr(ex) => e.emit_enum_variant(disc, |e| ex.encode(e)), - } - } -} - impl PartialEq for ConstKind { fn eq(&self, other: &Self) -> bool { match (self, other) { diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index a056fbeda981..e8785fff2efc 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -10,6 +10,8 @@ #![deny(rustc::diagnostic_outside_of_impl)] #![allow(internal_features)] +extern crate self as rustc_type_ir; + #[macro_use] extern crate bitflags; #[macro_use] diff --git a/compiler/rustc_type_ir/src/predicate_kind.rs b/compiler/rustc_type_ir/src/predicate_kind.rs index 23117fdd5310..48662d426423 100644 --- a/compiler/rustc_type_ir/src/predicate_kind.rs +++ b/compiler/rustc_type_ir/src/predicate_kind.rs @@ -1,18 +1,16 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; -use rustc_serialize::Decoder; -use rustc_serialize::{Decodable, Encodable}; use std::fmt; use std::ops::ControlFlow; use crate::fold::{FallibleTypeFolder, TypeFoldable}; use crate::visit::{TypeVisitable, TypeVisitor}; use crate::{HashStableContext, Interner}; -use crate::{TyDecoder, TyEncoder}; /// A clause is something that can appear in where bounds or be inferred /// by implied bounds. #[derive(derivative::Derivative)] #[derivative(Clone(bound = ""), Hash(bound = ""))] +#[derive(TyEncodable, TyDecodable)] pub enum ClauseKind { /// Corresponds to `where Foo: Bar`. `Foo` here would be /// the `Self` type of the trait reference and `A`, `B`, and `C` @@ -161,65 +159,9 @@ where } } -impl> Decodable for ClauseKind -where - I::Ty: Decodable, - I::Const: Decodable, - I::GenericArg: Decodable, - I::TraitPredicate: Decodable, - I::ProjectionPredicate: Decodable, - I::TypeOutlivesPredicate: Decodable, - I::RegionOutlivesPredicate: Decodable, -{ - fn decode(d: &mut D) -> Self { - match Decoder::read_usize(d) { - 0 => ClauseKind::Trait(Decodable::decode(d)), - 1 => ClauseKind::RegionOutlives(Decodable::decode(d)), - 2 => ClauseKind::TypeOutlives(Decodable::decode(d)), - 3 => ClauseKind::Projection(Decodable::decode(d)), - 4 => ClauseKind::ConstArgHasType(Decodable::decode(d), Decodable::decode(d)), - 5 => ClauseKind::WellFormed(Decodable::decode(d)), - 6 => ClauseKind::ConstEvaluatable(Decodable::decode(d)), - _ => panic!( - "{}", - format!( - "invalid enum variant tag while decoding `{}`, expected 0..{}", - "ClauseKind", 7, - ) - ), - } - } -} - -impl Encodable for ClauseKind -where - I::Ty: Encodable, - I::Const: Encodable, - I::GenericArg: Encodable, - I::TraitPredicate: Encodable, - I::ProjectionPredicate: Encodable, - I::TypeOutlivesPredicate: Encodable, - I::RegionOutlivesPredicate: Encodable, -{ - fn encode(&self, s: &mut E) { - let discriminant = clause_kind_discriminant(self); - match self { - ClauseKind::Trait(p) => s.emit_enum_variant(discriminant, |s| p.encode(s)), - ClauseKind::RegionOutlives(p) => s.emit_enum_variant(discriminant, |s| p.encode(s)), - ClauseKind::TypeOutlives(p) => s.emit_enum_variant(discriminant, |s| p.encode(s)), - ClauseKind::Projection(p) => s.emit_enum_variant(discriminant, |s| p.encode(s)), - ClauseKind::ConstArgHasType(c, t) => s.emit_enum_variant(discriminant, |s| { - c.encode(s); - t.encode(s); - }), - ClauseKind::WellFormed(p) => s.emit_enum_variant(discriminant, |s| p.encode(s)), - ClauseKind::ConstEvaluatable(p) => s.emit_enum_variant(discriminant, |s| p.encode(s)), - } - } -} - #[derive(derivative::Derivative)] #[derivative(Clone(bound = ""), Hash(bound = ""))] +#[derive(TyEncodable, TyDecodable)] pub enum PredicateKind { /// Prove a clause Clause(ClauseKind), @@ -418,83 +360,6 @@ where } } -impl> Decodable for PredicateKind -where - I::DefId: Decodable, - I::Const: Decodable, - I::GenericArgs: Decodable, - I::Term: Decodable, - I::CoercePredicate: Decodable, - I::SubtypePredicate: Decodable, - I::ClosureKind: Decodable, - ClauseKind: Decodable, -{ - fn decode(d: &mut D) -> Self { - match Decoder::read_usize(d) { - 0 => PredicateKind::Clause(Decodable::decode(d)), - 1 => PredicateKind::ObjectSafe(Decodable::decode(d)), - 2 => PredicateKind::ClosureKind( - Decodable::decode(d), - Decodable::decode(d), - Decodable::decode(d), - ), - 3 => PredicateKind::Subtype(Decodable::decode(d)), - 4 => PredicateKind::Coerce(Decodable::decode(d)), - 5 => PredicateKind::ConstEquate(Decodable::decode(d), Decodable::decode(d)), - 6 => PredicateKind::Ambiguous, - 7 => PredicateKind::AliasRelate( - Decodable::decode(d), - Decodable::decode(d), - Decodable::decode(d), - ), - _ => panic!( - "{}", - format!( - "invalid enum variant tag while decoding `{}`, expected 0..{}", - "PredicateKind", 8, - ) - ), - } - } -} - -impl Encodable for PredicateKind -where - I::DefId: Encodable, - I::Const: Encodable, - I::GenericArgs: Encodable, - I::Term: Encodable, - I::CoercePredicate: Encodable, - I::SubtypePredicate: Encodable, - I::ClosureKind: Encodable, - ClauseKind: Encodable, -{ - fn encode(&self, s: &mut E) { - let discriminant = predicate_kind_discriminant(self); - match self { - PredicateKind::Clause(c) => s.emit_enum_variant(discriminant, |s| c.encode(s)), - PredicateKind::ObjectSafe(d) => s.emit_enum_variant(discriminant, |s| d.encode(s)), - PredicateKind::ClosureKind(d, g, k) => s.emit_enum_variant(discriminant, |s| { - d.encode(s); - g.encode(s); - k.encode(s); - }), - PredicateKind::Subtype(c) => s.emit_enum_variant(discriminant, |s| c.encode(s)), - PredicateKind::Coerce(c) => s.emit_enum_variant(discriminant, |s| c.encode(s)), - PredicateKind::ConstEquate(a, b) => s.emit_enum_variant(discriminant, |s| { - a.encode(s); - b.encode(s); - }), - PredicateKind::Ambiguous => s.emit_enum_variant(discriminant, |_s| {}), - PredicateKind::AliasRelate(a, b, d) => s.emit_enum_variant(discriminant, |s| { - a.encode(s); - b.encode(s); - d.encode(s); - }), - } - } -} - #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)] #[derive(HashStable_Generic, Encodable, Decodable)] pub enum AliasRelationDirection { diff --git a/compiler/rustc_type_ir/src/region_kind.rs b/compiler/rustc_type_ir/src/region_kind.rs index 72f86fc06929..69ed5badaea3 100644 --- a/compiler/rustc_type_ir/src/region_kind.rs +++ b/compiler/rustc_type_ir/src/region_kind.rs @@ -1,12 +1,8 @@ use rustc_data_structures::stable_hasher::HashStable; use rustc_data_structures::stable_hasher::StableHasher; -use rustc_serialize::{Decodable, Decoder, Encodable}; use std::fmt; -use crate::{ - DebruijnIndex, DebugWithInfcx, HashStableContext, InferCtxtLike, Interner, TyDecoder, - TyEncoder, WithInfcx, -}; +use crate::{DebruijnIndex, DebugWithInfcx, HashStableContext, InferCtxtLike, Interner, WithInfcx}; use self::RegionKind::*; @@ -125,6 +121,7 @@ use self::RegionKind::*; Ord = "feature_allow_slow_enum", Hash(bound = "") )] +#[derive(TyEncodable, TyDecodable)] pub enum RegionKind { /// Region bound in a type or fn declaration which will be /// substituted 'early' -- that is, at the same time when type @@ -245,72 +242,6 @@ impl fmt::Debug for RegionKind { } } -// This is manually implemented because a derive would require `I: Encodable` -impl> Encodable for RegionKind -where - I::EarlyBoundRegion: Encodable, - I::BoundRegion: Encodable, - I::FreeRegion: Encodable, - I::InferRegion: Encodable, - I::PlaceholderRegion: Encodable, -{ - fn encode(&self, e: &mut E) { - let disc = regionkind_discriminant(self); - match self { - ReEarlyBound(a) => e.emit_enum_variant(disc, |e| { - a.encode(e); - }), - ReLateBound(a, b) => e.emit_enum_variant(disc, |e| { - a.encode(e); - b.encode(e); - }), - ReFree(a) => e.emit_enum_variant(disc, |e| { - a.encode(e); - }), - ReStatic => e.emit_enum_variant(disc, |_| {}), - ReVar(a) => e.emit_enum_variant(disc, |e| { - a.encode(e); - }), - RePlaceholder(a) => e.emit_enum_variant(disc, |e| { - a.encode(e); - }), - ReErased => e.emit_enum_variant(disc, |_| {}), - ReError(_) => e.emit_enum_variant(disc, |_| {}), - } - } -} - -// This is manually implemented because a derive would require `I: Decodable` -impl> Decodable for RegionKind -where - I::EarlyBoundRegion: Decodable, - I::BoundRegion: Decodable, - I::FreeRegion: Decodable, - I::InferRegion: Decodable, - I::PlaceholderRegion: Decodable, - I::ErrorGuaranteed: Decodable, -{ - fn decode(d: &mut D) -> Self { - match Decoder::read_usize(d) { - 0 => ReEarlyBound(Decodable::decode(d)), - 1 => ReLateBound(Decodable::decode(d), Decodable::decode(d)), - 2 => ReFree(Decodable::decode(d)), - 3 => ReStatic, - 4 => ReVar(Decodable::decode(d)), - 5 => RePlaceholder(Decodable::decode(d)), - 6 => ReErased, - 7 => ReError(Decodable::decode(d)), - _ => panic!( - "{}", - format!( - "invalid enum variant tag while decoding `{}`, expected 0..{}", - "RegionKind", 8, - ) - ), - } - } -} - // This is not a derived impl because a derive would require `I: HashStable` impl HashStable for RegionKind where diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index 2138c2733413..09a9a332269e 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -2,14 +2,11 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::unify::{EqUnifyValue, UnifyKey}; -use rustc_serialize::{Decodable, Decoder, Encodable}; use std::fmt; use std::mem::discriminant; use crate::HashStableContext; use crate::Interner; -use crate::TyDecoder; -use crate::TyEncoder; use crate::{DebruijnIndex, DebugWithInfcx, InferCtxtLike, WithInfcx}; use self::TyKind::*; @@ -122,6 +119,7 @@ pub enum AliasKind { Ord = "feature_allow_slow_enum", Hash(bound = "") )] +#[derive(TyEncodable, TyDecodable)] pub enum TyKind { /// The primitive boolean type. Written as `bool`. Bool, @@ -472,178 +470,6 @@ impl fmt::Debug for TyKind { } } -// This is manually implemented because a derive would require `I: Encodable` -impl> Encodable for TyKind -where - I::ErrorGuaranteed: Encodable, - I::AdtDef: Encodable, - I::GenericArgs: Encodable, - I::DefId: Encodable, - I::Ty: Encodable, - I::Const: Encodable, - I::Region: Encodable, - I::TypeAndMut: Encodable, - I::PolyFnSig: Encodable, - I::BoundExistentialPredicates: Encodable, - I::Tys: Encodable, - I::AliasTy: Encodable, - I::ParamTy: Encodable, - I::BoundTy: Encodable, - I::PlaceholderTy: Encodable, - I::InferTy: Encodable, - I::AllocId: Encodable, -{ - fn encode(&self, e: &mut E) { - let disc = tykind_discriminant(self); - match self { - Bool => e.emit_enum_variant(disc, |_| {}), - Char => e.emit_enum_variant(disc, |_| {}), - Int(i) => e.emit_enum_variant(disc, |e| { - i.encode(e); - }), - Uint(u) => e.emit_enum_variant(disc, |e| { - u.encode(e); - }), - Float(f) => e.emit_enum_variant(disc, |e| { - f.encode(e); - }), - Adt(adt, args) => e.emit_enum_variant(disc, |e| { - adt.encode(e); - args.encode(e); - }), - Foreign(def_id) => e.emit_enum_variant(disc, |e| { - def_id.encode(e); - }), - Str => e.emit_enum_variant(disc, |_| {}), - Array(t, c) => e.emit_enum_variant(disc, |e| { - t.encode(e); - c.encode(e); - }), - Slice(t) => e.emit_enum_variant(disc, |e| { - t.encode(e); - }), - RawPtr(tam) => e.emit_enum_variant(disc, |e| { - tam.encode(e); - }), - Ref(r, t, m) => e.emit_enum_variant(disc, |e| { - r.encode(e); - t.encode(e); - m.encode(e); - }), - FnDef(def_id, args) => e.emit_enum_variant(disc, |e| { - def_id.encode(e); - args.encode(e); - }), - FnPtr(polyfnsig) => e.emit_enum_variant(disc, |e| { - polyfnsig.encode(e); - }), - Dynamic(l, r, repr) => e.emit_enum_variant(disc, |e| { - l.encode(e); - r.encode(e); - repr.encode(e); - }), - Closure(def_id, args) => e.emit_enum_variant(disc, |e| { - def_id.encode(e); - args.encode(e); - }), - Coroutine(def_id, args, m) => e.emit_enum_variant(disc, |e| { - def_id.encode(e); - args.encode(e); - m.encode(e); - }), - CoroutineWitness(def_id, args) => e.emit_enum_variant(disc, |e| { - def_id.encode(e); - args.encode(e); - }), - Never => e.emit_enum_variant(disc, |_| {}), - Tuple(args) => e.emit_enum_variant(disc, |e| { - args.encode(e); - }), - Alias(k, p) => e.emit_enum_variant(disc, |e| { - k.encode(e); - p.encode(e); - }), - Param(p) => e.emit_enum_variant(disc, |e| { - p.encode(e); - }), - Bound(d, b) => e.emit_enum_variant(disc, |e| { - d.encode(e); - b.encode(e); - }), - Placeholder(p) => e.emit_enum_variant(disc, |e| { - p.encode(e); - }), - Infer(i) => e.emit_enum_variant(disc, |e| { - i.encode(e); - }), - Error(d) => e.emit_enum_variant(disc, |e| { - d.encode(e); - }), - } - } -} - -// This is manually implemented because a derive would require `I: Decodable` -impl> Decodable for TyKind -where - I::ErrorGuaranteed: Decodable, - I::AdtDef: Decodable, - I::GenericArgs: Decodable, - I::DefId: Decodable, - I::Ty: Decodable, - I::Const: Decodable, - I::Region: Decodable, - I::TypeAndMut: Decodable, - I::PolyFnSig: Decodable, - I::BoundExistentialPredicates: Decodable, - I::Tys: Decodable, - I::AliasTy: Decodable, - I::ParamTy: Decodable, - I::AliasTy: Decodable, - I::BoundTy: Decodable, - I::PlaceholderTy: Decodable, - I::InferTy: Decodable, - I::AllocId: Decodable, -{ - fn decode(d: &mut D) -> Self { - match Decoder::read_usize(d) { - 0 => Bool, - 1 => Char, - 2 => Int(Decodable::decode(d)), - 3 => Uint(Decodable::decode(d)), - 4 => Float(Decodable::decode(d)), - 5 => Adt(Decodable::decode(d), Decodable::decode(d)), - 6 => Foreign(Decodable::decode(d)), - 7 => Str, - 8 => Array(Decodable::decode(d), Decodable::decode(d)), - 9 => Slice(Decodable::decode(d)), - 10 => RawPtr(Decodable::decode(d)), - 11 => Ref(Decodable::decode(d), Decodable::decode(d), Decodable::decode(d)), - 12 => FnDef(Decodable::decode(d), Decodable::decode(d)), - 13 => FnPtr(Decodable::decode(d)), - 14 => Dynamic(Decodable::decode(d), Decodable::decode(d), Decodable::decode(d)), - 15 => Closure(Decodable::decode(d), Decodable::decode(d)), - 16 => Coroutine(Decodable::decode(d), Decodable::decode(d), Decodable::decode(d)), - 17 => CoroutineWitness(Decodable::decode(d), Decodable::decode(d)), - 18 => Never, - 19 => Tuple(Decodable::decode(d)), - 20 => Alias(Decodable::decode(d), Decodable::decode(d)), - 21 => Param(Decodable::decode(d)), - 22 => Bound(Decodable::decode(d), Decodable::decode(d)), - 23 => Placeholder(Decodable::decode(d)), - 24 => Infer(Decodable::decode(d)), - 25 => Error(Decodable::decode(d)), - _ => panic!( - "{}", - format!( - "invalid enum variant tag while decoding `{}`, expected 0..{}", - "TyKind", 26, - ) - ), - } - } -} - // This is not a derived impl because a derive would require `I: HashStable` #[allow(rustc::usage_of_ty_tykind)] impl HashStable for TyKind From f9bd7dabcf36a10fb0d4c6d5e56b8431fd59f4be Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Tue, 4 Jul 2023 14:23:16 -0400 Subject: [PATCH 242/435] Check alignment of pointers only when read/written through --- .../src/check_alignment.rs | 107 +++++++++--------- tests/debuginfo/simple-struct.rs | 2 +- .../mir/{ => alignment}/addrof_alignment.rs | 3 +- .../i686-pc-windows-msvc.rs} | 4 +- .../misaligned_lhs.rs} | 4 +- tests/ui/mir/alignment/misaligned_rhs.rs | 13 +++ tests/ui/mir/alignment/packed.rs | 29 +++++ tests/ui/mir/alignment/place_computation.rs | 16 +++ tests/ui/mir/alignment/place_without_read.rs | 9 ++ tests/ui/mir/alignment/two_pointers.rs | 15 +++ 10 files changed, 143 insertions(+), 59 deletions(-) rename tests/ui/mir/{ => alignment}/addrof_alignment.rs (64%) rename tests/ui/mir/{mir_alignment_check_i686-pc-windows-msvc.rs => alignment/i686-pc-windows-msvc.rs} (85%) rename tests/ui/mir/{mir_alignment_check.rs => alignment/misaligned_lhs.rs} (75%) create mode 100644 tests/ui/mir/alignment/misaligned_rhs.rs create mode 100644 tests/ui/mir/alignment/packed.rs create mode 100644 tests/ui/mir/alignment/place_computation.rs create mode 100644 tests/ui/mir/alignment/place_without_read.rs create mode 100644 tests/ui/mir/alignment/two_pointers.rs diff --git a/compiler/rustc_mir_transform/src/check_alignment.rs b/compiler/rustc_mir_transform/src/check_alignment.rs index 28765af20ad3..42b2f18869c2 100644 --- a/compiler/rustc_mir_transform/src/check_alignment.rs +++ b/compiler/rustc_mir_transform/src/check_alignment.rs @@ -1,13 +1,12 @@ use crate::MirPass; -use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; use rustc_index::IndexVec; use rustc_middle::mir::*; use rustc_middle::mir::{ interpret::Scalar, - visit::{PlaceContext, Visitor}, + visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor}, }; -use rustc_middle::ty::{Ty, TyCtxt, TypeAndMut}; +use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, TypeAndMut}; use rustc_session::Session; pub struct CheckAlignment; @@ -30,7 +29,12 @@ impl<'tcx> MirPass<'tcx> for CheckAlignment { let basic_blocks = body.basic_blocks.as_mut(); let local_decls = &mut body.local_decls; + let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); + // This pass inserts new blocks. Each insertion changes the Location for all + // statements/blocks after. Iterating or visiting the MIR in order would require updating + // our current location after every insertion. By iterating backwards, we dodge this issue: + // The only Locations that an insertion changes have already been handled. for block in (0..basic_blocks.len()).rev() { let block = block.into(); for statement_index in (0..basic_blocks[block].statements.len()).rev() { @@ -38,22 +42,19 @@ impl<'tcx> MirPass<'tcx> for CheckAlignment { let statement = &basic_blocks[block].statements[statement_index]; let source_info = statement.source_info; - let mut finder = PointerFinder { - local_decls, - tcx, - pointers: Vec::new(), - def_id: body.source.def_id(), - }; - for (pointer, pointee_ty) in finder.find_pointers(statement) { - debug!("Inserting alignment check for {:?}", pointer.ty(&*local_decls, tcx).ty); + let mut finder = + PointerFinder { tcx, local_decls, param_env, pointers: Vec::new() }; + finder.visit_statement(statement, location); + for (local, ty) in finder.pointers { + debug!("Inserting alignment check for {:?}", ty); let new_block = split_block(basic_blocks, location); insert_alignment_check( tcx, local_decls, &mut basic_blocks[block], - pointer, - pointee_ty, + local, + ty, source_info, new_block, ); @@ -63,69 +64,71 @@ impl<'tcx> MirPass<'tcx> for CheckAlignment { } } -impl<'tcx, 'a> PointerFinder<'tcx, 'a> { - fn find_pointers(&mut self, statement: &Statement<'tcx>) -> Vec<(Place<'tcx>, Ty<'tcx>)> { - self.pointers.clear(); - self.visit_statement(statement, Location::START); - core::mem::take(&mut self.pointers) - } -} - struct PointerFinder<'tcx, 'a> { - local_decls: &'a mut LocalDecls<'tcx>, tcx: TyCtxt<'tcx>, - def_id: DefId, + local_decls: &'a mut LocalDecls<'tcx>, + param_env: ParamEnv<'tcx>, pointers: Vec<(Place<'tcx>, Ty<'tcx>)>, } impl<'tcx, 'a> Visitor<'tcx> for PointerFinder<'tcx, 'a> { - fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) { - if let Rvalue::AddressOf(..) = rvalue { - // Ignore dereferences inside of an AddressOf - return; + fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) { + // We want to only check reads and writes to Places, so we specifically exclude + // Borrows and AddressOf. + match context { + PlaceContext::MutatingUse( + MutatingUseContext::Store + | MutatingUseContext::AsmOutput + | MutatingUseContext::Call + | MutatingUseContext::Yield + | MutatingUseContext::Drop, + ) => {} + PlaceContext::NonMutatingUse( + NonMutatingUseContext::Copy | NonMutatingUseContext::Move, + ) => {} + _ => { + return; + } } - self.super_rvalue(rvalue, location); - } - fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, _location: Location) { - if let PlaceContext::NonUse(_) = context { - return; - } if !place.is_indirect() { return; } + // Since Deref projections must come first and only once, the pointer for an indirect place + // is the Local that the Place is based on. let pointer = Place::from(place.local); - let pointer_ty = pointer.ty(&*self.local_decls, self.tcx).ty; + let pointer_ty = self.local_decls[place.local].ty; - // We only want to check unsafe pointers + // We only want to check places based on unsafe pointers if !pointer_ty.is_unsafe_ptr() { - trace!("Indirect, but not an unsafe ptr, not checking {:?}", pointer_ty); + trace!("Indirect, but not based on an unsafe ptr, not checking {:?}", place); return; } - let Some(pointee) = pointer_ty.builtin_deref(true) else { - debug!("Indirect but no builtin deref: {:?}", pointer_ty); + let pointee_ty = + pointer_ty.builtin_deref(true).expect("no builtin_deref for an unsafe pointer").ty; + // Ideally we'd support this in the future, but for now we are limited to sized types. + if !pointee_ty.is_sized(self.tcx, self.param_env) { + debug!("Unsafe pointer, but pointee is not known to be sized: {:?}", pointer_ty); return; + } + + // Try to detect types we are sure have an alignment of 1 and skip the check + // We don't need to look for str and slices, we already rejected unsized types above + let element_ty = match pointee_ty.kind() { + ty::Array(ty, _) => *ty, + _ => pointee_ty, }; - let mut pointee_ty = pointee.ty; - if pointee_ty.is_array() || pointee_ty.is_slice() || pointee_ty.is_str() { - pointee_ty = pointee_ty.sequence_element_type(self.tcx); - } - - if !pointee_ty.is_sized(self.tcx, self.tcx.param_env_reveal_all_normalized(self.def_id)) { - debug!("Unsafe pointer, but unsized: {:?}", pointer_ty); + if [self.tcx.types.bool, self.tcx.types.i8, self.tcx.types.u8].contains(&element_ty) { + debug!("Trivially aligned place type: {:?}", pointee_ty); return; } - if [self.tcx.types.bool, self.tcx.types.i8, self.tcx.types.u8, self.tcx.types.str_] - .contains(&pointee_ty) - { - debug!("Trivially aligned pointee type: {:?}", pointer_ty); - return; - } + // Ensure that this place is based on an aligned pointer. + self.pointers.push((pointer, pointee_ty)); - self.pointers.push((pointer, pointee_ty)) + self.super_place(place, context, location); } } diff --git a/tests/debuginfo/simple-struct.rs b/tests/debuginfo/simple-struct.rs index aa3cf023a718..fea8109223ad 100644 --- a/tests/debuginfo/simple-struct.rs +++ b/tests/debuginfo/simple-struct.rs @@ -1,7 +1,7 @@ // min-lldb-version: 310 // ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155 -// compile-flags:-g +// compile-flags: -g -Zmir-enable-passes=-CheckAlignment // === GDB TESTS =================================================================================== diff --git a/tests/ui/mir/addrof_alignment.rs b/tests/ui/mir/alignment/addrof_alignment.rs similarity index 64% rename from tests/ui/mir/addrof_alignment.rs rename to tests/ui/mir/alignment/addrof_alignment.rs index 892638bfb92b..f3423e97a8a0 100644 --- a/tests/ui/mir/addrof_alignment.rs +++ b/tests/ui/mir/alignment/addrof_alignment.rs @@ -1,5 +1,4 @@ // run-pass -// ignore-wasm32-bare: No panic messages // compile-flags: -C debug-assertions struct Misalignment { @@ -9,7 +8,7 @@ struct Misalignment { fn main() { let items: [Misalignment; 2] = [Misalignment { a: 0 }, Misalignment { a: 1 }]; unsafe { - let ptr: *const Misalignment = items.as_ptr().cast::().add(1).cast::(); + let ptr: *const Misalignment = items.as_ptr().byte_add(1); let _ptr = core::ptr::addr_of!((*ptr).a); } } diff --git a/tests/ui/mir/mir_alignment_check_i686-pc-windows-msvc.rs b/tests/ui/mir/alignment/i686-pc-windows-msvc.rs similarity index 85% rename from tests/ui/mir/mir_alignment_check_i686-pc-windows-msvc.rs rename to tests/ui/mir/alignment/i686-pc-windows-msvc.rs index 56388c1047e9..74ba1fde6499 100644 --- a/tests/ui/mir/mir_alignment_check_i686-pc-windows-msvc.rs +++ b/tests/ui/mir/alignment/i686-pc-windows-msvc.rs @@ -11,9 +11,9 @@ fn main() { let mut x = [0u64; 2]; - let ptr: *mut u8 = x.as_mut_ptr().cast::(); + let ptr = x.as_mut_ptr(); unsafe { - let misaligned = ptr.add(4).cast::(); + let misaligned = ptr.byte_add(4); assert!(misaligned.addr() % 8 != 0); assert!(misaligned.addr() % 4 == 0); *misaligned = 42; diff --git a/tests/ui/mir/mir_alignment_check.rs b/tests/ui/mir/alignment/misaligned_lhs.rs similarity index 75% rename from tests/ui/mir/mir_alignment_check.rs rename to tests/ui/mir/alignment/misaligned_lhs.rs index d1bf3d46a7c7..97644ba8e094 100644 --- a/tests/ui/mir/mir_alignment_check.rs +++ b/tests/ui/mir/alignment/misaligned_lhs.rs @@ -6,8 +6,8 @@ fn main() { let mut x = [0u32; 2]; - let ptr: *mut u8 = x.as_mut_ptr().cast::(); + let ptr = x.as_mut_ptr(); unsafe { - *(ptr.add(1).cast::()) = 42; + *(ptr.byte_add(1)) = 42; } } diff --git a/tests/ui/mir/alignment/misaligned_rhs.rs b/tests/ui/mir/alignment/misaligned_rhs.rs new file mode 100644 index 000000000000..8534bc71a3a2 --- /dev/null +++ b/tests/ui/mir/alignment/misaligned_rhs.rs @@ -0,0 +1,13 @@ +// run-fail +// ignore-wasm32-bare: No panic messages +// ignore-i686-pc-windows-msvc: #112480 +// compile-flags: -C debug-assertions +// error-pattern: misaligned pointer dereference: address must be a multiple of 0x4 but is + +fn main() { + let mut x = [0u32; 2]; + let ptr = x.as_mut_ptr(); + unsafe { + let _v = *(ptr.byte_add(1)); + } +} diff --git a/tests/ui/mir/alignment/packed.rs b/tests/ui/mir/alignment/packed.rs new file mode 100644 index 000000000000..754698591e33 --- /dev/null +++ b/tests/ui/mir/alignment/packed.rs @@ -0,0 +1,29 @@ +// run-pass +// compile-flags: -C debug-assertions + +#![feature(strict_provenance, pointer_is_aligned)] + +#[repr(packed)] +struct Misaligner { + _head: u8, + tail: u64, +} + +fn main() { + let memory = [Misaligner { _head: 0, tail: 0}, Misaligner { _head: 0, tail: 0}]; + // Test that we can use addr_of! to get the address of a packed member which according to its + // type is not aligned, but because it is a projection from a packed type is a valid place. + let ptr0 = std::ptr::addr_of!(memory[0].tail); + let ptr1 = std::ptr::addr_of!(memory[0].tail); + // Even if ptr0 happens to be aligned by chance, ptr1 is not. + assert!(!ptr0.is_aligned() || !ptr1.is_aligned()); + + // And also test that we can get the addr of a packed struct then do a member read from it. + unsafe { + let ptr = std::ptr::addr_of!(memory[0]); + let _tail = (*ptr).tail; + + let ptr = std::ptr::addr_of!(memory[1]); + let _tail = (*ptr).tail; + } +} diff --git a/tests/ui/mir/alignment/place_computation.rs b/tests/ui/mir/alignment/place_computation.rs new file mode 100644 index 000000000000..fdd4864250ac --- /dev/null +++ b/tests/ui/mir/alignment/place_computation.rs @@ -0,0 +1,16 @@ +// run-pass +// compile-flags: -C debug-assertions + +#[repr(align(8))] +struct Misalignment { + a: u8, +} + +fn main() { + let mem = 0u64; + let ptr = &mem as *const u64 as *const Misalignment; + unsafe { + let ptr = ptr.byte_add(1); + let _ref: &u8 = &(*ptr).a; + } +} diff --git a/tests/ui/mir/alignment/place_without_read.rs b/tests/ui/mir/alignment/place_without_read.rs new file mode 100644 index 000000000000..b4be7a50f61d --- /dev/null +++ b/tests/ui/mir/alignment/place_without_read.rs @@ -0,0 +1,9 @@ +// run-pass +// compile-flags: -C debug-assertions + +fn main() { + let ptr = 1 as *const u16; + unsafe { + let _ = *ptr; + } +} diff --git a/tests/ui/mir/alignment/two_pointers.rs b/tests/ui/mir/alignment/two_pointers.rs new file mode 100644 index 000000000000..29af21dffc19 --- /dev/null +++ b/tests/ui/mir/alignment/two_pointers.rs @@ -0,0 +1,15 @@ +// run-fail +// ignore-wasm32-bare: No panic messages +// ignore-i686-pc-windows-msvc: #112480 +// compile-flags: -C debug-assertions +// error-pattern: misaligned pointer dereference: address must be a multiple of 0x4 but is + +fn main() { + let x = [0u32; 2]; + let ptr = x.as_ptr(); + let mut dest = 0u32; + let dest_ptr = &mut dest as *mut u32; + unsafe { + *dest_ptr = *(ptr.byte_add(1)); + } +} From 5d3535c616e4f23b5c2d82102a0d3eae9f3e7ee4 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sat, 4 Nov 2023 13:11:10 -0400 Subject: [PATCH 243/435] Bump compiler_builtins to 0.1.103 --- Cargo.lock | 4 ++-- library/std/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d56d7e3f2b03..54d315c47cd8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -722,9 +722,9 @@ checksum = "55b672471b4e9f9e95499ea597ff64941a309b2cdbffcc46f2cc5e2d971fd335" [[package]] name = "compiler_builtins" -version = "0.1.101" +version = "0.1.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01a6d58e9c3408138099a396a98fd0d0e6cfb25d723594d2ae48b5004513fd5b" +checksum = "a3b73c3443a5fd2438d7ba4853c64e4c8efc2404a9e28a9234cc2d5eebc6c242" dependencies = [ "cc", "rustc-std-workspace-core", diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 2eb7608c7ae6..f3e79b28faf8 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -18,7 +18,7 @@ panic_unwind = { path = "../panic_unwind", optional = true } panic_abort = { path = "../panic_abort" } core = { path = "../core", public = true } libc = { version = "0.2.149", default-features = false, features = ['rustc-dep-of-std'], public = true } -compiler_builtins = { version = "0.1.100" } +compiler_builtins = { version = "0.1.103" } profiler_builtins = { path = "../profiler_builtins", optional = true } unwind = { path = "../unwind" } hashbrown = { version = "0.14", default-features = false, features = ['rustc-dep-of-std'] } From bcb97ea22122735aa3d19addeb35eed91cf07e89 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 4 Nov 2023 17:19:16 +0000 Subject: [PATCH 244/435] No lifetime on PlaceholderConst --- compiler/rustc_middle/src/infer/canonical.rs | 2 +- compiler/rustc_middle/src/ty/consts.rs | 2 +- compiler/rustc_middle/src/ty/context.rs | 2 +- compiler/rustc_middle/src/ty/mod.rs | 2 +- compiler/rustc_trait_selection/src/traits/project.rs | 10 +++++----- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs index 0b5426c3bb1a..64b63f4c5eb4 100644 --- a/compiler/rustc_middle/src/infer/canonical.rs +++ b/compiler/rustc_middle/src/infer/canonical.rs @@ -222,7 +222,7 @@ pub enum CanonicalVarKind<'tcx> { Effect, /// A "placeholder" that represents "any const". - PlaceholderConst(ty::PlaceholderConst<'tcx>, Ty<'tcx>), + PlaceholderConst(ty::PlaceholderConst, Ty<'tcx>), } impl<'tcx> CanonicalVarKind<'tcx> { diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index cfacccd26799..af5ffc20d489 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -84,7 +84,7 @@ impl<'tcx> Const<'tcx> { #[inline] pub fn new_placeholder( tcx: TyCtxt<'tcx>, - placeholder: ty::PlaceholderConst<'tcx>, + placeholder: ty::PlaceholderConst, ty: Ty<'tcx>, ) -> Const<'tcx> { Const::new(tcx, ty::ConstKind::Placeholder(placeholder), ty) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 68812bba42fd..551c4a15dd0d 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -106,7 +106,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type Const = ty::Const<'tcx>; type InferConst = ty::InferConst; type AliasConst = ty::UnevaluatedConst<'tcx>; - type PlaceholderConst = ty::PlaceholderConst<'tcx>; + type PlaceholderConst = ty::PlaceholderConst; type ParamConst = ty::ParamConst; type BoundConst = ty::BoundVar; type ValueConst = ty::ValTree<'tcx>; diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 739d4fa886ec..f6ef1783aa41 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1527,7 +1527,7 @@ pub struct BoundConst<'tcx> { pub ty: Ty<'tcx>, } -pub type PlaceholderConst<'tcx> = Placeholder; +pub type PlaceholderConst = Placeholder; /// When type checking, we use the `ParamEnv` to track /// details about the set of where-clauses that are in scope at this diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index e4f7592c409e..471d10dbdbd8 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -783,7 +783,7 @@ pub struct BoundVarReplacer<'me, 'tcx> { // the `var` (but we *could* bring that into scope if we were to track them as we pass them). mapped_regions: BTreeMap, mapped_types: BTreeMap, - mapped_consts: BTreeMap, ty::BoundVar>, + mapped_consts: BTreeMap, // The current depth relative to *this* folding, *not* the entire normalization. In other words, // the depth of binders we've passed here. current_index: ty::DebruijnIndex, @@ -843,11 +843,11 @@ impl<'me, 'tcx> BoundVarReplacer<'me, 'tcx> { T, BTreeMap, BTreeMap, - BTreeMap, ty::BoundVar>, + BTreeMap, ) { let mapped_regions: BTreeMap = BTreeMap::new(); let mapped_types: BTreeMap = BTreeMap::new(); - let mapped_consts: BTreeMap, ty::BoundVar> = BTreeMap::new(); + let mapped_consts: BTreeMap = BTreeMap::new(); let mut replacer = BoundVarReplacer { infcx, @@ -966,7 +966,7 @@ pub struct PlaceholderReplacer<'me, 'tcx> { infcx: &'me InferCtxt<'tcx>, mapped_regions: BTreeMap, mapped_types: BTreeMap, - mapped_consts: BTreeMap, ty::BoundVar>, + mapped_consts: BTreeMap, universe_indices: &'me [Option], current_index: ty::DebruijnIndex, } @@ -976,7 +976,7 @@ impl<'me, 'tcx> PlaceholderReplacer<'me, 'tcx> { infcx: &'me InferCtxt<'tcx>, mapped_regions: BTreeMap, mapped_types: BTreeMap, - mapped_consts: BTreeMap, ty::BoundVar>, + mapped_consts: BTreeMap, universe_indices: &'me [Option], value: T, ) -> T { From 7a2f83fa3f78181af159c03c60a974ac3554dd05 Mon Sep 17 00:00:00 2001 From: jmaargh Date: Fri, 14 Apr 2023 23:49:57 +0100 Subject: [PATCH 245/435] Draft fleshed-out deref docs Re-draft Deref docs Make general advice more explicit and note the difference between generic and specific implementations. Re-draft DerefMut docs in-line with Deref Fix Deref docs typos Fix broken links Clarify advice for specific-over-generic impls Add comment addressing Issue #73682 x fmt Copy faillibility warning to DerefMut --- library/core/src/convert/mod.rs | 4 +- library/core/src/ops/deref.rs | 162 ++++++++++++++++++++++++-------- 2 files changed, 125 insertions(+), 41 deletions(-) diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs index 89125b7955e0..8c01b0973d65 100644 --- a/library/core/src/convert/mod.rs +++ b/library/core/src/convert/mod.rs @@ -138,7 +138,7 @@ pub const fn identity(x: T) -> T { /// /// [dereferenceable types]: core::ops::Deref /// [pointed-to value]: core::ops::Deref::Target -/// ['`Deref` coercion']: core::ops::Deref#more-on-deref-coercion +/// ['`Deref` coercion']: core::ops::Deref#deref-coercion /// /// ``` /// let x = Box::new(5i32); @@ -244,7 +244,7 @@ pub trait AsRef { /// /// [mutably dereferenceable types]: core::ops::DerefMut /// [pointed-to value]: core::ops::Deref::Target -/// ['`Deref` coercion']: core::ops::DerefMut#more-on-deref-coercion +/// ['`Deref` coercion']: core::ops::DerefMut#mutable-deref-coercion /// /// ``` /// let mut x = Box::new(5i32); diff --git a/library/core/src/ops/deref.rs b/library/core/src/ops/deref.rs index d6f2f5ca3662..99adbb91599a 100644 --- a/library/core/src/ops/deref.rs +++ b/library/core/src/ops/deref.rs @@ -3,40 +3,107 @@ /// In addition to being used for explicit dereferencing operations with the /// (unary) `*` operator in immutable contexts, `Deref` is also used implicitly /// by the compiler in many circumstances. This mechanism is called -/// ['`Deref` coercion'][more]. In mutable contexts, [`DerefMut`] is used. +/// ["`Deref` coercion"][coercion]. In mutable contexts, [`DerefMut`] is used and +/// mutable deref coercion similarly occurs. /// -/// Implementing `Deref` for smart pointers makes accessing the data behind them -/// convenient, which is why they implement `Deref`. On the other hand, the -/// rules regarding `Deref` and [`DerefMut`] were designed specifically to -/// accommodate smart pointers. Because of this, **`Deref` should only be -/// implemented for smart pointers** to avoid confusion. +/// **Warning:** Deref coercion is a powerful language feature which has +/// far-reaching implications for every type that implements `Deref`. The +/// compiler will silently insert calls to `Deref::deref`. For this reason, one +/// should be careful about implementing `Deref` and only do so when deref +/// coercion is desirable. See [below][implementing] for advice on when this is +/// typically desirable or undesirable. /// -/// For similar reasons, **this trait should never fail**. Failure during -/// dereferencing can be extremely confusing when `Deref` is invoked implicitly. +/// Types that implement `Deref` or `DerefMut` are often called "smart +/// pointers" and the mechanism of deref coercion has been specifically designed +/// to facilitate the pointer-like behaviour that name suggests. Often, the +/// purpose of a "smart pointer" type is to change the ownership semantics +/// of a contained value (for example, [`Rc`][rc] or [`Cow`][cow]) or the +/// storage semantics of a contained value (for example, [`Box`][box]). /// -/// Violating these requirements is a logic error. The behavior resulting from a logic error is not -/// specified, but users of the trait must ensure that such logic errors do *not* result in -/// undefined behavior. This means that `unsafe` code **must not** rely on the correctness of this -/// method. +/// # Deref coercion /// -/// # More on `Deref` coercion +/// If `T` implements `Deref`, and `v` is a value of type `T`, then: /// -/// If `T` implements `Deref`, and `x` is a value of type `T`, then: -/// -/// * In immutable contexts, `*x` (where `T` is neither a reference nor a raw pointer) -/// is equivalent to `*Deref::deref(&x)`. +/// * In immutable contexts, `*v` (where `T` is neither a reference nor a raw +/// pointer) is equivalent to `*Deref::deref(&v)`. /// * Values of type `&T` are coerced to values of type `&U` -/// * `T` implicitly implements all the (immutable) methods of the type `U`. +/// * `T` implicitly implements all the methods of the type `U` which take the +/// `&self` receiver. /// /// For more details, visit [the chapter in *The Rust Programming Language*][book] /// as well as the reference sections on [the dereference operator][ref-deref-op], -/// [method resolution] and [type coercions]. +/// [method resolution], and [type coercions]. +/// +/// # When to implement `Deref` or `DerefMut` +/// +/// The same advice applies to both deref traits. In general, deref traits +/// **should** be implemented if: +/// +/// 1. a value of the type transparently behaves like a value of the target +/// type; +/// 1. the implementation of the deref function is cheap; and +/// 1. users of the type will not be surprised by any deref coercion behaviour. +/// +/// In general, deref traits **should not** be implemented if: +/// +/// 1. the deref implementations could fail unexpectedly; or +/// 1. the type has methods that are likely to collide with methods on the +/// target type; or +/// 1. committing to deref coercion as part of the public API is not desirable. +/// +/// Note that there's a large difference between implementing deref traits +/// generically over many target types, and doing so only for specific target +/// types. +/// +/// Generic implementations, such as for [`Box`][box] (which is generic over +/// every type and dereferences to `T`) should be careful to provide few or no +/// methods, since the target type is unknown and therefore every method could +/// collide with one on the target type, causing confusion for users. +/// `impl Box` has no methods (though several associated functions), +/// partly for this reason. +/// +/// Specific implementations, such as for [`String`][string] (whose `Deref` +/// implementation has `Target = str`) can have many methods, since avoiding +/// collision is much easier. `String` and `str` both have many methods, and +/// `String` additionally behaves as if it has every method of `str` because of +/// deref coercion. The implementing type may also be generic while the +/// implementation is still specific in this sense; for example, [`Vec`][vec] +/// dereferences to `[T]`, so methods of `T` are not applicable. +/// +/// Consider also that deref coericion means that deref traits are a much larger +/// part of a type's public API than any other trait as it is implicitly called +/// by the compiler. Therefore, it is advisable to consider whether this is +/// something you are comfortable supporting as a public API. +/// +/// The [`AsRef`] and [`Borrow`][core::borrow::Borrow] traits have very similar +/// signatures to `Deref`. It may be desirable to implement either or both of +/// these, whether in addition to or rather than deref traits. See their +/// documentation for details. +/// +/// # Fallibility +/// +/// **This trait's method should never unexpectedly fail**. Deref coercion means +/// the compiler will often insert calls to `Deref::deref` implicitly. Failure +/// during dereferencing can be extremely confusing when `Deref` is invoked +/// implicitly. In the majority of uses it should be infallible, though it may +/// be acceptable to panic if the type is misused through programmer error, for +/// example. +/// +/// However, infallibility is not enforced and therefore not guaranteed. +/// As such, `unsafe` code should not rely on infallibility in general for +/// soundness. /// /// [book]: ../../book/ch15-02-deref.html -/// [more]: #more-on-deref-coercion +/// [coercion]: #deref-coercion +/// [implementing]: #when-to-implement-deref-or-derefmut /// [ref-deref-op]: ../../reference/expressions/operator-expr.html#the-dereference-operator /// [method resolution]: ../../reference/expressions/method-call-expr.html /// [type coercions]: ../../reference/type-coercions.html +/// [box]: ../../alloc/boxed/struct.Box.html +/// [string]: ../../alloc/string/struct.String.html +/// [vec]: ../../alloc/vec/struct.Vec.html +/// [rc]: ../../alloc/rc/struct.Rc.html +/// [cow]: ../../alloc/borrow/enum.Cow.html /// /// # Examples /// @@ -107,30 +174,29 @@ impl Deref for &mut T { /// In addition to being used for explicit dereferencing operations with the /// (unary) `*` operator in mutable contexts, `DerefMut` is also used implicitly /// by the compiler in many circumstances. This mechanism is called -/// ['`Deref` coercion'][more]. In immutable contexts, [`Deref`] is used. +/// ["mutable deref coercion"][coercion]. In immutable contexts, [`Deref`] is used. /// -/// Implementing `DerefMut` for smart pointers makes mutating the data behind -/// them convenient, which is why they implement `DerefMut`. On the other hand, -/// the rules regarding [`Deref`] and `DerefMut` were designed specifically to -/// accommodate smart pointers. Because of this, **`DerefMut` should only be -/// implemented for smart pointers** to avoid confusion. +/// **Warning:** Deref coercion is a powerful language feature which has +/// far-reaching implications for every type that implements `DerefMut`. The +/// compiler will silently insert calls to `DerefMut::deref_mut`. For this +/// reason, one should be careful about implementing `DerefMut` and only do so +/// when mutable deref coercion is desirable. See [the `Deref` docs][implementing] +/// for advice on when this is typically desirable or undesirable. /// -/// For similar reasons, **this trait should never fail**. Failure during -/// dereferencing can be extremely confusing when `DerefMut` is invoked -/// implicitly. +/// Types that implement `DerefMut` or `Deref` are often called "smart +/// pointers" and the mechanism of deref coercion has been specifically designed +/// to facilitate the pointer-like behaviour that name suggests. Often, the +/// purpose of a "smart pointer" type is to change the ownership semantics +/// of a contained value (for example, [`Rc`][rc] or [`Cow`][cow]) or the +/// storage semantics of a contained value (for example, [`Box`][box]). /// -/// Violating these requirements is a logic error. The behavior resulting from a logic error is not -/// specified, but users of the trait must ensure that such logic errors do *not* result in -/// undefined behavior. This means that `unsafe` code **must not** rely on the correctness of this -/// method. +/// # Mutable deref coercion /// -/// # More on `Deref` coercion -/// -/// If `T` implements `DerefMut`, and `x` is a value of type `T`, +/// If `T` implements `DerefMut`, and `v` is a value of type `T`, /// then: /// -/// * In mutable contexts, `*x` (where `T` is neither a reference nor a raw pointer) -/// is equivalent to `*DerefMut::deref_mut(&mut x)`. +/// * In mutable contexts, `*v` (where `T` is neither a reference nor a raw pointer) +/// is equivalent to `*DerefMut::deref_mut(&mut v)`. /// * Values of type `&mut T` are coerced to values of type `&mut U` /// * `T` implicitly implements all the (mutable) methods of the type `U`. /// @@ -138,11 +204,29 @@ impl Deref for &mut T { /// as well as the reference sections on [the dereference operator][ref-deref-op], /// [method resolution] and [type coercions]. /// +/// # Fallibility +/// +/// **This trait's method should never unexpectedly fail**. Deref coercion means +/// the compiler will often insert calls to `DerefMut::deref_mut` implicitly. +/// Failure during dereferencing can be extremely confusing when `DerefMut` is +/// invoked implicitly. In the majority of uses it should be infallible, though +/// it may be acceptable to panic if the type is misused through programmer +/// error, for example. +/// +/// However, infallibility is not enforced and therefore not guaranteed. +/// As such, `unsafe` code should not rely on infallibility in general for +/// soundness. +/// /// [book]: ../../book/ch15-02-deref.html -/// [more]: #more-on-deref-coercion +/// [coercion]: #mutable-deref-coercion +/// [implementing]: Deref#when-to-implement-deref-or-derefmut /// [ref-deref-op]: ../../reference/expressions/operator-expr.html#the-dereference-operator /// [method resolution]: ../../reference/expressions/method-call-expr.html /// [type coercions]: ../../reference/type-coercions.html +/// [box]: ../../alloc/boxed/struct.Box.html +/// [string]: ../../alloc/string/struct.String.html +/// [rc]: ../../alloc/rc/struct.Rc.html +/// [cow]: ../../alloc/borrow/enum.Cow.html /// /// # Examples /// From 8de489918ba83e3b6080f10cd6294434564028fa Mon Sep 17 00:00:00 2001 From: Dinu Blanovschi Date: Sat, 4 Nov 2023 19:39:32 +0100 Subject: [PATCH 246/435] feat(hir): Store the `Span` of the `move` keyword --- compiler/rustc_ast/src/ast.rs | 5 ++++- compiler/rustc_parse/src/parser/expr.rs | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 146a4db200ca..c85ff6f5c445 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1548,7 +1548,10 @@ pub struct QSelf { #[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)] pub enum CaptureBy { /// `move |x| y + x`. - Value, + Value { + /// The span of the `move` keyword. + move_kw: Span, + }, /// `move` keyword was not specified. Ref, } diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 36125e138b2d..2bae5d4ba18a 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2303,13 +2303,16 @@ impl<'a> Parser<'a> { /// Parses an optional `move` prefix to a closure-like construct. fn parse_capture_clause(&mut self) -> PResult<'a, CaptureBy> { if self.eat_keyword(kw::Move) { + let move_kw_span = self.prev_token.span; // Check for `move async` and recover if self.check_keyword(kw::Async) { let move_async_span = self.token.span.with_lo(self.prev_token.span.data().lo); Err(errors::AsyncMoveOrderIncorrect { span: move_async_span } .into_diagnostic(&self.sess.span_diagnostic)) } else { - Ok(CaptureBy::Value) + Ok(CaptureBy::Value { + move_kw: move_kw_span, + }) } } else { Ok(CaptureBy::Ref) From 241a654c07e0741ea1f32ea9f41761bcf6adcefc Mon Sep 17 00:00:00 2001 From: Dinu Blanovschi Date: Sat, 4 Nov 2023 19:48:44 +0100 Subject: [PATCH 247/435] Fix remaining uses of `CaptureBy::Value` --- compiler/rustc_ast_lowering/src/item.rs | 2 +- compiler/rustc_ast_pretty/src/pprust/state/expr.rs | 2 +- compiler/rustc_hir_pretty/src/lib.rs | 2 +- compiler/rustc_hir_typeck/src/upvar.rs | 10 +++++----- .../src/traits/error_reporting/suggestions.rs | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index c73d2382db80..9a70e6d7c4a1 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1201,7 +1201,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } let async_expr = this.make_async_expr( - CaptureBy::Value, + CaptureBy::Value { move_kw: rustc_span::DUMMY_SP }, closure_id, None, body.span, diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs index e84af12d3f9c..edbc3500373b 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs @@ -673,7 +673,7 @@ impl<'a> State<'a> { fn print_capture_clause(&mut self, capture_clause: ast::CaptureBy) { match capture_clause { - ast::CaptureBy::Value => self.word_space("move"), + ast::CaptureBy::Value { .. } => self.word_space("move"), ast::CaptureBy::Ref => {} } } diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 1ce6bb6ca15f..5f82d9f06c6e 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -2017,7 +2017,7 @@ impl<'a> State<'a> { fn print_capture_clause(&mut self, capture_clause: hir::CaptureBy) { match capture_clause { - hir::CaptureBy::Value => self.word_space("move"), + hir::CaptureBy::Value { .. } => self.word_space("move"), hir::CaptureBy::Ref => {} } } diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index 75c70ec59fb7..a05372bfcd42 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -424,7 +424,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { origin = updated.1; let (place, capture_kind) = match capture_clause { - hir::CaptureBy::Value => adjust_for_move_closure(place, capture_kind), + hir::CaptureBy::Value { .. } => adjust_for_move_closure(place, capture_kind), hir::CaptureBy::Ref => adjust_for_non_move_closure(place, capture_kind), }; @@ -958,7 +958,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let ty = self.resolve_vars_if_possible(self.node_ty(var_hir_id)); let ty = match closure_clause { - hir::CaptureBy::Value => ty, // For move closure the capture kind should be by value + hir::CaptureBy::Value { .. } => ty, // For move closure the capture kind should be by value hir::CaptureBy::Ref => { // For non move closure the capture kind is the max capture kind of all captures // according to the ordering ImmBorrow < UniqueImmBorrow < MutBorrow < ByValue @@ -1073,7 +1073,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match closure_clause { // Only migrate if closure is a move closure - hir::CaptureBy::Value => { + hir::CaptureBy::Value { .. } => { let mut diagnostics_info = FxIndexSet::default(); let upvars = self.tcx.upvars_mentioned(closure_def_id).expect("must be an upvar"); @@ -1479,10 +1479,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // If the data will be moved out of this place, then the place will be truncated // at the first Deref in `adjust_upvar_borrow_kind_for_consume` and then moved into // the closure. - hir::CaptureBy::Value if !place.deref_tys().any(Ty::is_ref) => { + hir::CaptureBy::Value { .. } if !place.deref_tys().any(Ty::is_ref) => { ty::UpvarCapture::ByValue } - hir::CaptureBy::Value | hir::CaptureBy::Ref => ty::UpvarCapture::ByRef(ty::ImmBorrow), + hir::CaptureBy::Value { .. } | hir::CaptureBy::Ref => ty::UpvarCapture::ByRef(ty::ImmBorrow), } } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 31da437f2e90..78ceddcd2630 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -2938,7 +2938,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { else { bug!("expected closure in SizedClosureCapture obligation"); }; - if let hir::CaptureBy::Value = closure.capture_clause + if let hir::CaptureBy::Value { .. } = closure.capture_clause && let Some(span) = closure.fn_arg_span { err.span_label(span, "this closure captures all values by move"); From a6b41aa6baa1eb9011732c341dadde4fc3c422d9 Mon Sep 17 00:00:00 2001 From: Dinu Blanovschi Date: Sat, 4 Nov 2023 20:04:02 +0100 Subject: [PATCH 248/435] fmt --- compiler/rustc_hir_typeck/src/upvar.rs | 4 +++- compiler/rustc_parse/src/parser/expr.rs | 4 +--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index a05372bfcd42..17b81acd506a 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -1482,7 +1482,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { hir::CaptureBy::Value { .. } if !place.deref_tys().any(Ty::is_ref) => { ty::UpvarCapture::ByValue } - hir::CaptureBy::Value { .. } | hir::CaptureBy::Ref => ty::UpvarCapture::ByRef(ty::ImmBorrow), + hir::CaptureBy::Value { .. } | hir::CaptureBy::Ref => { + ty::UpvarCapture::ByRef(ty::ImmBorrow) + } } } diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 2bae5d4ba18a..19690a6964be 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2310,9 +2310,7 @@ impl<'a> Parser<'a> { Err(errors::AsyncMoveOrderIncorrect { span: move_async_span } .into_diagnostic(&self.sess.span_diagnostic)) } else { - Ok(CaptureBy::Value { - move_kw: move_kw_span, - }) + Ok(CaptureBy::Value { move_kw: move_kw_span }) } } else { Ok(CaptureBy::Ref) From 1f09bae6a8c5fe82587f3bdf6d4d271823b5c0d5 Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Sat, 4 Nov 2023 19:05:50 +0000 Subject: [PATCH 249/435] Implement min/max neon intrisics --- build_system/tests.rs | 1 + config.txt | 1 + example/neon.rs | 155 +++++++++++++++++++++++++++++++++ src/intrinsics/llvm_aarch64.rs | 91 +++++++++++++++---- src/intrinsics/mod.rs | 30 +++++++ 5 files changed, 259 insertions(+), 19 deletions(-) create mode 100644 example/neon.rs diff --git a/build_system/tests.rs b/build_system/tests.rs index 1e24d1b113fe..10736ff9a55c 100644 --- a/build_system/tests.rs +++ b/build_system/tests.rs @@ -99,6 +99,7 @@ const BASE_SYSROOT_SUITE: &[TestCase] = &[ TestCase::build_bin_and_run("aot.mod_bench", "example/mod_bench.rs", &[]), TestCase::build_bin_and_run("aot.issue-72793", "example/issue-72793.rs", &[]), TestCase::build_bin("aot.issue-59326", "example/issue-59326.rs"), + TestCase::build_bin_and_run("aot.neon", "example/neon.rs", &[]), ]; pub(crate) static RAND_REPO: GitRepo = GitRepo::github( diff --git a/config.txt b/config.txt index 7ff805e58d96..2ccdc7d78748 100644 --- a/config.txt +++ b/config.txt @@ -42,6 +42,7 @@ aot.float-minmax-pass aot.mod_bench aot.issue-72793 aot.issue-59326 +aot.neon testsuite.extended_sysroot test.rust-random/rand diff --git a/example/neon.rs b/example/neon.rs new file mode 100644 index 000000000000..0e23e862df1f --- /dev/null +++ b/example/neon.rs @@ -0,0 +1,155 @@ +// Most of these tests are copied from https://github.com/japaric/stdsimd/blob/0f4413d01c4f0c3ffbc5a69e9a37fbc7235b31a9/coresimd/arm/neon.rs + +#![feature(portable_simd)] +use std::arch::aarch64::*; +use std::mem::transmute; +use std::simd::*; + +#[cfg(target_arch = "aarch64")] +unsafe fn test_vpmin_s8() { + let a = i8x8::from([1, -2, 3, -4, 5, 6, 7, 8]); + let b = i8x8::from([0, 3, 2, 5, 4, 7, 6, 9]); + let e = i8x8::from([-2, -4, 5, 7, 0, 2, 4, 6]); + let r: i8x8 = transmute(vpmin_s8(transmute(a), transmute(b))); + assert_eq!(r, e); +} + +#[cfg(target_arch = "aarch64")] +unsafe fn test_vpmin_s16() { + let a = i16x4::from([1, 2, 3, -4]); + let b = i16x4::from([0, 3, 2, 5]); + let e = i16x4::from([1, -4, 0, 2]); + let r: i16x4 = transmute(vpmin_s16(transmute(a), transmute(b))); + assert_eq!(r, e); +} + +#[cfg(target_arch = "aarch64")] +unsafe fn test_vpmin_s32() { + let a = i32x2::from([1, -2]); + let b = i32x2::from([0, 3]); + let e = i32x2::from([-2, 0]); + let r: i32x2 = transmute(vpmin_s32(transmute(a), transmute(b))); + assert_eq!(r, e); +} + +#[cfg(target_arch = "aarch64")] +unsafe fn test_vpmin_u8() { + let a = u8x8::from([1, 2, 3, 4, 5, 6, 7, 8]); + let b = u8x8::from([0, 3, 2, 5, 4, 7, 6, 9]); + let e = u8x8::from([1, 3, 5, 7, 0, 2, 4, 6]); + let r: u8x8 = transmute(vpmin_u8(transmute(a), transmute(b))); + assert_eq!(r, e); +} + +#[cfg(target_arch = "aarch64")] +unsafe fn test_vpmin_u16() { + let a = u16x4::from([1, 2, 3, 4]); + let b = u16x4::from([0, 3, 2, 5]); + let e = u16x4::from([1, 3, 0, 2]); + let r: u16x4 = transmute(vpmin_u16(transmute(a), transmute(b))); + assert_eq!(r, e); +} + +#[cfg(target_arch = "aarch64")] +unsafe fn test_vpmin_u32() { + let a = u32x2::from([1, 2]); + let b = u32x2::from([0, 3]); + let e = u32x2::from([1, 0]); + let r: u32x2 = transmute(vpmin_u32(transmute(a), transmute(b))); + assert_eq!(r, e); +} + +#[cfg(target_arch = "aarch64")] +unsafe fn test_vpmin_f32() { + let a = f32x2::from([1., -2.]); + let b = f32x2::from([0., 3.]); + let e = f32x2::from([-2., 0.]); + let r: f32x2 = transmute(vpmin_f32(transmute(a), transmute(b))); + assert_eq!(r, e); +} + +#[cfg(target_arch = "aarch64")] +unsafe fn test_vpmax_s8() { + let a = i8x8::from([1, -2, 3, -4, 5, 6, 7, 8]); + let b = i8x8::from([0, 3, 2, 5, 4, 7, 6, 9]); + let e = i8x8::from([1, 3, 6, 8, 3, 5, 7, 9]); + let r: i8x8 = transmute(vpmax_s8(transmute(a), transmute(b))); + assert_eq!(r, e); +} + +#[cfg(target_arch = "aarch64")] +unsafe fn test_vpmax_s16() { + let a = i16x4::from([1, 2, 3, -4]); + let b = i16x4::from([0, 3, 2, 5]); + let e = i16x4::from([2, 3, 3, 5]); + let r: i16x4 = transmute(vpmax_s16(transmute(a), transmute(b))); + assert_eq!(r, e); +} + +#[cfg(target_arch = "aarch64")] +unsafe fn test_vpmax_s32() { + let a = i32x2::from([1, -2]); + let b = i32x2::from([0, 3]); + let e = i32x2::from([1, 3]); + let r: i32x2 = transmute(vpmax_s32(transmute(a), transmute(b))); + assert_eq!(r, e); +} + +#[cfg(target_arch = "aarch64")] +unsafe fn test_vpmax_u8() { + let a = u8x8::from([1, 2, 3, 4, 5, 6, 7, 8]); + let b = u8x8::from([0, 3, 2, 5, 4, 7, 6, 9]); + let e = u8x8::from([2, 4, 6, 8, 3, 5, 7, 9]); + let r: u8x8 = transmute(vpmax_u8(transmute(a), transmute(b))); + assert_eq!(r, e); +} + +#[cfg(target_arch = "aarch64")] +unsafe fn test_vpmax_u16() { + let a = u16x4::from([1, 2, 3, 4]); + let b = u16x4::from([0, 3, 2, 5]); + let e = u16x4::from([2, 4, 3, 5]); + let r: u16x4 = transmute(vpmax_u16(transmute(a), transmute(b))); + assert_eq!(r, e); +} + +#[cfg(target_arch = "aarch64")] +unsafe fn test_vpmax_u32() { + let a = u32x2::from([1, 2]); + let b = u32x2::from([0, 3]); + let e = u32x2::from([2, 3]); + let r: u32x2 = transmute(vpmax_u32(transmute(a), transmute(b))); + assert_eq!(r, e); +} + +#[cfg(target_arch = "aarch64")] +unsafe fn test_vpmax_f32() { + let a = f32x2::from([1., -2.]); + let b = f32x2::from([0., 3.]); + let e = f32x2::from([1., 3.]); + let r: f32x2 = transmute(vpmax_f32(transmute(a), transmute(b))); + assert_eq!(r, e); +} + +#[cfg(target_arch = "aarch64")] +fn main() { + unsafe { + test_vpmin_s8(); + test_vpmin_s16(); + test_vpmin_s32(); + test_vpmin_u8(); + test_vpmin_u16(); + test_vpmin_u32(); + test_vpmin_f32(); + test_vpmax_s8(); + test_vpmax_s16(); + test_vpmax_s32(); + test_vpmax_u8(); + test_vpmax_u16(); + test_vpmax_u32(); + test_vpmax_f32(); + } +} + +#[cfg(target_arch = "x86_64")] +fn main() {} diff --git a/src/intrinsics/llvm_aarch64.rs b/src/intrinsics/llvm_aarch64.rs index 0c211a06dc4a..ed318a89fa05 100644 --- a/src/intrinsics/llvm_aarch64.rs +++ b/src/intrinsics/llvm_aarch64.rs @@ -156,6 +156,78 @@ pub(crate) fn codegen_aarch64_llvm_intrinsic_call<'tcx>( }); } + _ if intrinsic.starts_with("llvm.aarch64.neon.umaxp.v") => { + intrinsic_args!(fx, args => (x, y); intrinsic); + + simd_horizontal_pair_for_each_lane( + fx, + x, + y, + ret, + &|fx, _lane_ty, _res_lane_ty, x_lane, y_lane| fx.bcx.ins().umax(x_lane, y_lane), + ); + } + + _ if intrinsic.starts_with("llvm.aarch64.neon.smaxp.v") => { + intrinsic_args!(fx, args => (x, y); intrinsic); + + simd_horizontal_pair_for_each_lane( + fx, + x, + y, + ret, + &|fx, _lane_ty, _res_lane_ty, x_lane, y_lane| fx.bcx.ins().smax(x_lane, y_lane), + ); + } + + _ if intrinsic.starts_with("llvm.aarch64.neon.uminp.v") => { + intrinsic_args!(fx, args => (x, y); intrinsic); + + simd_horizontal_pair_for_each_lane( + fx, + x, + y, + ret, + &|fx, _lane_ty, _res_lane_ty, x_lane, y_lane| fx.bcx.ins().umin(x_lane, y_lane), + ); + } + + _ if intrinsic.starts_with("llvm.aarch64.neon.sminp.v") => { + intrinsic_args!(fx, args => (x, y); intrinsic); + + simd_horizontal_pair_for_each_lane( + fx, + x, + y, + ret, + &|fx, _lane_ty, _res_lane_ty, x_lane, y_lane| fx.bcx.ins().smin(x_lane, y_lane), + ); + } + + _ if intrinsic.starts_with("llvm.aarch64.neon.fminp.v") => { + intrinsic_args!(fx, args => (x, y); intrinsic); + + simd_horizontal_pair_for_each_lane( + fx, + x, + y, + ret, + &|fx, _lane_ty, _res_lane_ty, x_lane, y_lane| fx.bcx.ins().fmin(x_lane, y_lane), + ); + } + + _ if intrinsic.starts_with("llvm.aarch64.neon.fmaxp.v") => { + intrinsic_args!(fx, args => (x, y); intrinsic); + + simd_horizontal_pair_for_each_lane( + fx, + x, + y, + ret, + &|fx, _lane_ty, _res_lane_ty, x_lane, y_lane| fx.bcx.ins().fmax(x_lane, y_lane), + ); + } + // FIXME generalize vector types "llvm.aarch64.neon.tbl1.v16i8" => { intrinsic_args!(fx, args => (t, idx); intrinsic); @@ -172,25 +244,6 @@ pub(crate) fn codegen_aarch64_llvm_intrinsic_call<'tcx>( } } - // FIXME generalize vector types - "llvm.aarch64.neon.umaxp.v16i8" => { - intrinsic_args!(fx, args => (a, b); intrinsic); - - // FIXME add helper for horizontal pairwise operations - for i in 0..8 { - let lane1 = a.value_lane(fx, i * 2).load_scalar(fx); - let lane2 = a.value_lane(fx, i * 2 + 1).load_scalar(fx); - let res = fx.bcx.ins().umax(lane1, lane2); - ret.place_lane(fx, i).to_ptr().store(fx, res, MemFlags::trusted()); - } - for i in 0..8 { - let lane1 = b.value_lane(fx, i * 2).load_scalar(fx); - let lane2 = b.value_lane(fx, i * 2 + 1).load_scalar(fx); - let res = fx.bcx.ins().umax(lane1, lane2); - ret.place_lane(fx, 8 + i).to_ptr().store(fx, res, MemFlags::trusted()); - } - } - /* _ if intrinsic.starts_with("llvm.aarch64.neon.sshl.v") || intrinsic.starts_with("llvm.aarch64.neon.sqshl.v") diff --git a/src/intrinsics/mod.rs b/src/intrinsics/mod.rs index 58b31a534328..bfeeb117ff5b 100644 --- a/src/intrinsics/mod.rs +++ b/src/intrinsics/mod.rs @@ -132,6 +132,36 @@ fn simd_pair_for_each_lane<'tcx>( } } +fn simd_horizontal_pair_for_each_lane<'tcx>( + fx: &mut FunctionCx<'_, '_, 'tcx>, + x: CValue<'tcx>, + y: CValue<'tcx>, + ret: CPlace<'tcx>, + f: &dyn Fn(&mut FunctionCx<'_, '_, 'tcx>, Ty<'tcx>, Ty<'tcx>, Value, Value) -> Value, +) { + assert_eq!(x.layout(), y.layout()); + let layout = x.layout(); + + let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx); + let lane_layout = fx.layout_of(lane_ty); + let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx); + let ret_lane_layout = fx.layout_of(ret_lane_ty); + assert_eq!(lane_count, ret_lane_count); + + for lane_idx in 0..lane_count { + let src = if lane_idx < (lane_count / 2) { x } else { y }; + let src_idx = lane_idx % (lane_count / 2); + + let lhs_lane = src.value_lane(fx, src_idx * 2).load_scalar(fx); + let rhs_lane = src.value_lane(fx, src_idx * 2 + 1).load_scalar(fx); + + let res_lane = f(fx, lane_layout.ty, ret_lane_layout.ty, lhs_lane, rhs_lane); + let res_lane = CValue::by_val(res_lane, ret_lane_layout); + + ret.place_lane(fx, lane_idx).write_cvalue(fx, res_lane); + } +} + fn simd_trio_for_each_lane<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, x: CValue<'tcx>, From 88c2e7896b991e503b889da25e5c6a948586b16b Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Sat, 4 Nov 2023 19:11:15 +0000 Subject: [PATCH 250/435] Implement aarch64 addp intrinsics --- example/neon.rs | 56 ++++++++++++++++++++++++++++++++++ src/intrinsics/llvm_aarch64.rs | 12 ++++++++ 2 files changed, 68 insertions(+) diff --git a/example/neon.rs b/example/neon.rs index 0e23e862df1f..6ea053d0b004 100644 --- a/example/neon.rs +++ b/example/neon.rs @@ -131,6 +131,55 @@ unsafe fn test_vpmax_f32() { assert_eq!(r, e); } +#[cfg(target_arch = "aarch64")] +unsafe fn test_vpadd_s16() { + let a = i16x4::from([1, 2, 3, 4]); + let b = i16x4::from([0, -1, -2, -3]); + let r: i16x4 = transmute(vpadd_s16(transmute(a), transmute(b))); + let e = i16x4::from([3, 7, -1, -5]); + assert_eq!(r, e); +} +#[cfg(target_arch = "aarch64")] +unsafe fn test_vpadd_s32() { + let a = i32x2::from([1, 2]); + let b = i32x2::from([0, -1]); + let r: i32x2 = transmute(vpadd_s32(transmute(a), transmute(b))); + let e = i32x2::from([3, -1]); + assert_eq!(r, e); +} +#[cfg(target_arch = "aarch64")] +unsafe fn test_vpadd_s8() { + let a = i8x8::from([1, 2, 3, 4, 5, 6, 7, 8]); + let b = i8x8::from([0, -1, -2, -3, -4, -5, -6, -7]); + let r: i8x8 = transmute(vpadd_s8(transmute(a), transmute(b))); + let e = i8x8::from([3, 7, 11, 15, -1, -5, -9, -13]); + assert_eq!(r, e); +} +#[cfg(target_arch = "aarch64")] +unsafe fn test_vpadd_u16() { + let a = u16x4::from([1, 2, 3, 4]); + let b = u16x4::from([30, 31, 32, 33]); + let r: u16x4 = transmute(vpadd_u16(transmute(a), transmute(b))); + let e = u16x4::from([3, 7, 61, 65]); + assert_eq!(r, e); +} +#[cfg(target_arch = "aarch64")] +unsafe fn test_vpadd_u32() { + let a = u32x2::from([1, 2]); + let b = u32x2::from([30, 31]); + let r: u32x2 = transmute(vpadd_u32(transmute(a), transmute(b))); + let e = u32x2::from([3, 61]); + assert_eq!(r, e); +} +#[cfg(target_arch = "aarch64")] +unsafe fn test_vpadd_u8() { + let a = u8x8::from([1, 2, 3, 4, 5, 6, 7, 8]); + let b = u8x8::from([30, 31, 32, 33, 34, 35, 36, 37]); + let r: u8x8 = transmute(vpadd_u8(transmute(a), transmute(b))); + let e = u8x8::from([3, 7, 11, 15, 61, 65, 69, 73]); + assert_eq!(r, e); +} + #[cfg(target_arch = "aarch64")] fn main() { unsafe { @@ -148,6 +197,13 @@ fn main() { test_vpmax_u16(); test_vpmax_u32(); test_vpmax_f32(); + + test_vpadd_s16(); + test_vpadd_s32(); + test_vpadd_s8(); + test_vpadd_u16(); + test_vpadd_u32(); + test_vpadd_u8(); } } diff --git a/src/intrinsics/llvm_aarch64.rs b/src/intrinsics/llvm_aarch64.rs index ed318a89fa05..fdad5a474d6d 100644 --- a/src/intrinsics/llvm_aarch64.rs +++ b/src/intrinsics/llvm_aarch64.rs @@ -228,6 +228,18 @@ pub(crate) fn codegen_aarch64_llvm_intrinsic_call<'tcx>( ); } + _ if intrinsic.starts_with("llvm.aarch64.neon.addp.v") => { + intrinsic_args!(fx, args => (x, y); intrinsic); + + simd_horizontal_pair_for_each_lane( + fx, + x, + y, + ret, + &|fx, _lane_ty, _res_lane_ty, x_lane, y_lane| fx.bcx.ins().iadd(x_lane, y_lane), + ); + } + // FIXME generalize vector types "llvm.aarch64.neon.tbl1.v16i8" => { intrinsic_args!(fx, args => (t, idx); intrinsic); From f6ce646d3f840181dcc3f5d9edc4e4cff0051b78 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Thu, 28 Sep 2023 01:57:01 -0400 Subject: [PATCH 251/435] Stabilize `const_maybe_uninit_zeroed` Make `MaybeUninit::zeroed` const stable. Newly stable API: // core::mem impl MaybeUninit { pub const fn zeroed() -> MaybeUninit; } Use of `const_mut_refs` should be acceptable since we do not leak the mutability. Tracking issue: #91850 --- library/alloc/src/lib.rs | 1 - library/core/src/mem/maybe_uninit.rs | 17 +++++++++++------ library/core/tests/mem.rs | 21 +++++++++++++++++++++ 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index f435f503fc16..5b7062dec7a5 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -113,7 +113,6 @@ #![feature(const_eval_select)] #![feature(const_maybe_uninit_as_mut_ptr)] #![feature(const_maybe_uninit_write)] -#![feature(const_maybe_uninit_zeroed)] #![feature(const_pin)] #![feature(const_refs_to_cell)] #![feature(const_size_of_val)] diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index d09a24b4b1d5..a86ccaeb839c 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -374,6 +374,9 @@ impl MaybeUninit { /// assert_eq!(x, (0, false)); /// ``` /// + /// This can be used in const contexts, such as to indicate the end of static arrays for + /// plugin registration. + /// /// *Incorrect* usage of this function: calling `x.zeroed().assume_init()` /// when `0` is not a valid bit-pattern for the type: /// @@ -387,17 +390,19 @@ impl MaybeUninit { /// // Inside a pair, we create a `NotZero` that does not have a valid discriminant. /// // This is undefined behavior. ⚠️ /// ``` - #[stable(feature = "maybe_uninit", since = "1.36.0")] - #[rustc_const_unstable(feature = "const_maybe_uninit_zeroed", issue = "91850")] - #[must_use] #[inline] + #[must_use] #[rustc_diagnostic_item = "maybe_uninit_zeroed"] + #[stable(feature = "maybe_uninit", since = "1.36.0")] + // These are OK to allow since we do not leak &mut to user-visible API + #[rustc_allow_const_fn_unstable(const_mut_refs)] + #[rustc_allow_const_fn_unstable(const_ptr_write)] + #[rustc_allow_const_fn_unstable(const_maybe_uninit_as_mut_ptr)] + #[rustc_const_stable(feature = "const_maybe_uninit_zeroed", since = "CURRENT_RUSTC_VERSION")] pub const fn zeroed() -> MaybeUninit { let mut u = MaybeUninit::::uninit(); // SAFETY: `u.as_mut_ptr()` points to allocated memory. - unsafe { - u.as_mut_ptr().write_bytes(0u8, 1); - } + unsafe { u.as_mut_ptr().write_bytes(0u8, 1) }; u } diff --git a/library/core/tests/mem.rs b/library/core/tests/mem.rs index 5c2e18745ea2..20498b16cb22 100644 --- a/library/core/tests/mem.rs +++ b/library/core/tests/mem.rs @@ -565,3 +565,24 @@ fn offset_of_addr() { assert_eq!(ptr::addr_of!(base).addr() + offset_of!(Foo, z.0), ptr::addr_of!(base.z.0).addr()); assert_eq!(ptr::addr_of!(base).addr() + offset_of!(Foo, z.1), ptr::addr_of!(base.z.1).addr()); } + +#[test] +fn const_maybe_uninit_zeroed() { + // Sanity check for `MaybeUninit::zeroed` in a realistic const situation (plugin array term) + #[repr(C)] + struct Foo { + a: Option<&'static str>, + b: Bar, + c: f32, + d: *const u8, + } + #[repr(C)] + struct Bar(usize); + struct FooPtr(*const Foo); + unsafe impl Sync for FooPtr {} + + static UNINIT: FooPtr = FooPtr([unsafe { MaybeUninit::zeroed().assume_init() }].as_ptr()); + const SIZE: usize = size_of::(); + + assert_eq!(unsafe { (*UNINIT.0.cast::<[[u8; SIZE]; 1]>())[0] }, [0u8; SIZE]); +} From 5e5f3341e3749f18a6d6fbb2228a9d3b42c0b280 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Fri, 29 Sep 2023 02:40:30 -0400 Subject: [PATCH 252/435] Stabilize `const_mem_zeroed` Make `core::mem::zeroed` const stable. Newly stable API: // core::mem pub const unsafe fn zeroed() -> T; This is stabilized with `const_maybe_uninit_zeroed` since it is a simple wrapper. In order to make this possible, intrinsics `assert_zero_valid` was made const stable under `const_assert_type2`. `assert_mem_uninitialized_valid` was also made const stable since it is under the same gate. --- library/core/src/intrinsics.rs | 4 ++-- library/core/src/mem/mod.rs | 3 ++- tests/ui/consts/assert-type-intrinsics.rs | 1 - tests/ui/consts/assert-type-intrinsics.stderr | 12 ++++++------ 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 4c76662ac097..40dc323032ed 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -1072,7 +1072,7 @@ extern "rust-intrinsic" { /// zero-initialization: This will statically either panic, or do nothing. /// /// This intrinsic does not have a stable counterpart. - #[rustc_const_unstable(feature = "const_assert_type2", issue = "none")] + #[rustc_const_stable(feature = "const_assert_type2", since = "CURRENT_RUSTC_VERSION")] #[rustc_safe_intrinsic] #[rustc_nounwind] pub fn assert_zero_valid(); @@ -1080,7 +1080,7 @@ extern "rust-intrinsic" { /// A guard for `std::mem::uninitialized`. This will statically either panic, or do nothing. /// /// This intrinsic does not have a stable counterpart. - #[rustc_const_unstable(feature = "const_assert_type2", issue = "none")] + #[rustc_const_stable(feature = "const_assert_type2", since = "CURRENT_RUSTC_VERSION")] #[rustc_safe_intrinsic] #[rustc_nounwind] pub fn assert_mem_uninitialized_valid(); diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index d7abc9a0e23a..82ce901140ad 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -647,7 +647,8 @@ pub const fn needs_drop() -> bool { #[allow(deprecated)] #[rustc_diagnostic_item = "mem_zeroed"] #[track_caller] -pub unsafe fn zeroed() -> T { +#[rustc_const_stable(feature = "const_mem_zeroed", since = "CURRENT_RUSTC_VERSION")] +pub const unsafe fn zeroed() -> T { // SAFETY: the caller must guarantee that an all-zero value is valid for `T`. unsafe { intrinsics::assert_zero_valid::(); diff --git a/tests/ui/consts/assert-type-intrinsics.rs b/tests/ui/consts/assert-type-intrinsics.rs index b4fd423becd9..32b5f5c92c52 100644 --- a/tests/ui/consts/assert-type-intrinsics.rs +++ b/tests/ui/consts/assert-type-intrinsics.rs @@ -1,5 +1,4 @@ #![feature(never_type)] -#![feature(const_assert_type2)] #![feature(core_intrinsics)] use std::intrinsics; diff --git a/tests/ui/consts/assert-type-intrinsics.stderr b/tests/ui/consts/assert-type-intrinsics.stderr index 3c03b03deee3..66c4f0f9cd65 100644 --- a/tests/ui/consts/assert-type-intrinsics.stderr +++ b/tests/ui/consts/assert-type-intrinsics.stderr @@ -1,20 +1,20 @@ error[E0080]: evaluation of constant value failed - --> $DIR/assert-type-intrinsics.rs:12:9 + --> $DIR/assert-type-intrinsics.rs:11:9 | LL | MaybeUninit::::uninit().assume_init(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'aborted execution: attempted to instantiate uninhabited type `!`', $DIR/assert-type-intrinsics.rs:12:36 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'aborted execution: attempted to instantiate uninhabited type `!`', $DIR/assert-type-intrinsics.rs:11:36 error[E0080]: evaluation of constant value failed - --> $DIR/assert-type-intrinsics.rs:16:9 + --> $DIR/assert-type-intrinsics.rs:15:9 | LL | intrinsics::assert_mem_uninitialized_valid::<&'static i32>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'aborted execution: attempted to leave type `&i32` uninitialized, which is invalid', $DIR/assert-type-intrinsics.rs:16:9 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'aborted execution: attempted to leave type `&i32` uninitialized, which is invalid', $DIR/assert-type-intrinsics.rs:15:9 error[E0080]: evaluation of constant value failed - --> $DIR/assert-type-intrinsics.rs:20:9 + --> $DIR/assert-type-intrinsics.rs:19:9 | LL | intrinsics::assert_zero_valid::<&'static i32>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'aborted execution: attempted to zero-initialize type `&i32`, which is invalid', $DIR/assert-type-intrinsics.rs:20:9 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'aborted execution: attempted to zero-initialize type `&i32`, which is invalid', $DIR/assert-type-intrinsics.rs:19:9 error: aborting due to 3 previous errors From 70a6abfd29c20fbaa7bee58259a16a62ed48ad93 Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Sat, 4 Nov 2023 19:37:36 +0000 Subject: [PATCH 253/435] Add unsigned saturating add/sub intrinsics for aarch64 --- example/neon.rs | 21 +++++++++++++++++++++ src/intrinsics/llvm_aarch64.rs | 8 ++++++-- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/example/neon.rs b/example/neon.rs index 6ea053d0b004..103371373224 100644 --- a/example/neon.rs +++ b/example/neon.rs @@ -180,6 +180,24 @@ unsafe fn test_vpadd_u8() { assert_eq!(r, e); } +#[cfg(target_arch = "aarch64")] +unsafe fn test_vqsub_u8() { + let a = u8x8::from([1, 2, 3, 4, 5, 6, 7, 0xff]); + let b = u8x8::from([30, 1, 1, 1, 34, 0xff, 36, 37]); + let r: u8x8 = transmute(vqsub_u8(transmute(a), transmute(b))); + let e = u8x8::from([0, 1, 2, 3, 0, 0, 0, 218]); + assert_eq!(r, e); +} + +#[cfg(target_arch = "aarch64")] +unsafe fn test_vqadd_u8() { + let a = u8x8::from([1, 2, 3, 4, 5, 6, 7, 0xff]); + let b = u8x8::from([30, 1, 1, 1, 34, 0xff, 36, 37]); + let r: u8x8 = transmute(vqadd_u8(transmute(a), transmute(b))); + let e = u8x8::from([31, 3, 4, 5, 39, 0xff, 43, 0xff]); + assert_eq!(r, e); +} + #[cfg(target_arch = "aarch64")] fn main() { unsafe { @@ -204,6 +222,9 @@ fn main() { test_vpadd_u16(); test_vpadd_u32(); test_vpadd_u8(); + + test_vqsub_u8(); + test_vqadd_u8(); } } diff --git a/src/intrinsics/llvm_aarch64.rs b/src/intrinsics/llvm_aarch64.rs index fdad5a474d6d..ee098be1fce6 100644 --- a/src/intrinsics/llvm_aarch64.rs +++ b/src/intrinsics/llvm_aarch64.rs @@ -44,7 +44,9 @@ pub(crate) fn codegen_aarch64_llvm_intrinsic_call<'tcx>( }); } - _ if intrinsic.starts_with("llvm.aarch64.neon.sqadd.v") => { + _ if intrinsic.starts_with("llvm.aarch64.neon.sqadd.v") + || intrinsic.starts_with("llvm.aarch64.neon.uqadd.v") => + { intrinsic_args!(fx, args => (x, y); intrinsic); simd_pair_for_each_lane_typed(fx, x, y, ret, &|fx, x_lane, y_lane| { @@ -52,7 +54,9 @@ pub(crate) fn codegen_aarch64_llvm_intrinsic_call<'tcx>( }); } - _ if intrinsic.starts_with("llvm.aarch64.neon.sqsub.v") => { + _ if intrinsic.starts_with("llvm.aarch64.neon.sqsub.v") + || intrinsic.starts_with("llvm.aarch64.neon.uqsub.v") => + { intrinsic_args!(fx, args => (x, y); intrinsic); simd_pair_for_each_lane_typed(fx, x, y, ret, &|fx, x_lane, y_lane| { From df85b28b7261801e10867e15e7292df60f7a9bf7 Mon Sep 17 00:00:00 2001 From: Dinu Blanovschi Date: Sat, 4 Nov 2023 20:39:15 +0100 Subject: [PATCH 254/435] fixes for rustfmt + ast visitor --- compiler/rustc_ast/src/visit.rs | 6 +++++- src/tools/rustfmt/src/closures.rs | 2 +- src/tools/rustfmt/src/expr.rs | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index e091961a1443..1caa39e2dd99 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -251,6 +251,9 @@ pub trait Visitor<'ast>: Sized { fn visit_inline_asm_sym(&mut self, sym: &'ast InlineAsmSym) { walk_inline_asm_sym(self, sym) } + fn visit_capture_by(&mut self, _capture_by: &'ast CaptureBy) { + // Nothing to do + } } #[macro_export] @@ -857,7 +860,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) { } ExprKind::Closure(box Closure { binder, - capture_clause: _, + capture_clause, asyncness: _, constness: _, movability: _, @@ -866,6 +869,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) { fn_decl_span: _, fn_arg_span: _, }) => { + visitor.visit_capture_by(capture_clause); visitor.visit_fn(FnKind::Closure(binder, fn_decl, body), expression.span, expression.id) } ExprKind::Block(block, opt_label) => { diff --git a/src/tools/rustfmt/src/closures.rs b/src/tools/rustfmt/src/closures.rs index 16b8ce7a916a..8a4089a56f09 100644 --- a/src/tools/rustfmt/src/closures.rs +++ b/src/tools/rustfmt/src/closures.rs @@ -264,7 +264,7 @@ fn rewrite_closure_fn_decl( "" }; let is_async = if asyncness.is_async() { "async " } else { "" }; - let mover = if capture == ast::CaptureBy::Value { + let mover = if matches!(capture, ast::CaptureBy::Value { .. }) { "move " } else { "" diff --git a/src/tools/rustfmt/src/expr.rs b/src/tools/rustfmt/src/expr.rs index 8c2262fde811..fa941e6146ad 100644 --- a/src/tools/rustfmt/src/expr.rs +++ b/src/tools/rustfmt/src/expr.rs @@ -368,7 +368,7 @@ pub(crate) fn format_expr( } } ast::ExprKind::Gen(capture_by, ref block, ref kind) => { - let mover = if capture_by == ast::CaptureBy::Value { + let mover = if matches!(capture_by, ast::CaptureBy::Value { .. }) { "move " } else { "" From f824da66c60a5b252bab6bcbabcc30a489b29019 Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Sat, 4 Nov 2023 19:41:08 +0000 Subject: [PATCH 255/435] Make neon example build in all arches --- example/neon.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/neon.rs b/example/neon.rs index 103371373224..41b518905600 100644 --- a/example/neon.rs +++ b/example/neon.rs @@ -228,5 +228,5 @@ fn main() { } } -#[cfg(target_arch = "x86_64")] +#[cfg(not(target_arch = "aarch64"))] fn main() {} From 209476e33acbeb14213c2edbb6e877dd251d4943 Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Sat, 4 Nov 2023 19:47:56 +0000 Subject: [PATCH 256/435] Only import aarch64 intrinsics on aarch64 --- example/neon.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/example/neon.rs b/example/neon.rs index 41b518905600..bad26947967d 100644 --- a/example/neon.rs +++ b/example/neon.rs @@ -1,6 +1,8 @@ // Most of these tests are copied from https://github.com/japaric/stdsimd/blob/0f4413d01c4f0c3ffbc5a69e9a37fbc7235b31a9/coresimd/arm/neon.rs #![feature(portable_simd)] + +#[cfg(target_arch = "aarch64")] use std::arch::aarch64::*; use std::mem::transmute; use std::simd::*; From 00a9ed34b1afad45c13c58acc8441ab9442d2cdd Mon Sep 17 00:00:00 2001 From: George Bateman Date: Sat, 4 Nov 2023 19:50:21 +0000 Subject: [PATCH 257/435] De-indent closing bracket Co-authored-by: Camille Gillot --- compiler/rustc_hir_typeck/src/expr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 23a8cc4e8ecc..f279d7d48275 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -3124,7 +3124,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { sym::offset_of_enum, ident.span, "using enums in offset_of is experimental", - ).emit(); + ).emit(); } let Some((index, variant)) = container_def.variants() From 54ce0346c040b8dc725a0c7d0be316217d01f1de Mon Sep 17 00:00:00 2001 From: Dinu Blanovschi Date: Sat, 4 Nov 2023 21:04:54 +0100 Subject: [PATCH 258/435] add `fn visit_capture_by` to MutVisitor and fix pprust-expr-roundtrip.rs --- compiler/rustc_ast/src/mut_visit.rs | 13 +++++++++++++ tests/ui-fulldeps/pprust-expr-roundtrip.rs | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 0634ee970ec5..ae1a8e7d0fac 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -302,6 +302,10 @@ pub trait MutVisitor: Sized { fn visit_format_args(&mut self, fmt: &mut FormatArgs) { noop_visit_format_args(fmt, self) } + + fn visit_capture_by(&mut self, capture_by: &mut CaptureBy) { + noop_visit_capture_by(capture_by, self) + } } /// Use a map-style function (`FnOnce(T) -> T`) to overwrite a `&mut T`. Useful @@ -1562,6 +1566,15 @@ pub fn noop_visit_vis(visibility: &mut Visibility, vis: &mut T) { vis.visit_span(&mut visibility.span); } +pub fn noop_visit_capture_by(capture_by: &mut CaptureBy, vis: &mut T) { + match capture_by { + CaptureBy::Ref => {} + CaptureBy::Value { move_kw } => { + vis.visit_span(move_kw); + } + } +} + /// Some value for the AST node that is valid but possibly meaningless. pub trait DummyAstNode { fn dummy() -> Self; diff --git a/tests/ui-fulldeps/pprust-expr-roundtrip.rs b/tests/ui-fulldeps/pprust-expr-roundtrip.rs index 3d6cff00a6d2..685a029dcb22 100644 --- a/tests/ui-fulldeps/pprust-expr-roundtrip.rs +++ b/tests/ui-fulldeps/pprust-expr-roundtrip.rs @@ -130,7 +130,7 @@ fn iter_exprs(depth: usize, f: &mut dyn FnMut(P)) { iter_exprs(depth - 1, &mut |e| { g(ExprKind::Closure(Box::new(Closure { binder: ClosureBinder::NotPresent, - capture_clause: CaptureBy::Value, + capture_clause: CaptureBy::Value { move_kw: DUMMY_SP }, constness: Const::No, asyncness: Async::No, movability: Movability::Movable, From 876f69879046b97918b58d1f8463dd3c03e9bc85 Mon Sep 17 00:00:00 2001 From: Dinu Blanovschi Date: Sat, 4 Nov 2023 21:11:03 +0100 Subject: [PATCH 259/435] Add the vis.visit_capture_by() in noop_visit_expr --- compiler/rustc_ast/src/mut_visit.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index ae1a8e7d0fac..7c0a78253a21 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -1401,7 +1401,7 @@ pub fn noop_visit_expr( } ExprKind::Closure(box Closure { binder, - capture_clause: _, + capture_clause, constness, asyncness, movability: _, @@ -1413,6 +1413,7 @@ pub fn noop_visit_expr( vis.visit_closure_binder(binder); visit_constness(constness, vis); vis.visit_asyncness(asyncness); + vis.visit_capture_by(capture_clause); vis.visit_fn_decl(fn_decl); vis.visit_expr(body); vis.visit_span(fn_decl_span); From a3b964b9ea362b42da05b8b69a5be4a6a2cca9a7 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sat, 4 Nov 2023 20:16:03 +0000 Subject: [PATCH 260/435] Remove unused LoadResult::DecodeIncrCache variant --- compiler/rustc_incremental/messages.ftl | 2 -- compiler/rustc_incremental/src/errors.rs | 6 ------ compiler/rustc_incremental/src/persist/load.rs | 11 +---------- 3 files changed, 1 insertion(+), 18 deletions(-) diff --git a/compiler/rustc_incremental/messages.ftl b/compiler/rustc_incremental/messages.ftl index 5d885e07192d..e74173b24a97 100644 --- a/compiler/rustc_incremental/messages.ftl +++ b/compiler/rustc_incremental/messages.ftl @@ -30,8 +30,6 @@ incremental_create_lock = incremental compilation: could not create session directory lock file: {$lock_err} incremental_create_new = failed to create {$name} at `{$path}`: {$err} -incremental_decode_incr_cache = could not decode incremental cache: {$err} - incremental_delete_full = error deleting incremental compilation session directory `{$path}`: {$err} incremental_delete_incompatible = diff --git a/compiler/rustc_incremental/src/errors.rs b/compiler/rustc_incremental/src/errors.rs index 05ed4f7598d4..61bb0353a9f4 100644 --- a/compiler/rustc_incremental/src/errors.rs +++ b/compiler/rustc_incremental/src/errors.rs @@ -270,12 +270,6 @@ pub struct LoadDepGraph { pub err: std::io::Error, } -#[derive(Diagnostic)] -#[diag(incremental_decode_incr_cache)] -pub struct DecodeIncrCache { - pub err: String, -} - #[derive(Diagnostic)] #[diag(incremental_write_dep_graph)] pub struct WriteDepGraph<'a> { diff --git a/compiler/rustc_incremental/src/persist/load.rs b/compiler/rustc_incremental/src/persist/load.rs index cbd55fe42056..6dfc40969106 100644 --- a/compiler/rustc_incremental/src/persist/load.rs +++ b/compiler/rustc_incremental/src/persist/load.rs @@ -30,8 +30,6 @@ pub enum LoadResult { DataOutOfDate, /// Loading the dep graph failed. LoadDepGraph(PathBuf, std::io::Error), - /// Decoding loaded incremental cache failed. - DecodeIncrCache(Box), } impl LoadResult { @@ -44,9 +42,7 @@ impl LoadResult { } ( Some(IncrementalStateAssertion::Loaded), - LoadResult::LoadDepGraph(..) - | LoadResult::DecodeIncrCache(..) - | LoadResult::DataOutOfDate, + LoadResult::LoadDepGraph(..) | LoadResult::DataOutOfDate, ) => { sess.emit_fatal(errors::AssertLoaded); } @@ -58,10 +54,6 @@ impl LoadResult { sess.emit_warning(errors::LoadDepGraph { path, err }); Default::default() } - LoadResult::DecodeIncrCache(err) => { - sess.emit_warning(errors::DecodeIncrCache { err: format!("{err:?}") }); - Default::default() - } LoadResult::DataOutOfDate => { if let Err(err) = delete_all_session_dir_contents(sess) { sess.emit_err(errors::DeleteIncompatible { path: dep_graph_path(sess), err }); @@ -150,7 +142,6 @@ fn load_dep_graph(sess: &Session) -> LoadResult<(SerializedDepGraph, WorkProduct match load_data(&path, sess) { LoadResult::DataOutOfDate => LoadResult::DataOutOfDate, LoadResult::LoadDepGraph(path, err) => LoadResult::LoadDepGraph(path, err), - LoadResult::DecodeIncrCache(err) => LoadResult::DecodeIncrCache(err), LoadResult::Ok { data: (bytes, start_pos) } => { let mut decoder = MemDecoder::new(&bytes, start_pos); let prev_commandline_args_hash = u64::decode(&mut decoder); From 32294fc0ed1810a16fcea649955a9b21ea061734 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 4 Nov 2023 20:18:44 +0000 Subject: [PATCH 261/435] Make sure that predicates with unmentioned bound vars are still considered global in the old solver --- compiler/rustc_middle/src/ty/erase_regions.rs | 4 +-- compiler/rustc_middle/src/ty/flags.rs | 26 +++------------ compiler/rustc_middle/src/ty/visit.rs | 14 +++----- compiler/rustc_type_ir/src/flags.rs | 3 ++ .../predicate-is-global.rs | 32 +++++++++++++++++++ 5 files changed, 47 insertions(+), 32 deletions(-) create mode 100644 tests/ui/late-bound-lifetimes/predicate-is-global.rs diff --git a/compiler/rustc_middle/src/ty/erase_regions.rs b/compiler/rustc_middle/src/ty/erase_regions.rs index 7895993ccffa..3371ea3bec8c 100644 --- a/compiler/rustc_middle/src/ty/erase_regions.rs +++ b/compiler/rustc_middle/src/ty/erase_regions.rs @@ -20,8 +20,8 @@ impl<'tcx> TyCtxt<'tcx> { where T: TypeFoldable>, { - // If there's nothing to erase avoid performing the query at all - if !value.has_type_flags(TypeFlags::HAS_LATE_BOUND | TypeFlags::HAS_FREE_REGIONS) { + // If there's nothing to erase or anonymize, avoid performing the query at all + if !value.has_type_flags(TypeFlags::HAS_BINDER_VARS | TypeFlags::HAS_FREE_REGIONS) { return value; } debug!("erase_regions({:?})", value); diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index a348e9f608aa..ec36bdc5a518 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -34,26 +34,6 @@ impl FlagComputation { result.flags } - pub fn bound_var_flags(vars: &ty::List) -> FlagComputation { - let mut computation = FlagComputation::new(); - - for bv in vars { - match bv { - ty::BoundVariableKind::Ty(_) => { - computation.flags |= TypeFlags::HAS_TY_LATE_BOUND; - } - ty::BoundVariableKind::Region(_) => { - computation.flags |= TypeFlags::HAS_RE_LATE_BOUND; - } - ty::BoundVariableKind::Const => { - computation.flags |= TypeFlags::HAS_CT_LATE_BOUND; - } - } - } - - computation - } - fn add_flags(&mut self, flags: TypeFlags) { self.flags = self.flags | flags; } @@ -77,7 +57,11 @@ impl FlagComputation { where F: FnOnce(&mut Self, T), { - let mut computation = FlagComputation::bound_var_flags(value.bound_vars()); + let mut computation = FlagComputation::new(); + + if !value.bound_vars().is_empty() { + computation.add_flags(TypeFlags::HAS_BINDER_VARS); + } f(&mut computation, value.skip_binder()); diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs index ab0999b3f197..8fc5c0302778 100644 --- a/compiler/rustc_middle/src/ty/visit.rs +++ b/compiler/rustc_middle/src/ty/visit.rs @@ -494,15 +494,11 @@ impl<'tcx> TypeVisitor> for HasTypeFlagsVisitor { &mut self, t: &Binder<'tcx, T>, ) -> ControlFlow { - // If we're looking for any of the HAS_*_LATE_BOUND flags, we need to - // additionally consider the bound vars on the binder itself, even if - // the contents of a the binder (e.g. a `TraitRef`) doesn't reference - // the bound vars. - if self.flags.intersects(TypeFlags::HAS_LATE_BOUND) { - let bound_var_flags = FlagComputation::bound_var_flags(t.bound_vars()); - if bound_var_flags.flags.intersects(self.flags) { - return ControlFlow::Break(FoundFlags); - } + // If we're looking for the HAS_BINDER_VARS flag, check if the + // binder has vars. This won't be present in the binder's bound + // value, so we need to check here too. + if self.flags.intersects(TypeFlags::HAS_BINDER_VARS) && !t.bound_vars().is_empty() { + return ControlFlow::Break(FoundFlags); } t.super_visit_with(self) diff --git a/compiler/rustc_type_ir/src/flags.rs b/compiler/rustc_type_ir/src/flags.rs index d5cadd4e83a7..8472a0845053 100644 --- a/compiler/rustc_type_ir/src/flags.rs +++ b/compiler/rustc_type_ir/src/flags.rs @@ -115,5 +115,8 @@ bitflags! { /// Does this have `Coroutine` or `CoroutineWitness`? const HAS_TY_COROUTINE = 1 << 23; + + /// Does this have any binders with bound vars (e.g. that need to be anonymized)? + const HAS_BINDER_VARS = 1 << 24; } } diff --git a/tests/ui/late-bound-lifetimes/predicate-is-global.rs b/tests/ui/late-bound-lifetimes/predicate-is-global.rs new file mode 100644 index 000000000000..ee4c4706005f --- /dev/null +++ b/tests/ui/late-bound-lifetimes/predicate-is-global.rs @@ -0,0 +1,32 @@ +// check-pass + +trait Foo { + type Assoc; + + fn do_it(_: &Self::Assoc) + where + for<'a> Self: Baz<'a>; +} + +trait Baz<'a>: Foo {} + +impl Foo for () { + type Assoc = Inherent; + + // Ensure that the `for<'a> Self: Baz<'a>` predicate, which has + // a supertrait `for<'a> Self: Foo`, does not cause us to fail + // to normalize `Self::Assoc`. + fn do_it(x: &Self::Assoc) + where + for<'a> Self: Baz<'a>, + { + x.inherent(); + } +} + +struct Inherent; +impl Inherent { + fn inherent(&self) {} +} + +fn main() {} From c077147200edaeb30dd294cbdc62dd02b01a8212 Mon Sep 17 00:00:00 2001 From: Dinu Blanovschi Date: Sat, 4 Nov 2023 21:43:18 +0100 Subject: [PATCH 262/435] fix clippy author and failing test --- src/tools/clippy/clippy_lints/src/utils/author.rs | 9 +++++++-- src/tools/clippy/tests/ui/author/blocks.stdout | 4 ++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs index ce93aea21360..152248afc903 100644 --- a/src/tools/clippy/clippy_lints/src/utils/author.rs +++ b/src/tools/clippy/clippy_lints/src/utils/author.rs @@ -7,7 +7,7 @@ use rustc_ast::LitIntType; use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; use rustc_hir::{ - ArrayLen, BindingAnnotation, Closure, ExprKind, FnRetTy, HirId, Lit, PatKind, QPath, StmtKind, TyKind, + ArrayLen, BindingAnnotation, Closure, ExprKind, FnRetTy, HirId, Lit, PatKind, QPath, StmtKind, TyKind, CaptureBy }; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::declare_lint_pass; @@ -479,6 +479,11 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { movability, .. }) => { + let capture_clause = match capture_clause { + CaptureBy::Value { .. } => "Value { .. }", + CaptureBy::Ref => "Ref", + }; + let movability = OptionPat::new(movability.map(|m| format!("Movability::{m:?}"))); let ret_ty = match fn_decl.output { @@ -487,7 +492,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { }; bind!(self, fn_decl, body_id); - kind!("Closure(CaptureBy::{capture_clause:?}, {fn_decl}, {body_id}, _, {movability})"); + kind!("Closure(CaptureBy::{capture_clause}, {fn_decl}, {body_id}, _, {movability})"); chain!(self, "let {ret_ty} = {fn_decl}.output"); self.body(body_id); }, diff --git a/src/tools/clippy/tests/ui/author/blocks.stdout b/src/tools/clippy/tests/ui/author/blocks.stdout index eb3e5189c823..140300a16730 100644 --- a/src/tools/clippy/tests/ui/author/blocks.stdout +++ b/src/tools/clippy/tests/ui/author/blocks.stdout @@ -40,10 +40,10 @@ if let ExprKind::Block(block, None) = expr.kind { // report your lint here } -if let ExprKind::Closure(CaptureBy::Value, fn_decl, body_id, _, None) = expr.kind +if let ExprKind::Closure(CaptureBy::Value { .. }, fn_decl, body_id, _, None) = expr.kind && let FnRetTy::DefaultReturn(_) = fn_decl.output && expr1 = &cx.tcx.hir().body(body_id).value - && let ExprKind::Closure(CaptureBy::Value, fn_decl1, body_id1, _, Some(Movability::Static)) = expr1.kind + && let ExprKind::Closure(CaptureBy::Value { .. }, fn_decl1, body_id1, _, Some(Movability::Static)) = expr1.kind && let FnRetTy::DefaultReturn(_) = fn_decl1.output && expr2 = &cx.tcx.hir().body(body_id1).value && let ExprKind::Block(block, None) = expr2.kind From 86fca873ba43ae6d74c4ff65b8fb036eb8c14bd1 Mon Sep 17 00:00:00 2001 From: Thom Chiovoloni Date: Sat, 4 Nov 2023 14:04:01 -0700 Subject: [PATCH 263/435] Use the correct span when emitting the `env!` result --- compiler/rustc_builtin_macros/src/env.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_builtin_macros/src/env.rs b/compiler/rustc_builtin_macros/src/env.rs index 92da0c069e51..8c2fa6ee95f3 100644 --- a/compiler/rustc_builtin_macros/src/env.rs +++ b/compiler/rustc_builtin_macros/src/env.rs @@ -108,7 +108,7 @@ pub fn expand_env<'cx>( return DummyResult::any(sp); } - Some(value) => cx.expr_str(sp, value), + Some(value) => cx.expr_str(span, value), }; MacEager::expr(e) } From 1dcdf839273d6de6ae7105aa23d99cb44e38a38c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Fri, 3 Nov 2023 01:44:09 +0100 Subject: [PATCH 264/435] rustdoc: properly elide cross-crate host effect args --- src/librustdoc/clean/mod.rs | 3 +- src/librustdoc/clean/utils.rs | 6 +--- tests/rustdoc/const-effect-param.rs | 2 ++ .../auxiliary/const-effect-param.rs | 16 ++++++++++ .../inline_cross/auxiliary/const-fn.rs | 5 ---- .../inline_cross/const-effect-param.rs | 29 +++++++++++++++++++ tests/rustdoc/inline_cross/const-fn.rs | 10 ------- 7 files changed, 50 insertions(+), 21 deletions(-) create mode 100644 tests/rustdoc/inline_cross/auxiliary/const-effect-param.rs delete mode 100644 tests/rustdoc/inline_cross/auxiliary/const-fn.rs create mode 100644 tests/rustdoc/inline_cross/const-effect-param.rs delete mode 100644 tests/rustdoc/inline_cross/const-fn.rs diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index e6e2d60f2e5b..1b7ca7bf7dd0 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2534,7 +2534,8 @@ fn clean_generic_args<'tcx>( } hir::GenericArg::Lifetime(_) => GenericArg::Lifetime(Lifetime::elided()), hir::GenericArg::Type(ty) => GenericArg::Type(clean_ty(ty, cx)), - // FIXME(effects): This will still emit `` for non-const impls of const traits + // Checking for `#[rustc_host]` on the `AnonConst` not only accounts for the case + // where the argument is `host` but for all possible cases (e.g., `true`, `false`). hir::GenericArg::Const(ct) if cx.tcx.has_attr(ct.value.def_id, sym::rustc_host) => { diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index dea7bfaf7e22..13d467d3d815 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -124,11 +124,7 @@ pub(crate) fn ty_args_to_args<'tcx>( ))) } GenericArgKind::Const(ct) => { - // FIXME(effects): this relies on the host effect being called `host`, which users could also name - // their const generics. - // FIXME(effects): this causes `host = true` and `host = false` generics to also be emitted. - if let ty::ConstKind::Param(p) = ct.kind() - && p.name == sym::host + if let ty::GenericParamDefKind::Const { is_host_effect: true, .. } = params[index].kind { return None; } diff --git a/tests/rustdoc/const-effect-param.rs b/tests/rustdoc/const-effect-param.rs index f50a9b96d812..b6379c05a859 100644 --- a/tests/rustdoc/const-effect-param.rs +++ b/tests/rustdoc/const-effect-param.rs @@ -1,3 +1,5 @@ +// Check that we don't render host effect parameters & arguments. + #![crate_name = "foo"] #![feature(effects, const_trait_impl)] diff --git a/tests/rustdoc/inline_cross/auxiliary/const-effect-param.rs b/tests/rustdoc/inline_cross/auxiliary/const-effect-param.rs new file mode 100644 index 000000000000..b0c21ffaeb99 --- /dev/null +++ b/tests/rustdoc/inline_cross/auxiliary/const-effect-param.rs @@ -0,0 +1,16 @@ +#![feature(effects, const_trait_impl)] + +#[const_trait] +pub trait Resource {} + +pub const fn load() -> i32 { + 0 +} + +pub const fn lock() {} + +#[allow(non_upper_case_globals)] +pub trait Clash {} + +#[allow(non_upper_case_globals)] +pub const fn clash, const host: u64>() {} diff --git a/tests/rustdoc/inline_cross/auxiliary/const-fn.rs b/tests/rustdoc/inline_cross/auxiliary/const-fn.rs deleted file mode 100644 index 26332b419b6d..000000000000 --- a/tests/rustdoc/inline_cross/auxiliary/const-fn.rs +++ /dev/null @@ -1,5 +0,0 @@ -#![feature(effects)] - -pub const fn load() -> i32 { - 0 -} diff --git a/tests/rustdoc/inline_cross/const-effect-param.rs b/tests/rustdoc/inline_cross/const-effect-param.rs new file mode 100644 index 000000000000..1d003e28f36d --- /dev/null +++ b/tests/rustdoc/inline_cross/const-effect-param.rs @@ -0,0 +1,29 @@ +// Regression test for issue #116629. +// Check that we don't render host effect parameters & arguments. + +// aux-crate:const_effect_param=const-effect-param.rs +// edition: 2021 +#![crate_name = "user"] + +// Don't render the host param on `load` and the host arg `host` passed to `Resource`. +// @has user/fn.load.html +// @has - '//pre[@class="rust item-decl"]' "pub const fn load() -> i32\ +// where \ +// R: Resource" +pub use const_effect_param::load; + +// Don't render the host arg `true` passed to `Resource`. +// @has user/fn.lock.html +// @has - '//pre[@class="rust item-decl"]' "pub const fn lock()\ +// where \ +// R: Resource" +pub use const_effect_param::lock; + +// Regression test for an issue introduced in PR #116670. +// Don't hide the const param `host` since it actually isn't the host effect param. +// @has user/fn.clash.html +// @has - '//pre[@class="rust item-decl"]' \ +// "pub const fn clash()\ +// where \ +// T: Clash" +pub use const_effect_param::clash; diff --git a/tests/rustdoc/inline_cross/const-fn.rs b/tests/rustdoc/inline_cross/const-fn.rs deleted file mode 100644 index 24934b873c25..000000000000 --- a/tests/rustdoc/inline_cross/const-fn.rs +++ /dev/null @@ -1,10 +0,0 @@ -// Regression test for issue #116629. -// Check that we render the correct generic params of const fn - -// aux-crate:const_fn=const-fn.rs -// edition: 2021 -#![crate_name = "user"] - -// @has user/fn.load.html -// @has - '//pre[@class="rust item-decl"]' "pub const fn load() -> i32" -pub use const_fn::load; From 65bec86b425b3580bba0b3eccdf44294d2baa88f Mon Sep 17 00:00:00 2001 From: Thom Chiovoloni Date: Sat, 4 Nov 2023 17:00:51 -0700 Subject: [PATCH 265/435] Add diagnostic items for a few of core's builtin macros --- library/core/src/macros/mod.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 125a6f57bfba..7f5908e477cf 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -1044,6 +1044,7 @@ pub(crate) mod builtin { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_builtin_macro] #[macro_export] + #[rustc_diagnostic_item = "env_macro"] // useful for external lints macro_rules! env { ($name:expr $(,)?) => {{ /* compiler built-in */ }}; ($name:expr, $error_msg:expr $(,)?) => {{ /* compiler built-in */ }}; @@ -1074,6 +1075,7 @@ pub(crate) mod builtin { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_builtin_macro] #[macro_export] + #[rustc_diagnostic_item = "option_env_macro"] // useful for external lints macro_rules! option_env { ($name:expr $(,)?) => {{ /* compiler built-in */ }}; } @@ -1479,6 +1481,7 @@ pub(crate) mod builtin { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_builtin_macro] #[macro_export] + #[rustc_diagnostic_item = "include_macro"] // useful for external lints macro_rules! include { ($file:expr $(,)?) => {{ /* compiler built-in */ }}; } From 8d8d12120d057f4b0b6585147695a177178d1f70 Mon Sep 17 00:00:00 2001 From: Young-Flash <871946895@qq.com> Date: Sat, 4 Nov 2023 11:32:15 +0800 Subject: [PATCH 266/435] feat: add generate_mut_trait_impl assist --- .../src/handlers/generate_mut_trait_impl.rs | 195 ++++++++++++++++++ crates/ide-assists/src/lib.rs | 2 + crates/ide-assists/src/tests/generated.rs | 35 ++++ crates/syntax/src/ast/make.rs | 4 + 4 files changed, 236 insertions(+) create mode 100644 crates/ide-assists/src/handlers/generate_mut_trait_impl.rs diff --git a/crates/ide-assists/src/handlers/generate_mut_trait_impl.rs b/crates/ide-assists/src/handlers/generate_mut_trait_impl.rs new file mode 100644 index 000000000000..ceb9d22c1b9f --- /dev/null +++ b/crates/ide-assists/src/handlers/generate_mut_trait_impl.rs @@ -0,0 +1,195 @@ +use syntax::{ + ast::{self, make}, + ted, AstNode, +}; + +use crate::{AssistContext, AssistId, AssistKind, Assists}; + +// Generate proper `index_mut` method body refer to `index` method body may impossible due to the unpredicable case [#15581]. +// Here just leave the `index_mut` method body be same as `index` method body, user can modify it manually to meet their need. + +// Assist: generate_mut_trait_impl +// +// Adds a IndexMut impl from the `Index` trait. +// +// ``` +// pub enum Axis { X = 0, Y = 1, Z = 2 } +// +// impl Index$0 for [T; 3] { +// type Output = T; +// +// fn index(&self, index: Axis) -> &Self::Output { +// &self[index as usize] +// } +// } +// ``` +// -> +// ``` +// pub enum Axis { X = 0, Y = 1, Z = 2 } +// +// $0impl IndexMut for [T; 3] { +// fn index_mut(&mut self, index: Axis) -> &mut Self::Output { +// &self[index as usize] +// } +// } +// +// impl Index for [T; 3] { +// type Output = T; +// +// fn index(&self, index: Axis) -> &Self::Output { +// &self[index as usize] +// } +// } +// ``` +pub(crate) fn generate_mut_trait_impl(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { + let impl_def = ctx.find_node_at_offset::()?.clone_for_update(); + + let trait_ = impl_def.trait_()?; + if let ast::Type::PathType(trait_type) = trait_.clone() { + let trait_name = trait_type.path()?.segment()?.name_ref()?.to_string(); + if trait_name != "Index" { + return None; + } + } + + // Index -> IndexMut + let index_trait = impl_def + .syntax() + .descendants() + .filter_map(ast::NameRef::cast) + .find(|it| it.text() == "Index")?; + ted::replace( + index_trait.syntax(), + make::path_segment(make::name_ref("IndexMut")).clone_for_update().syntax(), + ); + + // index -> index_mut + let trait_method_name = impl_def + .syntax() + .descendants() + .filter_map(ast::Name::cast) + .find(|it| it.text() == "index")?; + ted::replace(trait_method_name.syntax(), make::name("index_mut").clone_for_update().syntax()); + + let type_alias = impl_def.syntax().descendants().find_map(ast::TypeAlias::cast)?; + ted::remove(type_alias.syntax()); + + // &self -> &mut self + let mut_self_param = make::mut_self_param(); + let self_param: ast::SelfParam = + impl_def.syntax().descendants().find_map(ast::SelfParam::cast)?; + ted::replace(self_param.syntax(), mut_self_param.clone_for_update().syntax()); + + // &Self::Output -> &mut Self::Output + let ret_type = impl_def.syntax().descendants().find_map(ast::RetType::cast)?; + ted::replace( + ret_type.syntax(), + make::ret_type(make::ty("&mut Self::Output")).clone_for_update().syntax(), + ); + + let fn_ = impl_def.assoc_item_list()?.assoc_items().find_map(|it| match it { + ast::AssocItem::Fn(f) => Some(f), + _ => None, + })?; + + let assoc_list = make::assoc_item_list().clone_for_update(); + assoc_list.add_item(syntax::ast::AssocItem::Fn(fn_)); + ted::replace(impl_def.assoc_item_list()?.syntax(), assoc_list.syntax()); + + let target = impl_def.syntax().text_range(); + acc.add( + AssistId("generate_mut_trait_impl", AssistKind::Generate), + "Generate `IndexMut` impl from this `Index` trait", + target, + |edit| { + edit.insert(target.start(), format!("$0{}\n\n", impl_def.to_string())); + }, + ) +} + +#[cfg(test)] +mod tests { + use crate::tests::{check_assist, check_assist_not_applicable}; + + use super::*; + + #[test] + fn test_generate_mut_trait_impl() { + check_assist( + generate_mut_trait_impl, + r#" +pub enum Axis { X = 0, Y = 1, Z = 2 } + +impl Index$0 for [T; 3] { + type Output = T; + + fn index(&self, index: Axis) -> &Self::Output { + &self[index as usize] + } +} +"#, + r#" +pub enum Axis { X = 0, Y = 1, Z = 2 } + +$0impl IndexMut for [T; 3] { + fn index_mut(&mut self, index: Axis) -> &mut Self::Output { + &self[index as usize] + } +} + +impl Index for [T; 3] { + type Output = T; + + fn index(&self, index: Axis) -> &Self::Output { + &self[index as usize] + } +} +"#, + ); + + check_assist( + generate_mut_trait_impl, + r#" +pub enum Axis { X = 0, Y = 1, Z = 2 } + +impl Index$0 for [T; 3] where T: Copy { + type Output = T; + + fn index(&self, index: Axis) -> &Self::Output { + let var_name = &self[index as usize]; + var_name + } +} +"#, + r#" +pub enum Axis { X = 0, Y = 1, Z = 2 } + +$0impl IndexMut for [T; 3] where T: Copy { + fn index_mut(&mut self, index: Axis) -> &mut Self::Output { + let var_name = &self[index as usize]; + var_name + } +} + +impl Index for [T; 3] where T: Copy { + type Output = T; + + fn index(&self, index: Axis) -> &Self::Output { + let var_name = &self[index as usize]; + var_name + } +} +"#, + ); + } + + #[test] + fn test_generate_mut_trait_impl_not_applicable() { + check_assist_not_applicable( + generate_mut_trait_impl, + r#" +impl Add$0 for [T; 3] {} +"#, + ); + } +} diff --git a/crates/ide-assists/src/lib.rs b/crates/ide-assists/src/lib.rs index d2b291631c8a..e6f03214ed30 100644 --- a/crates/ide-assists/src/lib.rs +++ b/crates/ide-assists/src/lib.rs @@ -160,6 +160,7 @@ mod handlers { mod generate_getter_or_setter; mod generate_impl; mod generate_is_empty_from_len; + mod generate_mut_trait_impl; mod generate_new; mod generate_delegate_methods; mod generate_trait_from_impl; @@ -274,6 +275,7 @@ mod handlers { generate_function::generate_function, generate_impl::generate_impl, generate_impl::generate_trait_impl, + generate_mut_trait_impl::generate_mut_trait_impl, generate_is_empty_from_len::generate_is_empty_from_len, generate_new::generate_new, generate_trait_from_impl::generate_trait_from_impl, diff --git a/crates/ide-assists/src/tests/generated.rs b/crates/ide-assists/src/tests/generated.rs index 8523632acfbd..f7b394d481cc 100644 --- a/crates/ide-assists/src/tests/generated.rs +++ b/crates/ide-assists/src/tests/generated.rs @@ -1538,6 +1538,41 @@ impl MyStruct { ) } +#[test] +fn doctest_generate_mut_trait_impl() { + check_doc_test( + "generate_mut_trait_impl", + r#####" +pub enum Axis { X = 0, Y = 1, Z = 2 } + +impl Index$0 for [T; 3] { + type Output = T; + + fn index(&self, index: Axis) -> &Self::Output { + &self[index as usize] + } +} +"#####, + r#####" +pub enum Axis { X = 0, Y = 1, Z = 2 } + +$0impl IndexMut for [T; 3] { + fn index_mut(&mut self, index: Axis) -> &mut Self::Output { + &self[index as usize] + } +} + +impl Index for [T; 3] { + type Output = T; + + fn index(&self, index: Axis) -> &Self::Output { + &self[index as usize] + } +} +"#####, + ) +} + #[test] fn doctest_generate_new() { check_doc_test( diff --git a/crates/syntax/src/ast/make.rs b/crates/syntax/src/ast/make.rs index 96f685d8d6d8..31a858b91a7d 100644 --- a/crates/syntax/src/ast/make.rs +++ b/crates/syntax/src/ast/make.rs @@ -852,6 +852,10 @@ pub fn self_param() -> ast::SelfParam { ast_from_text("fn f(&self) { }") } +pub fn mut_self_param() -> ast::SelfParam { + ast_from_text("fn f(&mut self) { }") +} + pub fn ret_type(ty: ast::Type) -> ast::RetType { ast_from_text(&format!("fn f() -> {ty} {{ }}")) } From b84940b199c45799fc9b6b01ed30615c28e98546 Mon Sep 17 00:00:00 2001 From: Young-Flash <871946895@qq.com> Date: Sun, 5 Nov 2023 12:20:32 +0800 Subject: [PATCH 267/435] make generate_mut_trait_impl assist trigged for std trait only --- .../src/handlers/generate_mut_trait_impl.rs | 35 +++++++++++-------- crates/ide-assists/src/tests/generated.rs | 7 ++-- crates/ide-db/src/famous_defs.rs | 4 +++ 3 files changed, 29 insertions(+), 17 deletions(-) diff --git a/crates/ide-assists/src/handlers/generate_mut_trait_impl.rs b/crates/ide-assists/src/handlers/generate_mut_trait_impl.rs index ceb9d22c1b9f..cb8ef395650b 100644 --- a/crates/ide-assists/src/handlers/generate_mut_trait_impl.rs +++ b/crates/ide-assists/src/handlers/generate_mut_trait_impl.rs @@ -1,3 +1,4 @@ +use ide_db::famous_defs::FamousDefs; use syntax::{ ast::{self, make}, ted, AstNode, @@ -5,7 +6,7 @@ use syntax::{ use crate::{AssistContext, AssistId, AssistKind, Assists}; -// Generate proper `index_mut` method body refer to `index` method body may impossible due to the unpredicable case [#15581]. +// FIXME: Generate proper `index_mut` method body refer to `index` method body may impossible due to the unpredicable case [#15581]. // Here just leave the `index_mut` method body be same as `index` method body, user can modify it manually to meet their need. // Assist: generate_mut_trait_impl @@ -13,9 +14,10 @@ use crate::{AssistContext, AssistId, AssistKind, Assists}; // Adds a IndexMut impl from the `Index` trait. // // ``` +// # //- minicore: index // pub enum Axis { X = 0, Y = 1, Z = 2 } // -// impl Index$0 for [T; 3] { +// impl core::ops::Index$0 for [T; 3] { // type Output = T; // // fn index(&self, index: Axis) -> &Self::Output { @@ -27,13 +29,13 @@ use crate::{AssistContext, AssistId, AssistKind, Assists}; // ``` // pub enum Axis { X = 0, Y = 1, Z = 2 } // -// $0impl IndexMut for [T; 3] { +// $0impl core::ops::IndexMut for [T; 3] { // fn index_mut(&mut self, index: Axis) -> &mut Self::Output { // &self[index as usize] // } // } // -// impl Index for [T; 3] { +// impl core::ops::Index for [T; 3] { // type Output = T; // // fn index(&self, index: Axis) -> &Self::Output { @@ -45,9 +47,10 @@ pub(crate) fn generate_mut_trait_impl(acc: &mut Assists, ctx: &AssistContext<'_> let impl_def = ctx.find_node_at_offset::()?.clone_for_update(); let trait_ = impl_def.trait_()?; - if let ast::Type::PathType(trait_type) = trait_.clone() { - let trait_name = trait_type.path()?.segment()?.name_ref()?.to_string(); - if trait_name != "Index" { + if let ast::Type::PathType(trait_path) = trait_.clone() { + let trait_type = ctx.sema.resolve_trait(&trait_path.path()?)?; + let scope = ctx.sema.scope(trait_path.syntax())?; + if trait_type != FamousDefs(&ctx.sema, scope.krate()).core_convert_Index()? { return None; } } @@ -118,9 +121,10 @@ mod tests { check_assist( generate_mut_trait_impl, r#" +//- minicore: index pub enum Axis { X = 0, Y = 1, Z = 2 } -impl Index$0 for [T; 3] { +impl core::ops::Index$0 for [T; 3] { type Output = T; fn index(&self, index: Axis) -> &Self::Output { @@ -131,13 +135,13 @@ impl Index$0 for [T; 3] { r#" pub enum Axis { X = 0, Y = 1, Z = 2 } -$0impl IndexMut for [T; 3] { +$0impl core::ops::IndexMut for [T; 3] { fn index_mut(&mut self, index: Axis) -> &mut Self::Output { &self[index as usize] } } -impl Index for [T; 3] { +impl core::ops::Index for [T; 3] { type Output = T; fn index(&self, index: Axis) -> &Self::Output { @@ -150,9 +154,10 @@ impl Index for [T; 3] { check_assist( generate_mut_trait_impl, r#" +//- minicore: index pub enum Axis { X = 0, Y = 1, Z = 2 } -impl Index$0 for [T; 3] where T: Copy { +impl core::ops::Index$0 for [T; 3] where T: Copy { type Output = T; fn index(&self, index: Axis) -> &Self::Output { @@ -164,14 +169,14 @@ impl Index$0 for [T; 3] where T: Copy { r#" pub enum Axis { X = 0, Y = 1, Z = 2 } -$0impl IndexMut for [T; 3] where T: Copy { +$0impl core::ops::IndexMut for [T; 3] where T: Copy { fn index_mut(&mut self, index: Axis) -> &mut Self::Output { let var_name = &self[index as usize]; var_name } } -impl Index for [T; 3] where T: Copy { +impl core::ops::Index for [T; 3] where T: Copy { type Output = T; fn index(&self, index: Axis) -> &Self::Output { @@ -188,7 +193,9 @@ impl Index for [T; 3] where T: Copy { check_assist_not_applicable( generate_mut_trait_impl, r#" -impl Add$0 for [T; 3] {} +pub trait Index {} + +impl Index$0 for [T; 3] {} "#, ); } diff --git a/crates/ide-assists/src/tests/generated.rs b/crates/ide-assists/src/tests/generated.rs index f7b394d481cc..da5822bba9c8 100644 --- a/crates/ide-assists/src/tests/generated.rs +++ b/crates/ide-assists/src/tests/generated.rs @@ -1543,9 +1543,10 @@ fn doctest_generate_mut_trait_impl() { check_doc_test( "generate_mut_trait_impl", r#####" +//- minicore: index pub enum Axis { X = 0, Y = 1, Z = 2 } -impl Index$0 for [T; 3] { +impl core::ops::Index$0 for [T; 3] { type Output = T; fn index(&self, index: Axis) -> &Self::Output { @@ -1556,13 +1557,13 @@ impl Index$0 for [T; 3] { r#####" pub enum Axis { X = 0, Y = 1, Z = 2 } -$0impl IndexMut for [T; 3] { +$0impl core::ops::IndexMut for [T; 3] { fn index_mut(&mut self, index: Axis) -> &mut Self::Output { &self[index as usize] } } -impl Index for [T; 3] { +impl core::ops::Index for [T; 3] { type Output = T; fn index(&self, index: Axis) -> &Self::Output { diff --git a/crates/ide-db/src/famous_defs.rs b/crates/ide-db/src/famous_defs.rs index b63dde2c21e7..722517a7677b 100644 --- a/crates/ide-db/src/famous_defs.rs +++ b/crates/ide-db/src/famous_defs.rs @@ -54,6 +54,10 @@ impl FamousDefs<'_, '_> { self.find_trait("core:convert:Into") } + pub fn core_convert_Index(&self) -> Option { + self.find_trait("core:ops:Index") + } + pub fn core_option_Option(&self) -> Option { self.find_enum("core:option:Option") } From 81af5b5031e346c5e2bdb8d0a88bf2904308a731 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 4 Nov 2023 10:55:18 +0100 Subject: [PATCH 268/435] update and clarify addr_of docs --- library/core/src/ptr/mod.rs | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 84b179df8c19..12c6922eec0c 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -1989,9 +1989,18 @@ impl fmt::Debug for F { /// as all other references. This macro can create a raw pointer *without* creating /// a reference first. /// -/// Note, however, that the `expr` in `addr_of!(expr)` is still subject to all -/// the usual rules. In particular, `addr_of!(*ptr::null())` is Undefined -/// Behavior because it dereferences a null pointer. +/// The `expr` in `addr_of!(expr)` is evaluated as a place expression, but never loads +/// from the place or requires the place to be dereferenceable. This means that +/// `addr_of!(*ptr)` is defined behavior even if `ptr` is dangling or misaligned. +/// Note however that `addr_of!((*ptr).field)` still requires the projection to +/// `field` to be in-bounds, using the same rules as [`offset`]. +/// +/// Note that `Deref`/`Index` coercions (and their mutable counterparts) are applied inside +/// `addr_of!` like everywhere else, in which case a reference is created to call `Deref::deref` or +/// `Index::index`, respectively. The statements above only apply when no such coercions are +/// applied. +/// +/// [`offset`]: pointer::offset /// /// # Example /// @@ -2029,9 +2038,18 @@ pub macro addr_of($place:expr) { /// as all other references. This macro can create a raw pointer *without* creating /// a reference first. /// -/// Note, however, that the `expr` in `addr_of_mut!(expr)` is still subject to all -/// the usual rules. In particular, `addr_of_mut!(*ptr::null_mut())` is Undefined -/// Behavior because it dereferences a null pointer. +/// The `expr` in `addr_of_mut!(expr)` is evaluated as a place expression, but never loads +/// from the place or requires the place to be dereferenceable. This means that +/// `addr_of_mut!(*ptr)` is defined behavior even if `ptr` is dangling or misaligned. +/// Note however that `addr_of_mut!((*ptr).field)` still requires the projection to +/// `field` to be in-bounds, using the same rules as [`offset`]. +/// +/// Note that `Deref`/`Index` coercions (and their mutable counterparts) are applied inside +/// `addr_of_mut!` like everywhere else, in which case a reference is created to call `Deref::deref` +/// or `Index::index`, respectively. The statements above only apply when no such coercions are +/// applied. +/// +/// [`offset`]: pointer::offset /// /// # Examples /// From 38ff91c453a36257dcc4e9f487520f96079da578 Mon Sep 17 00:00:00 2001 From: klensy Date: Sun, 5 Nov 2023 14:09:19 +0300 Subject: [PATCH 269/435] bump clang version for dist-x86_64-linux from 17.0.2 to 17.0.4 This fixes few miscompiles, so nice to have. --- src/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh index 56ee348a337e..1d9568702cc3 100755 --- a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh +++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh @@ -4,7 +4,7 @@ set -ex source shared.sh -LLVM=llvmorg-17.0.2 +LLVM=llvmorg-17.0.4 mkdir llvm-project cd llvm-project From b0df8216ed4ab2d59e8cb94974ca5d2e01c8fc63 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Sat, 4 Nov 2023 19:35:58 +0300 Subject: [PATCH 270/435] bootstrap: improve linking of tool docs Signed-off-by: onur-ozkan --- src/bootstrap/src/core/build_steps/doc.rs | 81 +++++++++++------------ 1 file changed, 40 insertions(+), 41 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs index 1ef481408f95..f2a185f70fe0 100644 --- a/src/bootstrap/src/core/build_steps/doc.rs +++ b/src/bootstrap/src/core/build_steps/doc.rs @@ -685,8 +685,6 @@ impl Step for Rustc { target, ); - let out_dir = builder.stage_out(compiler, Mode::Rustc).join(target.triple).join("doc"); - // Build cargo command. let mut cargo = builder.cargo(compiler, Mode::Rustc, SourceType::InTree, target, "doc"); cargo.rustdocflag("--document-private-items"); @@ -713,6 +711,7 @@ impl Step for Rustc { let mut to_open = None; + let out_dir = builder.stage_out(compiler, Mode::Rustc).join(target.triple).join("doc"); for krate in &*self.crates { // Create all crate output directories first to make sure rustdoc uses // relative links. @@ -766,10 +765,10 @@ macro_rules! tool_doc { $should_run: literal, $path: literal, $(rustc_tool = $rustc_tool:literal, )? - $(in_tree = $in_tree:literal, )? - [$($extra_arg: literal),+ $(,)?] - $(,)? - ) => { + $(in_tree = $in_tree:literal ,)? + $(is_library = $is_library:expr,)? + $(crates = $crates:expr)? + ) => { #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct $tool { target: TargetSelection, @@ -822,17 +821,6 @@ macro_rules! tool_doc { SourceType::Submodule }; - // Symlink compiler docs to the output directory of rustdoc documentation. - let out_dirs = [ - builder.stage_out(compiler, Mode::ToolRustc).join(target.triple).join("doc"), - // Cargo uses a different directory for proc macros. - builder.stage_out(compiler, Mode::ToolRustc).join("doc"), - ]; - for out_dir in out_dirs { - t!(fs::create_dir_all(&out_dir)); - symlink_dir_force(&builder.config, &out, &out_dir); - } - // Build cargo command. let mut cargo = prepare_tool_cargo( builder, @@ -849,9 +837,13 @@ macro_rules! tool_doc { // Only include compiler crates, no dependencies of those, such as `libc`. cargo.arg("--no-deps"); - $( - cargo.arg($extra_arg); - )+ + if false $(|| $is_library)? { + cargo.arg("--lib"); + } + + $(for krate in $crates { + cargo.arg("-p").arg(krate); + })? cargo.rustdocflag("--document-private-items"); // Since we always pass --document-private-items, there's no need to warn about linking to private items. @@ -861,62 +853,69 @@ macro_rules! tool_doc { cargo.rustdocflag("--generate-link-to-definition"); cargo.rustdocflag("-Zunstable-options"); + let out_dir = builder.stage_out(compiler, Mode::ToolRustc).join(target.triple).join("doc"); + $(for krate in $crates { + let dir_name = krate.replace("-", "_"); + t!(fs::create_dir_all(out_dir.join(&*dir_name))); + })? + + // Symlink compiler docs to the output directory of rustdoc documentation. + symlink_dir_force(&builder.config, &out, &out_dir); + let proc_macro_out_dir = builder.stage_out(compiler, Mode::ToolRustc).join("doc"); + symlink_dir_force(&builder.config, &out, &proc_macro_out_dir); + let _guard = builder.msg_doc(compiler, stringify!($tool).to_lowercase(), target); builder.run(&mut cargo.into()); + + if !builder.config.dry_run() { + // Sanity check on linked doc directories + $(for krate in $crates { + let dir_name = krate.replace("-", "_"); + // Making sure the directory exists and is not empty. + assert!(out.join(&*dir_name).read_dir().unwrap().next().is_some()); + })? + } } } } } -tool_doc!( - Rustdoc, - "rustdoc-tool", - "src/tools/rustdoc", - ["-p", "rustdoc", "-p", "rustdoc-json-types"] -); +tool_doc!(Rustdoc, "rustdoc-tool", "src/tools/rustdoc", crates = ["rustdoc", "rustdoc-json-types"]); tool_doc!( Rustfmt, "rustfmt-nightly", "src/tools/rustfmt", - ["-p", "rustfmt-nightly", "-p", "rustfmt-config_proc_macro"], + crates = ["rustfmt-nightly", "rustfmt-config_proc_macro"] ); -tool_doc!(Clippy, "clippy", "src/tools/clippy", ["-p", "clippy_utils"]); -tool_doc!(Miri, "miri", "src/tools/miri", ["-p", "miri"]); +tool_doc!(Clippy, "clippy", "src/tools/clippy", crates = ["clippy_utils"]); +tool_doc!(Miri, "miri", "src/tools/miri", crates = ["miri"]); tool_doc!( Cargo, "cargo", "src/tools/cargo", rustc_tool = false, in_tree = false, - [ - "-p", + crates = [ "cargo", - "-p", "cargo-platform", - "-p", "cargo-util", - "-p", "crates-io", - "-p", "cargo-test-macro", - "-p", "cargo-test-support", - "-p", "cargo-credential", - "-p", "mdman", // FIXME: this trips a license check in tidy. - // "-p", // "resolver-tests", ] ); -tool_doc!(Tidy, "tidy", "src/tools/tidy", rustc_tool = false, ["-p", "tidy"]); +tool_doc!(Tidy, "tidy", "src/tools/tidy", rustc_tool = false, crates = ["tidy"]); tool_doc!( Bootstrap, "bootstrap", "src/bootstrap", rustc_tool = false, - ["--lib", "-p", "bootstrap"] + is_library = true, + crates = ["bootstrap"] ); #[derive(Ord, PartialOrd, Debug, Copy, Clone, Hash, PartialEq, Eq)] From 6e33e89337e13a8fb4fbe660f153188622558205 Mon Sep 17 00:00:00 2001 From: Jack Huey <31162821+jackh726@users.noreply.github.com> Date: Sun, 5 Nov 2023 10:09:51 -0500 Subject: [PATCH 271/435] Remove from vacation and compiler review group --- triagebot.toml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/triagebot.toml b/triagebot.toml index b846edca98b3..69bbbdb03bf4 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -608,19 +608,18 @@ cc = ["@nnethercote"] [assign] warn_non_default_branch = true contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html" -users_on_vacation = ["jyn514", "jackh726", "WaffleLapkin", "oli-obk"] +users_on_vacation = ["jyn514", "WaffleLapkin", "oli-obk"] [assign.adhoc_groups] compiler-team = [ "@cjgillot", + "@compiler-errors", "@petrochenkov", "@davidtwco", "@oli-obk", "@wesleywiser", ] compiler-team-contributors = [ - "@compiler-errors", - "@jackh726", "@TaKO8Ki", "@WaffleLapkin", "@b-naber", From 1a1b10fa637e422a00af82941f9854928c12bf95 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sat, 4 Nov 2023 18:02:31 +0000 Subject: [PATCH 272/435] Don't steal the parse query when using --pretty This is the only place aside from the global_ctxt query where it is stolen. --- compiler/rustc_driver_impl/src/lib.rs | 8 ++++++-- compiler/rustc_driver_impl/src/pretty.rs | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index ee4337754a9c..19e0a61e820a 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -421,8 +421,12 @@ fn run_compiler( // effects of writing the dep-info and reporting errors. queries.global_ctxt()?.enter(|tcx| tcx.output_filenames(())); } else { - let krate = queries.parse()?.steal(); - pretty::print(sess, *ppm, pretty::PrintExtra::AfterParsing { krate }); + let krate = queries.parse()?; + pretty::print( + sess, + *ppm, + pretty::PrintExtra::AfterParsing { krate: &*krate.borrow() }, + ); } trace!("finished pretty-printing"); return early_exit(); diff --git a/compiler/rustc_driver_impl/src/pretty.rs b/compiler/rustc_driver_impl/src/pretty.rs index 8c6fee830130..cc533b9941ab 100644 --- a/compiler/rustc_driver_impl/src/pretty.rs +++ b/compiler/rustc_driver_impl/src/pretty.rs @@ -217,7 +217,7 @@ fn write_or_print(out: &str, sess: &Session) { // Extra data for pretty-printing, the form of which depends on what kind of // pretty-printing we are doing. pub enum PrintExtra<'tcx> { - AfterParsing { krate: ast::Crate }, + AfterParsing { krate: &'tcx ast::Crate }, NeedsAstMap { tcx: TyCtxt<'tcx> }, } From ba82056a1434bb9086bb9fa7b75878600996a327 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sat, 4 Nov 2023 18:12:22 +0000 Subject: [PATCH 273/435] Use the actual computed crate name for -Zprint-vtable-sizes --- compiler/rustc_driver_impl/src/lib.rs | 4 ++-- compiler/rustc_session/src/code_stats.rs | 2 +- .../traits/object/print_vtable_sizes.stdout | 22 +++++++++---------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 19e0a61e820a..84ae45d6a2b6 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -41,6 +41,7 @@ use rustc_session::cstore::MetadataLoader; use rustc_session::getopts::{self, Matches}; use rustc_session::lint::{Lint, LintId}; use rustc_session::{config, EarlyErrorHandler, Session}; +use rustc_span::def_id::LOCAL_CRATE; use rustc_span::source_map::FileLoader; use rustc_span::symbol::sym; use rustc_span::FileName; @@ -481,8 +482,7 @@ fn run_compiler( } if sess.opts.unstable_opts.print_vtable_sizes { - let crate_name = - compiler.session().opts.crate_name.as_deref().unwrap_or(""); + let crate_name = queries.global_ctxt()?.enter(|tcx| tcx.crate_name(LOCAL_CRATE)); sess.code_stats.print_vtable_sizes(crate_name); } diff --git a/compiler/rustc_session/src/code_stats.rs b/compiler/rustc_session/src/code_stats.rs index f792b8f2cdd5..e1eb58fecc7d 100644 --- a/compiler/rustc_session/src/code_stats.rs +++ b/compiler/rustc_session/src/code_stats.rs @@ -226,7 +226,7 @@ impl CodeStats { } } - pub fn print_vtable_sizes(&self, crate_name: &str) { + pub fn print_vtable_sizes(&self, crate_name: Symbol) { let mut infos = std::mem::take(&mut *self.vtable_sizes.lock()).into_values().collect::>(); diff --git a/tests/ui/traits/object/print_vtable_sizes.stdout b/tests/ui/traits/object/print_vtable_sizes.stdout index ce90c76217b9..b43e168df3f3 100644 --- a/tests/ui/traits/object/print_vtable_sizes.stdout +++ b/tests/ui/traits/object/print_vtable_sizes.stdout @@ -1,11 +1,11 @@ -print-vtable-sizes { "crate_name": "", "trait_name": "E", "entries": "6", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "2", "upcasting_cost_percent": "50" } -print-vtable-sizes { "crate_name": "", "trait_name": "G", "entries": "14", "entries_ignoring_upcasting": "11", "entries_for_upcasting": "3", "upcasting_cost_percent": "27.27272727272727" } -print-vtable-sizes { "crate_name": "", "trait_name": "A", "entries": "6", "entries_ignoring_upcasting": "5", "entries_for_upcasting": "1", "upcasting_cost_percent": "20" } -print-vtable-sizes { "crate_name": "", "trait_name": "B", "entries": "4", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } -print-vtable-sizes { "crate_name": "", "trait_name": "D", "entries": "4", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } -print-vtable-sizes { "crate_name": "", "trait_name": "F", "entries": "6", "entries_ignoring_upcasting": "6", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } -print-vtable-sizes { "crate_name": "", "trait_name": "_::S", "entries": "3", "entries_ignoring_upcasting": "3", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } -print-vtable-sizes { "crate_name": "", "trait_name": "_::S", "entries": "3", "entries_ignoring_upcasting": "3", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } -print-vtable-sizes { "crate_name": "", "trait_name": "help::MarkerWithSuper", "entries": "4", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } -print-vtable-sizes { "crate_name": "", "trait_name": "help::Super", "entries": "4", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } -print-vtable-sizes { "crate_name": "", "trait_name": "help::V", "entries": "3", "entries_ignoring_upcasting": "3", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } +print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "E", "entries": "6", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "2", "upcasting_cost_percent": "50" } +print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "G", "entries": "14", "entries_ignoring_upcasting": "11", "entries_for_upcasting": "3", "upcasting_cost_percent": "27.27272727272727" } +print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "A", "entries": "6", "entries_ignoring_upcasting": "5", "entries_for_upcasting": "1", "upcasting_cost_percent": "20" } +print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "B", "entries": "4", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } +print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "D", "entries": "4", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } +print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "F", "entries": "6", "entries_ignoring_upcasting": "6", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } +print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "_::S", "entries": "3", "entries_ignoring_upcasting": "3", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } +print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "_::S", "entries": "3", "entries_ignoring_upcasting": "3", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } +print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "help::MarkerWithSuper", "entries": "4", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } +print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "help::Super", "entries": "4", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } +print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "help::V", "entries": "3", "entries_ignoring_upcasting": "3", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } From ec29a02071a3bdc95bb36d8f1a5693803295431e Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 5 Nov 2023 12:29:15 +0000 Subject: [PATCH 274/435] Update doc comment for CodegenBackend::link --- compiler/rustc_codegen_ssa/src/traits/backend.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs index ac8123bc1be9..35744d9a167f 100644 --- a/compiler/rustc_codegen_ssa/src/traits/backend.rs +++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs @@ -104,11 +104,7 @@ pub trait CodegenBackend { outputs: &OutputFilenames, ) -> Result<(CodegenResults, FxIndexMap), ErrorGuaranteed>; - /// This is called on the returned `Box` from `join_codegen` - /// - /// # Panics - /// - /// Panics when the passed `Box` was not returned by `join_codegen`. + /// This is called on the returned `CodegenResults` from `join_codegen` fn link( &self, sess: &Session, From 15719a8c1dd74e38fd81e825d77450479a4e6823 Mon Sep 17 00:00:00 2001 From: Urgau Date: Sun, 5 Nov 2023 15:27:20 +0100 Subject: [PATCH 275/435] libc: bump dependency to 0.2.150 --- Cargo.lock | 4 ++-- library/std/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 376176e85a90..a3f995be9038 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2215,9 +2215,9 @@ checksum = "db13adb97ab515a3691f56e4dbab09283d0b86cb45abd991d8634a9d6f501760" [[package]] name = "libc" -version = "0.2.149" +version = "0.2.150" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" +checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" dependencies = [ "rustc-std-workspace-core", ] diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index f3e79b28faf8..f666b18887cb 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -17,7 +17,7 @@ cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] } panic_unwind = { path = "../panic_unwind", optional = true } panic_abort = { path = "../panic_abort" } core = { path = "../core", public = true } -libc = { version = "0.2.149", default-features = false, features = ['rustc-dep-of-std'], public = true } +libc = { version = "0.2.150", default-features = false, features = ['rustc-dep-of-std'], public = true } compiler_builtins = { version = "0.1.103" } profiler_builtins = { path = "../profiler_builtins", optional = true } unwind = { path = "../unwind" } From c8a25eddfe1f3c82d16850fc5979de93f79a7732 Mon Sep 17 00:00:00 2001 From: hkalbasi Date: Sun, 5 Nov 2023 21:51:47 +0330 Subject: [PATCH 276/435] Make the randomize feature of rustc_abi additive --- compiler/rustc_abi/src/layout.rs | 5 ++--- compiler/rustc_abi/src/lib.rs | 5 ++--- compiler/rustc_middle/src/ty/mod.rs | 2 +- compiler/rustc_mir_transform/src/sroa.rs | 4 ++-- 4 files changed, 7 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index 9127e1d06e88..996fd5bbecfc 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -906,9 +906,8 @@ fn univariant< use rand::{seq::SliceRandom, SeedableRng}; // `ReprOptions.layout_seed` is a deterministic seed we can use to randomize field // ordering. - let mut rng = rand_xoshiro::Xoshiro128StarStar::seed_from_u64( - repr.field_shuffle_seed.as_u64(), - ); + let mut rng = + rand_xoshiro::Xoshiro128StarStar::seed_from_u64(repr.field_shuffle_seed); // Shuffle the ordering of the fields. optimizing.shuffle(&mut rng); diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 8e7aa59ee341..09a87cf8e2f0 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -76,15 +76,14 @@ pub struct ReprOptions { pub align: Option, pub pack: Option, pub flags: ReprFlags, - #[cfg(feature = "randomize")] /// The seed to be used for randomizing a type's layout /// - /// Note: This could technically be a `Hash128` which would + /// Note: This could technically be a `u128` which would /// be the "most accurate" hash as it'd encompass the item and crate /// hash without loss, but it does pay the price of being larger. /// Everything's a tradeoff, a 64-bit seed should be sufficient for our /// purposes (primarily `-Z randomize-layout`) - pub field_shuffle_seed: rustc_data_structures::stable_hasher::Hash64, + pub field_shuffle_seed: u64, } impl ReprOptions { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 739d4fa886ec..b98ccf747ee0 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2011,7 +2011,7 @@ impl<'tcx> TyCtxt<'tcx> { // Generate a deterministically-derived seed from the item's path hash // to allow for cross-crate compilation to actually work - let mut field_shuffle_seed = self.def_path_hash(did).0.to_smaller_hash(); + let mut field_shuffle_seed = self.def_path_hash(did).0.to_smaller_hash().as_u64(); // If the user defined a custom seed for layout randomization, xor the item's // path hash with the user defined seed, this will allowing determinism while diff --git a/compiler/rustc_mir_transform/src/sroa.rs b/compiler/rustc_mir_transform/src/sroa.rs index 427cc1e19241..7de4ca667949 100644 --- a/compiler/rustc_mir_transform/src/sroa.rs +++ b/compiler/rustc_mir_transform/src/sroa.rs @@ -7,7 +7,7 @@ use rustc_middle::mir::visit::*; use rustc_middle::mir::*; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_mir_dataflow::value_analysis::{excluded_locals, iter_fields}; -use rustc_target::abi::{FieldIdx, ReprFlags, FIRST_VARIANT}; +use rustc_target::abi::{FieldIdx, FIRST_VARIANT}; pub struct ScalarReplacementOfAggregates; @@ -66,7 +66,7 @@ fn escaping_locals<'tcx>( return true; } if let ty::Adt(def, _args) = ty.kind() { - if def.repr().flags.contains(ReprFlags::IS_SIMD) { + if def.repr().simd() { // Exclude #[repr(simd)] types so that they are not de-optimized into an array return true; } From 6a53acefd8520d2d3a92dc56db78e4c5e5c26cf9 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 5 Nov 2023 18:24:39 +0000 Subject: [PATCH 277/435] Implement _mm256_permute2f128_ps and _mm256_permute2f128_pd intrinsics --- src/intrinsics/llvm_x86.rs | 38 +++++++++++++------------- src/value_and_place.rs | 56 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 19 deletions(-) diff --git a/src/intrinsics/llvm_x86.rs b/src/intrinsics/llvm_x86.rs index 6fd85ab8bf1d..97759b59ebe6 100644 --- a/src/intrinsics/llvm_x86.rs +++ b/src/intrinsics/llvm_x86.rs @@ -172,8 +172,12 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( } } } - "llvm.x86.avx2.vperm2i128" => { + "llvm.x86.avx2.vperm2i128" + | "llvm.x86.avx.vperm2f128.ps.256" + | "llvm.x86.avx.vperm2f128.pd.256" => { // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_permute2x128_si256 + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_permute2f128_ps + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_permute2f128_pd let (a, b, imm8) = match args { [a, b, imm8] => (a, b, imm8), _ => bug!("wrong number of args for intrinsic {intrinsic}"), @@ -182,19 +186,11 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( let b = codegen_operand(fx, b); let imm8 = codegen_operand(fx, imm8).load_scalar(fx); - let a_0 = a.value_lane(fx, 0).load_scalar(fx); - let a_1 = a.value_lane(fx, 1).load_scalar(fx); - let a_low = fx.bcx.ins().iconcat(a_0, a_1); - let a_2 = a.value_lane(fx, 2).load_scalar(fx); - let a_3 = a.value_lane(fx, 3).load_scalar(fx); - let a_high = fx.bcx.ins().iconcat(a_2, a_3); + let a_low = a.value_typed_lane(fx, fx.tcx.types.u128, 0).load_scalar(fx); + let a_high = a.value_typed_lane(fx, fx.tcx.types.u128, 1).load_scalar(fx); - let b_0 = b.value_lane(fx, 0).load_scalar(fx); - let b_1 = b.value_lane(fx, 1).load_scalar(fx); - let b_low = fx.bcx.ins().iconcat(b_0, b_1); - let b_2 = b.value_lane(fx, 2).load_scalar(fx); - let b_3 = b.value_lane(fx, 3).load_scalar(fx); - let b_high = fx.bcx.ins().iconcat(b_2, b_3); + let b_low = b.value_typed_lane(fx, fx.tcx.types.u128, 0).load_scalar(fx); + let b_high = b.value_typed_lane(fx, fx.tcx.types.u128, 1).load_scalar(fx); fn select4( fx: &mut FunctionCx<'_, '_, '_>, @@ -219,16 +215,20 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( let control0 = imm8; let res_low = select4(fx, a_high, a_low, b_high, b_low, control0); - let (res_0, res_1) = fx.bcx.ins().isplit(res_low); let control1 = fx.bcx.ins().ushr_imm(imm8, 4); let res_high = select4(fx, a_high, a_low, b_high, b_low, control1); - let (res_2, res_3) = fx.bcx.ins().isplit(res_high); - ret.place_lane(fx, 0).to_ptr().store(fx, res_0, MemFlags::trusted()); - ret.place_lane(fx, 1).to_ptr().store(fx, res_1, MemFlags::trusted()); - ret.place_lane(fx, 2).to_ptr().store(fx, res_2, MemFlags::trusted()); - ret.place_lane(fx, 3).to_ptr().store(fx, res_3, MemFlags::trusted()); + ret.place_typed_lane(fx, fx.tcx.types.u128, 0).to_ptr().store( + fx, + res_low, + MemFlags::trusted(), + ); + ret.place_typed_lane(fx, fx.tcx.types.u128, 1).to_ptr().store( + fx, + res_high, + MemFlags::trusted(), + ); } "llvm.x86.ssse3.pabs.b.128" | "llvm.x86.ssse3.pabs.w.128" | "llvm.x86.ssse3.pabs.d.128" => { let a = match args { diff --git a/src/value_and_place.rs b/src/value_and_place.rs index 5f0aa6c5581d..21ad2a835fc9 100644 --- a/src/value_and_place.rs +++ b/src/value_and_place.rs @@ -243,6 +243,34 @@ impl<'tcx> CValue<'tcx> { let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx); let lane_layout = fx.layout_of(lane_ty); assert!(lane_idx < lane_count); + + match self.0 { + CValueInner::ByVal(_) | CValueInner::ByValPair(_, _) => unreachable!(), + CValueInner::ByRef(ptr, None) => { + let field_offset = lane_layout.size * lane_idx; + let field_ptr = ptr.offset_i64(fx, i64::try_from(field_offset.bytes()).unwrap()); + CValue::by_ref(field_ptr, lane_layout) + } + CValueInner::ByRef(_, Some(_)) => unreachable!(), + } + } + + /// Like [`CValue::value_field`] except using the passed type as lane type instead of the one + /// specified by the vector type. + pub(crate) fn value_typed_lane( + self, + fx: &mut FunctionCx<'_, '_, 'tcx>, + lane_ty: Ty<'tcx>, + lane_idx: u64, + ) -> CValue<'tcx> { + let layout = self.1; + assert!(layout.ty.is_simd()); + let (orig_lane_count, orig_lane_ty) = layout.ty.simd_size_and_type(fx.tcx); + let lane_layout = fx.layout_of(lane_ty); + assert!( + (lane_idx + 1) * lane_layout.size <= orig_lane_count * fx.layout_of(orig_lane_ty).size + ); + match self.0 { CValueInner::ByVal(_) | CValueInner::ByValPair(_, _) => unreachable!(), CValueInner::ByRef(ptr, None) => { @@ -734,6 +762,34 @@ impl<'tcx> CPlace<'tcx> { } } + /// Like [`CPlace::place_field`] except using the passed type as lane type instead of the one + /// specified by the vector type. + pub(crate) fn place_typed_lane( + self, + fx: &mut FunctionCx<'_, '_, 'tcx>, + lane_ty: Ty<'tcx>, + lane_idx: u64, + ) -> CPlace<'tcx> { + let layout = self.layout(); + assert!(layout.ty.is_simd()); + let (orig_lane_count, orig_lane_ty) = layout.ty.simd_size_and_type(fx.tcx); + let lane_layout = fx.layout_of(lane_ty); + assert!( + (lane_idx + 1) * lane_layout.size <= orig_lane_count * fx.layout_of(orig_lane_ty).size + ); + + match self.inner { + CPlaceInner::Var(_, _) => unreachable!(), + CPlaceInner::VarPair(_, _, _) => unreachable!(), + CPlaceInner::Addr(ptr, None) => { + let field_offset = lane_layout.size * lane_idx; + let field_ptr = ptr.offset_i64(fx, i64::try_from(field_offset.bytes()).unwrap()); + CPlace::for_ptr(field_ptr, lane_layout) + } + CPlaceInner::Addr(_, Some(_)) => unreachable!(), + } + } + pub(crate) fn place_index( self, fx: &mut FunctionCx<'_, '_, 'tcx>, From 438194980b9184fc13dab03444e604db9f5a8a07 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 5 Nov 2023 19:49:30 +0000 Subject: [PATCH 278/435] Implement all avx2 intrinsics used by the image crate --- src/intrinsics/llvm_x86.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/intrinsics/llvm_x86.rs b/src/intrinsics/llvm_x86.rs index 97759b59ebe6..9c415d468d87 100644 --- a/src/intrinsics/llvm_x86.rs +++ b/src/intrinsics/llvm_x86.rs @@ -304,7 +304,9 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( fx.bcx.ins().sshr(a_lane, saturated_count) }); } - "llvm.x86.sse2.psad.bw" => { + "llvm.x86.sse2.psad.bw" | "llvm.x86.avx2.psad.bw" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_sad_epu8&ig_expand=5770 + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_sad_epu8&ig_expand=5771 intrinsic_args!(fx, args => (a, b); intrinsic); assert_eq!(a.layout(), b.layout()); @@ -335,7 +337,9 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( ret.place_lane(fx, out_lane_idx).write_cvalue(fx, res_lane); } } - "llvm.x86.ssse3.pmadd.ub.sw.128" => { + "llvm.x86.ssse3.pmadd.ub.sw.128" | "llvm.x86.avx2.pmadd.ub.sw" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_maddubs_epi16&ig_expand=4267 + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_maddubs_epi16&ig_expand=4270 intrinsic_args!(fx, args => (a, b); intrinsic); let (lane_count, lane_ty) = a.layout().ty.simd_size_and_type(fx.tcx); @@ -374,7 +378,9 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( ret.place_lane(fx, out_lane_idx).write_cvalue(fx, res_lane); } } - "llvm.x86.sse2.pmadd.wd" => { + "llvm.x86.sse2.pmadd.wd" | "llvm.x86.avx2.pmadd.wd" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_madd_epi16&ig_expand=4231 + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_madd_epi16&ig_expand=4234 intrinsic_args!(fx, args => (a, b); intrinsic); assert_eq!(a.layout(), b.layout()); From f2a40e99ffcb8620634ba73ebf4a2b7d77661874 Mon Sep 17 00:00:00 2001 From: SparrowLii Date: Mon, 6 Nov 2023 09:58:51 +0800 Subject: [PATCH 279/435] use portable AtomicU64 for powerPC and MIPS --- Cargo.lock | 5 +++-- compiler/rustc_data_structures/Cargo.toml | 3 +++ compiler/rustc_data_structures/src/marker.rs | 13 ++++++++++++- compiler/rustc_data_structures/src/sync.rs | 10 +++++++++- src/tools/tidy/src/deps.rs | 1 + 5 files changed, 28 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2b1e918e2f5e..9e45a5edc91b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2982,9 +2982,9 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.4.2" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f32154ba0af3a075eefa1eda8bb414ee928f62303a54ea85b8d6638ff1a6ee9e" +checksum = "3bccab0e7fd7cc19f820a1c8c91720af652d0c88dc9664dd72aef2614f04af3b" [[package]] name = "ppv-lite86" @@ -3712,6 +3712,7 @@ dependencies = [ "measureme", "memmap2", "parking_lot 0.12.1", + "portable-atomic", "rustc-hash", "rustc-rayon", "rustc-rayon-core", diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml index 2701fdbbd77f..8d91c4c43768 100644 --- a/compiler/rustc_data_structures/Cargo.toml +++ b/compiler/rustc_data_structures/Cargo.toml @@ -47,6 +47,9 @@ features = [ memmap2 = "0.2.1" # tidy-alphabetical-end +[target.'cfg(any(target_arch = "powerpc", target_arch = "mips"))'.dependencies] +portable-atomic = "1.5.1" + [features] # tidy-alphabetical-start rustc_use_parallel_compiler = ["indexmap/rustc-rayon", "rustc-rayon", "rustc-rayon-core"] diff --git a/compiler/rustc_data_structures/src/marker.rs b/compiler/rustc_data_structures/src/marker.rs index a8c442377fbc..266e54604a6b 100644 --- a/compiler/rustc_data_structures/src/marker.rs +++ b/compiler/rustc_data_structures/src/marker.rs @@ -138,7 +138,6 @@ cfg_match! { [std::sync::atomic::AtomicUsize] [std::sync::atomic::AtomicU8] [std::sync::atomic::AtomicU32] - [std::sync::atomic::AtomicU64] [std::backtrace::Backtrace] [std::io::Error] [std::fs::File] @@ -148,6 +147,18 @@ cfg_match! { [crate::owned_slice::OwnedSlice] ); + // PowerPC and MIPS platforms with 32-bit pointers do not + // have AtomicU64 type. + #[cfg(not(any(target_arch = "powerpc", target_arch = "mips")))] + already_sync!( + [std::sync::atomic::AtomicU64] + ); + + #[cfg(any(target_arch = "powerpc", target_arch = "mips"))] + already_sync!( + [portable_atomic::AtomicU64] + ); + macro_rules! impl_dyn_sync { ($($($attr: meta)* [$ty: ty where $($generics2: tt)*])*) => { $(unsafe impl<$($generics2)*> DynSync for $ty {})* diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs index f957734b04d9..43221d70e21c 100644 --- a/compiler/rustc_data_structures/src/sync.rs +++ b/compiler/rustc_data_structures/src/sync.rs @@ -265,7 +265,15 @@ cfg_match! { pub use std::sync::OnceLock; - pub use std::sync::atomic::{AtomicBool, AtomicUsize, AtomicU32, AtomicU64}; + pub use std::sync::atomic::{AtomicBool, AtomicUsize, AtomicU32}; + + // PowerPC and MIPS platforms with 32-bit pointers do not + // have AtomicU64 type. + #[cfg(not(any(target_arch = "powerpc", target_arch = "mips")))] + pub use std::sync::atomic::AtomicU64; + + #[cfg(any(target_arch = "powerpc", target_arch = "mips"))] + pub use portable_atomic::AtomicU64; pub use std::sync::Arc as Lrc; pub use std::sync::Weak as Weak; diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index f89faacc2d17..e392efb2e341 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -211,6 +211,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "perf-event-open-sys", "pin-project-lite", "polonius-engine", + "portable-atomic", // dependency for platforms doesn't support `AtomicU64` in std "ppv-lite86", "proc-macro-hack", "proc-macro2", From b85c6835d0030b53b03b0cf10614dabd0be578f6 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 5 Nov 2023 18:06:19 +0100 Subject: [PATCH 280/435] warn when using an unstable feature with -Ctarget-feature --- compiler/rustc_codegen_llvm/messages.ftl | 8 +++- compiler/rustc_codegen_llvm/src/errors.rs | 7 +++ compiler/rustc_codegen_llvm/src/llvm_util.rs | 47 +++++++++++-------- .../rustc_codegen_ssa/src/target_features.rs | 9 ++++ .../similar-feature-suggestion.stderr | 4 +- tests/ui/target-feature/unstable-feature.rs | 6 +++ .../ui/target-feature/unstable-feature.stderr | 6 +++ 7 files changed, 64 insertions(+), 23 deletions(-) create mode 100644 tests/ui/target-feature/unstable-feature.rs create mode 100644 tests/ui/target-feature/unstable-feature.stderr diff --git a/compiler/rustc_codegen_llvm/messages.ftl b/compiler/rustc_codegen_llvm/messages.ftl index c0cfe39f1e0a..7a86ddc7556a 100644 --- a/compiler/rustc_codegen_llvm/messages.ftl +++ b/compiler/rustc_codegen_llvm/messages.ftl @@ -76,8 +76,8 @@ codegen_llvm_target_machine = could not create LLVM TargetMachine for triple: {$ codegen_llvm_target_machine_with_llvm_err = could not create LLVM TargetMachine for triple: {$triple}: {$llvm_err} codegen_llvm_unknown_ctarget_feature = - unknown feature specified for `-Ctarget-feature`: `{$feature}` - .note = it is still passed through to the codegen backend + unknown and unstable feature specified for `-Ctarget-feature`: `{$feature}` + .note = it is still passed through to the codegen backend, but use of this feature might be unsound and the behavior of this feature can change in the future .possible_feature = you might have meant: `{$rust_feature}` .consider_filing_feature_request = consider filing a feature request @@ -87,6 +87,10 @@ codegen_llvm_unknown_ctarget_feature_prefix = codegen_llvm_unknown_debuginfo_compression = unknown debuginfo compression algorithm {$algorithm} - will fall back to uncompressed debuginfo +codegen_llvm_unstable_ctarget_feature = + unstable feature specified for `-Ctarget-feature`: `{$feature}` + .note = this feature is not stably supported; its behavior can change in the future + codegen_llvm_write_bytecode = failed to write bytecode to {$path}: {$err} codegen_llvm_write_ir = failed to write LLVM IR to {$path} diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index 665d195790c2..10ca5ad802a0 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -26,6 +26,13 @@ pub(crate) struct UnknownCTargetFeature<'a> { pub rust_feature: PossibleFeature<'a>, } +#[derive(Diagnostic)] +#[diag(codegen_llvm_unstable_ctarget_feature)] +#[note] +pub(crate) struct UnstableCTargetFeature<'a> { + pub feature: &'a str, +} + #[derive(Subdiagnostic)] pub(crate) enum PossibleFeature<'a> { #[help(codegen_llvm_possible_feature)] diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 7c8ef67ffd10..cc4ccaf19c28 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -1,7 +1,7 @@ use crate::back::write::create_informational_target_machine; use crate::errors::{ PossibleFeature, TargetFeatureDisableOrEnable, UnknownCTargetFeature, - UnknownCTargetFeaturePrefix, + UnknownCTargetFeaturePrefix, UnstableCTargetFeature, }; use crate::llvm; use libc::c_int; @@ -531,25 +531,34 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec)] = &[ // tidy-alphabetical-start diff --git a/tests/ui/target-feature/similar-feature-suggestion.stderr b/tests/ui/target-feature/similar-feature-suggestion.stderr index 2f376065fdfb..f39dfd401e07 100644 --- a/tests/ui/target-feature/similar-feature-suggestion.stderr +++ b/tests/ui/target-feature/similar-feature-suggestion.stderr @@ -1,6 +1,6 @@ -warning: unknown feature specified for `-Ctarget-feature`: `rdrnd` +warning: unknown and unstable feature specified for `-Ctarget-feature`: `rdrnd` | - = note: it is still passed through to the codegen backend + = note: it is still passed through to the codegen backend, but use of this feature might be unsound and the behavior of this feature can change in the future = help: you might have meant: `rdrand` warning: 1 warning emitted diff --git a/tests/ui/target-feature/unstable-feature.rs b/tests/ui/target-feature/unstable-feature.rs new file mode 100644 index 000000000000..bd0d72938f4d --- /dev/null +++ b/tests/ui/target-feature/unstable-feature.rs @@ -0,0 +1,6 @@ +// compile-flags: -Ctarget-feature=+vaes --crate-type=rlib --target=x86_64-unknown-linux-gnu +// build-pass +// needs-llvm-components: x86 + +#![feature(no_core)] +#![no_core] diff --git a/tests/ui/target-feature/unstable-feature.stderr b/tests/ui/target-feature/unstable-feature.stderr new file mode 100644 index 000000000000..d34544c5c277 --- /dev/null +++ b/tests/ui/target-feature/unstable-feature.stderr @@ -0,0 +1,6 @@ +warning: unstable feature specified for `-Ctarget-feature`: `vaes` + | + = note: this feature is not stably supported; its behavior can change in the future + +warning: 1 warning emitted + From 3a096e96fa74e270623ad4cfc12b643aa3ada303 Mon Sep 17 00:00:00 2001 From: Sven Marnach Date: Mon, 6 Nov 2023 11:38:27 +0100 Subject: [PATCH 281/435] Documentation cleanup for core::error::Request. --- library/core/src/error.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/library/core/src/error.rs b/library/core/src/error.rs index 1170221c10c4..f1a7ad935480 100644 --- a/library/core/src/error.rs +++ b/library/core/src/error.rs @@ -439,10 +439,10 @@ where /// * A Producer initializes the value of one of its fields of a specific type. (or is otherwise /// prepared to generate a value requested). eg, `backtrace::Backtrace` or /// `std::backtrace::Backtrace` -/// * A Consumer requests an object of a specific type (say `std::backtrace::Backtrace). In the case -/// of a `dyn Error` trait object (the Producer), there are methods called `request_ref` and -/// `request_value` are available to simplify obtaining an ``Option`` for a given type. * The -/// Producer, when requested, populates the given Request object which is given as a mutable +/// * A Consumer requests an object of a specific type (say `std::backtrace::Backtrace`). In the +/// case of a `dyn Error` trait object (the Producer), there are functions called `request_ref` and +/// `request_value` to simplify obtaining an `Option` for a given type. +/// * The Producer, when requested, populates the given Request object which is given as a mutable /// reference. /// * The Consumer extracts a value or reference to the requested type from the `Request` object /// wrapped in an `Option`; in the case of `dyn Error` the aforementioned `request_ref` and ` From ffffc2038f27af4b6ea28df5b5f296f4cbf3c34d Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Mon, 6 Nov 2023 13:42:20 +0000 Subject: [PATCH 282/435] Update ICU4X This updates all ICU4X crates and regenerates rustc_baked_icu_data. Since the new unicode license under which they are licensed does not have an SPDX identifier yet, we define some exceptions. The license has to be reviewed to make sure it is still fine to use here, but I assume that is the case. I also added an exception for rustc_icu_data to the unexplained ignore doctest tidy lint. This is a bit hacky but the whole style.rs in tidy is a mess so I didn't want to touch it more than this small hack. --- Cargo.lock | 78 +++++++---- compiler/rustc_baked_icu_data/Cargo.toml | 3 +- .../src/data/fallback/likelysubtags_v1/mod.rs | 6 - .../fallback/likelysubtags_v1/und.rs.data | 66 --------- .../src/data/fallback/mod.rs | 4 - .../src/data/fallback/parents_v1/mod.rs | 6 - .../src/data/fallback/parents_v1/und.rs.data | 13 -- .../src/data/fallback/supplement/co_v1/mod.rs | 6 - .../fallback/supplement/co_v1/und.rs.data | 22 --- .../src/data/fallback/supplement/mod.rs | 2 - .../src/data/list/and_v1/en.rs.data | 50 ------- .../src/data/list/and_v1/es.rs.data | 116 ---------------- .../src/data/list/and_v1/fr.rs.data | 50 ------- .../src/data/list/and_v1/it.rs.data | 50 ------- .../src/data/list/and_v1/ja.rs.data | 50 ------- .../src/data/list/and_v1/mod.rs | 22 --- .../src/data/list/and_v1/pt.rs.data | 50 ------- .../src/data/list/and_v1/ru.rs.data | 50 ------- .../src/data/list/and_v1/tr.rs.data | 50 ------- .../src/data/list/and_v1/und.rs.data | 50 ------- .../src/data/list/and_v1/zh-Hant.rs.data | 50 ------- .../src/data/list/and_v1/zh.rs.data | 50 ------- .../rustc_baked_icu_data/src/data/list/mod.rs | 2 - .../rustc_baked_icu_data/src/data/macros.rs | 46 +++++++ .../macros/fallback_likelysubtags_v1.data.rs | 40 ++++++ .../data/macros/fallback_parents_v1.data.rs | 28 ++++ .../macros/fallback_supplement_co_v1.data.rs | 32 +++++ .../src/data/macros/list_and_v1.data.rs | 35 +++++ compiler/rustc_baked_icu_data/src/data/mod.rs | 125 +++--------------- src/tools/tidy/src/deps.rs | 29 ++++ src/tools/tidy/src/style.rs | 7 +- 31 files changed, 288 insertions(+), 900 deletions(-) delete mode 100644 compiler/rustc_baked_icu_data/src/data/fallback/likelysubtags_v1/mod.rs delete mode 100644 compiler/rustc_baked_icu_data/src/data/fallback/likelysubtags_v1/und.rs.data delete mode 100644 compiler/rustc_baked_icu_data/src/data/fallback/mod.rs delete mode 100644 compiler/rustc_baked_icu_data/src/data/fallback/parents_v1/mod.rs delete mode 100644 compiler/rustc_baked_icu_data/src/data/fallback/parents_v1/und.rs.data delete mode 100644 compiler/rustc_baked_icu_data/src/data/fallback/supplement/co_v1/mod.rs delete mode 100644 compiler/rustc_baked_icu_data/src/data/fallback/supplement/co_v1/und.rs.data delete mode 100644 compiler/rustc_baked_icu_data/src/data/fallback/supplement/mod.rs delete mode 100644 compiler/rustc_baked_icu_data/src/data/list/and_v1/en.rs.data delete mode 100644 compiler/rustc_baked_icu_data/src/data/list/and_v1/es.rs.data delete mode 100644 compiler/rustc_baked_icu_data/src/data/list/and_v1/fr.rs.data delete mode 100644 compiler/rustc_baked_icu_data/src/data/list/and_v1/it.rs.data delete mode 100644 compiler/rustc_baked_icu_data/src/data/list/and_v1/ja.rs.data delete mode 100644 compiler/rustc_baked_icu_data/src/data/list/and_v1/mod.rs delete mode 100644 compiler/rustc_baked_icu_data/src/data/list/and_v1/pt.rs.data delete mode 100644 compiler/rustc_baked_icu_data/src/data/list/and_v1/ru.rs.data delete mode 100644 compiler/rustc_baked_icu_data/src/data/list/and_v1/tr.rs.data delete mode 100644 compiler/rustc_baked_icu_data/src/data/list/and_v1/und.rs.data delete mode 100644 compiler/rustc_baked_icu_data/src/data/list/and_v1/zh-Hant.rs.data delete mode 100644 compiler/rustc_baked_icu_data/src/data/list/and_v1/zh.rs.data delete mode 100644 compiler/rustc_baked_icu_data/src/data/list/mod.rs create mode 100644 compiler/rustc_baked_icu_data/src/data/macros.rs create mode 100644 compiler/rustc_baked_icu_data/src/data/macros/fallback_likelysubtags_v1.data.rs create mode 100644 compiler/rustc_baked_icu_data/src/data/macros/fallback_parents_v1.data.rs create mode 100644 compiler/rustc_baked_icu_data/src/data/macros/fallback_supplement_co_v1.data.rs create mode 100644 compiler/rustc_baked_icu_data/src/data/macros/list_and_v1.data.rs diff --git a/Cargo.lock b/Cargo.lock index e6c5de3ca6c4..804499643df3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1890,21 +1890,29 @@ dependencies = [ [[package]] name = "icu_list" -version = "1.2.0" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd7ba7442d9235b689d4fdce17c452ea229934980fd81ba50cc28275752c9f90" +checksum = "dc1a44bbed77a7e7b555f9d7dd4b43f75ec1402b438a901d20451943d50cbd90" dependencies = [ "displaydoc", + "icu_list_data", + "icu_locid_transform", "icu_provider", "regex-automata 0.2.0", "writeable", ] [[package]] -name = "icu_locid" -version = "1.2.0" +name = "icu_list_data" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3003f85dccfc0e238ff567693248c59153a46f4e6125ba4020b973cef4d1d335" +checksum = "d3237583f0cb7feafabb567c4492fe9ef1d2d4113f6a8798a923273ea5de996d" + +[[package]] +name = "icu_locid" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f284eb342dc49d3e9d9f3b188489d76b5d22dfb1d1a5e0d1941811253bac625c" dependencies = [ "displaydoc", "litemap", @@ -1914,15 +1922,36 @@ dependencies = [ ] [[package]] -name = "icu_provider" -version = "1.2.0" +name = "icu_locid_transform" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8dc312a7b6148f7dfe098047ae2494d12d4034f48ade58d4f353000db376e305" +checksum = "6551daf80882d8e68eee186cc19e132d8bde1b1f059a79b93384a5ca0e8fc5e7" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a741eba5431f75eb2f1f9022d3cffabcadda6771e54fb4e77c8ba8653e4da44" + +[[package]] +name = "icu_provider" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68acdef80034b5e35d8524e9817479d389a4f9774f3f0cbe1bf3884d80fd5934" dependencies = [ "displaydoc", "icu_locid", "icu_provider_macros", "stable_deref_trait", + "tinystr", "writeable", "yoke", "zerofrom", @@ -1931,26 +1960,26 @@ dependencies = [ [[package]] name = "icu_provider_adapters" -version = "1.2.0" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4ae1e2bd0c41728b77e7c46e9afdec5e2127d1eedacc684724667d50c126bd3" +checksum = "36b380ef2d3d93b015cd0563d7e0d005cc07f82a5503716dbc191798d0079e1d" dependencies = [ "icu_locid", + "icu_locid_transform", "icu_provider", "tinystr", - "yoke", "zerovec", ] [[package]] name = "icu_provider_macros" -version = "1.2.0" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b728b9421e93eff1d9f8681101b78fa745e0748c95c655c83f337044a7e10" +checksum = "2060258edfcfe32ca7058849bf0f146cb5c59aadbedf480333c0d0002f97bc99" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.29", ] [[package]] @@ -2310,9 +2339,9 @@ checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f" [[package]] name = "litemap" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a04a5b2b6f54acba899926491d0a6c59d98012938ca2ab5befb281c034e8f94" +checksum = "77a1a2647d5b7134127971a6de0d533c49de2159167e7f259c427195f87168a1" [[package]] name = "lld-wrapper" @@ -3558,6 +3587,7 @@ version = "0.0.0" dependencies = [ "icu_list", "icu_locid", + "icu_locid_transform", "icu_provider", "icu_provider_adapters", "zerovec", @@ -5498,9 +5528,9 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.7.1" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ac3f5b6856e931e15e07b478e98c8045239829a65f9156d4fa7e7788197a5ef" +checksum = "d5d0e245e80bdc9b4e5356fc45a72184abbc3861992603f515270e9340f5a219" dependencies = [ "displaydoc", "zerovec", @@ -6296,9 +6326,9 @@ dependencies = [ [[package]] name = "writeable" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60e49e42bdb1d5dc76f4cd78102f8f0714d32edfa3efb82286eb0f0b1fc0da0f" +checksum = "c0af0c3d13faebf8dda0b5256fa7096a2d5ccb662f7b9f54a40fe201077ab1c2" [[package]] name = "xattr" @@ -6358,9 +6388,9 @@ dependencies = [ [[package]] name = "yoke" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1848075a23a28f9773498ee9a0f2cf58fcbad4f8c0ccf84a210ab33c6ae495de" +checksum = "61e38c508604d6bbbd292dadb3c02559aa7fff6b654a078a36217cad871636e4" dependencies = [ "serde", "stable_deref_trait", @@ -6403,9 +6433,9 @@ dependencies = [ [[package]] name = "zerovec" -version = "0.9.4" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "198f54134cd865f437820aa3b43d0ad518af4e68ee161b444cdd15d8e567c8ea" +checksum = "1194130c5b155bf8ae50ab16c86ab758cd695cf9ad176d2f870b744cbdbb572e" dependencies = [ "yoke", "zerofrom", diff --git a/compiler/rustc_baked_icu_data/Cargo.toml b/compiler/rustc_baked_icu_data/Cargo.toml index fb54937a098f..48af4e6f600b 100644 --- a/compiler/rustc_baked_icu_data/Cargo.toml +++ b/compiler/rustc_baked_icu_data/Cargo.toml @@ -7,9 +7,10 @@ edition = "2021" # tidy-alphabetical-start icu_list = "1.2" icu_locid = "1.2" +icu_locid_transform = "1.3.2" icu_provider = "1.2" icu_provider_adapters = "1.2" -zerovec = "0.9.4" +zerovec = "0.10.0" # tidy-alphabetical-end [features] diff --git a/compiler/rustc_baked_icu_data/src/data/fallback/likelysubtags_v1/mod.rs b/compiler/rustc_baked_icu_data/src/data/fallback/likelysubtags_v1/mod.rs deleted file mode 100644 index 57f7496dcff8..000000000000 --- a/compiler/rustc_baked_icu_data/src/data/fallback/likelysubtags_v1/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -// @generated -type DataStruct = < :: icu_provider_adapters :: fallback :: provider :: LocaleFallbackLikelySubtagsV1Marker as :: icu_provider :: DataMarker > :: Yokeable ; -pub fn lookup(locale: &icu_provider::DataLocale) -> Option<&'static DataStruct> { - locale.is_empty().then(|| &UND) -} -static UND: DataStruct = include!("und.rs.data"); diff --git a/compiler/rustc_baked_icu_data/src/data/fallback/likelysubtags_v1/und.rs.data b/compiler/rustc_baked_icu_data/src/data/fallback/likelysubtags_v1/und.rs.data deleted file mode 100644 index e4aaf50f5d67..000000000000 --- a/compiler/rustc_baked_icu_data/src/data/fallback/likelysubtags_v1/und.rs.data +++ /dev/null @@ -1,66 +0,0 @@ -::icu_provider_adapters::fallback::provider::LocaleFallbackLikelySubtagsV1 { - l2s: unsafe { - #[allow(unused_unsafe)] - ::zerovec::ZeroMap::from_parts_unchecked( - unsafe { - :: zerovec :: ZeroVec :: from_bytes_unchecked (b"am\0ar\0as\0be\0bg\0bgcbhobn\0brxchrcv\0doiel\0fa\0gu\0he\0hi\0hy\0ja\0ka\0kk\0km\0kn\0ko\0kokks\0ky\0lo\0maimk\0ml\0mn\0mnimr\0my\0ne\0or\0pa\0ps\0rajru\0sa\0satsd\0si\0sr\0ta\0te\0tg\0th\0ti\0tt\0uk\0ur\0yuezh\0") - }, - unsafe { - :: zerovec :: ZeroVec :: from_bytes_unchecked (b"EthiArabBengCyrlCyrlDevaDevaBengDevaCherCyrlDevaGrekArabGujrHebrDevaArmnJpanGeorCyrlKhmrKndaKoreDevaArabCyrlLaooDevaCyrlMlymCyrlBengDevaMymrDevaOryaGuruArabDevaCyrlDevaOlckArabSinhCyrlTamlTeluCyrlThaiEthiCyrlCyrlArabHantHans") - }, - ) - }, - lr2s: unsafe { - #[allow(unused_unsafe)] - ::zerovec::ZeroMap2d::from_parts_unchecked( - unsafe { - ::zerovec::ZeroVec::from_bytes_unchecked( - b"az\0ha\0kk\0ky\0mn\0ms\0pa\0sd\0sr\0tg\0uz\0yuezh\0", - ) - }, - unsafe { - :: zerovec :: ZeroVec :: from_bytes_unchecked (b"\x03\0\0\0\x05\0\0\0\t\0\0\0\x0B\0\0\0\x0C\0\0\0\r\0\0\0\x0E\0\0\0\x0F\0\0\0\x13\0\0\0\x14\0\0\0\x16\0\0\0\x17\0\0\0&\0\0\0") - }, - unsafe { - :: zerovec :: ZeroVec :: from_bytes_unchecked (b"IQ\0IR\0RU\0CM\0SD\0AF\0CN\0IR\0MN\0CN\0TR\0CN\0CC\0PK\0IN\0ME\0RO\0RU\0TR\0PK\0AF\0CN\0CN\0AU\0BN\0GB\0GF\0HK\0ID\0MO\0PA\0PF\0PH\0SR\0TH\0TW\0US\0VN\0") - }, - unsafe { - :: zerovec :: ZeroVec :: from_bytes_unchecked (b"ArabArabCyrlArabArabArabArabArabArabArabLatnMongArabArabDevaLatnLatnLatnLatnArabArabCyrlHansHantHantHantHantHantHantHantHantHantHantHantHantHantHantHant") - }, - ) - }, - l2r: unsafe { - #[allow(unused_unsafe)] - ::zerovec::ZeroMap::from_parts_unchecked( - unsafe { - :: zerovec :: ZeroVec :: from_bytes_unchecked (b"af\0am\0ar\0as\0astaz\0be\0bg\0bgcbhobn\0br\0brxbs\0ca\0cebchrcs\0cv\0cy\0da\0de\0doidsbel\0en\0es\0et\0eu\0fa\0ff\0fi\0filfo\0fr\0ga\0gd\0gl\0gu\0ha\0he\0hi\0hr\0hsbhu\0hy\0ia\0id\0ig\0is\0it\0ja\0jv\0ka\0keakgpkk\0km\0kn\0ko\0kokks\0ky\0lo\0lt\0lv\0maimi\0mk\0ml\0mn\0mnimr\0ms\0my\0ne\0nl\0nn\0no\0or\0pa\0pcmpl\0ps\0pt\0qu\0rajrm\0ro\0ru\0sa\0satsc\0sd\0si\0sk\0sl\0so\0sq\0sr\0su\0sv\0sw\0ta\0te\0tg\0th\0ti\0tk\0to\0tr\0tt\0uk\0ur\0uz\0vi\0wo\0xh\0yo\0yrlyuezh\0zu\0") - }, - unsafe { - :: zerovec :: ZeroVec :: from_bytes_unchecked (b"ZA\0ET\0EG\0IN\0ES\0AZ\0BY\0BG\0IN\0IN\0BD\0FR\0IN\0BA\0ES\0PH\0US\0CZ\0RU\0GB\0DK\0DE\0IN\0DE\0GR\0US\0ES\0EE\0ES\0IR\0SN\0FI\0PH\0FO\0FR\0IE\0GB\0ES\0IN\0NG\0IL\0IN\0HR\0DE\0HU\0AM\x00001ID\0NG\0IS\0IT\0JP\0ID\0GE\0CV\0BR\0KZ\0KH\0IN\0KR\0IN\0IN\0KG\0LA\0LT\0LV\0IN\0NZ\0MK\0IN\0MN\0IN\0IN\0MY\0MM\0NP\0NL\0NO\0NO\0IN\0IN\0NG\0PL\0AF\0BR\0PE\0IN\0CH\0RO\0RU\0IN\0IN\0IT\0PK\0LK\0SK\0SI\0SO\0AL\0RS\0ID\0SE\0TZ\0IN\0IN\0TJ\0TH\0ET\0TM\0TO\0TR\0RU\0UA\0PK\0UZ\0VN\0SN\0ZA\0NG\0BR\0HK\0CN\0ZA\0") - }, - ) - }, - ls2r: unsafe { - #[allow(unused_unsafe)] - ::zerovec::ZeroMap2d::from_parts_unchecked( - unsafe { - ::zerovec::ZeroVec::from_bytes_unchecked( - b"az\0en\0ff\0kk\0ky\0mn\0pa\0sd\0tg\0uz\0yuezh\0", - ) - }, - unsafe { - :: zerovec :: ZeroVec :: from_bytes_unchecked (b"\x01\0\0\0\x02\0\0\0\x03\0\0\0\x04\0\0\0\x06\0\0\0\x07\0\0\0\x08\0\0\0\x0B\0\0\0\x0C\0\0\0\r\0\0\0\x0E\0\0\0\x11\0\0\0") - }, - unsafe { - ::zerovec::ZeroVec::from_bytes_unchecked( - b"ArabShawAdlmArabArabLatnMongArabDevaKhojSindArabArabHansBopoHanbHant", - ) - }, - unsafe { - ::zerovec::ZeroVec::from_bytes_unchecked( - b"IR\0GB\0GN\0CN\0CN\0TR\0CN\0PK\0IN\0IN\0IN\0PK\0AF\0CN\0TW\0TW\0TW\0", - ) - }, - ) - }, -} diff --git a/compiler/rustc_baked_icu_data/src/data/fallback/mod.rs b/compiler/rustc_baked_icu_data/src/data/fallback/mod.rs deleted file mode 100644 index a485a5af64ca..000000000000 --- a/compiler/rustc_baked_icu_data/src/data/fallback/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -// @generated -pub mod likelysubtags_v1; -pub mod parents_v1; -pub mod supplement; diff --git a/compiler/rustc_baked_icu_data/src/data/fallback/parents_v1/mod.rs b/compiler/rustc_baked_icu_data/src/data/fallback/parents_v1/mod.rs deleted file mode 100644 index ce04af868aa5..000000000000 --- a/compiler/rustc_baked_icu_data/src/data/fallback/parents_v1/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -// @generated -type DataStruct = < :: icu_provider_adapters :: fallback :: provider :: LocaleFallbackParentsV1Marker as :: icu_provider :: DataMarker > :: Yokeable ; -pub fn lookup(locale: &icu_provider::DataLocale) -> Option<&'static DataStruct> { - locale.is_empty().then(|| &UND) -} -static UND: DataStruct = include!("und.rs.data"); diff --git a/compiler/rustc_baked_icu_data/src/data/fallback/parents_v1/und.rs.data b/compiler/rustc_baked_icu_data/src/data/fallback/parents_v1/und.rs.data deleted file mode 100644 index a13646a0b925..000000000000 --- a/compiler/rustc_baked_icu_data/src/data/fallback/parents_v1/und.rs.data +++ /dev/null @@ -1,13 +0,0 @@ -::icu_provider_adapters::fallback::provider::LocaleFallbackParentsV1 { - parents: unsafe { - #[allow(unused_unsafe)] - ::zerovec::ZeroMap::from_parts_unchecked( - unsafe { - :: zerovec :: VarZeroVec :: from_bytes_unchecked (b"\x84\0\0\0\0\0\x06\0\x0B\0\x10\0\x15\0\x1A\0\x1F\0$\0)\0.\x003\08\0=\0B\0G\0L\0Q\0V\0[\0`\0e\0j\0o\0t\0y\0~\0\x83\0\x88\0\x8D\0\x92\0\x97\0\x9C\0\xA1\0\xA6\0\xAB\0\xB0\0\xB5\0\xBA\0\xBF\0\xC4\0\xC9\0\xCE\0\xD3\0\xD8\0\xDD\0\xE2\0\xE7\0\xEC\0\xF1\0\xF6\0\xFB\0\0\x01\x05\x01\n\x01\x0F\x01\x14\x01\x19\x01\x1E\x01#\x01(\x01-\x012\x017\x01<\x01A\x01F\x01K\x01P\x01U\x01Z\x01_\x01d\x01i\x01n\x01s\x01x\x01}\x01\x82\x01\x87\x01\x8C\x01\x91\x01\x96\x01\x9B\x01\xA0\x01\xA5\x01\xAA\x01\xAF\x01\xB4\x01\xB9\x01\xBE\x01\xC3\x01\xC8\x01\xCD\x01\xD2\x01\xD7\x01\xDC\x01\xE1\x01\xE6\x01\xEB\x01\xF0\x01\xF5\x01\xFA\x01\xFF\x01\x04\x02\t\x02\x0E\x02\x13\x02\x18\x02\x1D\x02\"\x02'\x02,\x021\x026\x02;\x02@\x02G\x02I\x02K\x02M\x02R\x02W\x02\\\x02a\x02f\x02k\x02p\x02u\x02z\x02\x7F\x02\x84\x02\x89\x02en-150en-AGen-AIen-ATen-AUen-BBen-BEen-BMen-BSen-BWen-BZen-CCen-CHen-CKen-CMen-CXen-CYen-DEen-DGen-DKen-DMen-ERen-FIen-FJen-FKen-FMen-GBen-GDen-GGen-GHen-GIen-GMen-GYen-HKen-IEen-ILen-IMen-INen-IOen-JEen-JMen-KEen-KIen-KNen-KYen-LCen-LRen-LSen-MGen-MOen-MSen-MTen-MUen-MVen-MWen-MYen-NAen-NFen-NGen-NLen-NRen-NUen-NZen-PGen-PKen-PNen-PWen-RWen-SBen-SCen-SDen-SEen-SGen-SHen-SIen-SLen-SSen-SXen-SZen-TCen-TKen-TOen-TTen-TVen-TZen-UGen-VCen-VGen-VUen-WSen-ZAen-ZMen-ZWes-ARes-BOes-BRes-BZes-CLes-COes-CRes-CUes-DOes-ECes-GTes-HNes-MXes-NIes-PAes-PEes-PRes-PYes-SVes-USes-UYes-VEhi-Latnhtnbnnno-NOpt-AOpt-CHpt-CVpt-FRpt-GQpt-GWpt-LUpt-MOpt-MZpt-STpt-TLzh-Hant-MO") - }, - unsafe { - :: zerovec :: ZeroVec :: from_bytes_unchecked (b"en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419en\0\0\0\0\0\0\x01IN\0fr\0\0\0\0\0\0\x01HT\0no\0\0\0\0\0\0\0\0\0\0no\0\0\0\0\0\0\0\0\0\0no\0\0\0\0\0\0\0\0\0\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0zh\0\x01Hant\x01HK\0") - }, - ) - }, -} diff --git a/compiler/rustc_baked_icu_data/src/data/fallback/supplement/co_v1/mod.rs b/compiler/rustc_baked_icu_data/src/data/fallback/supplement/co_v1/mod.rs deleted file mode 100644 index 9023647138b1..000000000000 --- a/compiler/rustc_baked_icu_data/src/data/fallback/supplement/co_v1/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -// @generated -type DataStruct = < :: icu_provider_adapters :: fallback :: provider :: CollationFallbackSupplementV1Marker as :: icu_provider :: DataMarker > :: Yokeable ; -pub fn lookup(locale: &icu_provider::DataLocale) -> Option<&'static DataStruct> { - locale.is_empty().then(|| &UND) -} -static UND: DataStruct = include!("und.rs.data"); diff --git a/compiler/rustc_baked_icu_data/src/data/fallback/supplement/co_v1/und.rs.data b/compiler/rustc_baked_icu_data/src/data/fallback/supplement/co_v1/und.rs.data deleted file mode 100644 index 647f8f516019..000000000000 --- a/compiler/rustc_baked_icu_data/src/data/fallback/supplement/co_v1/und.rs.data +++ /dev/null @@ -1,22 +0,0 @@ -::icu_provider_adapters::fallback::provider::LocaleFallbackSupplementV1 { - parents: unsafe { - #[allow(unused_unsafe)] - ::zerovec::ZeroMap::from_parts_unchecked( - unsafe { ::zerovec::VarZeroVec::from_bytes_unchecked(b"\x01\0\0\0\0\0yue") }, - unsafe { ::zerovec::ZeroVec::from_bytes_unchecked(b"zh\0\x01Hant\0\0\0\0") }, - ) - }, - unicode_extension_defaults: unsafe { - #[allow(unused_unsafe)] - ::zerovec::ZeroMap2d::from_parts_unchecked( - unsafe { ::zerovec::ZeroVec::from_bytes_unchecked(b"co") }, - unsafe { ::zerovec::ZeroVec::from_bytes_unchecked(b"\x02\0\0\0") }, - unsafe { - ::zerovec::VarZeroVec::from_bytes_unchecked(b"\x02\0\0\0\0\0\x02\0zhzh-Hant") - }, - unsafe { - ::zerovec::VarZeroVec::from_bytes_unchecked(b"\x02\0\0\0\0\0\x06\0pinyinstroke") - }, - ) - }, -} diff --git a/compiler/rustc_baked_icu_data/src/data/fallback/supplement/mod.rs b/compiler/rustc_baked_icu_data/src/data/fallback/supplement/mod.rs deleted file mode 100644 index 62957134f075..000000000000 --- a/compiler/rustc_baked_icu_data/src/data/fallback/supplement/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -// @generated -pub mod co_v1; diff --git a/compiler/rustc_baked_icu_data/src/data/list/and_v1/en.rs.data b/compiler/rustc_baked_icu_data/src/data/list/and_v1/en.rs.data deleted file mode 100644 index 4bf244019ff1..000000000000 --- a/compiler/rustc_baked_icu_data/src/data/list/and_v1/en.rs.data +++ /dev/null @@ -1,50 +0,0 @@ -::icu_list::provider::ListFormatterPatternsV1([ - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", and ", 6u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(" and ", 5u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", & ", 4u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(" & ", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, -]) diff --git a/compiler/rustc_baked_icu_data/src/data/list/and_v1/es.rs.data b/compiler/rustc_baked_icu_data/src/data/list/and_v1/es.rs.data deleted file mode 100644 index 84de7cd01a7e..000000000000 --- a/compiler/rustc_baked_icu_data/src/data/list/and_v1/es.rs.data +++ /dev/null @@ -1,116 +0,0 @@ -::icu_list::provider::ListFormatterPatternsV1([ - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(" y ", 3u8), - special_case: Some(::icu_list::provider::SpecialCasePattern { - condition: unsafe { - ::icu_list::provider::SerdeDFA::from_dfa_bytes_unchecked( - if cfg!(target_endian = "little") { - b"rust-regex-automata-dfa-sparse\0\0\xFF\xFE\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B(\x01\0\0\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#\0\0\0" - } else { - b"rust-regex-automata-dfa-sparse\0\0\0\0\xFE\xFF\0\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\0\0\x01(\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#" - }, - ) - }, - pattern: ::icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), - }), - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(" y ", 3u8), - special_case: Some(::icu_list::provider::SpecialCasePattern { - condition: unsafe { - ::icu_list::provider::SerdeDFA::from_dfa_bytes_unchecked( - if cfg!(target_endian = "little") { - b"rust-regex-automata-dfa-sparse\0\0\xFF\xFE\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B(\x01\0\0\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#\0\0\0" - } else { - b"rust-regex-automata-dfa-sparse\0\0\0\0\xFE\xFF\0\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\0\0\x01(\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#" - }, - ) - }, - pattern: ::icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), - }), - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(" y ", 3u8), - special_case: Some(::icu_list::provider::SpecialCasePattern { - condition: unsafe { - ::icu_list::provider::SerdeDFA::from_dfa_bytes_unchecked( - if cfg!(target_endian = "little") { - b"rust-regex-automata-dfa-sparse\0\0\xFF\xFE\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B(\x01\0\0\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#\0\0\0" - } else { - b"rust-regex-automata-dfa-sparse\0\0\0\0\xFE\xFF\0\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\0\0\x01(\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#" - }, - ) - }, - pattern: ::icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), - }), - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(" y ", 3u8), - special_case: Some(::icu_list::provider::SpecialCasePattern { - condition: unsafe { - ::icu_list::provider::SerdeDFA::from_dfa_bytes_unchecked( - if cfg!(target_endian = "little") { - b"rust-regex-automata-dfa-sparse\0\0\xFF\xFE\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B(\x01\0\0\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#\0\0\0" - } else { - b"rust-regex-automata-dfa-sparse\0\0\0\0\xFE\xFF\0\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\0\0\x01(\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#" - }, - ) - }, - pattern: ::icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), - }), - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(" y ", 3u8), - special_case: Some(::icu_list::provider::SpecialCasePattern { - condition: unsafe { - ::icu_list::provider::SerdeDFA::from_dfa_bytes_unchecked( - if cfg!(target_endian = "little") { - b"rust-regex-automata-dfa-sparse\0\0\xFF\xFE\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B(\x01\0\0\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#\0\0\0" - } else { - b"rust-regex-automata-dfa-sparse\0\0\0\0\xFE\xFF\0\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\0\0\x01(\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#" - }, - ) - }, - pattern: ::icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), - }), - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(" y ", 3u8), - special_case: Some(::icu_list::provider::SpecialCasePattern { - condition: unsafe { - ::icu_list::provider::SerdeDFA::from_dfa_bytes_unchecked( - if cfg!(target_endian = "little") { - b"rust-regex-automata-dfa-sparse\0\0\xFF\xFE\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B(\x01\0\0\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#\0\0\0" - } else { - b"rust-regex-automata-dfa-sparse\0\0\0\0\xFE\xFF\0\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\0\0\x01(\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#" - }, - ) - }, - pattern: ::icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), - }), - }, -]) diff --git a/compiler/rustc_baked_icu_data/src/data/list/and_v1/fr.rs.data b/compiler/rustc_baked_icu_data/src/data/list/and_v1/fr.rs.data deleted file mode 100644 index 79a97e50f5a8..000000000000 --- a/compiler/rustc_baked_icu_data/src/data/list/and_v1/fr.rs.data +++ /dev/null @@ -1,50 +0,0 @@ -::icu_list::provider::ListFormatterPatternsV1([ - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(" et ", 4u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(" et ", 4u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(" et ", 4u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(" et ", 4u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, -]) diff --git a/compiler/rustc_baked_icu_data/src/data/list/and_v1/it.rs.data b/compiler/rustc_baked_icu_data/src/data/list/and_v1/it.rs.data deleted file mode 100644 index b976b6cb65aa..000000000000 --- a/compiler/rustc_baked_icu_data/src/data/list/and_v1/it.rs.data +++ /dev/null @@ -1,50 +0,0 @@ -::icu_list::provider::ListFormatterPatternsV1([ - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), - special_case: None, - }, -]) diff --git a/compiler/rustc_baked_icu_data/src/data/list/and_v1/ja.rs.data b/compiler/rustc_baked_icu_data/src/data/list/and_v1/ja.rs.data deleted file mode 100644 index d76d567ebf87..000000000000 --- a/compiler/rustc_baked_icu_data/src/data/list/and_v1/ja.rs.data +++ /dev/null @@ -1,50 +0,0 @@ -::icu_list::provider::ListFormatterPatternsV1([ - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), - special_case: None, - }, -]) diff --git a/compiler/rustc_baked_icu_data/src/data/list/and_v1/mod.rs b/compiler/rustc_baked_icu_data/src/data/list/and_v1/mod.rs deleted file mode 100644 index e20941f0c676..000000000000 --- a/compiler/rustc_baked_icu_data/src/data/list/and_v1/mod.rs +++ /dev/null @@ -1,22 +0,0 @@ -// @generated -type DataStruct = <::icu_list::provider::AndListV1Marker as ::icu_provider::DataMarker>::Yokeable; -pub fn lookup(locale: &icu_provider::DataLocale) -> Option<&'static DataStruct> { - static KEYS: [&str; 12usize] = - ["en", "es", "fr", "it", "ja", "pt", "ru", "tr", "und", "zh", "zh-Hans", "zh-Hant"]; - static DATA: [&DataStruct; 12usize] = - [&EN, &ES, &FR, &IT, &JA, &PT, &RU, &TR, &UND, &ZH, &ZH, &ZH_HANT]; - KEYS.binary_search_by(|k| locale.strict_cmp(k.as_bytes()).reverse()) - .ok() - .map(|i| unsafe { *DATA.get_unchecked(i) }) -} -static EN: DataStruct = include!("en.rs.data"); -static ES: DataStruct = include!("es.rs.data"); -static FR: DataStruct = include!("fr.rs.data"); -static IT: DataStruct = include!("it.rs.data"); -static JA: DataStruct = include!("ja.rs.data"); -static PT: DataStruct = include!("pt.rs.data"); -static RU: DataStruct = include!("ru.rs.data"); -static TR: DataStruct = include!("tr.rs.data"); -static UND: DataStruct = include!("und.rs.data"); -static ZH_HANT: DataStruct = include!("zh-Hant.rs.data"); -static ZH: DataStruct = include!("zh.rs.data"); diff --git a/compiler/rustc_baked_icu_data/src/data/list/and_v1/pt.rs.data b/compiler/rustc_baked_icu_data/src/data/list/and_v1/pt.rs.data deleted file mode 100644 index 3d8c89f9072f..000000000000 --- a/compiler/rustc_baked_icu_data/src/data/list/and_v1/pt.rs.data +++ /dev/null @@ -1,50 +0,0 @@ -::icu_list::provider::ListFormatterPatternsV1([ - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, -]) diff --git a/compiler/rustc_baked_icu_data/src/data/list/and_v1/ru.rs.data b/compiler/rustc_baked_icu_data/src/data/list/and_v1/ru.rs.data deleted file mode 100644 index 653ce28d615a..000000000000 --- a/compiler/rustc_baked_icu_data/src/data/list/and_v1/ru.rs.data +++ /dev/null @@ -1,50 +0,0 @@ -::icu_list::provider::ListFormatterPatternsV1([ - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(" и ", 4u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(" и ", 4u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(" и ", 4u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(" и ", 4u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, -]) diff --git a/compiler/rustc_baked_icu_data/src/data/list/and_v1/tr.rs.data b/compiler/rustc_baked_icu_data/src/data/list/and_v1/tr.rs.data deleted file mode 100644 index 9fa6eb56ade2..000000000000 --- a/compiler/rustc_baked_icu_data/src/data/list/and_v1/tr.rs.data +++ /dev/null @@ -1,50 +0,0 @@ -::icu_list::provider::ListFormatterPatternsV1([ - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(" ve ", 4u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(" ve ", 4u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(" ve ", 4u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(" ve ", 4u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, -]) diff --git a/compiler/rustc_baked_icu_data/src/data/list/and_v1/und.rs.data b/compiler/rustc_baked_icu_data/src/data/list/and_v1/und.rs.data deleted file mode 100644 index 66b55c253688..000000000000 --- a/compiler/rustc_baked_icu_data/src/data/list/and_v1/und.rs.data +++ /dev/null @@ -1,50 +0,0 @@ -::icu_list::provider::ListFormatterPatternsV1([ - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, -]) diff --git a/compiler/rustc_baked_icu_data/src/data/list/and_v1/zh-Hant.rs.data b/compiler/rustc_baked_icu_data/src/data/list/and_v1/zh-Hant.rs.data deleted file mode 100644 index 38da6ecf8152..000000000000 --- a/compiler/rustc_baked_icu_data/src/data/list/and_v1/zh-Hant.rs.data +++ /dev/null @@ -1,50 +0,0 @@ -::icu_list::provider::ListFormatterPatternsV1([ - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), - special_case: None, - }, -]) diff --git a/compiler/rustc_baked_icu_data/src/data/list/and_v1/zh.rs.data b/compiler/rustc_baked_icu_data/src/data/list/and_v1/zh.rs.data deleted file mode 100644 index d4dac1c386ec..000000000000 --- a/compiler/rustc_baked_icu_data/src/data/list/and_v1/zh.rs.data +++ /dev/null @@ -1,50 +0,0 @@ -::icu_list::provider::ListFormatterPatternsV1([ - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), - special_case: None, - }, -]) diff --git a/compiler/rustc_baked_icu_data/src/data/list/mod.rs b/compiler/rustc_baked_icu_data/src/data/list/mod.rs deleted file mode 100644 index 931822513cc0..000000000000 --- a/compiler/rustc_baked_icu_data/src/data/list/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -// @generated -pub mod and_v1; diff --git a/compiler/rustc_baked_icu_data/src/data/macros.rs b/compiler/rustc_baked_icu_data/src/data/macros.rs new file mode 100644 index 000000000000..bee309f9b811 --- /dev/null +++ b/compiler/rustc_baked_icu_data/src/data/macros.rs @@ -0,0 +1,46 @@ +// @generated +/// Marks a type as a data provider. You can then use macros like +/// `impl_core_helloworld_v1` to add implementations. +/// +/// ```ignore +/// struct MyProvider; +/// const _: () = { +/// include!("path/to/generated/macros.rs"); +/// make_provider!(MyProvider); +/// impl_core_helloworld_v1!(MyProvider); +/// } +/// ``` +#[doc(hidden)] +#[macro_export] +macro_rules! __make_provider { + ($ name : ty) => { + #[clippy::msrv = "1.66"] + impl $name { + #[doc(hidden)] + #[allow(dead_code)] + pub const MUST_USE_MAKE_PROVIDER_MACRO: () = (); + } + }; +} +#[doc(inline)] +pub use __make_provider as make_provider; +#[macro_use] +#[path = "macros/fallback_likelysubtags_v1.data.rs"] +mod fallback_likelysubtags_v1; +#[doc(inline)] +pub use __impl_fallback_likelysubtags_v1 as impl_fallback_likelysubtags_v1; +#[macro_use] +#[path = "macros/fallback_parents_v1.data.rs"] +mod fallback_parents_v1; +#[doc(inline)] +pub use __impl_fallback_parents_v1 as impl_fallback_parents_v1; +#[macro_use] +#[path = "macros/fallback_supplement_co_v1.data.rs"] +mod fallback_supplement_co_v1; +#[doc(inline)] +pub use __impl_fallback_supplement_co_v1 as impl_fallback_supplement_co_v1; +#[macro_use] +#[path = "macros/list_and_v1.data.rs"] +mod list_and_v1; +#[doc(inline)] +pub use __impl_list_and_v1 as impl_list_and_v1; diff --git a/compiler/rustc_baked_icu_data/src/data/macros/fallback_likelysubtags_v1.data.rs b/compiler/rustc_baked_icu_data/src/data/macros/fallback_likelysubtags_v1.data.rs new file mode 100644 index 000000000000..1adb58743f72 --- /dev/null +++ b/compiler/rustc_baked_icu_data/src/data/macros/fallback_likelysubtags_v1.data.rs @@ -0,0 +1,40 @@ +// @generated +/// Implement `DataProvider` on the given struct using the data +/// hardcoded in this file. This allows the struct to be used with +/// `icu`'s `_unstable` constructors. +#[doc(hidden)] +#[macro_export] +macro_rules! __impl_fallback_likelysubtags_v1 { + ($ provider : ty) => { + #[clippy::msrv = "1.66"] + const _: () = <$provider>::MUST_USE_MAKE_PROVIDER_MACRO; + #[clippy::msrv = "1.66"] + impl $provider { + #[doc(hidden)] + pub const SINGLETON_FALLBACK_LIKELYSUBTAGS_V1: &'static ::Yokeable = &icu_locid_transform::provider::LocaleFallbackLikelySubtagsV1 { + l2s: unsafe { + #[allow(unused_unsafe)] + zerovec::ZeroMap::from_parts_unchecked(unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"am\0ar\0as\0be\0bg\0bgcbhobn\0brxchrcv\0doiel\0fa\0gu\0he\0hi\0hy\0ja\0ka\0kk\0km\0kn\0ko\0kokks\0ky\0lo\0maimk\0ml\0mn\0mnimr\0my\0ne\0or\0pa\0ps\0rajru\0sa\0satsd\0si\0sr\0ta\0te\0tg\0th\0ti\0tt\0uk\0ur\0yuezh\0") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"EthiArabBengCyrlCyrlDevaDevaBengDevaCherCyrlDevaGrekArabGujrHebrDevaArmnJpanGeorCyrlKhmrKndaKoreDevaArabCyrlLaooDevaCyrlMlymCyrlBengDevaMymrDevaOryaGuruArabDevaCyrlDevaOlckArabSinhCyrlTamlTeluCyrlThaiEthiCyrlCyrlArabHantHans") }) + }, + lr2s: unsafe { + #[allow(unused_unsafe)] + zerovec::ZeroMap2d::from_parts_unchecked(unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"az\0ha\0kk\0ky\0mn\0ms\0pa\0sd\0sr\0tg\0uz\0yuezh\0") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"\x03\0\0\0\x05\0\0\0\t\0\0\0\x0B\0\0\0\x0C\0\0\0\r\0\0\0\x0E\0\0\0\x0F\0\0\0\x13\0\0\0\x14\0\0\0\x16\0\0\0\x17\0\0\0&\0\0\0") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"IQ\0IR\0RU\0CM\0SD\0AF\0CN\0IR\0MN\0CN\0TR\0CN\0CC\0PK\0IN\0ME\0RO\0RU\0TR\0PK\0AF\0CN\0CN\0AU\0BN\0GB\0GF\0HK\0ID\0MO\0PA\0PF\0PH\0SR\0TH\0TW\0US\0VN\0") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"ArabArabCyrlArabArabArabArabArabArabArabLatnMongArabArabDevaLatnLatnLatnLatnArabArabCyrlHansHantHantHantHantHantHantHantHantHantHantHantHantHantHantHant") }) + }, + l2r: unsafe { + #[allow(unused_unsafe)] + zerovec::ZeroMap::from_parts_unchecked(unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"af\0am\0ar\0as\0astaz\0be\0bg\0bgcbhobn\0br\0brxbs\0ca\0cebchrcs\0cv\0cy\0da\0de\0doidsbel\0en\0es\0et\0eu\0fa\0ff\0fi\0filfo\0fr\0ga\0gd\0gl\0gu\0ha\0he\0hi\0hr\0hsbhu\0hy\0ia\0id\0ig\0is\0it\0ja\0jv\0ka\0keakgpkk\0km\0kn\0ko\0kokks\0ky\0lo\0lt\0lv\0maimi\0mk\0ml\0mn\0mnimr\0ms\0my\0ne\0nl\0nn\0no\0or\0pa\0pcmpl\0ps\0pt\0qu\0rajrm\0ro\0ru\0sa\0satsc\0sd\0si\0sk\0sl\0so\0sq\0sr\0su\0sv\0sw\0ta\0te\0tg\0th\0ti\0tk\0to\0tr\0tt\0uk\0ur\0uz\0vi\0wo\0xh\0yo\0yrlyuezh\0zu\0") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"ZA\0ET\0EG\0IN\0ES\0AZ\0BY\0BG\0IN\0IN\0BD\0FR\0IN\0BA\0ES\0PH\0US\0CZ\0RU\0GB\0DK\0DE\0IN\0DE\0GR\0US\0ES\0EE\0ES\0IR\0SN\0FI\0PH\0FO\0FR\0IE\0GB\0ES\0IN\0NG\0IL\0IN\0HR\0DE\0HU\0AM\x00001ID\0NG\0IS\0IT\0JP\0ID\0GE\0CV\0BR\0KZ\0KH\0IN\0KR\0IN\0IN\0KG\0LA\0LT\0LV\0IN\0NZ\0MK\0IN\0MN\0IN\0IN\0MY\0MM\0NP\0NL\0NO\0NO\0IN\0IN\0NG\0PL\0AF\0BR\0PE\0IN\0CH\0RO\0RU\0IN\0IN\0IT\0PK\0LK\0SK\0SI\0SO\0AL\0RS\0ID\0SE\0TZ\0IN\0IN\0TJ\0TH\0ET\0TM\0TO\0TR\0RU\0UA\0PK\0UZ\0VN\0SN\0ZA\0NG\0BR\0HK\0CN\0ZA\0") }) + }, + ls2r: unsafe { + #[allow(unused_unsafe)] + zerovec::ZeroMap2d::from_parts_unchecked(unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"az\0en\0ff\0kk\0ky\0mn\0pa\0sd\0tg\0uz\0yuezh\0") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"\x01\0\0\0\x02\0\0\0\x03\0\0\0\x04\0\0\0\x06\0\0\0\x07\0\0\0\x08\0\0\0\x0B\0\0\0\x0C\0\0\0\r\0\0\0\x0E\0\0\0\x11\0\0\0") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"ArabShawAdlmArabArabLatnMongArabDevaKhojSindArabArabHansBopoHanbHant") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"IR\0GB\0GN\0CN\0CN\0TR\0CN\0PK\0IN\0IN\0IN\0PK\0AF\0CN\0TW\0TW\0TW\0") }) + }, + }; + } + #[clippy::msrv = "1.66"] + impl icu_provider::DataProvider for $provider { + fn load(&self, req: icu_provider::DataRequest) -> Result, icu_provider::DataError> { + if req.locale.is_empty() { Ok(icu_provider::DataResponse { payload: Some(icu_provider::DataPayload::from_static_ref(Self::SINGLETON_FALLBACK_LIKELYSUBTAGS_V1)), metadata: Default::default() }) } else { Err(icu_provider::DataErrorKind::ExtraneousLocale.with_req(::KEY, req)) } + } + } + }; +} diff --git a/compiler/rustc_baked_icu_data/src/data/macros/fallback_parents_v1.data.rs b/compiler/rustc_baked_icu_data/src/data/macros/fallback_parents_v1.data.rs new file mode 100644 index 000000000000..6f8d6590b085 --- /dev/null +++ b/compiler/rustc_baked_icu_data/src/data/macros/fallback_parents_v1.data.rs @@ -0,0 +1,28 @@ +// @generated +/// Implement `DataProvider` on the given struct using the data +/// hardcoded in this file. This allows the struct to be used with +/// `icu`'s `_unstable` constructors. +#[doc(hidden)] +#[macro_export] +macro_rules! __impl_fallback_parents_v1 { + ($ provider : ty) => { + #[clippy::msrv = "1.66"] + const _: () = <$provider>::MUST_USE_MAKE_PROVIDER_MACRO; + #[clippy::msrv = "1.66"] + impl $provider { + #[doc(hidden)] + pub const SINGLETON_FALLBACK_PARENTS_V1: &'static ::Yokeable = &icu_locid_transform::provider::LocaleFallbackParentsV1 { + parents: unsafe { + #[allow(unused_unsafe)] + zerovec::ZeroMap::from_parts_unchecked(unsafe { zerovec::VarZeroVec::from_bytes_unchecked(b"\x84\0\0\0\0\0\x06\0\x0B\0\x10\0\x15\0\x1A\0\x1F\0$\0)\0.\x003\08\0=\0B\0G\0L\0Q\0V\0[\0`\0e\0j\0o\0t\0y\0~\0\x83\0\x88\0\x8D\0\x92\0\x97\0\x9C\0\xA1\0\xA6\0\xAB\0\xB0\0\xB5\0\xBA\0\xBF\0\xC4\0\xC9\0\xCE\0\xD3\0\xD8\0\xDD\0\xE2\0\xE7\0\xEC\0\xF1\0\xF6\0\xFB\0\0\x01\x05\x01\n\x01\x0F\x01\x14\x01\x19\x01\x1E\x01#\x01(\x01-\x012\x017\x01<\x01A\x01F\x01K\x01P\x01U\x01Z\x01_\x01d\x01i\x01n\x01s\x01x\x01}\x01\x82\x01\x87\x01\x8C\x01\x91\x01\x96\x01\x9B\x01\xA0\x01\xA5\x01\xAA\x01\xAF\x01\xB4\x01\xB9\x01\xBE\x01\xC3\x01\xC8\x01\xCD\x01\xD2\x01\xD7\x01\xDC\x01\xE1\x01\xE6\x01\xEB\x01\xF0\x01\xF5\x01\xFA\x01\xFF\x01\x04\x02\t\x02\x0E\x02\x13\x02\x18\x02\x1D\x02\"\x02'\x02,\x021\x026\x02;\x02@\x02G\x02I\x02K\x02M\x02R\x02W\x02\\\x02a\x02f\x02k\x02p\x02u\x02z\x02\x7F\x02\x84\x02\x89\x02en-150en-AGen-AIen-ATen-AUen-BBen-BEen-BMen-BSen-BWen-BZen-CCen-CHen-CKen-CMen-CXen-CYen-DEen-DGen-DKen-DMen-ERen-FIen-FJen-FKen-FMen-GBen-GDen-GGen-GHen-GIen-GMen-GYen-HKen-IEen-ILen-IMen-INen-IOen-JEen-JMen-KEen-KIen-KNen-KYen-LCen-LRen-LSen-MGen-MOen-MSen-MTen-MUen-MVen-MWen-MYen-NAen-NFen-NGen-NLen-NRen-NUen-NZen-PGen-PKen-PNen-PWen-RWen-SBen-SCen-SDen-SEen-SGen-SHen-SIen-SLen-SSen-SXen-SZen-TCen-TKen-TOen-TTen-TVen-TZen-UGen-VCen-VGen-VUen-WSen-ZAen-ZMen-ZWes-ARes-BOes-BRes-BZes-CLes-COes-CRes-CUes-DOes-ECes-GTes-HNes-MXes-NIes-PAes-PEes-PRes-PYes-SVes-USes-UYes-VEhi-Latnhtnbnnno-NOpt-AOpt-CHpt-CVpt-FRpt-GQpt-GWpt-LUpt-MOpt-MZpt-STpt-TLzh-Hant-MO") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419en\0\0\0\0\0\0\x01IN\0fr\0\0\0\0\0\0\x01HT\0no\0\0\0\0\0\0\0\0\0\0no\0\0\0\0\0\0\0\0\0\0no\0\0\0\0\0\0\0\0\0\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0zh\0\x01Hant\x01HK\0") }) + }, + }; + } + #[clippy::msrv = "1.66"] + impl icu_provider::DataProvider for $provider { + fn load(&self, req: icu_provider::DataRequest) -> Result, icu_provider::DataError> { + if req.locale.is_empty() { Ok(icu_provider::DataResponse { payload: Some(icu_provider::DataPayload::from_static_ref(Self::SINGLETON_FALLBACK_PARENTS_V1)), metadata: Default::default() }) } else { Err(icu_provider::DataErrorKind::ExtraneousLocale.with_req(::KEY, req)) } + } + } + }; +} diff --git a/compiler/rustc_baked_icu_data/src/data/macros/fallback_supplement_co_v1.data.rs b/compiler/rustc_baked_icu_data/src/data/macros/fallback_supplement_co_v1.data.rs new file mode 100644 index 000000000000..02eec37ee09f --- /dev/null +++ b/compiler/rustc_baked_icu_data/src/data/macros/fallback_supplement_co_v1.data.rs @@ -0,0 +1,32 @@ +// @generated +/// Implement `DataProvider` on the given struct using the data +/// hardcoded in this file. This allows the struct to be used with +/// `icu`'s `_unstable` constructors. +#[doc(hidden)] +#[macro_export] +macro_rules! __impl_fallback_supplement_co_v1 { + ($ provider : ty) => { + #[clippy::msrv = "1.66"] + const _: () = <$provider>::MUST_USE_MAKE_PROVIDER_MACRO; + #[clippy::msrv = "1.66"] + impl $provider { + #[doc(hidden)] + pub const SINGLETON_FALLBACK_SUPPLEMENT_CO_V1: &'static ::Yokeable = &icu_locid_transform::provider::LocaleFallbackSupplementV1 { + parents: unsafe { + #[allow(unused_unsafe)] + zerovec::ZeroMap::from_parts_unchecked(unsafe { zerovec::VarZeroVec::from_bytes_unchecked(b"\x01\0\0\0\0\0yue") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"zh\0\x01Hant\0\0\0\0") }) + }, + unicode_extension_defaults: unsafe { + #[allow(unused_unsafe)] + zerovec::ZeroMap2d::from_parts_unchecked(unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"co") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"\x02\0\0\0") }, unsafe { zerovec::VarZeroVec::from_bytes_unchecked(b"\x02\0\0\0\0\0\x02\0zhzh-Hant") }, unsafe { zerovec::VarZeroVec::from_bytes_unchecked(b"\x02\0\0\0\0\0\x06\0pinyinstroke") }) + }, + }; + } + #[clippy::msrv = "1.66"] + impl icu_provider::DataProvider for $provider { + fn load(&self, req: icu_provider::DataRequest) -> Result, icu_provider::DataError> { + if req.locale.is_empty() { Ok(icu_provider::DataResponse { payload: Some(icu_provider::DataPayload::from_static_ref(Self::SINGLETON_FALLBACK_SUPPLEMENT_CO_V1)), metadata: Default::default() }) } else { Err(icu_provider::DataErrorKind::ExtraneousLocale.with_req(::KEY, req)) } + } + } + }; +} diff --git a/compiler/rustc_baked_icu_data/src/data/macros/list_and_v1.data.rs b/compiler/rustc_baked_icu_data/src/data/macros/list_and_v1.data.rs new file mode 100644 index 000000000000..186f706cdb28 --- /dev/null +++ b/compiler/rustc_baked_icu_data/src/data/macros/list_and_v1.data.rs @@ -0,0 +1,35 @@ +// @generated +/// Implement `DataProvider` on the given struct using the data +/// hardcoded in this file. This allows the struct to be used with +/// `icu`'s `_unstable` constructors. +#[doc(hidden)] +#[macro_export] +macro_rules! __impl_list_and_v1 { + ($ provider : ty) => { + #[clippy::msrv = "1.66"] + const _: () = <$provider>::MUST_USE_MAKE_PROVIDER_MACRO; + #[clippy::msrv = "1.66"] + impl icu_provider::DataProvider for $provider { + fn load(&self, req: icu_provider::DataRequest) -> Result, icu_provider::DataError> { + static EN_001: ::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" and ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" and ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" and ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" and ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }]); + static EN_IN: ::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" and ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" and ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" and ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" and ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", and ", 6u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }]); + static IT: ::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), special_case: None }]); + static PT: ::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }]); + static FR: ::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" et ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" et ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" et ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" et ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }]); + static TR: ::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" ve ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" ve ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" ve ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" ve ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }]); + static ES: ::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" y ", 3u8), special_case: Some(icu_list::provider::SpecialCasePattern { condition: unsafe { icu_list::provider::SerdeDFA::from_dfa_bytes_unchecked(if cfg!(target_endian = "little") { b"rust-regex-automata-dfa-sparse\0\0\xFF\xFE\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B(\x01\0\0\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#\0\0\0" } else { b"rust-regex-automata-dfa-sparse\0\0\0\0\xFE\xFF\0\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\0\0\x01(\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#" }) }, pattern: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8) }) }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" y ", 3u8), special_case: Some(icu_list::provider::SpecialCasePattern { condition: unsafe { icu_list::provider::SerdeDFA::from_dfa_bytes_unchecked(if cfg!(target_endian = "little") { b"rust-regex-automata-dfa-sparse\0\0\xFF\xFE\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B(\x01\0\0\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#\0\0\0" } else { b"rust-regex-automata-dfa-sparse\0\0\0\0\xFE\xFF\0\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\0\0\x01(\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#" }) }, pattern: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8) }) }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" y ", 3u8), special_case: Some(icu_list::provider::SpecialCasePattern { condition: unsafe { icu_list::provider::SerdeDFA::from_dfa_bytes_unchecked(if cfg!(target_endian = "little") { b"rust-regex-automata-dfa-sparse\0\0\xFF\xFE\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B(\x01\0\0\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#\0\0\0" } else { b"rust-regex-automata-dfa-sparse\0\0\0\0\xFE\xFF\0\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\0\0\x01(\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#" }) }, pattern: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8) }) }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" y ", 3u8), special_case: Some(icu_list::provider::SpecialCasePattern { condition: unsafe { icu_list::provider::SerdeDFA::from_dfa_bytes_unchecked(if cfg!(target_endian = "little") { b"rust-regex-automata-dfa-sparse\0\0\xFF\xFE\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B(\x01\0\0\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#\0\0\0" } else { b"rust-regex-automata-dfa-sparse\0\0\0\0\xFE\xFF\0\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\0\0\x01(\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#" }) }, pattern: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8) }) }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" y ", 3u8), special_case: Some(icu_list::provider::SpecialCasePattern { condition: unsafe { icu_list::provider::SerdeDFA::from_dfa_bytes_unchecked(if cfg!(target_endian = "little") { b"rust-regex-automata-dfa-sparse\0\0\xFF\xFE\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B(\x01\0\0\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#\0\0\0" } else { b"rust-regex-automata-dfa-sparse\0\0\0\0\xFE\xFF\0\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\0\0\x01(\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#" }) }, pattern: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8) }) }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" y ", 3u8), special_case: Some(icu_list::provider::SpecialCasePattern { condition: unsafe { icu_list::provider::SerdeDFA::from_dfa_bytes_unchecked(if cfg!(target_endian = "little") { b"rust-regex-automata-dfa-sparse\0\0\xFF\xFE\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B(\x01\0\0\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#\0\0\0" } else { b"rust-regex-automata-dfa-sparse\0\0\0\0\xFE\xFF\0\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\0\0\x01(\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#" }) }, pattern: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8) }) }]); + static RU: ::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" и ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" и ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" и ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" и ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }]); + static UND: ::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }]); + static EN: ::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", and ", 6u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" and ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", & ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" & ", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }]); + static HI_LATN: ::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", aur ", 6u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" aur ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", aur ", 6u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" aur ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" aur ", 5u8), special_case: None }]); + static JA: ::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }]); + static ZH_HK: ::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("及", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("及", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("及", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("及", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("及", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("及", 3u8), special_case: None }]); + static ZH: ::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }]); + static ZH_HANT: ::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), special_case: None }]); + static VALUES: [&::Yokeable; 215usize] = [&EN, &EN_001, &EN_001, &EN, &EN_001, &EN_001, &EN, &EN_001, &EN_001, &EN_001, &EN_001, &EN, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_IN, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN, &EN_001, &EN, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN, &EN_001, &EN_001, &EN, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN, &EN_001, &EN_001, &EN, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &HI_LATN, &IT, &IT, &IT, &IT, &JA, &PT, &PT, &PT, &PT, &PT, &PT, &PT, &PT, &PT, &PT, &PT, &PT, &RU, &RU, &RU, &RU, &RU, &RU, &TR, &TR, &UND, &ZH, &ZH_HK, &ZH, &ZH, &ZH, &ZH_HANT, &ZH_HK, &ZH]; + static KEYS: [&str; 215usize] = ["en", "en-001", "en-150", "en-AE", "en-AG", "en-AI", "en-AS", "en-AT", "en-AU", "en-BB", "en-BE", "en-BI", "en-BM", "en-BS", "en-BW", "en-BZ", "en-CA", "en-CC", "en-CH", "en-CK", "en-CM", "en-CX", "en-CY", "en-DE", "en-DG", "en-DK", "en-DM", "en-ER", "en-FI", "en-FJ", "en-FK", "en-FM", "en-GB", "en-GD", "en-GG", "en-GH", "en-GI", "en-GM", "en-GU", "en-GY", "en-HK", "en-IE", "en-IL", "en-IM", "en-IN", "en-IO", "en-JE", "en-JM", "en-KE", "en-KI", "en-KN", "en-KY", "en-LC", "en-LR", "en-LS", "en-MG", "en-MH", "en-MO", "en-MP", "en-MS", "en-MT", "en-MU", "en-MV", "en-MW", "en-MY", "en-NA", "en-NF", "en-NG", "en-NL", "en-NR", "en-NU", "en-NZ", "en-PG", "en-PH", "en-PK", "en-PN", "en-PR", "en-PW", "en-RW", "en-SB", "en-SC", "en-SD", "en-SE", "en-SG", "en-SH", "en-SI", "en-SL", "en-SS", "en-SX", "en-SZ", "en-TC", "en-TK", "en-TO", "en-TT", "en-TV", "en-TZ", "en-UG", "en-UM", "en-VC", "en-VG", "en-VI", "en-VU", "en-WS", "en-ZA", "en-ZM", "en-ZW", "es", "es-419", "es-AR", "es-BO", "es-BR", "es-BZ", "es-CL", "es-CO", "es-CR", "es-CU", "es-DO", "es-EA", "es-EC", "es-GQ", "es-GT", "es-HN", "es-IC", "es-MX", "es-NI", "es-PA", "es-PE", "es-PH", "es-PR", "es-PY", "es-SV", "es-US", "es-UY", "es-VE", "fr", "fr-BE", "fr-BF", "fr-BI", "fr-BJ", "fr-BL", "fr-CA", "fr-CD", "fr-CF", "fr-CG", "fr-CH", "fr-CI", "fr-CM", "fr-DJ", "fr-DZ", "fr-GA", "fr-GF", "fr-GN", "fr-GP", "fr-GQ", "fr-HT", "fr-KM", "fr-LU", "fr-MA", "fr-MC", "fr-MF", "fr-MG", "fr-ML", "fr-MQ", "fr-MR", "fr-MU", "fr-NC", "fr-NE", "fr-PF", "fr-PM", "fr-RE", "fr-RW", "fr-SC", "fr-SN", "fr-SY", "fr-TD", "fr-TG", "fr-TN", "fr-VU", "fr-WF", "fr-YT", "hi-Latn", "it", "it-CH", "it-SM", "it-VA", "ja", "pt", "pt-AO", "pt-CH", "pt-CV", "pt-GQ", "pt-GW", "pt-LU", "pt-MO", "pt-MZ", "pt-PT", "pt-ST", "pt-TL", "ru", "ru-BY", "ru-KG", "ru-KZ", "ru-MD", "ru-UA", "tr", "tr-CY", "und", "zh", "zh-HK", "zh-Hans", "zh-Hans-HK", "zh-Hans-MO", "zh-Hant", "zh-MO", "zh-SG"]; + if let Ok(payload) = KEYS.binary_search_by(|k| req.locale.strict_cmp(k.as_bytes()).reverse()).map(|i| *unsafe { VALUES.get_unchecked(i) }) { Ok(icu_provider::DataResponse { payload: Some(icu_provider::DataPayload::from_static_ref(payload)), metadata: Default::default() }) } else { Err(icu_provider::DataErrorKind::MissingLocale.with_req(::KEY, req)) } + } + } + }; +} diff --git a/compiler/rustc_baked_icu_data/src/data/mod.rs b/compiler/rustc_baked_icu_data/src/data/mod.rs index 943187808b81..465689f0cb8d 100644 --- a/compiler/rustc_baked_icu_data/src/data/mod.rs +++ b/compiler/rustc_baked_icu_data/src/data/mod.rs @@ -1,122 +1,31 @@ // @generated -#[clippy::msrv = "1.61"] -mod fallback; -#[clippy::msrv = "1.61"] -mod list; -#[clippy::msrv = "1.61"] -use icu_provider::prelude::*; -/// Implement [`DataProvider`] on the given struct using the data -/// hardcoded in this module. This allows the struct to be used with -/// `icu`'s `_unstable` constructors. -/// -/// This macro can only be called from its definition-site, i.e. right -/// after `include!`-ing the generated module. -/// -/// ```compile_fail -/// struct MyDataProvider; -/// include!("/path/to/generated/mod.rs"); -/// impl_data_provider(MyDataProvider); -/// ``` -#[allow(unused_macros)] +include!("macros.rs"); macro_rules! impl_data_provider { - ($ provider : path) => { - #[clippy::msrv = "1.61"] - impl DataProvider<::icu_list::provider::AndListV1Marker> for $provider { - fn load(&self, req: DataRequest) -> Result, DataError> { - list::and_v1::lookup(&req.locale) - .map(zerofrom::ZeroFrom::zero_from) - .map(DataPayload::from_owned) - .map(|payload| DataResponse { metadata: Default::default(), payload: Some(payload) }) - .ok_or_else(|| DataErrorKind::MissingLocale.with_req(::icu_list::provider::AndListV1Marker::KEY, req)) - } - } - #[clippy::msrv = "1.61"] - impl DataProvider<::icu_provider_adapters::fallback::provider::CollationFallbackSupplementV1Marker> for $provider { - fn load( - &self, - req: DataRequest, - ) -> Result, DataError> { - fallback::supplement::co_v1::lookup(&req.locale) - .map(zerofrom::ZeroFrom::zero_from) - .map(DataPayload::from_owned) - .map(|payload| DataResponse { metadata: Default::default(), payload: Some(payload) }) - .ok_or_else(|| { - DataErrorKind::MissingLocale - .with_req(::icu_provider_adapters::fallback::provider::CollationFallbackSupplementV1Marker::KEY, req) - }) - } - } - #[clippy::msrv = "1.61"] - impl DataProvider<::icu_provider_adapters::fallback::provider::LocaleFallbackLikelySubtagsV1Marker> for $provider { - fn load( - &self, - req: DataRequest, - ) -> Result, DataError> { - fallback::likelysubtags_v1::lookup(&req.locale) - .map(zerofrom::ZeroFrom::zero_from) - .map(DataPayload::from_owned) - .map(|payload| DataResponse { metadata: Default::default(), payload: Some(payload) }) - .ok_or_else(|| { - DataErrorKind::MissingLocale - .with_req(::icu_provider_adapters::fallback::provider::LocaleFallbackLikelySubtagsV1Marker::KEY, req) - }) - } - } - #[clippy::msrv = "1.61"] - impl DataProvider<::icu_provider_adapters::fallback::provider::LocaleFallbackParentsV1Marker> for $provider { - fn load( - &self, - req: DataRequest, - ) -> Result, DataError> { - fallback::parents_v1::lookup(&req.locale) - .map(zerofrom::ZeroFrom::zero_from) - .map(DataPayload::from_owned) - .map(|payload| DataResponse { metadata: Default::default(), payload: Some(payload) }) - .ok_or_else(|| { - DataErrorKind::MissingLocale.with_req(::icu_provider_adapters::fallback::provider::LocaleFallbackParentsV1Marker::KEY, req) - }) - } - } + ($ provider : ty) => { + make_provider!($provider); + impl_fallback_likelysubtags_v1!($provider); + impl_fallback_parents_v1!($provider); + impl_fallback_supplement_co_v1!($provider); + impl_list_and_v1!($provider); }; } -/// Implement [`AnyProvider`] on the given struct using the data -/// hardcoded in this module. This allows the struct to be used with -/// `icu`'s `_any` constructors. -/// -/// This macro can only be called from its definition-site, i.e. right -/// after `include!`-ing the generated module. -/// -/// ```compile_fail -/// struct MyAnyProvider; -/// include!("/path/to/generated/mod.rs"); -/// impl_any_provider(MyAnyProvider); -/// ``` #[allow(unused_macros)] macro_rules! impl_any_provider { - ($ provider : path) => { - #[clippy::msrv = "1.61"] - impl AnyProvider for $provider { - fn load_any(&self, key: DataKey, req: DataRequest) -> Result { - const ANDLISTV1MARKER: ::icu_provider::DataKeyHash = ::icu_list::provider::AndListV1Marker::KEY.hashed(); - const COLLATIONFALLBACKSUPPLEMENTV1MARKER: ::icu_provider::DataKeyHash = - ::icu_provider_adapters::fallback::provider::CollationFallbackSupplementV1Marker::KEY.hashed(); - const LOCALEFALLBACKLIKELYSUBTAGSV1MARKER: ::icu_provider::DataKeyHash = - ::icu_provider_adapters::fallback::provider::LocaleFallbackLikelySubtagsV1Marker::KEY.hashed(); - const LOCALEFALLBACKPARENTSV1MARKER: ::icu_provider::DataKeyHash = - ::icu_provider_adapters::fallback::provider::LocaleFallbackParentsV1Marker::KEY.hashed(); + ($ provider : ty) => { + #[clippy::msrv = "1.66"] + impl icu_provider::AnyProvider for $provider { + fn load_any(&self, key: icu_provider::DataKey, req: icu_provider::DataRequest) -> Result { match key.hashed() { - ANDLISTV1MARKER => list::and_v1::lookup(&req.locale).map(AnyPayload::from_static_ref), - COLLATIONFALLBACKSUPPLEMENTV1MARKER => fallback::supplement::co_v1::lookup(&req.locale).map(AnyPayload::from_static_ref), - LOCALEFALLBACKLIKELYSUBTAGSV1MARKER => fallback::likelysubtags_v1::lookup(&req.locale).map(AnyPayload::from_static_ref), - LOCALEFALLBACKPARENTSV1MARKER => fallback::parents_v1::lookup(&req.locale).map(AnyPayload::from_static_ref), - _ => return Err(DataErrorKind::MissingDataKey.with_req(key, req)), + h if h == ::KEY.hashed() => icu_provider::DataProvider::::load(self, req).map(icu_provider::DataResponse::wrap_into_any_response), + h if h == ::KEY.hashed() => icu_provider::DataProvider::::load(self, req).map(icu_provider::DataResponse::wrap_into_any_response), + h if h == ::KEY.hashed() => icu_provider::DataProvider::::load(self, req).map(icu_provider::DataResponse::wrap_into_any_response), + h if h == ::KEY.hashed() => icu_provider::DataProvider::::load(self, req).map(icu_provider::DataResponse::wrap_into_any_response), + _ => Err(icu_provider::DataErrorKind::MissingDataKey.with_req(key, req)), } - .map(|payload| AnyResponse { payload: Some(payload), metadata: Default::default() }) - .ok_or_else(|| DataErrorKind::MissingLocale.with_req(key, req)) } } }; } -#[clippy::msrv = "1.61"] +#[clippy::msrv = "1.66"] pub struct BakedDataProvider; impl_data_provider!(BakedDataProvider); diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index b10cccc79f6b..3a65b4a49a88 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -247,7 +247,10 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "hashbrown", "hermit-abi", "icu_list", + "icu_list_data", "icu_locid", + "icu_locid_transform", + "icu_locid_transform_data", "icu_provider", "icu_provider_adapters", "icu_provider_macros", @@ -398,6 +401,28 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ // tidy-alphabetical-end ]; +// These crates come from ICU4X and are licensed under the unicode license. +// It currently doesn't have an SPDX identifier, so they cannot put one there. +// See https://github.com/unicode-org/icu4x/pull/3875 +// FIXME: This should be removed once ICU4X crates update. +const ICU4X_UNICODE_LICENSE_DEPENDENCIES: &[&str] = &[ + // tidy-alphabetical-start + "icu_list", + "icu_list_data", + "icu_locid", + "icu_locid_transform", + "icu_locid_transform_data", + "icu_provider", + "icu_provider_adapters", + "icu_provider_macros", + "litemap", + "tinystr", + "writeable", + "yoke", + "zerovec", + // tidy-alphabetical-end +]; + const PERMITTED_CRANELIFT_DEPENDENCIES: &[&str] = &[ // tidy-alphabetical-start "ahash", @@ -590,6 +615,10 @@ fn check_license_exceptions(metadata: &Metadata, exceptions: &[(&str, &str)], ba let license = match &pkg.license { Some(license) => license, None => { + if ICU4X_UNICODE_LICENSE_DEPENDENCIES.contains(&pkg.name.as_str()) { + // See the comment on ICU4X_UNICODE_LICENSE_DEPENDENCIES. + continue; + } tidy_error!(bad, "dependency `{}` does not define a license expression", pkg.id); continue; } diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs index 11480e2be603..cb40c6e3a386 100644 --- a/src/tools/tidy/src/style.rs +++ b/src/tools/tidy/src/style.rs @@ -427,9 +427,12 @@ pub fn check(path: &Path, bad: &mut bool) { "copyright notices attributed to the Rust Project Developers are deprecated" ); } - if is_unexplained_ignore(&extension, line) { - err(UNEXPLAINED_IGNORE_DOCTEST_INFO); + if !file.components().any(|c| c.as_os_str() == "rustc_baked_icu_data") { + if is_unexplained_ignore(&extension, line) { + err(UNEXPLAINED_IGNORE_DOCTEST_INFO); + } } + if filename.ends_with(".cpp") && line.contains("llvm_unreachable") { err(LLVM_UNREACHABLE_INFO); } From 580fa0c1a9d4d5f90988c55bde7c77cdce52c3b1 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Mon, 6 Nov 2023 15:53:32 +0100 Subject: [PATCH 283/435] rename github_repository to git_repository --- src/bootstrap/src/core/build_steps/suggest.rs | 2 +- src/bootstrap/src/core/build_steps/test.rs | 2 +- src/bootstrap/src/core/config/config.rs | 4 ++-- src/stage0.json | 2 +- src/tools/build_helper/src/git.rs | 6 +++--- src/tools/compiletest/src/common.rs | 4 ++-- src/tools/compiletest/src/header/tests.rs | 2 +- src/tools/compiletest/src/lib.rs | 4 ++-- src/tools/suggest-tests/src/main.rs | 2 +- 9 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/suggest.rs b/src/bootstrap/src/core/build_steps/suggest.rs index 70b46fa92390..622a4c4953cc 100644 --- a/src/bootstrap/src/core/build_steps/suggest.rs +++ b/src/bootstrap/src/core/build_steps/suggest.rs @@ -12,7 +12,7 @@ pub fn suggest(builder: &Builder<'_>, run: bool) { let git_config = builder.config.git_config(); let suggestions = builder .tool_cmd(Tool::SuggestTests) - .env("SUGGEST_TESTS_GITHUB_REPOSITORY", git_config.github_repository) + .env("SUGGEST_TESTS_GIT_REPOSITORY", git_config.git_repository) .env("SUGGEST_TESTS_NIGHTLY_BRANCH", git_config.nightly_branch) .output() .expect("failed to run `suggest-tests` tool"); diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 6c166332c18b..8d9959fecbfe 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -1874,7 +1874,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the } let git_config = builder.config.git_config(); - cmd.arg("--github-repository").arg(git_config.github_repository); + cmd.arg("--git-repository").arg(git_config.git_repository); cmd.arg("--nightly-branch").arg(git_config.nightly_branch); builder.ci_env.force_coloring_in_ci(&mut cmd); diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index d3345f2d2a11..05b9f190ae14 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -319,7 +319,7 @@ pub struct Stage0Config { pub artifacts_server: String, pub artifacts_with_llvm_assertions_server: String, pub git_merge_commit_email: String, - pub github_repository: String, + pub git_repository: String, pub nightly_branch: String, } #[derive(Default, Deserialize, Clone)] @@ -2009,7 +2009,7 @@ impl Config { pub fn git_config(&self) -> GitConfig<'_> { GitConfig { - github_repository: &self.stage0_metadata.config.github_repository, + git_repository: &self.stage0_metadata.config.git_repository, nightly_branch: &self.stage0_metadata.config.nightly_branch, } } diff --git a/src/stage0.json b/src/stage0.json index 8e6c43dc46d4..2b39e1b11589 100644 --- a/src/stage0.json +++ b/src/stage0.json @@ -4,7 +4,7 @@ "artifacts_server": "https://ci-artifacts.rust-lang.org/rustc-builds", "artifacts_with_llvm_assertions_server": "https://ci-artifacts.rust-lang.org/rustc-builds-alt", "git_merge_commit_email": "bors@rust-lang.org", - "github_repository": "rust-lang/rust", + "git_repository": "rust-lang/rust", "nightly_branch": "master" }, "__comments": [ diff --git a/src/tools/build_helper/src/git.rs b/src/tools/build_helper/src/git.rs index 66f694dc919d..b91dc38e9248 100644 --- a/src/tools/build_helper/src/git.rs +++ b/src/tools/build_helper/src/git.rs @@ -2,7 +2,7 @@ use std::process::Stdio; use std::{path::Path, process::Command}; pub struct GitConfig<'a> { - pub github_repository: &'a str, + pub git_repository: &'a str, pub nightly_branch: &'a str, } @@ -45,8 +45,8 @@ pub fn get_rust_lang_rust_remote( let rust_lang_remote = stdout .lines() - .find(|remote| remote.contains(config.github_repository)) - .ok_or_else(|| format!("{} remote not found", config.github_repository))?; + .find(|remote| remote.contains(config.git_repository)) + .ok_or_else(|| format!("{} remote not found", config.git_repository))?; let remote_name = rust_lang_remote.split('.').nth(1).ok_or_else(|| "remote name not found".to_owned())?; diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index cd9cf748aff0..f42fa588b6ec 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -373,7 +373,7 @@ pub struct Config { pub nocapture: bool, // Needed both to construct build_helper::git::GitConfig - pub github_repository: String, + pub git_repository: String, pub nightly_branch: String, } @@ -449,7 +449,7 @@ impl Config { pub fn git_config(&self) -> GitConfig<'_> { GitConfig { - github_repository: &self.github_repository, + git_repository: &self.git_repository, nightly_branch: &self.nightly_branch, } } diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs index 1c89f8ba7639..85e745bed112 100644 --- a/src/tools/compiletest/src/header/tests.rs +++ b/src/tools/compiletest/src/header/tests.rs @@ -126,7 +126,7 @@ impl ConfigBuilder { self.host.as_deref().unwrap_or("x86_64-unknown-linux-gnu"), "--target", self.target.as_deref().unwrap_or("x86_64-unknown-linux-gnu"), - "--github-repository=", + "--git-repository=", "--nightly-branch=", ]; let mut args: Vec = args.iter().map(ToString::to_string).collect(); diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index 52e7f4174f10..bb09c03ef5b7 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -145,7 +145,7 @@ pub fn parse_config(args: Vec) -> Config { .reqopt("", "channel", "current Rust channel", "CHANNEL") .optflag("", "git-hash", "run tests which rely on commit version being compiled into the binaries") .optopt("", "edition", "default Rust edition", "EDITION") - .reqopt("", "github-repository", "name of the GitHub repository", "ORG/REPO") + .reqopt("", "git-repository", "name of the git repository", "ORG/REPO") .reqopt("", "nightly-branch", "name of the git branch for nightly", "BRANCH"); let (argv0, args_) = args.split_first().unwrap(); @@ -310,7 +310,7 @@ pub fn parse_config(args: Vec) -> Config { nocapture: matches.opt_present("nocapture"), - github_repository: matches.opt_str("github-repository").unwrap(), + git_repository: matches.opt_str("git-repository").unwrap(), nightly_branch: matches.opt_str("nightly-branch").unwrap(), } } diff --git a/src/tools/suggest-tests/src/main.rs b/src/tools/suggest-tests/src/main.rs index be3dde4f0bb7..8e3625c24491 100644 --- a/src/tools/suggest-tests/src/main.rs +++ b/src/tools/suggest-tests/src/main.rs @@ -6,7 +6,7 @@ use suggest_tests::get_suggestions; fn main() -> ExitCode { let modified_files = get_git_modified_files( &GitConfig { - github_repository: &env("SUGGEST_TESTS_GITHUB_REPOSITORY"), + git_repository: &env("SUGGEST_TESTS_GIT_REPOSITORY"), nightly_branch: &env("SUGGEST_TESTS_NIGHTLY_BRANCH"), }, None, From 2beca157c96329da93320de83bdb7192bf02fa96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Mon, 6 Nov 2023 15:46:17 +0000 Subject: [PATCH 284/435] check binders with bound vars for global bounds that don't hold (instead of just late bound vars) --- compiler/rustc_hir_analysis/src/check/wfcheck.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 046983e90f7b..eb4491b89bf1 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -32,6 +32,7 @@ use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _ use rustc_trait_selection::traits::{ self, ObligationCause, ObligationCauseCode, ObligationCtxt, WellFormedLoc, }; +use rustc_type_ir::TypeFlags; use std::cell::LazyCell; use std::ops::{ControlFlow, Deref}; @@ -1877,7 +1878,7 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> { continue; } // Match the existing behavior. - if pred.is_global() && !pred.has_late_bound_vars() { + if pred.is_global() && !pred.has_type_flags(TypeFlags::HAS_BINDER_VARS) { let pred = self.normalize(span, None, pred); let hir_node = tcx.hir().find_by_def_id(self.body_def_id); From 58351ae03f19520a586e7c3c1b13e74a9613d1d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Mon, 6 Nov 2023 15:47:31 +0000 Subject: [PATCH 285/435] add test for trivial bound not holding in `soa-derive` --- tests/ui/late-bound-lifetimes/predicate-is-global.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/ui/late-bound-lifetimes/predicate-is-global.rs b/tests/ui/late-bound-lifetimes/predicate-is-global.rs index ee4c4706005f..be017a3f94fb 100644 --- a/tests/ui/late-bound-lifetimes/predicate-is-global.rs +++ b/tests/ui/late-bound-lifetimes/predicate-is-global.rs @@ -29,4 +29,12 @@ impl Inherent { fn inherent(&self) {} } +// This trivial bound doesn't hold, but the unused lifetime tripped up that check after #117589, and +// showed up in its crater results (in `soa-derive 0.13.0`). +fn do_it() +where + for<'a> Inherent: Clone, +{ +} + fn main() {} From 931692fa13dd9fd39f4b5c2678ae7bfabad92b2a Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Thu, 26 Oct 2023 15:33:41 +0000 Subject: [PATCH 286/435] Recognise thread local statics in THIR unsafeck --- .../rustc_mir_build/src/check_unsafety.rs | 4 +- ....stderr => thread-local-static.mir.stderr} | 10 ++--- tests/ui/thread-local/thread-local-static.rs | 3 ++ .../thread-local-static.thir.stderr | 44 +++++++++++++++++++ 4 files changed, 55 insertions(+), 6 deletions(-) rename tests/ui/thread-local/{thread-local-static.stderr => thread-local-static.mir.stderr} (88%) create mode 100644 tests/ui/thread-local/thread-local-static.thir.stderr diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 45be50153713..637036a70e86 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -394,7 +394,9 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { } } ExprKind::Deref { arg } => { - if let ExprKind::StaticRef { def_id, .. } = self.thir[arg].kind { + if let ExprKind::StaticRef { def_id, .. } | ExprKind::ThreadLocalRef(def_id) = + self.thir[arg].kind + { if self.tcx.is_mutable_static(def_id) { self.requires_unsafe(expr.span, UseOfMutableStatic); } else if self.tcx.is_foreign_item(def_id) { diff --git a/tests/ui/thread-local/thread-local-static.stderr b/tests/ui/thread-local/thread-local-static.mir.stderr similarity index 88% rename from tests/ui/thread-local/thread-local-static.stderr rename to tests/ui/thread-local/thread-local-static.mir.stderr index 712050a25fcf..607d7ee902cb 100644 --- a/tests/ui/thread-local/thread-local-static.stderr +++ b/tests/ui/thread-local/thread-local-static.mir.stderr @@ -1,5 +1,5 @@ error[E0658]: mutable references are not allowed in constant functions - --> $DIR/thread-local-static.rs:7:12 + --> $DIR/thread-local-static.rs:10:12 | LL | const fn g(x: &mut [u32; 8]) { | ^ @@ -8,13 +8,13 @@ LL | const fn g(x: &mut [u32; 8]) { = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable error[E0625]: thread-local statics cannot be accessed at compile-time - --> $DIR/thread-local-static.rs:9:28 + --> $DIR/thread-local-static.rs:12:28 | LL | std::mem::swap(x, &mut STATIC_VAR_2) | ^^^^^^^^^^^^ error[E0013]: constant functions cannot refer to statics - --> $DIR/thread-local-static.rs:9:28 + --> $DIR/thread-local-static.rs:12:28 | LL | std::mem::swap(x, &mut STATIC_VAR_2) | ^^^^^^^^^^^^ @@ -22,7 +22,7 @@ LL | std::mem::swap(x, &mut STATIC_VAR_2) = help: consider extracting the value of the `static` to a `const`, and referring to that error[E0658]: mutable references are not allowed in constant functions - --> $DIR/thread-local-static.rs:9:23 + --> $DIR/thread-local-static.rs:12:23 | LL | std::mem::swap(x, &mut STATIC_VAR_2) | ^^^^^^^^^^^^^^^^^ @@ -31,7 +31,7 @@ LL | std::mem::swap(x, &mut STATIC_VAR_2) = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable error[E0133]: use of mutable static is unsafe and requires unsafe function or block - --> $DIR/thread-local-static.rs:9:23 + --> $DIR/thread-local-static.rs:12:23 | LL | std::mem::swap(x, &mut STATIC_VAR_2) | ^^^^^^^^^^^^^^^^^ use of mutable static diff --git a/tests/ui/thread-local/thread-local-static.rs b/tests/ui/thread-local/thread-local-static.rs index c7fee9e6b4c5..afaffbb7e9bb 100644 --- a/tests/ui/thread-local/thread-local-static.rs +++ b/tests/ui/thread-local/thread-local-static.rs @@ -1,7 +1,10 @@ // edition:2018 +// revisions: mir thir +//thir: -Zthir-unsafeck #![feature(thread_local)] #![feature(const_swap)] + #[thread_local] static mut STATIC_VAR_2: [u32; 8] = [4; 8]; const fn g(x: &mut [u32; 8]) { diff --git a/tests/ui/thread-local/thread-local-static.thir.stderr b/tests/ui/thread-local/thread-local-static.thir.stderr new file mode 100644 index 000000000000..607d7ee902cb --- /dev/null +++ b/tests/ui/thread-local/thread-local-static.thir.stderr @@ -0,0 +1,44 @@ +error[E0658]: mutable references are not allowed in constant functions + --> $DIR/thread-local-static.rs:10:12 + | +LL | const fn g(x: &mut [u32; 8]) { + | ^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0625]: thread-local statics cannot be accessed at compile-time + --> $DIR/thread-local-static.rs:12:28 + | +LL | std::mem::swap(x, &mut STATIC_VAR_2) + | ^^^^^^^^^^^^ + +error[E0013]: constant functions cannot refer to statics + --> $DIR/thread-local-static.rs:12:28 + | +LL | std::mem::swap(x, &mut STATIC_VAR_2) + | ^^^^^^^^^^^^ + | + = help: consider extracting the value of the `static` to a `const`, and referring to that + +error[E0658]: mutable references are not allowed in constant functions + --> $DIR/thread-local-static.rs:12:23 + | +LL | std::mem::swap(x, &mut STATIC_VAR_2) + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0133]: use of mutable static is unsafe and requires unsafe function or block + --> $DIR/thread-local-static.rs:12:23 + | +LL | std::mem::swap(x, &mut STATIC_VAR_2) + | ^^^^^^^^^^^^^^^^^ use of mutable static + | + = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0013, E0133, E0625, E0658. +For more information about an error, try `rustc --explain E0013`. From 2b2c0f98869ce582716d47a7be5db2625b0558fc Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Thu, 26 Oct 2023 15:38:10 +0000 Subject: [PATCH 287/435] Allow tests with rust-rustfix and revisions --- src/tools/compiletest/src/runtest.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index e74d66a85992..620844f6f097 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -3962,7 +3962,7 @@ impl<'test> TestCx<'test> { // And finally, compile the fixed code and make sure it both // succeeds and has no diagnostics. let rustc = self.make_compile_args( - &self.testpaths.file.with_extension(UI_FIXED), + &self.expected_output_path(UI_FIXED), TargetLocation::ThisFile(self.make_exe_name()), emit_metadata, AllowUnused::No, From 2b599927368823496942da52b31bea81917f0ec7 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Thu, 26 Oct 2023 15:39:25 +0000 Subject: [PATCH 288/435] Add suggestion to THIR unsafe_op_in_unsafe_fn lint --- compiler/rustc_hir/src/hir.rs | 9 ++ compiler/rustc_mir_build/messages.ftl | 3 + .../rustc_mir_build/src/check_unsafety.rs | 76 ++++++++++++-- compiler/rustc_mir_build/src/errors.rs | 43 ++++++++ ...on-2024-unsafe_op_in_unsafe_fn.mir.stderr} | 4 +- .../edition-2024-unsafe_op_in_unsafe_fn.rs | 10 +- ...on-2024-unsafe_op_in_unsafe_fn.thir.stderr | 16 +++ ...fc-2585-unsafe_op_in_unsafe_fn.thir.stderr | 10 ++ ...d => wrapping-unsafe-block-sugg.mir.fixed} | 19 ++-- ... => wrapping-unsafe-block-sugg.mir.stderr} | 54 +++++----- tests/ui/unsafe/wrapping-unsafe-block-sugg.rs | 19 ++-- .../wrapping-unsafe-block-sugg.thir.fixed | 73 ++++++++++++++ .../wrapping-unsafe-block-sugg.thir.stderr | 99 +++++++++++++++++++ 13 files changed, 381 insertions(+), 54 deletions(-) rename tests/ui/unsafe/{edition-2024-unsafe_op_in_unsafe_fn.stderr => edition-2024-unsafe_op_in_unsafe_fn.mir.stderr} (80%) create mode 100644 tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.thir.stderr rename tests/ui/unsafe/{wrapping-unsafe-block-sugg.fixed => wrapping-unsafe-block-sugg.mir.fixed} (73%) rename tests/ui/unsafe/{wrapping-unsafe-block-sugg.stderr => wrapping-unsafe-block-sugg.mir.stderr} (86%) create mode 100644 tests/ui/unsafe/wrapping-unsafe-block-sugg.thir.fixed create mode 100644 tests/ui/unsafe/wrapping-unsafe-block-sugg.thir.stderr diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index d88f165b9e53..c4e44a6a4e38 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -3566,6 +3566,15 @@ impl<'hir> OwnerNode<'hir> { } } + pub fn fn_sig(self) -> Option<&'hir FnSig<'hir>> { + match self { + OwnerNode::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. }) + | OwnerNode::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. }) + | OwnerNode::Item(Item { kind: ItemKind::Fn(fn_sig, _, _), .. }) => Some(fn_sig), + _ => None, + } + } + pub fn fn_decl(self) -> Option<&'hir FnDecl<'hir>> { match self { OwnerNode::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. }) diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl index 563851f712c6..54fc8f77f936 100644 --- a/compiler/rustc_mir_build/messages.ftl +++ b/compiler/rustc_mir_build/messages.ftl @@ -320,6 +320,7 @@ mir_build_unreachable_pattern = unreachable pattern .label = unreachable pattern .catchall_label = matches any value +mir_build_unsafe_fn_safe_body = an unsafe function restricts its caller, but its body is safe by default mir_build_unsafe_not_inherited = items do not inherit unsafety from separate enclosing items mir_build_unsafe_op_in_unsafe_fn_borrow_of_layout_constrained_field_requires_unsafe = @@ -386,3 +387,5 @@ mir_build_unused_unsafe = unnecessary `unsafe` block mir_build_unused_unsafe_enclosing_block_label = because it's nested under this `unsafe` block mir_build_variant_defined_here = not covered + +mir_build_wrap_suggestion = consider wrapping the function body in an unsafe block diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 637036a70e86..373ed61ff879 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -35,6 +35,10 @@ struct UnsafetyVisitor<'a, 'tcx> { param_env: ParamEnv<'tcx>, inside_adt: bool, warnings: &'a mut Vec, + + /// Flag to ensure that we only suggest wrapping the entire function body in + /// an unsafe block once. + suggest_unsafe_block: bool, } impl<'tcx> UnsafetyVisitor<'_, 'tcx> { @@ -95,7 +99,13 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> { SafetyContext::UnsafeFn if unsafe_op_in_unsafe_fn_allowed => {} SafetyContext::UnsafeFn => { // unsafe_op_in_unsafe_fn is disallowed - kind.emit_unsafe_op_in_unsafe_fn_lint(self.tcx, self.hir_context, span); + kind.emit_unsafe_op_in_unsafe_fn_lint( + self.tcx, + self.hir_context, + span, + self.suggest_unsafe_block, + ); + self.suggest_unsafe_block = false; } SafetyContext::Safe => { kind.emit_requires_unsafe_err( @@ -297,6 +307,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { } PatKind::InlineConstant { def, .. } => { self.visit_inner_body(*def); + visit::walk_pat(self, pat); } _ => { visit::walk_pat(self, pat); @@ -545,7 +556,22 @@ impl UnsafeOpKind { tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, + suggest_unsafe_block: bool, ) { + let parent_id = tcx.hir().get_parent_item(hir_id); + let parent_owner = tcx.hir().owner(parent_id); + let should_suggest = parent_owner.fn_sig().map_or(false, |sig| sig.header.is_unsafe()); + let unsafe_not_inherited_note = if should_suggest { + suggest_unsafe_block.then(|| { + let body_span = tcx.hir().body(parent_owner.body_id().unwrap()).value.span; + UnsafeNotInheritedLintNote { + signature_span: tcx.def_span(parent_id.def_id), + body_span, + } + }) + } else { + None + }; // FIXME: ideally we would want to trim the def paths, but this is not // feasible with the current lint emission API (see issue #106126). match self { @@ -556,61 +582,89 @@ impl UnsafeOpKind { UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafe { span, function: &with_no_trimmed_paths!(tcx.def_path_str(*did)), + unsafe_not_inherited_note, }, ), CallToUnsafeFunction(None) => tcx.emit_spanned_lint( UNSAFE_OP_IN_UNSAFE_FN, hir_id, span, - UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafeNameless { span }, + UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafeNameless { + span, + unsafe_not_inherited_note, + }, ), UseOfInlineAssembly => tcx.emit_spanned_lint( UNSAFE_OP_IN_UNSAFE_FN, hir_id, span, - UnsafeOpInUnsafeFnUseOfInlineAssemblyRequiresUnsafe { span }, + UnsafeOpInUnsafeFnUseOfInlineAssemblyRequiresUnsafe { + span, + unsafe_not_inherited_note, + }, ), InitializingTypeWith => tcx.emit_spanned_lint( UNSAFE_OP_IN_UNSAFE_FN, hir_id, span, - UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe { span }, + UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe { + span, + unsafe_not_inherited_note, + }, ), UseOfMutableStatic => tcx.emit_spanned_lint( UNSAFE_OP_IN_UNSAFE_FN, hir_id, span, - UnsafeOpInUnsafeFnUseOfMutableStaticRequiresUnsafe { span }, + UnsafeOpInUnsafeFnUseOfMutableStaticRequiresUnsafe { + span, + unsafe_not_inherited_note, + }, ), UseOfExternStatic => tcx.emit_spanned_lint( UNSAFE_OP_IN_UNSAFE_FN, hir_id, span, - UnsafeOpInUnsafeFnUseOfExternStaticRequiresUnsafe { span }, + UnsafeOpInUnsafeFnUseOfExternStaticRequiresUnsafe { + span, + unsafe_not_inherited_note, + }, ), DerefOfRawPointer => tcx.emit_spanned_lint( UNSAFE_OP_IN_UNSAFE_FN, hir_id, span, - UnsafeOpInUnsafeFnDerefOfRawPointerRequiresUnsafe { span }, + UnsafeOpInUnsafeFnDerefOfRawPointerRequiresUnsafe { + span, + unsafe_not_inherited_note, + }, ), AccessToUnionField => tcx.emit_spanned_lint( UNSAFE_OP_IN_UNSAFE_FN, hir_id, span, - UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe { span }, + UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe { + span, + unsafe_not_inherited_note, + }, ), MutationOfLayoutConstrainedField => tcx.emit_spanned_lint( UNSAFE_OP_IN_UNSAFE_FN, hir_id, span, - UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsafe { span }, + UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsafe { + span, + unsafe_not_inherited_note, + }, ), BorrowOfLayoutConstrainedField => tcx.emit_spanned_lint( UNSAFE_OP_IN_UNSAFE_FN, hir_id, span, - UnsafeOpInUnsafeFnBorrowOfLayoutConstrainedFieldRequiresUnsafe { span }, + UnsafeOpInUnsafeFnBorrowOfLayoutConstrainedFieldRequiresUnsafe { + span, + unsafe_not_inherited_note, + }, ), CallToFunctionWith(did) => tcx.emit_spanned_lint( UNSAFE_OP_IN_UNSAFE_FN, @@ -619,6 +673,7 @@ impl UnsafeOpKind { UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe { span, function: &with_no_trimmed_paths!(tcx.def_path_str(*did)), + unsafe_not_inherited_note, }, ), } @@ -833,6 +888,7 @@ pub fn thir_check_unsafety(tcx: TyCtxt<'_>, def: LocalDefId) { param_env: tcx.param_env(def), inside_adt: false, warnings: &mut warnings, + suggest_unsafe_block: true, }; visitor.visit_expr(&thir[expr]); diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index c4eed5532ee6..418f9bb9de94 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -29,6 +29,8 @@ pub struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafe<'a> { #[label] pub span: Span, pub function: &'a str, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] @@ -37,6 +39,8 @@ pub struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafe<'a> { pub struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafeNameless { #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] @@ -45,6 +49,8 @@ pub struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafeNameless { pub struct UnsafeOpInUnsafeFnUseOfInlineAssemblyRequiresUnsafe { #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] @@ -53,6 +59,8 @@ pub struct UnsafeOpInUnsafeFnUseOfInlineAssemblyRequiresUnsafe { pub struct UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe { #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] @@ -61,6 +69,8 @@ pub struct UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe { pub struct UnsafeOpInUnsafeFnUseOfMutableStaticRequiresUnsafe { #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] @@ -69,6 +79,8 @@ pub struct UnsafeOpInUnsafeFnUseOfMutableStaticRequiresUnsafe { pub struct UnsafeOpInUnsafeFnUseOfExternStaticRequiresUnsafe { #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] @@ -77,6 +89,8 @@ pub struct UnsafeOpInUnsafeFnUseOfExternStaticRequiresUnsafe { pub struct UnsafeOpInUnsafeFnDerefOfRawPointerRequiresUnsafe { #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] @@ -85,6 +99,8 @@ pub struct UnsafeOpInUnsafeFnDerefOfRawPointerRequiresUnsafe { pub struct UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe { #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] @@ -93,6 +109,8 @@ pub struct UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe { pub struct UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsafe { #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] @@ -100,6 +118,8 @@ pub struct UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsafe { pub struct UnsafeOpInUnsafeFnBorrowOfLayoutConstrainedFieldRequiresUnsafe { #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] @@ -109,6 +129,8 @@ pub struct UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe<'a> { #[label] pub span: Span, pub function: &'a str, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] @@ -376,6 +398,27 @@ pub struct UnsafeNotInheritedNote { pub span: Span, } +pub struct UnsafeNotInheritedLintNote { + pub signature_span: Span, + pub body_span: Span, +} + +impl AddToDiagnostic for UnsafeNotInheritedLintNote { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) + where + F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, + { + diag.span_note(self.signature_span, fluent::mir_build_unsafe_fn_safe_body); + let body_start = self.body_span.shrink_to_lo(); + let body_end = self.body_span.shrink_to_hi(); + diag.tool_only_multipart_suggestion( + fluent::mir_build_wrap_suggestion, + vec![(body_start, "{ unsafe ".into()), (body_end, "}".into())], + Applicability::MaybeIncorrect, + ); + } +} + #[derive(LintDiagnostic)] #[diag(mir_build_unused_unsafe)] pub struct UnusedUnsafe { diff --git a/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.stderr b/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.mir.stderr similarity index 80% rename from tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.stderr rename to tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.mir.stderr index fbc621f4d0e3..ea53bf59d310 100644 --- a/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.stderr +++ b/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.mir.stderr @@ -1,12 +1,12 @@ warning: call to unsafe function is unsafe and requires unsafe block (error E0133) - --> $DIR/edition-2024-unsafe_op_in_unsafe_fn.rs:12:5 + --> $DIR/edition-2024-unsafe_op_in_unsafe_fn.rs:13:5 | LL | unsf(); | ^^^^^^ call to unsafe function | = note: consult the function's documentation for information on how to avoid undefined behavior note: an unsafe function restricts its caller, but its body is safe by default - --> $DIR/edition-2024-unsafe_op_in_unsafe_fn.rs:11:1 + --> $DIR/edition-2024-unsafe_op_in_unsafe_fn.rs:12:1 | LL | unsafe fn foo() { | ^^^^^^^^^^^^^^^ diff --git a/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.rs b/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.rs index a192f3445f73..1b429955cb03 100644 --- a/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.rs +++ b/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.rs @@ -1,17 +1,21 @@ // edition: 2024 // compile-flags: -Zunstable-options // check-pass +// revisions: mir thir +// [thir]compile-flags: -Zthir-unsafeck #![crate_type = "lib"] - #![deny(unused_unsafe)] unsafe fn unsf() {} unsafe fn foo() { unsf(); - //~^ WARN call to unsafe function is unsafe and requires unsafe block + //[mir]~^ WARN call to unsafe function is unsafe and requires unsafe block + //[thir]~^^ WARN call to unsafe function `unsf` is unsafe and requires unsafe block // no unused_unsafe - unsafe { unsf(); } + unsafe { + unsf(); + } } diff --git a/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.thir.stderr b/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.thir.stderr new file mode 100644 index 000000000000..d63843ed2b36 --- /dev/null +++ b/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.thir.stderr @@ -0,0 +1,16 @@ +warning: call to unsafe function `unsf` is unsafe and requires unsafe block (error E0133) + --> $DIR/edition-2024-unsafe_op_in_unsafe_fn.rs:13:5 + | +LL | unsf(); + | ^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior +note: an unsafe function restricts its caller, but its body is safe by default + --> $DIR/edition-2024-unsafe_op_in_unsafe_fn.rs:12:1 + | +LL | unsafe fn foo() { + | ^^^^^^^^^^^^^^^ + = note: `#[warn(unsafe_op_in_unsafe_fn)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.thir.stderr b/tests/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.thir.stderr index 4cdd97e5e06a..ad0621a1d043 100644 --- a/tests/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.thir.stderr +++ b/tests/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.thir.stderr @@ -5,6 +5,11 @@ LL | unsf(); | ^^^^^^ call to unsafe function | = note: consult the function's documentation for information on how to avoid undefined behavior +note: an unsafe function restricts its caller, but its body is safe by default + --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:11:1 + | +LL | unsafe fn deny_level() { + | ^^^^^^^^^^^^^^^^^^^^^^ note: the lint level is defined here --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:4:9 | @@ -46,6 +51,11 @@ LL | unsf(); | ^^^^^^ call to unsafe function | = note: consult the function's documentation for information on how to avoid undefined behavior +note: an unsafe function restricts its caller, but its body is safe by default + --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:27:1 + | +LL | unsafe fn warning_level() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ note: the lint level is defined here --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:26:8 | diff --git a/tests/ui/unsafe/wrapping-unsafe-block-sugg.fixed b/tests/ui/unsafe/wrapping-unsafe-block-sugg.mir.fixed similarity index 73% rename from tests/ui/unsafe/wrapping-unsafe-block-sugg.fixed rename to tests/ui/unsafe/wrapping-unsafe-block-sugg.mir.fixed index db1c102210e3..b59029df6429 100644 --- a/tests/ui/unsafe/wrapping-unsafe-block-sugg.fixed +++ b/tests/ui/unsafe/wrapping-unsafe-block-sugg.mir.fixed @@ -1,7 +1,10 @@ // run-rustfix // aux-build:external_unsafe_macro.rs +// revisions: mir thir +// [thir]compile-flags: -Zthir-unsafeck #![deny(unsafe_op_in_unsafe_fn)] //~ NOTE +#![crate_name = "wrapping_unsafe_block_sugg"] extern crate external_unsafe_macro; @@ -9,11 +12,13 @@ unsafe fn unsf() {} pub unsafe fn foo() { unsafe { //~^ NOTE an unsafe function restricts its caller, but its body is safe by default - unsf(); //~ ERROR call to unsafe function is unsafe - //~^ NOTE + unsf(); //[mir]~ ERROR call to unsafe function is unsafe + //[thir]~^ ERROR call to unsafe function `unsf` is unsafe + //~^^ NOTE //~| NOTE - unsf(); //~ ERROR call to unsafe function is unsafe - //~^ NOTE + unsf(); //[mir]~ ERROR call to unsafe function is unsafe + //[thir]~^ ERROR call to unsafe function `unsf` is unsafe + //~^^ NOTE //~| NOTE }} @@ -39,10 +44,12 @@ pub unsafe fn baz() -> i32 { unsafe { }} macro_rules! unsafe_macro { () => (unsf()) } -//~^ ERROR call to unsafe function is unsafe +//[mir]~^ ERROR call to unsafe function is unsafe +//[thir]~^^ ERROR call to unsafe function `unsf` is unsafe //~| NOTE //~| NOTE -//~| ERROR call to unsafe function is unsafe +//[mir]~| ERROR call to unsafe function is unsafe +//[thir]~| ERROR call to unsafe function `unsf` is unsafe //~| NOTE //~| NOTE diff --git a/tests/ui/unsafe/wrapping-unsafe-block-sugg.stderr b/tests/ui/unsafe/wrapping-unsafe-block-sugg.mir.stderr similarity index 86% rename from tests/ui/unsafe/wrapping-unsafe-block-sugg.stderr rename to tests/ui/unsafe/wrapping-unsafe-block-sugg.mir.stderr index 43f619c27d27..7a1b83c7367d 100644 --- a/tests/ui/unsafe/wrapping-unsafe-block-sugg.stderr +++ b/tests/ui/unsafe/wrapping-unsafe-block-sugg.mir.stderr @@ -1,21 +1,3 @@ -error: call to unsafe function is unsafe and requires unsafe block (error E0133) - --> $DIR/wrapping-unsafe-block-sugg.rs:12:5 - | -LL | unsf(); - | ^^^^^^ call to unsafe function - | - = note: consult the function's documentation for information on how to avoid undefined behavior -note: an unsafe function restricts its caller, but its body is safe by default - --> $DIR/wrapping-unsafe-block-sugg.rs:10:1 - | -LL | pub unsafe fn foo() { - | ^^^^^^^^^^^^^^^^^^^ -note: the lint level is defined here - --> $DIR/wrapping-unsafe-block-sugg.rs:4:9 - | -LL | #![deny(unsafe_op_in_unsafe_fn)] - | ^^^^^^^^^^^^^^^^^^^^^^ - error: call to unsafe function is unsafe and requires unsafe block (error E0133) --> $DIR/wrapping-unsafe-block-sugg.rs:15:5 | @@ -23,22 +5,40 @@ LL | unsf(); | ^^^^^^ call to unsafe function | = note: consult the function's documentation for information on how to avoid undefined behavior +note: an unsafe function restricts its caller, but its body is safe by default + --> $DIR/wrapping-unsafe-block-sugg.rs:13:1 + | +LL | pub unsafe fn foo() { + | ^^^^^^^^^^^^^^^^^^^ +note: the lint level is defined here + --> $DIR/wrapping-unsafe-block-sugg.rs:6:9 + | +LL | #![deny(unsafe_op_in_unsafe_fn)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: call to unsafe function is unsafe and requires unsafe block (error E0133) + --> $DIR/wrapping-unsafe-block-sugg.rs:19:5 + | +LL | unsf(); + | ^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior error: dereference of raw pointer is unsafe and requires unsafe block (error E0133) - --> $DIR/wrapping-unsafe-block-sugg.rs:22:13 + --> $DIR/wrapping-unsafe-block-sugg.rs:27:13 | LL | let y = *x; | ^^ dereference of raw pointer | = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior note: an unsafe function restricts its caller, but its body is safe by default - --> $DIR/wrapping-unsafe-block-sugg.rs:20:1 + --> $DIR/wrapping-unsafe-block-sugg.rs:25:1 | LL | pub unsafe fn bar(x: *const i32) -> i32 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: dereference of raw pointer is unsafe and requires unsafe block (error E0133) - --> $DIR/wrapping-unsafe-block-sugg.rs:25:9 + --> $DIR/wrapping-unsafe-block-sugg.rs:30:9 | LL | y + *x | ^^ dereference of raw pointer @@ -46,20 +46,20 @@ LL | y + *x = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior error: use of mutable static is unsafe and requires unsafe block (error E0133) - --> $DIR/wrapping-unsafe-block-sugg.rs:33:13 + --> $DIR/wrapping-unsafe-block-sugg.rs:38:13 | LL | let y = BAZ; | ^^^ use of mutable static | = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior note: an unsafe function restricts its caller, but its body is safe by default - --> $DIR/wrapping-unsafe-block-sugg.rs:31:1 + --> $DIR/wrapping-unsafe-block-sugg.rs:36:1 | LL | pub unsafe fn baz() -> i32 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of mutable static is unsafe and requires unsafe block (error E0133) - --> $DIR/wrapping-unsafe-block-sugg.rs:36:9 + --> $DIR/wrapping-unsafe-block-sugg.rs:41:9 | LL | y + BAZ | ^^^ use of mutable static @@ -67,7 +67,7 @@ LL | y + BAZ = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior error: call to unsafe function is unsafe and requires unsafe block (error E0133) - --> $DIR/wrapping-unsafe-block-sugg.rs:41:36 + --> $DIR/wrapping-unsafe-block-sugg.rs:46:36 | LL | macro_rules! unsafe_macro { () => (unsf()) } | ^^^^^^ call to unsafe function @@ -77,14 +77,14 @@ LL | unsafe_macro!(); | = note: consult the function's documentation for information on how to avoid undefined behavior note: an unsafe function restricts its caller, but its body is safe by default - --> $DIR/wrapping-unsafe-block-sugg.rs:49:1 + --> $DIR/wrapping-unsafe-block-sugg.rs:56:1 | LL | pub unsafe fn unsafe_in_macro() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the macro `unsafe_macro` (in Nightly builds, run with -Z macro-backtrace for more info) error: call to unsafe function is unsafe and requires unsafe block (error E0133) - --> $DIR/wrapping-unsafe-block-sugg.rs:41:36 + --> $DIR/wrapping-unsafe-block-sugg.rs:46:36 | LL | macro_rules! unsafe_macro { () => (unsf()) } | ^^^^^^ call to unsafe function diff --git a/tests/ui/unsafe/wrapping-unsafe-block-sugg.rs b/tests/ui/unsafe/wrapping-unsafe-block-sugg.rs index 9c6be45896e2..3629b8a1beb5 100644 --- a/tests/ui/unsafe/wrapping-unsafe-block-sugg.rs +++ b/tests/ui/unsafe/wrapping-unsafe-block-sugg.rs @@ -1,7 +1,10 @@ // run-rustfix // aux-build:external_unsafe_macro.rs +// revisions: mir thir +// [thir]compile-flags: -Zthir-unsafeck #![deny(unsafe_op_in_unsafe_fn)] //~ NOTE +#![crate_name = "wrapping_unsafe_block_sugg"] extern crate external_unsafe_macro; @@ -9,11 +12,13 @@ unsafe fn unsf() {} pub unsafe fn foo() { //~^ NOTE an unsafe function restricts its caller, but its body is safe by default - unsf(); //~ ERROR call to unsafe function is unsafe - //~^ NOTE + unsf(); //[mir]~ ERROR call to unsafe function is unsafe + //[thir]~^ ERROR call to unsafe function `unsf` is unsafe + //~^^ NOTE //~| NOTE - unsf(); //~ ERROR call to unsafe function is unsafe - //~^ NOTE + unsf(); //[mir]~ ERROR call to unsafe function is unsafe + //[thir]~^ ERROR call to unsafe function `unsf` is unsafe + //~^^ NOTE //~| NOTE } @@ -39,10 +44,12 @@ pub unsafe fn baz() -> i32 { } macro_rules! unsafe_macro { () => (unsf()) } -//~^ ERROR call to unsafe function is unsafe +//[mir]~^ ERROR call to unsafe function is unsafe +//[thir]~^^ ERROR call to unsafe function `unsf` is unsafe //~| NOTE //~| NOTE -//~| ERROR call to unsafe function is unsafe +//[mir]~| ERROR call to unsafe function is unsafe +//[thir]~| ERROR call to unsafe function `unsf` is unsafe //~| NOTE //~| NOTE diff --git a/tests/ui/unsafe/wrapping-unsafe-block-sugg.thir.fixed b/tests/ui/unsafe/wrapping-unsafe-block-sugg.thir.fixed new file mode 100644 index 000000000000..b59029df6429 --- /dev/null +++ b/tests/ui/unsafe/wrapping-unsafe-block-sugg.thir.fixed @@ -0,0 +1,73 @@ +// run-rustfix +// aux-build:external_unsafe_macro.rs +// revisions: mir thir +// [thir]compile-flags: -Zthir-unsafeck + +#![deny(unsafe_op_in_unsafe_fn)] //~ NOTE +#![crate_name = "wrapping_unsafe_block_sugg"] + +extern crate external_unsafe_macro; + +unsafe fn unsf() {} + +pub unsafe fn foo() { unsafe { + //~^ NOTE an unsafe function restricts its caller, but its body is safe by default + unsf(); //[mir]~ ERROR call to unsafe function is unsafe + //[thir]~^ ERROR call to unsafe function `unsf` is unsafe + //~^^ NOTE + //~| NOTE + unsf(); //[mir]~ ERROR call to unsafe function is unsafe + //[thir]~^ ERROR call to unsafe function `unsf` is unsafe + //~^^ NOTE + //~| NOTE +}} + +pub unsafe fn bar(x: *const i32) -> i32 { unsafe { + //~^ NOTE an unsafe function restricts its caller, but its body is safe by default + let y = *x; //~ ERROR dereference of raw pointer is unsafe and requires unsafe block + //~^ NOTE + //~| NOTE + y + *x //~ ERROR dereference of raw pointer is unsafe and requires unsafe block + //~^ NOTE + //~| NOTE +}} + +static mut BAZ: i32 = 0; +pub unsafe fn baz() -> i32 { unsafe { + //~^ NOTE an unsafe function restricts its caller, but its body is safe by default + let y = BAZ; //~ ERROR use of mutable static is unsafe and requires unsafe block + //~^ NOTE + //~| NOTE + y + BAZ //~ ERROR use of mutable static is unsafe and requires unsafe block + //~^ NOTE + //~| NOTE +}} + +macro_rules! unsafe_macro { () => (unsf()) } +//[mir]~^ ERROR call to unsafe function is unsafe +//[thir]~^^ ERROR call to unsafe function `unsf` is unsafe +//~| NOTE +//~| NOTE +//[mir]~| ERROR call to unsafe function is unsafe +//[thir]~| ERROR call to unsafe function `unsf` is unsafe +//~| NOTE +//~| NOTE + +pub unsafe fn unsafe_in_macro() { unsafe { + //~^ NOTE an unsafe function restricts its caller, but its body is safe by default + unsafe_macro!(); + //~^ NOTE + //~| NOTE + unsafe_macro!(); + //~^ NOTE + //~| NOTE +}} + +pub unsafe fn unsafe_in_external_macro() { + // FIXME: https://github.com/rust-lang/rust/issues/112504 + // FIXME: ~^ NOTE an unsafe function restricts its caller, but its body is safe by default + external_unsafe_macro::unsafe_macro!(); + external_unsafe_macro::unsafe_macro!(); +} + +fn main() {} diff --git a/tests/ui/unsafe/wrapping-unsafe-block-sugg.thir.stderr b/tests/ui/unsafe/wrapping-unsafe-block-sugg.thir.stderr new file mode 100644 index 000000000000..b1fb35f85a60 --- /dev/null +++ b/tests/ui/unsafe/wrapping-unsafe-block-sugg.thir.stderr @@ -0,0 +1,99 @@ +error: call to unsafe function `unsf` is unsafe and requires unsafe block (error E0133) + --> $DIR/wrapping-unsafe-block-sugg.rs:15:5 + | +LL | unsf(); + | ^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior +note: an unsafe function restricts its caller, but its body is safe by default + --> $DIR/wrapping-unsafe-block-sugg.rs:13:1 + | +LL | pub unsafe fn foo() { + | ^^^^^^^^^^^^^^^^^^^ +note: the lint level is defined here + --> $DIR/wrapping-unsafe-block-sugg.rs:6:9 + | +LL | #![deny(unsafe_op_in_unsafe_fn)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: call to unsafe function `unsf` is unsafe and requires unsafe block (error E0133) + --> $DIR/wrapping-unsafe-block-sugg.rs:19:5 + | +LL | unsf(); + | ^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: dereference of raw pointer is unsafe and requires unsafe block (error E0133) + --> $DIR/wrapping-unsafe-block-sugg.rs:27:13 + | +LL | let y = *x; + | ^^ dereference of raw pointer + | + = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior +note: an unsafe function restricts its caller, but its body is safe by default + --> $DIR/wrapping-unsafe-block-sugg.rs:25:1 + | +LL | pub unsafe fn bar(x: *const i32) -> i32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: dereference of raw pointer is unsafe and requires unsafe block (error E0133) + --> $DIR/wrapping-unsafe-block-sugg.rs:30:9 + | +LL | y + *x + | ^^ dereference of raw pointer + | + = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior + +error: use of mutable static is unsafe and requires unsafe block (error E0133) + --> $DIR/wrapping-unsafe-block-sugg.rs:38:13 + | +LL | let y = BAZ; + | ^^^ use of mutable static + | + = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior +note: an unsafe function restricts its caller, but its body is safe by default + --> $DIR/wrapping-unsafe-block-sugg.rs:36:1 + | +LL | pub unsafe fn baz() -> i32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: use of mutable static is unsafe and requires unsafe block (error E0133) + --> $DIR/wrapping-unsafe-block-sugg.rs:41:9 + | +LL | y + BAZ + | ^^^ use of mutable static + | + = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior + +error: call to unsafe function `unsf` is unsafe and requires unsafe block (error E0133) + --> $DIR/wrapping-unsafe-block-sugg.rs:46:36 + | +LL | macro_rules! unsafe_macro { () => (unsf()) } + | ^^^^^^ call to unsafe function +... +LL | unsafe_macro!(); + | --------------- in this macro invocation + | + = note: consult the function's documentation for information on how to avoid undefined behavior +note: an unsafe function restricts its caller, but its body is safe by default + --> $DIR/wrapping-unsafe-block-sugg.rs:56:1 + | +LL | pub unsafe fn unsafe_in_macro() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: this error originates in the macro `unsafe_macro` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: call to unsafe function `unsf` is unsafe and requires unsafe block (error E0133) + --> $DIR/wrapping-unsafe-block-sugg.rs:46:36 + | +LL | macro_rules! unsafe_macro { () => (unsf()) } + | ^^^^^^ call to unsafe function +... +LL | unsafe_macro!(); + | --------------- in this macro invocation + | + = note: consult the function's documentation for information on how to avoid undefined behavior + = note: this error originates in the macro `unsafe_macro` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 8 previous errors + From 868de8e76bbc6ae1a2b857ff2cdf5dc5cab0eadd Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Tue, 31 Oct 2023 15:47:18 +0000 Subject: [PATCH 289/435] Visit patterns in THIR let expressions This fixes some THIR unsafety checking errors not being emitted for let expressions in these situations. --- compiler/rustc_middle/src/thir/visit.rs | 3 +- .../rustc_mir_build/src/check_unsafety.rs | 8 ----- tests/ui/union/union-unsafe.mir.stderr | 28 ++++++++++------- tests/ui/union/union-unsafe.rs | 14 +++++---- tests/ui/union/union-unsafe.thir.stderr | 30 ++++++++++++------- .../ui/unsafe/ranged_ints2.mirunsafeck.stderr | 10 ++++++- tests/ui/unsafe/ranged_ints2.rs | 1 + .../unsafe/ranged_ints2.thirunsafeck.stderr | 10 ++++++- 8 files changed, 66 insertions(+), 38 deletions(-) diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs index d03d92c3a4b8..8feefb4c03cc 100644 --- a/compiler/rustc_middle/src/thir/visit.rs +++ b/compiler/rustc_middle/src/thir/visit.rs @@ -66,8 +66,9 @@ pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Exp Use { source } => visitor.visit_expr(&visitor.thir()[source]), NeverToAny { source } => visitor.visit_expr(&visitor.thir()[source]), PointerCoercion { source, cast: _ } => visitor.visit_expr(&visitor.thir()[source]), - Let { expr, .. } => { + Let { expr, ref pat } => { visitor.visit_expr(&visitor.thir()[expr]); + visitor.visit_pat(pat); } Loop { body } => visitor.visit_expr(&visitor.thir()[body]), Match { scrutinee, ref arms, .. } => { diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 373ed61ff879..3d895c131a85 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -495,14 +495,6 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { } } } - ExprKind::Let { expr: expr_id, .. } => { - let let_expr = &self.thir[expr_id]; - if let ty::Adt(adt_def, _) = let_expr.ty.kind() - && adt_def.is_union() - { - self.requires_unsafe(expr.span, AccessToUnionField); - } - } _ => {} } visit::walk_expr(self, expr); diff --git a/tests/ui/union/union-unsafe.mir.stderr b/tests/ui/union/union-unsafe.mir.stderr index 544213dbc554..15f059ffa487 100644 --- a/tests/ui/union/union-unsafe.mir.stderr +++ b/tests/ui/union/union-unsafe.mir.stderr @@ -1,5 +1,5 @@ error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:33:5 + --> $DIR/union-unsafe.rs:34:5 | LL | *(u.p) = 13; | ^^^^^^^^^^^ access to union field @@ -7,7 +7,7 @@ LL | *(u.p) = 13; = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:46:6 + --> $DIR/union-unsafe.rs:47:6 | LL | *u3.a = T::default(); | ^^^^ access to union field @@ -15,7 +15,7 @@ LL | *u3.a = T::default(); = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:52:6 + --> $DIR/union-unsafe.rs:53:6 | LL | *u3.a = T::default(); | ^^^^ access to union field @@ -23,7 +23,7 @@ LL | *u3.a = T::default(); = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:60:13 + --> $DIR/union-unsafe.rs:61:13 | LL | let a = u1.a; | ^^^^ access to union field @@ -31,7 +31,7 @@ LL | let a = u1.a; = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:63:14 + --> $DIR/union-unsafe.rs:64:14 | LL | let U1 { a } = u1; | ^ access to union field @@ -39,7 +39,7 @@ LL | let U1 { a } = u1; = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:64:12 + --> $DIR/union-unsafe.rs:65:12 | LL | if let U1 { a: 12 } = u1 {} | ^^^^^^^^^^^^ access to union field @@ -47,7 +47,15 @@ LL | if let U1 { a: 12 } = u1 {} = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:69:6 + --> $DIR/union-unsafe.rs:66:12 + | +LL | if let Some(U1 { a: 13 }) = Some(u1) {} + | ^^^^^^^^^^^^^^^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union-unsafe.rs:71:6 | LL | *u2.a = String::from("new"); | ^^^^ access to union field @@ -55,7 +63,7 @@ LL | *u2.a = String::from("new"); = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:73:6 + --> $DIR/union-unsafe.rs:75:6 | LL | *u3.a = 1; | ^^^^ access to union field @@ -63,13 +71,13 @@ LL | *u3.a = 1; = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:77:6 + --> $DIR/union-unsafe.rs:79:6 | LL | *u3.a = String::from("new"); | ^^^^ access to union field | = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior -error: aborting due to 9 previous errors +error: aborting due to 10 previous errors For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/union/union-unsafe.rs b/tests/ui/union/union-unsafe.rs index 5e1837a901d4..d1465486f778 100644 --- a/tests/ui/union/union-unsafe.rs +++ b/tests/ui/union/union-unsafe.rs @@ -1,30 +1,31 @@ // revisions: mir thir // [thir]compile-flags: -Z thir-unsafeck -use std::mem::ManuallyDrop; use std::cell::RefCell; +use std::mem::ManuallyDrop; union U1 { - a: u8 + a: u8, } union U2 { - a: ManuallyDrop + a: ManuallyDrop, } union U3 { - a: ManuallyDrop + a: ManuallyDrop, } union U4 { - a: T + a: T, } union URef { p: &'static mut i32, } -union URefCell { // field that does not drop but is not `Copy`, either +union URefCell { + // field that does not drop but is not `Copy`, either a: (ManuallyDrop>, i32), } @@ -62,6 +63,7 @@ fn main() { let U1 { a } = u1; //~ ERROR access to union field is unsafe if let U1 { a: 12 } = u1 {} //~ ERROR access to union field is unsafe + if let Some(U1 { a: 13 }) = Some(u1) {} //~ ERROR access to union field is unsafe // let U1 { .. } = u1; // OK let mut u2 = U2 { a: ManuallyDrop::new(String::from("old")) }; // OK diff --git a/tests/ui/union/union-unsafe.thir.stderr b/tests/ui/union/union-unsafe.thir.stderr index f959fe5bdb5c..9ce835497c51 100644 --- a/tests/ui/union/union-unsafe.thir.stderr +++ b/tests/ui/union/union-unsafe.thir.stderr @@ -1,5 +1,5 @@ error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:33:6 + --> $DIR/union-unsafe.rs:34:6 | LL | *(u.p) = 13; | ^^^^^ access to union field @@ -7,7 +7,7 @@ LL | *(u.p) = 13; = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:46:6 + --> $DIR/union-unsafe.rs:47:6 | LL | *u3.a = T::default(); | ^^^^ access to union field @@ -15,7 +15,7 @@ LL | *u3.a = T::default(); = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:52:6 + --> $DIR/union-unsafe.rs:53:6 | LL | *u3.a = T::default(); | ^^^^ access to union field @@ -23,7 +23,7 @@ LL | *u3.a = T::default(); = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:60:13 + --> $DIR/union-unsafe.rs:61:13 | LL | let a = u1.a; | ^^^^ access to union field @@ -31,7 +31,7 @@ LL | let a = u1.a; = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:63:14 + --> $DIR/union-unsafe.rs:64:14 | LL | let U1 { a } = u1; | ^ access to union field @@ -39,15 +39,23 @@ LL | let U1 { a } = u1; = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:64:8 + --> $DIR/union-unsafe.rs:65:20 | LL | if let U1 { a: 12 } = u1 {} - | ^^^^^^^^^^^^^^^^^^^^^ access to union field + | ^^ access to union field | = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:69:6 + --> $DIR/union-unsafe.rs:66:25 + | +LL | if let Some(U1 { a: 13 }) = Some(u1) {} + | ^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union-unsafe.rs:71:6 | LL | *u2.a = String::from("new"); | ^^^^ access to union field @@ -55,7 +63,7 @@ LL | *u2.a = String::from("new"); = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:73:6 + --> $DIR/union-unsafe.rs:75:6 | LL | *u3.a = 1; | ^^^^ access to union field @@ -63,13 +71,13 @@ LL | *u3.a = 1; = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:77:6 + --> $DIR/union-unsafe.rs:79:6 | LL | *u3.a = String::from("new"); | ^^^^ access to union field | = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior -error: aborting due to 9 previous errors +error: aborting due to 10 previous errors For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/ranged_ints2.mirunsafeck.stderr b/tests/ui/unsafe/ranged_ints2.mirunsafeck.stderr index 427843f8d45c..dc6bd72f56c5 100644 --- a/tests/ui/unsafe/ranged_ints2.mirunsafeck.stderr +++ b/tests/ui/unsafe/ranged_ints2.mirunsafeck.stderr @@ -6,6 +6,14 @@ LL | let y = &mut x.0; | = note: mutating layout constrained fields cannot statically be checked for valid values -error: aborting due to previous error +error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block + --> $DIR/ranged_ints2.rs:12:25 + | +LL | if let Some(NonZero(ref mut y)) = Some(x) {} + | ^^^^^^^^^ mutation of layout constrained field + | + = note: mutating layout constrained fields cannot statically be checked for valid values + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/ranged_ints2.rs b/tests/ui/unsafe/ranged_ints2.rs index 9a6bb18f9266..ad9d598aba2a 100644 --- a/tests/ui/unsafe/ranged_ints2.rs +++ b/tests/ui/unsafe/ranged_ints2.rs @@ -9,4 +9,5 @@ pub(crate) struct NonZero(pub(crate) T); fn main() { let mut x = unsafe { NonZero(1) }; let y = &mut x.0; //~ ERROR mutation of layout constrained field is unsafe + if let Some(NonZero(ref mut y)) = Some(x) {} //~ ERROR mutation of layout constrained field is unsafe } diff --git a/tests/ui/unsafe/ranged_ints2.thirunsafeck.stderr b/tests/ui/unsafe/ranged_ints2.thirunsafeck.stderr index 427843f8d45c..dc6bd72f56c5 100644 --- a/tests/ui/unsafe/ranged_ints2.thirunsafeck.stderr +++ b/tests/ui/unsafe/ranged_ints2.thirunsafeck.stderr @@ -6,6 +6,14 @@ LL | let y = &mut x.0; | = note: mutating layout constrained fields cannot statically be checked for valid values -error: aborting due to previous error +error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block + --> $DIR/ranged_ints2.rs:12:25 + | +LL | if let Some(NonZero(ref mut y)) = Some(x) {} + | ^^^^^^^^^ mutation of layout constrained field + | + = note: mutating layout constrained fields cannot statically be checked for valid values + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0133`. From bf65e3bddbbcb94479af6c35542138c848bb359c Mon Sep 17 00:00:00 2001 From: rustbot <47979223+rustbot@users.noreply.github.com> Date: Mon, 6 Nov 2023 12:00:35 -0500 Subject: [PATCH 290/435] Update books --- src/doc/reference | 2 +- src/doc/rust-by-example | 2 +- src/doc/rustc-dev-guide | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/doc/reference b/src/doc/reference index 16fd3c06d9e5..cd8193e972f6 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 16fd3c06d9e558dae2d52000818274ae70c9e90a +Subproject commit cd8193e972f61b92117095fc73b67af767b4d6bc diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index 6709beeb7d0f..311b84962016 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit 6709beeb7d0fbc5ffc91ac4893a24434123b9bfa +Subproject commit 311b84962016b28c75525c86e7b3f49fd9101a39 diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide index b0ee9ec8fa59..77dbe5782b24 160000 --- a/src/doc/rustc-dev-guide +++ b/src/doc/rustc-dev-guide @@ -1 +1 @@ -Subproject commit b0ee9ec8fa59a6c7620165e061f4747202377a62 +Subproject commit 77dbe5782b2488af3bb489ad702eaff438f465bf From 4b7aacaa4f5b2a5ceb05584f18b1a20f2572efa0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 27 Oct 2023 17:27:21 +0000 Subject: [PATCH 291/435] Silence redundant error on typo resulting on binop --- compiler/rustc_hir_typeck/src/expr.rs | 8 +++++++- compiler/rustc_hir_typeck/src/op.rs | 19 +++++------------- .../false-binop-caused-by-missing-semi.fixed | 10 ++++++++++ .../false-binop-caused-by-missing-semi.rs | 3 ++- .../false-binop-caused-by-missing-semi.stderr | 20 +++---------------- 5 files changed, 27 insertions(+), 33 deletions(-) create mode 100644 tests/ui/binop/false-binop-caused-by-missing-semi.fixed diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 9a2f242ec4e1..76d1b27e7e39 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -961,7 +961,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } /// Check if the expression that could not be assigned to was a typoed expression that - fn check_for_missing_semi(&self, expr: &'tcx hir::Expr<'tcx>, err: &mut Diagnostic) { + pub fn check_for_missing_semi( + &self, + expr: &'tcx hir::Expr<'tcx>, + err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>, + ) -> bool { if let hir::ExprKind::Binary(binop, lhs, rhs) = expr.kind && let hir::BinOpKind::Mul = binop.node && self.tcx.sess.source_map().is_multiline(lhs.span.between(rhs.span)) @@ -977,7 +981,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ";".to_string(), Applicability::MachineApplicable, ); + return true; } + false } // Check if an expression `original_expr_id` comes from the condition of a while loop, diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs index 92075c7832a9..f40406c67265 100644 --- a/compiler/rustc_hir_typeck/src/op.rs +++ b/compiler/rustc_hir_typeck/src/op.rs @@ -379,21 +379,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (err, output_def_id) } }; - if self.tcx.sess.source_map().is_multiline(lhs_expr.span.between(rhs_expr.span)) - && let IsAssign::No = is_assign - && let hir::BinOpKind::Mul = op.node - && rhs_expr.is_syntactic_place_expr() + if self.check_for_missing_semi(expr, &mut err) + && let hir::Node::Expr(expr) = self.tcx.hir().get_parent(expr.hir_id) + && let hir::ExprKind::Assign(..) = expr.kind { - // v missing semicolon here - // foo() - // *bar = baz; - // (#80446). - err.span_suggestion_verbose( - lhs_expr.span.shrink_to_hi(), - "you might have meant to write a semicolon here", - ";".to_string(), - Applicability::MaybeIncorrect, - ); + // We defer to the later error produced by `check_lhs_assignable`. + err.delay_as_bug(); } let suggest_deref_binop = diff --git a/tests/ui/binop/false-binop-caused-by-missing-semi.fixed b/tests/ui/binop/false-binop-caused-by-missing-semi.fixed new file mode 100644 index 000000000000..b47372c90648 --- /dev/null +++ b/tests/ui/binop/false-binop-caused-by-missing-semi.fixed @@ -0,0 +1,10 @@ +// run-rustfix +fn foo() {} +fn main() { + let mut y = 42; + let x = &mut y; + foo(); + *x = 0; //~ ERROR invalid left-hand side of assignment + let _ = x; + println!("{y}"); +} diff --git a/tests/ui/binop/false-binop-caused-by-missing-semi.rs b/tests/ui/binop/false-binop-caused-by-missing-semi.rs index 9cd32e1db500..14671de7e511 100644 --- a/tests/ui/binop/false-binop-caused-by-missing-semi.rs +++ b/tests/ui/binop/false-binop-caused-by-missing-semi.rs @@ -1,9 +1,10 @@ +// run-rustfix fn foo() {} fn main() { let mut y = 42; let x = &mut y; foo() *x = 0; //~ ERROR invalid left-hand side of assignment - //~^ ERROR cannot multiply `()` by `&mut {integer}` + let _ = x; println!("{y}"); } diff --git a/tests/ui/binop/false-binop-caused-by-missing-semi.stderr b/tests/ui/binop/false-binop-caused-by-missing-semi.stderr index 8d0f15fe2ea1..fca042b1c57d 100644 --- a/tests/ui/binop/false-binop-caused-by-missing-semi.stderr +++ b/tests/ui/binop/false-binop-caused-by-missing-semi.stderr @@ -1,18 +1,5 @@ -error[E0369]: cannot multiply `()` by `&mut {integer}` - --> $DIR/false-binop-caused-by-missing-semi.rs:6:5 - | -LL | foo() - | ----- () -LL | *x = 0; - | ^- &mut {integer} - | -help: you might have meant to write a semicolon here - | -LL | foo(); - | + - error[E0070]: invalid left-hand side of assignment - --> $DIR/false-binop-caused-by-missing-semi.rs:6:8 + --> $DIR/false-binop-caused-by-missing-semi.rs:7:8 | LL | / foo() LL | | *x = 0; @@ -25,7 +12,6 @@ help: you might have meant to write a semicolon here LL | foo(); | + -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0070, E0369. -For more information about an error, try `rustc --explain E0070`. +For more information about this error, try `rustc --explain E0070`. From c17d33f1df9492ad993da3d8b0ddfcfe08bd652e Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 6 Nov 2023 21:29:08 +0000 Subject: [PATCH 292/435] Extend builtin/auto trait args with error when they have >1 argument --- .../src/traits/select/mod.rs | 21 +++++++++++++------ tests/ui/auto-traits/has-arguments.rs | 10 +++++++++ tests/ui/auto-traits/has-arguments.stderr | 11 ++++++++++ 3 files changed, 36 insertions(+), 6 deletions(-) create mode 100644 tests/ui/auto-traits/has-arguments.rs create mode 100644 tests/ui/auto-traits/has-arguments.stderr diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index cf52e6726a17..08208cc60475 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2389,12 +2389,21 @@ impl<'tcx> SelectionContext<'_, 'tcx> { ) }); - let obligation = Obligation::new( - self.tcx(), - cause.clone(), - param_env, - ty::TraitRef::new(self.tcx(), trait_def_id, [normalized_ty]), - ); + let tcx = self.tcx(); + let trait_ref = if tcx.generics_of(trait_def_id).params.len() == 1 { + ty::TraitRef::new(tcx, trait_def_id, [normalized_ty]) + } else { + // If this is an ill-formed auto/built-in trait, then synthesize + // new error args for the missing generics. + let err_args = ty::GenericArgs::extend_with_error( + tcx, + trait_def_id, + &[normalized_ty.into()], + ); + ty::TraitRef::new(tcx, trait_def_id, err_args) + }; + + let obligation = Obligation::new(self.tcx(), cause.clone(), param_env, trait_ref); obligations.push(obligation); obligations }) diff --git a/tests/ui/auto-traits/has-arguments.rs b/tests/ui/auto-traits/has-arguments.rs new file mode 100644 index 000000000000..f579eb6772d4 --- /dev/null +++ b/tests/ui/auto-traits/has-arguments.rs @@ -0,0 +1,10 @@ +#![feature(auto_traits)] + +auto trait Trait1<'outer> {} +//~^ ERROR auto traits cannot have generic parameters + +fn f<'a>(x: impl Trait1<'a>) {} + +fn main() { + f(""); +} diff --git a/tests/ui/auto-traits/has-arguments.stderr b/tests/ui/auto-traits/has-arguments.stderr new file mode 100644 index 000000000000..3bba74badbce --- /dev/null +++ b/tests/ui/auto-traits/has-arguments.stderr @@ -0,0 +1,11 @@ +error[E0567]: auto traits cannot have generic parameters + --> $DIR/has-arguments.rs:3:18 + | +LL | auto trait Trait1<'outer> {} + | ------^^^^^^^^ help: remove the parameters + | | + | auto trait cannot have generic parameters + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0567`. From 24e14dd8b40a2434fc2343342c30d8d5748d1c5a Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 5 Nov 2023 13:36:00 +0000 Subject: [PATCH 293/435] Only check predicates for late-bound non-lifetime vars in object candidate assembly --- .../src/traits/select/candidate_assembly.rs | 5 ++++- .../disqualifying-object-candidates.rs | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 tests/ui/traits/non_lifetime_binders/disqualifying-object-candidates.rs diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 5c67188dd240..ba551127ce1b 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -628,7 +628,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } self.infcx.probe(|_snapshot| { - if obligation.has_non_region_late_bound() { + // FIXME(non_lifetime_binders): Really, we care only to check that we don't + // have any non-region *escaping* bound vars, but that's hard to check and + // we shouldn't really ever encounter those anyways. + if obligation.self_ty().has_non_region_late_bound() { return; } diff --git a/tests/ui/traits/non_lifetime_binders/disqualifying-object-candidates.rs b/tests/ui/traits/non_lifetime_binders/disqualifying-object-candidates.rs new file mode 100644 index 000000000000..b999f251d333 --- /dev/null +++ b/tests/ui/traits/non_lifetime_binders/disqualifying-object-candidates.rs @@ -0,0 +1,19 @@ +// check-pass + +trait Foo { + type Bar + where + dyn Send + 'static: Send; +} + +impl Foo for () { + type Bar = i32; + // We take `<() as Foo>::Bar: Sized` and normalize it under the where clause + // of `for <() as Foo>::Bar = i32`. This gives us back `i32: Send` with + // the nested obligation `(dyn Send + 'static): Send`. However, during candidate + // assembly for object types, we disqualify any obligations that has non-region + // late-bound vars in the param env(!), rather than just the predicate. This causes + // the where clause to not hold even though it trivially should. +} + +fn main() {} From 171d5587ca1677ced9d1e70992a02091794cfb55 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 6 Nov 2023 23:41:25 +0000 Subject: [PATCH 294/435] Don't instantiate the binder twice when assembling object candidate --- .../src/traits/select/candidate_assembly.rs | 24 ++++++------------- ...on-lifetime-via-dyn-builtin.current.stderr | 11 +++++++++ .../non-lifetime-via-dyn-builtin.next.stderr | 11 +++++++++ .../ui/traits/non-lifetime-via-dyn-builtin.rs | 16 +++++++++++++ 4 files changed, 45 insertions(+), 17 deletions(-) create mode 100644 tests/ui/traits/non-lifetime-via-dyn-builtin.current.stderr create mode 100644 tests/ui/traits/non-lifetime-via-dyn-builtin.next.stderr create mode 100644 tests/ui/traits/non-lifetime-via-dyn-builtin.rs diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index ba551127ce1b..f4b6d3bcfda2 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -628,18 +628,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } self.infcx.probe(|_snapshot| { - // FIXME(non_lifetime_binders): Really, we care only to check that we don't - // have any non-region *escaping* bound vars, but that's hard to check and - // we shouldn't really ever encounter those anyways. - if obligation.self_ty().has_non_region_late_bound() { - return; - } + let poly_trait_predicate = self.infcx.resolve_vars_if_possible(obligation.predicate); + let placeholder_trait_predicate = + self.infcx.instantiate_binder_with_placeholders(poly_trait_predicate); - // The code below doesn't care about regions, and the - // self-ty here doesn't escape this probe, so just erase - // any LBR. - let self_ty = self.tcx().erase_late_bound_regions(obligation.self_ty()); - let poly_trait_ref = match self_ty.kind() { + let self_ty = placeholder_trait_predicate.self_ty(); + let principal_trait_ref = match self_ty.kind() { ty::Dynamic(ref data, ..) => { if data.auto_traits().any(|did| did == obligation.predicate.def_id()) { debug!( @@ -671,18 +665,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { _ => return, }; - debug!(?poly_trait_ref, "assemble_candidates_from_object_ty"); - - let poly_trait_predicate = self.infcx.resolve_vars_if_possible(obligation.predicate); - let placeholder_trait_predicate = - self.infcx.instantiate_binder_with_placeholders(poly_trait_predicate); + debug!(?principal_trait_ref, "assemble_candidates_from_object_ty"); // Count only those upcast versions that match the trait-ref // we are looking for. Specifically, do not only check for the // correct trait, but also the correct type parameters. // For example, we may be trying to upcast `Foo` to `Bar`, // but `Foo` is declared as `trait Foo: Bar`. - let candidate_supertraits = util::supertraits(self.tcx(), poly_trait_ref) + let candidate_supertraits = util::supertraits(self.tcx(), principal_trait_ref) .enumerate() .filter(|&(_, upcast_trait_ref)| { self.infcx.probe(|_| { diff --git a/tests/ui/traits/non-lifetime-via-dyn-builtin.current.stderr b/tests/ui/traits/non-lifetime-via-dyn-builtin.current.stderr new file mode 100644 index 000000000000..9f373cc50f0a --- /dev/null +++ b/tests/ui/traits/non-lifetime-via-dyn-builtin.current.stderr @@ -0,0 +1,11 @@ +warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/non-lifetime-via-dyn-builtin.rs:5:12 + | +LL | #![feature(non_lifetime_binders)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #108185 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/traits/non-lifetime-via-dyn-builtin.next.stderr b/tests/ui/traits/non-lifetime-via-dyn-builtin.next.stderr new file mode 100644 index 000000000000..9f373cc50f0a --- /dev/null +++ b/tests/ui/traits/non-lifetime-via-dyn-builtin.next.stderr @@ -0,0 +1,11 @@ +warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/non-lifetime-via-dyn-builtin.rs:5:12 + | +LL | #![feature(non_lifetime_binders)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #108185 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/traits/non-lifetime-via-dyn-builtin.rs b/tests/ui/traits/non-lifetime-via-dyn-builtin.rs new file mode 100644 index 000000000000..9a8a5ced2e25 --- /dev/null +++ b/tests/ui/traits/non-lifetime-via-dyn-builtin.rs @@ -0,0 +1,16 @@ +// revisions: current next +//[next] compile-flags: -Ztrait-solver=next +// check-pass + +#![feature(non_lifetime_binders)] +//~^ WARN the feature `non_lifetime_binders` is incomplete and may not be safe + +fn trivial() +where + for dyn Fn(A, *const B): Fn(A, *const B), +{ +} + +fn main() { + trivial::(); +} From 5a9f07cc97ba09a05820f19a50b79620bd95a5ff Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 30 Oct 2023 23:27:33 +0000 Subject: [PATCH 295/435] Build a better MIR body when errors are encountered --- compiler/rustc_mir_build/src/build/mod.rs | 86 +++++++++++++++-------- 1 file changed, 58 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index 58d6be50b905..7c729016521b 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -620,29 +620,63 @@ fn construct_const<'a, 'tcx>( /// /// This is required because we may still want to run MIR passes on an item /// with type errors, but normal MIR construction can't handle that in general. -fn construct_error(tcx: TyCtxt<'_>, def: LocalDefId, err: ErrorGuaranteed) -> Body<'_> { - let span = tcx.def_span(def); - let hir_id = tcx.hir().local_def_id_to_hir_id(def); - let coroutine_kind = tcx.coroutine_kind(def); - let body_owner_kind = tcx.hir().body_owner_kind(def); +fn construct_error(tcx: TyCtxt<'_>, def_id: LocalDefId, guar: ErrorGuaranteed) -> Body<'_> { + let span = tcx.def_span(def_id); + let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); + let coroutine_kind = tcx.coroutine_kind(def_id); - let ty = Ty::new_error(tcx, err); - let num_params = match body_owner_kind { - hir::BodyOwnerKind::Fn => tcx.fn_sig(def).skip_binder().inputs().skip_binder().len(), - hir::BodyOwnerKind::Closure => { - let ty = tcx.type_of(def).instantiate_identity(); - match ty.kind() { - ty::Closure(_, args) => 1 + args.as_closure().sig().inputs().skip_binder().len(), - ty::Coroutine(..) => 2, - _ => bug!("expected closure or coroutine, found {ty:?}"), - } + let (inputs, output, yield_ty) = match tcx.def_kind(def_id) { + DefKind::Const + | DefKind::AssocConst + | DefKind::AnonConst + | DefKind::InlineConst + | DefKind::Static(_) => (vec![], tcx.type_of(def_id).instantiate_identity(), None), + DefKind::Ctor(..) | DefKind::Fn | DefKind::AssocFn => { + let sig = tcx.liberate_late_bound_regions( + def_id.to_def_id(), + tcx.fn_sig(def_id).instantiate_identity(), + ); + (sig.inputs().to_vec(), sig.output(), None) } - hir::BodyOwnerKind::Const { .. } => 0, - hir::BodyOwnerKind::Static(_) => 0, + DefKind::Closure => { + let closure_ty = tcx.type_of(def_id).instantiate_identity(); + let ty::Closure(_, args) = closure_ty.kind() else { bug!() }; + let args = args.as_closure(); + let sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), args.sig()); + let self_ty = match args.kind() { + ty::ClosureKind::Fn => Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, closure_ty), + ty::ClosureKind::FnMut => Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, closure_ty), + ty::ClosureKind::FnOnce => closure_ty, + }; + ([self_ty].into_iter().chain(sig.inputs().to_vec()).collect(), sig.output(), None) + } + DefKind::Coroutine => { + let coroutine_ty = tcx.type_of(def_id).instantiate_identity(); + let ty::Coroutine(_, args, _) = coroutine_ty.kind() else { bug!() }; + let args = args.as_coroutine(); + let yield_ty = args.yield_ty(); + let return_ty = args.return_ty(); + let self_ty = Ty::new_adt( + tcx, + tcx.adt_def(tcx.lang_items().pin_type().unwrap()), + tcx.mk_args(&[Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, coroutine_ty).into()]), + ); + let coroutine_state = Ty::new_adt( + tcx, + tcx.adt_def(tcx.lang_items().coroutine_state().unwrap()), + tcx.mk_args(&[yield_ty.into(), return_ty.into()]), + ); + (vec![self_ty, args.resume_ty()], coroutine_state, Some(yield_ty)) + } + dk => bug!("{:?} is not a body: {:?}", def_id, dk), }; + + let source_info = SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE }; + let local_decls = IndexVec::from_iter( + [output].iter().chain(&inputs).map(|ty| LocalDecl::with_source_info(*ty, source_info)), + ); let mut cfg = CFG { basic_blocks: IndexVec::new() }; let mut source_scopes = IndexVec::new(); - let mut local_decls = IndexVec::from_elem_n(LocalDecl::new(ty, span), 1); cfg.start_new_block(); source_scopes.push(SourceScopeData { @@ -655,28 +689,24 @@ fn construct_error(tcx: TyCtxt<'_>, def: LocalDefId, err: ErrorGuaranteed) -> Bo safety: Safety::Safe, }), }); - let source_info = SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE }; - // Some MIR passes will expect the number of parameters to match the - // function declaration. - for _ in 0..num_params { - local_decls.push(LocalDecl::with_source_info(ty, source_info)); - } cfg.terminate(START_BLOCK, source_info, TerminatorKind::Unreachable); let mut body = Body::new( - MirSource::item(def.to_def_id()), + MirSource::item(def_id.to_def_id()), cfg.basic_blocks, source_scopes, local_decls, IndexVec::new(), - num_params, + inputs.len(), vec![], span, coroutine_kind, - Some(err), + Some(guar), ); - body.coroutine.as_mut().map(|gen| gen.yield_ty = Some(ty)); + + body.coroutine.as_mut().map(|gen| gen.yield_ty = yield_ty); + body } From 7f8a6de72c1ddf25775da648dc42198847ca0a23 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 26 Oct 2023 21:34:49 +1100 Subject: [PATCH 296/435] coverage: Use `-Copt-level=2` by default in run-coverage tests This is a step towards being able to unify the two coverage test directories. There are two tests that require adjustment: - `overflow.rs` requires an explicit `-Coverflow-checks=yes` - `sort_groups.rs` is sensitive to provably unused instantiations --- src/tools/compiletest/src/runtest.rs | 4 +-- .../coverage-map/status-quo/overflow.cov-map | 8 ++--- tests/coverage-map/status-quo/overflow.rs | 1 + .../status-quo/sort_groups.cov-map | 29 ++++++++++++++----- tests/coverage-map/status-quo/sort_groups.rs | 2 +- tests/run-coverage/overflow.coverage | 1 + tests/run-coverage/overflow.rs | 1 + tests/run-coverage/sort_groups.coverage | 2 +- tests/run-coverage/sort_groups.rs | 2 +- 9 files changed, 34 insertions(+), 16 deletions(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index e74d66a85992..4c6f46ef0dce 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2481,9 +2481,9 @@ impl<'test> TestCx<'test> { RunCoverage => { rustc.arg("-Cinstrument-coverage"); // Coverage reports are sometimes sensitive to optimizations, - // and the current snapshots assume no optimization unless + // and the current snapshots assume `opt-level=2` unless // overridden by `compile-flags`. - rustc.arg("-Copt-level=0"); + rustc.arg("-Copt-level=2"); } RunPassValgrind | Pretty | DebugInfo | Codegen | Rustdoc | RustdocJson | RunMake | CodegenUnits | JsDocTest | Assembly => { diff --git a/tests/coverage-map/status-quo/overflow.cov-map b/tests/coverage-map/status-quo/overflow.cov-map index bfffd9b2ab51..39a5c05f879a 100644 --- a/tests/coverage-map/status-quo/overflow.cov-map +++ b/tests/coverage-map/status-quo/overflow.cov-map @@ -1,5 +1,5 @@ Function name: overflow::main -Raw bytes (65): 0x[01, 01, 08, 01, 1b, 05, 1f, 09, 0d, 03, 11, 16, 05, 03, 11, 05, 1f, 09, 0d, 09, 01, 0f, 01, 01, 1b, 03, 02, 0b, 00, 18, 16, 01, 0c, 00, 1a, 05, 00, 1b, 03, 0a, 12, 03, 13, 00, 20, 09, 00, 21, 03, 0a, 0d, 03, 0a, 00, 0b, 1b, 01, 09, 00, 17, 11, 02, 05, 01, 02] +Raw bytes (65): 0x[01, 01, 08, 01, 1b, 05, 1f, 09, 0d, 03, 11, 16, 05, 03, 11, 05, 1f, 09, 0d, 09, 01, 10, 01, 01, 1b, 03, 02, 0b, 00, 18, 16, 01, 0c, 00, 1a, 05, 00, 1b, 03, 0a, 12, 03, 13, 00, 20, 09, 00, 21, 03, 0a, 0d, 03, 0a, 00, 0b, 1b, 01, 09, 00, 17, 11, 02, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 8 @@ -12,7 +12,7 @@ Number of expressions: 8 - expression 6 operands: lhs = Counter(1), rhs = Expression(7, Add) - expression 7 operands: lhs = Counter(2), rhs = Counter(3) Number of file 0 mappings: 9 -- Code(Counter(0)) at (prev + 15, 1) to (start + 1, 27) +- Code(Counter(0)) at (prev + 16, 1) to (start + 1, 27) - Code(Expression(0, Add)) at (prev + 2, 11) to (start + 0, 24) = (c0 + (c1 + (c2 + c3))) - Code(Expression(5, Sub)) at (prev + 1, 12) to (start + 0, 26) @@ -27,14 +27,14 @@ Number of file 0 mappings: 9 - Code(Counter(4)) at (prev + 2, 5) to (start + 1, 2) Function name: overflow::might_overflow -Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 04, 01, 01, 12, 05, 01, 13, 02, 06, 02, 02, 06, 00, 07, 07, 01, 09, 05, 02] +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 05, 01, 01, 12, 05, 01, 13, 02, 06, 02, 02, 06, 00, 07, 07, 01, 09, 05, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 4, 1) to (start + 1, 18) +- Code(Counter(0)) at (prev + 5, 1) to (start + 1, 18) - Code(Counter(1)) at (prev + 1, 19) to (start + 2, 6) - Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7) = (c0 - c1) diff --git a/tests/coverage-map/status-quo/overflow.rs b/tests/coverage-map/status-quo/overflow.rs index bbb65c1b35df..1c40771b2747 100644 --- a/tests/coverage-map/status-quo/overflow.rs +++ b/tests/coverage-map/status-quo/overflow.rs @@ -1,4 +1,5 @@ #![allow(unused_assignments)] +// compile-flags: -Coverflow-checks=yes // failure-status: 101 fn might_overflow(to_add: u32) -> u32 { diff --git a/tests/coverage-map/status-quo/sort_groups.cov-map b/tests/coverage-map/status-quo/sort_groups.cov-map index db027f3dc324..3cbda6fbe1ab 100644 --- a/tests/coverage-map/status-quo/sort_groups.cov-map +++ b/tests/coverage-map/status-quo/sort_groups.cov-map @@ -28,6 +28,21 @@ Number of file 0 mappings: 4 - Code(Expression(1, Add)) at (prev + 1, 1) to (start + 0, 2) = (c1 + (c0 - c1)) +Function name: sort_groups::generic_fn:: +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 11, 01, 01, 0c, 05, 01, 0d, 02, 06, 02, 02, 06, 00, 07, 07, 01, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 2 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +- expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 17, 1) to (start + 1, 12) +- Code(Counter(1)) at (prev + 1, 13) to (start + 2, 6) +- Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7) + = (c0 - c1) +- Code(Expression(1, Add)) at (prev + 1, 1) to (start + 0, 2) + = (c1 + (c0 - c1)) + Function name: sort_groups::generic_fn:: Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 11, 01, 01, 0c, 05, 01, 0d, 02, 06, 02, 02, 06, 00, 07, 07, 01, 01, 00, 02] Number of files: 1 @@ -44,19 +59,19 @@ Number of file 0 mappings: 4 = (c1 + (c0 - c1)) Function name: sort_groups::main -Raw bytes (28): 0x[01, 01, 02, 01, 00, 00, 02, 04, 01, 06, 01, 04, 0d, 00, 04, 0e, 02, 06, 02, 02, 06, 00, 07, 07, 01, 05, 02, 02] +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 06, 01, 04, 23, 05, 04, 24, 02, 06, 02, 02, 06, 00, 07, 07, 01, 05, 02, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 -- expression 0 operands: lhs = Counter(0), rhs = Zero -- expression 1 operands: lhs = Zero, rhs = Expression(0, Sub) +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +- expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 6, 1) to (start + 4, 13) -- Code(Zero) at (prev + 4, 14) to (start + 2, 6) +- Code(Counter(0)) at (prev + 6, 1) to (start + 4, 35) +- Code(Counter(1)) at (prev + 4, 36) to (start + 2, 6) - Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7) - = (c0 - Zero) + = (c0 - c1) - Code(Expression(1, Add)) at (prev + 1, 5) to (start + 2, 2) - = (Zero + (c0 - Zero)) + = (c1 + (c0 - c1)) Function name: sort_groups::other_fn Raw bytes (9): 0x[01, 01, 00, 01, 01, 17, 01, 00, 11] diff --git a/tests/coverage-map/status-quo/sort_groups.rs b/tests/coverage-map/status-quo/sort_groups.rs index f89f9f3ec61f..5adbbc6a87d1 100644 --- a/tests/coverage-map/status-quo/sort_groups.rs +++ b/tests/coverage-map/status-quo/sort_groups.rs @@ -7,7 +7,7 @@ fn main() { let cond = std::env::args().len() > 1; generic_fn::<()>(cond); generic_fn::<&'static str>(!cond); - if false { + if std::hint::black_box(false) { generic_fn::(cond); } generic_fn::(cond); diff --git a/tests/run-coverage/overflow.coverage b/tests/run-coverage/overflow.coverage index cee076e88cd4..4f8dffc0c481 100644 --- a/tests/run-coverage/overflow.coverage +++ b/tests/run-coverage/overflow.coverage @@ -1,4 +1,5 @@ LL| |#![allow(unused_assignments)] + LL| |// compile-flags: -Coverflow-checks=yes LL| |// failure-status: 101 LL| | LL| 4|fn might_overflow(to_add: u32) -> u32 { diff --git a/tests/run-coverage/overflow.rs b/tests/run-coverage/overflow.rs index bbb65c1b35df..1c40771b2747 100644 --- a/tests/run-coverage/overflow.rs +++ b/tests/run-coverage/overflow.rs @@ -1,4 +1,5 @@ #![allow(unused_assignments)] +// compile-flags: -Coverflow-checks=yes // failure-status: 101 fn might_overflow(to_add: u32) -> u32 { diff --git a/tests/run-coverage/sort_groups.coverage b/tests/run-coverage/sort_groups.coverage index 8733bf48a9c8..c70d7b3b2825 100644 --- a/tests/run-coverage/sort_groups.coverage +++ b/tests/run-coverage/sort_groups.coverage @@ -7,7 +7,7 @@ LL| 1| let cond = std::env::args().len() > 1; LL| 1| generic_fn::<()>(cond); LL| 1| generic_fn::<&'static str>(!cond); - LL| 1| if false { + LL| 1| if std::hint::black_box(false) { LL| 0| generic_fn::(cond); LL| 1| } LL| 1| generic_fn::(cond); diff --git a/tests/run-coverage/sort_groups.rs b/tests/run-coverage/sort_groups.rs index f89f9f3ec61f..5adbbc6a87d1 100644 --- a/tests/run-coverage/sort_groups.rs +++ b/tests/run-coverage/sort_groups.rs @@ -7,7 +7,7 @@ fn main() { let cond = std::env::args().len() > 1; generic_fn::<()>(cond); generic_fn::<&'static str>(!cond); - if false { + if std::hint::black_box(false) { generic_fn::(cond); } generic_fn::(cond); From 8eef39f0825f03629373e430063f331149da6d37 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sat, 28 Oct 2023 21:20:32 +1100 Subject: [PATCH 297/435] coverage: Remove `tests/coverage-map/if.rs` There is another test named `if.rs` in `tests/coverage-map/status-quo/`, so this test stands in the way of flattening that directory into its parent. Fortunately both tests are more-or-less equivalent, so removing this one is fine. --- tests/coverage-map/if.cov-map | 15 --------------- tests/coverage-map/if.rs | 9 --------- 2 files changed, 24 deletions(-) delete mode 100644 tests/coverage-map/if.cov-map delete mode 100644 tests/coverage-map/if.rs diff --git a/tests/coverage-map/if.cov-map b/tests/coverage-map/if.cov-map deleted file mode 100644 index 3cedb5ffbecb..000000000000 --- a/tests/coverage-map/if.cov-map +++ /dev/null @@ -1,15 +0,0 @@ -Function name: if::main -Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 03, 01, 02, 0c, 05, 02, 0d, 02, 06, 02, 02, 06, 00, 07, 07, 01, 05, 01, 02] -Number of files: 1 -- file 0 => global file 1 -Number of expressions: 2 -- expression 0 operands: lhs = Counter(0), rhs = Counter(1) -- expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) -Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 3, 1) to (start + 2, 12) -- Code(Counter(1)) at (prev + 2, 13) to (start + 2, 6) -- Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7) - = (c0 - c1) -- Code(Expression(1, Add)) at (prev + 1, 5) to (start + 1, 2) - = (c1 + (c0 - c1)) - diff --git a/tests/coverage-map/if.rs b/tests/coverage-map/if.rs deleted file mode 100644 index ed3f69bdc98d..000000000000 --- a/tests/coverage-map/if.rs +++ /dev/null @@ -1,9 +0,0 @@ -// compile-flags: --edition=2021 - -fn main() { - let cond = std::env::args().len() == 1; - if cond { - println!("true"); - } - println!("done"); -} From f5df56b26b5a9c46299e74591602940c0e48b08c Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sat, 28 Oct 2023 21:23:23 +1100 Subject: [PATCH 298/435] coverage: Flatten `coverage-map/status-quo/` into its parent directory --- tests/coverage-map/README.md | 2 +- tests/coverage-map/{status-quo => }/abort.cov-map | 0 tests/coverage-map/{status-quo => }/abort.rs | 0 tests/coverage-map/{status-quo => }/assert.cov-map | 0 tests/coverage-map/{status-quo => }/assert.rs | 0 tests/coverage-map/{status-quo => }/async.cov-map | 0 tests/coverage-map/{status-quo => }/async.rs | 0 tests/coverage-map/{status-quo => }/async2.cov-map | 0 tests/coverage-map/{status-quo => }/async2.rs | 0 tests/coverage-map/{status-quo => }/bad_counter_ids.cov-map | 0 tests/coverage-map/{status-quo => }/bad_counter_ids.rs | 0 tests/coverage-map/{status-quo => }/closure.cov-map | 0 tests/coverage-map/{status-quo => }/closure.rs | 0 tests/coverage-map/{status-quo => }/closure_bug.cov-map | 0 tests/coverage-map/{status-quo => }/closure_bug.rs | 0 tests/coverage-map/{status-quo => }/closure_macro.cov-map | 0 tests/coverage-map/{status-quo => }/closure_macro.rs | 0 tests/coverage-map/{status-quo => }/closure_macro_async.cov-map | 0 tests/coverage-map/{status-quo => }/closure_macro_async.rs | 0 tests/coverage-map/{status-quo => }/conditions.cov-map | 0 tests/coverage-map/{status-quo => }/conditions.rs | 0 tests/coverage-map/{status-quo => }/continue.cov-map | 0 tests/coverage-map/{status-quo => }/continue.rs | 0 tests/coverage-map/{status-quo => }/coroutine.cov-map | 0 tests/coverage-map/{status-quo => }/coroutine.rs | 0 tests/coverage-map/{status-quo => }/dead_code.cov-map | 0 tests/coverage-map/{status-quo => }/dead_code.rs | 0 tests/coverage-map/{status-quo => }/drop_trait.cov-map | 0 tests/coverage-map/{status-quo => }/drop_trait.rs | 0 tests/coverage-map/{status-quo => }/generics.cov-map | 0 tests/coverage-map/{status-quo => }/generics.rs | 0 tests/coverage-map/{status-quo => }/if.cov-map | 0 tests/coverage-map/{status-quo => }/if.rs | 0 tests/coverage-map/{status-quo => }/if_else.cov-map | 0 tests/coverage-map/{status-quo => }/if_else.rs | 0 tests/coverage-map/{status-quo => }/inline-dead.cov-map | 0 tests/coverage-map/{status-quo => }/inline-dead.rs | 0 tests/coverage-map/{status-quo => }/inline.cov-map | 0 tests/coverage-map/{status-quo => }/inline.rs | 0 tests/coverage-map/{status-quo => }/inner_items.cov-map | 0 tests/coverage-map/{status-quo => }/inner_items.rs | 0 tests/coverage-map/{status-quo => }/issue-83601.cov-map | 0 tests/coverage-map/{status-quo => }/issue-83601.rs | 0 tests/coverage-map/{status-quo => }/issue-84561.cov-map | 0 tests/coverage-map/{status-quo => }/issue-84561.rs | 0 tests/coverage-map/{status-quo => }/issue-93054.cov-map | 0 tests/coverage-map/{status-quo => }/issue-93054.rs | 0 tests/coverage-map/{status-quo => }/lazy_boolean.cov-map | 0 tests/coverage-map/{status-quo => }/lazy_boolean.rs | 0 tests/coverage-map/{status-quo => }/loop_break_value.cov-map | 0 tests/coverage-map/{status-quo => }/loop_break_value.rs | 0 tests/coverage-map/{status-quo => }/loops_branches.cov-map | 0 tests/coverage-map/{status-quo => }/loops_branches.rs | 0 tests/coverage-map/{status-quo => }/match_or_pattern.cov-map | 0 tests/coverage-map/{status-quo => }/match_or_pattern.rs | 0 tests/coverage-map/{status-quo => }/nested_loops.cov-map | 0 tests/coverage-map/{status-quo => }/nested_loops.rs | 0 tests/coverage-map/{status-quo => }/no_cov_crate.cov-map | 0 tests/coverage-map/{status-quo => }/no_cov_crate.rs | 0 tests/coverage-map/{status-quo => }/overflow.cov-map | 0 tests/coverage-map/{status-quo => }/overflow.rs | 0 tests/coverage-map/{status-quo => }/panic_unwind.cov-map | 0 tests/coverage-map/{status-quo => }/panic_unwind.rs | 0 tests/coverage-map/{status-quo => }/partial_eq.cov-map | 0 tests/coverage-map/{status-quo => }/partial_eq.rs | 0 tests/coverage-map/{status-quo => }/simple_loop.cov-map | 0 tests/coverage-map/{status-quo => }/simple_loop.rs | 0 tests/coverage-map/{status-quo => }/simple_match.cov-map | 0 tests/coverage-map/{status-quo => }/simple_match.rs | 0 tests/coverage-map/{status-quo => }/sort_groups.cov-map | 0 tests/coverage-map/{status-quo => }/sort_groups.rs | 0 tests/coverage-map/{status-quo => }/test_harness.cov-map | 0 tests/coverage-map/{status-quo => }/test_harness.rs | 0 tests/coverage-map/{status-quo => }/tight_inf_loop.cov-map | 0 tests/coverage-map/{status-quo => }/tight_inf_loop.rs | 0 tests/coverage-map/{status-quo => }/try_error_result.cov-map | 0 tests/coverage-map/{status-quo => }/try_error_result.rs | 0 tests/coverage-map/{status-quo => }/unused.cov-map | 0 tests/coverage-map/{status-quo => }/unused.rs | 0 tests/coverage-map/{status-quo => }/while.cov-map | 0 tests/coverage-map/{status-quo => }/while.rs | 0 tests/coverage-map/{status-quo => }/while_early_ret.cov-map | 0 tests/coverage-map/{status-quo => }/while_early_ret.rs | 0 tests/coverage-map/{status-quo => }/yield.cov-map | 0 tests/coverage-map/{status-quo => }/yield.rs | 0 85 files changed, 1 insertion(+), 1 deletion(-) rename tests/coverage-map/{status-quo => }/abort.cov-map (100%) rename tests/coverage-map/{status-quo => }/abort.rs (100%) rename tests/coverage-map/{status-quo => }/assert.cov-map (100%) rename tests/coverage-map/{status-quo => }/assert.rs (100%) rename tests/coverage-map/{status-quo => }/async.cov-map (100%) rename tests/coverage-map/{status-quo => }/async.rs (100%) rename tests/coverage-map/{status-quo => }/async2.cov-map (100%) rename tests/coverage-map/{status-quo => }/async2.rs (100%) rename tests/coverage-map/{status-quo => }/bad_counter_ids.cov-map (100%) rename tests/coverage-map/{status-quo => }/bad_counter_ids.rs (100%) rename tests/coverage-map/{status-quo => }/closure.cov-map (100%) rename tests/coverage-map/{status-quo => }/closure.rs (100%) rename tests/coverage-map/{status-quo => }/closure_bug.cov-map (100%) rename tests/coverage-map/{status-quo => }/closure_bug.rs (100%) rename tests/coverage-map/{status-quo => }/closure_macro.cov-map (100%) rename tests/coverage-map/{status-quo => }/closure_macro.rs (100%) rename tests/coverage-map/{status-quo => }/closure_macro_async.cov-map (100%) rename tests/coverage-map/{status-quo => }/closure_macro_async.rs (100%) rename tests/coverage-map/{status-quo => }/conditions.cov-map (100%) rename tests/coverage-map/{status-quo => }/conditions.rs (100%) rename tests/coverage-map/{status-quo => }/continue.cov-map (100%) rename tests/coverage-map/{status-quo => }/continue.rs (100%) rename tests/coverage-map/{status-quo => }/coroutine.cov-map (100%) rename tests/coverage-map/{status-quo => }/coroutine.rs (100%) rename tests/coverage-map/{status-quo => }/dead_code.cov-map (100%) rename tests/coverage-map/{status-quo => }/dead_code.rs (100%) rename tests/coverage-map/{status-quo => }/drop_trait.cov-map (100%) rename tests/coverage-map/{status-quo => }/drop_trait.rs (100%) rename tests/coverage-map/{status-quo => }/generics.cov-map (100%) rename tests/coverage-map/{status-quo => }/generics.rs (100%) rename tests/coverage-map/{status-quo => }/if.cov-map (100%) rename tests/coverage-map/{status-quo => }/if.rs (100%) rename tests/coverage-map/{status-quo => }/if_else.cov-map (100%) rename tests/coverage-map/{status-quo => }/if_else.rs (100%) rename tests/coverage-map/{status-quo => }/inline-dead.cov-map (100%) rename tests/coverage-map/{status-quo => }/inline-dead.rs (100%) rename tests/coverage-map/{status-quo => }/inline.cov-map (100%) rename tests/coverage-map/{status-quo => }/inline.rs (100%) rename tests/coverage-map/{status-quo => }/inner_items.cov-map (100%) rename tests/coverage-map/{status-quo => }/inner_items.rs (100%) rename tests/coverage-map/{status-quo => }/issue-83601.cov-map (100%) rename tests/coverage-map/{status-quo => }/issue-83601.rs (100%) rename tests/coverage-map/{status-quo => }/issue-84561.cov-map (100%) rename tests/coverage-map/{status-quo => }/issue-84561.rs (100%) rename tests/coverage-map/{status-quo => }/issue-93054.cov-map (100%) rename tests/coverage-map/{status-quo => }/issue-93054.rs (100%) rename tests/coverage-map/{status-quo => }/lazy_boolean.cov-map (100%) rename tests/coverage-map/{status-quo => }/lazy_boolean.rs (100%) rename tests/coverage-map/{status-quo => }/loop_break_value.cov-map (100%) rename tests/coverage-map/{status-quo => }/loop_break_value.rs (100%) rename tests/coverage-map/{status-quo => }/loops_branches.cov-map (100%) rename tests/coverage-map/{status-quo => }/loops_branches.rs (100%) rename tests/coverage-map/{status-quo => }/match_or_pattern.cov-map (100%) rename tests/coverage-map/{status-quo => }/match_or_pattern.rs (100%) rename tests/coverage-map/{status-quo => }/nested_loops.cov-map (100%) rename tests/coverage-map/{status-quo => }/nested_loops.rs (100%) rename tests/coverage-map/{status-quo => }/no_cov_crate.cov-map (100%) rename tests/coverage-map/{status-quo => }/no_cov_crate.rs (100%) rename tests/coverage-map/{status-quo => }/overflow.cov-map (100%) rename tests/coverage-map/{status-quo => }/overflow.rs (100%) rename tests/coverage-map/{status-quo => }/panic_unwind.cov-map (100%) rename tests/coverage-map/{status-quo => }/panic_unwind.rs (100%) rename tests/coverage-map/{status-quo => }/partial_eq.cov-map (100%) rename tests/coverage-map/{status-quo => }/partial_eq.rs (100%) rename tests/coverage-map/{status-quo => }/simple_loop.cov-map (100%) rename tests/coverage-map/{status-quo => }/simple_loop.rs (100%) rename tests/coverage-map/{status-quo => }/simple_match.cov-map (100%) rename tests/coverage-map/{status-quo => }/simple_match.rs (100%) rename tests/coverage-map/{status-quo => }/sort_groups.cov-map (100%) rename tests/coverage-map/{status-quo => }/sort_groups.rs (100%) rename tests/coverage-map/{status-quo => }/test_harness.cov-map (100%) rename tests/coverage-map/{status-quo => }/test_harness.rs (100%) rename tests/coverage-map/{status-quo => }/tight_inf_loop.cov-map (100%) rename tests/coverage-map/{status-quo => }/tight_inf_loop.rs (100%) rename tests/coverage-map/{status-quo => }/try_error_result.cov-map (100%) rename tests/coverage-map/{status-quo => }/try_error_result.rs (100%) rename tests/coverage-map/{status-quo => }/unused.cov-map (100%) rename tests/coverage-map/{status-quo => }/unused.rs (100%) rename tests/coverage-map/{status-quo => }/while.cov-map (100%) rename tests/coverage-map/{status-quo => }/while.rs (100%) rename tests/coverage-map/{status-quo => }/while_early_ret.cov-map (100%) rename tests/coverage-map/{status-quo => }/while_early_ret.rs (100%) rename tests/coverage-map/{status-quo => }/yield.cov-map (100%) rename tests/coverage-map/{status-quo => }/yield.rs (100%) diff --git a/tests/coverage-map/README.md b/tests/coverage-map/README.md index 60d1352cd64f..146fbff5b204 100644 --- a/tests/coverage-map/README.md +++ b/tests/coverage-map/README.md @@ -1,4 +1,4 @@ -The tests in `./status-quo` were copied from `tests/run-coverage` in order to +Many of these tests were copied from `tests/run-coverage` in order to capture the current behavior of the instrumentor on non-trivial programs. The actual mappings have not been closely inspected. diff --git a/tests/coverage-map/status-quo/abort.cov-map b/tests/coverage-map/abort.cov-map similarity index 100% rename from tests/coverage-map/status-quo/abort.cov-map rename to tests/coverage-map/abort.cov-map diff --git a/tests/coverage-map/status-quo/abort.rs b/tests/coverage-map/abort.rs similarity index 100% rename from tests/coverage-map/status-quo/abort.rs rename to tests/coverage-map/abort.rs diff --git a/tests/coverage-map/status-quo/assert.cov-map b/tests/coverage-map/assert.cov-map similarity index 100% rename from tests/coverage-map/status-quo/assert.cov-map rename to tests/coverage-map/assert.cov-map diff --git a/tests/coverage-map/status-quo/assert.rs b/tests/coverage-map/assert.rs similarity index 100% rename from tests/coverage-map/status-quo/assert.rs rename to tests/coverage-map/assert.rs diff --git a/tests/coverage-map/status-quo/async.cov-map b/tests/coverage-map/async.cov-map similarity index 100% rename from tests/coverage-map/status-quo/async.cov-map rename to tests/coverage-map/async.cov-map diff --git a/tests/coverage-map/status-quo/async.rs b/tests/coverage-map/async.rs similarity index 100% rename from tests/coverage-map/status-quo/async.rs rename to tests/coverage-map/async.rs diff --git a/tests/coverage-map/status-quo/async2.cov-map b/tests/coverage-map/async2.cov-map similarity index 100% rename from tests/coverage-map/status-quo/async2.cov-map rename to tests/coverage-map/async2.cov-map diff --git a/tests/coverage-map/status-quo/async2.rs b/tests/coverage-map/async2.rs similarity index 100% rename from tests/coverage-map/status-quo/async2.rs rename to tests/coverage-map/async2.rs diff --git a/tests/coverage-map/status-quo/bad_counter_ids.cov-map b/tests/coverage-map/bad_counter_ids.cov-map similarity index 100% rename from tests/coverage-map/status-quo/bad_counter_ids.cov-map rename to tests/coverage-map/bad_counter_ids.cov-map diff --git a/tests/coverage-map/status-quo/bad_counter_ids.rs b/tests/coverage-map/bad_counter_ids.rs similarity index 100% rename from tests/coverage-map/status-quo/bad_counter_ids.rs rename to tests/coverage-map/bad_counter_ids.rs diff --git a/tests/coverage-map/status-quo/closure.cov-map b/tests/coverage-map/closure.cov-map similarity index 100% rename from tests/coverage-map/status-quo/closure.cov-map rename to tests/coverage-map/closure.cov-map diff --git a/tests/coverage-map/status-quo/closure.rs b/tests/coverage-map/closure.rs similarity index 100% rename from tests/coverage-map/status-quo/closure.rs rename to tests/coverage-map/closure.rs diff --git a/tests/coverage-map/status-quo/closure_bug.cov-map b/tests/coverage-map/closure_bug.cov-map similarity index 100% rename from tests/coverage-map/status-quo/closure_bug.cov-map rename to tests/coverage-map/closure_bug.cov-map diff --git a/tests/coverage-map/status-quo/closure_bug.rs b/tests/coverage-map/closure_bug.rs similarity index 100% rename from tests/coverage-map/status-quo/closure_bug.rs rename to tests/coverage-map/closure_bug.rs diff --git a/tests/coverage-map/status-quo/closure_macro.cov-map b/tests/coverage-map/closure_macro.cov-map similarity index 100% rename from tests/coverage-map/status-quo/closure_macro.cov-map rename to tests/coverage-map/closure_macro.cov-map diff --git a/tests/coverage-map/status-quo/closure_macro.rs b/tests/coverage-map/closure_macro.rs similarity index 100% rename from tests/coverage-map/status-quo/closure_macro.rs rename to tests/coverage-map/closure_macro.rs diff --git a/tests/coverage-map/status-quo/closure_macro_async.cov-map b/tests/coverage-map/closure_macro_async.cov-map similarity index 100% rename from tests/coverage-map/status-quo/closure_macro_async.cov-map rename to tests/coverage-map/closure_macro_async.cov-map diff --git a/tests/coverage-map/status-quo/closure_macro_async.rs b/tests/coverage-map/closure_macro_async.rs similarity index 100% rename from tests/coverage-map/status-quo/closure_macro_async.rs rename to tests/coverage-map/closure_macro_async.rs diff --git a/tests/coverage-map/status-quo/conditions.cov-map b/tests/coverage-map/conditions.cov-map similarity index 100% rename from tests/coverage-map/status-quo/conditions.cov-map rename to tests/coverage-map/conditions.cov-map diff --git a/tests/coverage-map/status-quo/conditions.rs b/tests/coverage-map/conditions.rs similarity index 100% rename from tests/coverage-map/status-quo/conditions.rs rename to tests/coverage-map/conditions.rs diff --git a/tests/coverage-map/status-quo/continue.cov-map b/tests/coverage-map/continue.cov-map similarity index 100% rename from tests/coverage-map/status-quo/continue.cov-map rename to tests/coverage-map/continue.cov-map diff --git a/tests/coverage-map/status-quo/continue.rs b/tests/coverage-map/continue.rs similarity index 100% rename from tests/coverage-map/status-quo/continue.rs rename to tests/coverage-map/continue.rs diff --git a/tests/coverage-map/status-quo/coroutine.cov-map b/tests/coverage-map/coroutine.cov-map similarity index 100% rename from tests/coverage-map/status-quo/coroutine.cov-map rename to tests/coverage-map/coroutine.cov-map diff --git a/tests/coverage-map/status-quo/coroutine.rs b/tests/coverage-map/coroutine.rs similarity index 100% rename from tests/coverage-map/status-quo/coroutine.rs rename to tests/coverage-map/coroutine.rs diff --git a/tests/coverage-map/status-quo/dead_code.cov-map b/tests/coverage-map/dead_code.cov-map similarity index 100% rename from tests/coverage-map/status-quo/dead_code.cov-map rename to tests/coverage-map/dead_code.cov-map diff --git a/tests/coverage-map/status-quo/dead_code.rs b/tests/coverage-map/dead_code.rs similarity index 100% rename from tests/coverage-map/status-quo/dead_code.rs rename to tests/coverage-map/dead_code.rs diff --git a/tests/coverage-map/status-quo/drop_trait.cov-map b/tests/coverage-map/drop_trait.cov-map similarity index 100% rename from tests/coverage-map/status-quo/drop_trait.cov-map rename to tests/coverage-map/drop_trait.cov-map diff --git a/tests/coverage-map/status-quo/drop_trait.rs b/tests/coverage-map/drop_trait.rs similarity index 100% rename from tests/coverage-map/status-quo/drop_trait.rs rename to tests/coverage-map/drop_trait.rs diff --git a/tests/coverage-map/status-quo/generics.cov-map b/tests/coverage-map/generics.cov-map similarity index 100% rename from tests/coverage-map/status-quo/generics.cov-map rename to tests/coverage-map/generics.cov-map diff --git a/tests/coverage-map/status-quo/generics.rs b/tests/coverage-map/generics.rs similarity index 100% rename from tests/coverage-map/status-quo/generics.rs rename to tests/coverage-map/generics.rs diff --git a/tests/coverage-map/status-quo/if.cov-map b/tests/coverage-map/if.cov-map similarity index 100% rename from tests/coverage-map/status-quo/if.cov-map rename to tests/coverage-map/if.cov-map diff --git a/tests/coverage-map/status-quo/if.rs b/tests/coverage-map/if.rs similarity index 100% rename from tests/coverage-map/status-quo/if.rs rename to tests/coverage-map/if.rs diff --git a/tests/coverage-map/status-quo/if_else.cov-map b/tests/coverage-map/if_else.cov-map similarity index 100% rename from tests/coverage-map/status-quo/if_else.cov-map rename to tests/coverage-map/if_else.cov-map diff --git a/tests/coverage-map/status-quo/if_else.rs b/tests/coverage-map/if_else.rs similarity index 100% rename from tests/coverage-map/status-quo/if_else.rs rename to tests/coverage-map/if_else.rs diff --git a/tests/coverage-map/status-quo/inline-dead.cov-map b/tests/coverage-map/inline-dead.cov-map similarity index 100% rename from tests/coverage-map/status-quo/inline-dead.cov-map rename to tests/coverage-map/inline-dead.cov-map diff --git a/tests/coverage-map/status-quo/inline-dead.rs b/tests/coverage-map/inline-dead.rs similarity index 100% rename from tests/coverage-map/status-quo/inline-dead.rs rename to tests/coverage-map/inline-dead.rs diff --git a/tests/coverage-map/status-quo/inline.cov-map b/tests/coverage-map/inline.cov-map similarity index 100% rename from tests/coverage-map/status-quo/inline.cov-map rename to tests/coverage-map/inline.cov-map diff --git a/tests/coverage-map/status-quo/inline.rs b/tests/coverage-map/inline.rs similarity index 100% rename from tests/coverage-map/status-quo/inline.rs rename to tests/coverage-map/inline.rs diff --git a/tests/coverage-map/status-quo/inner_items.cov-map b/tests/coverage-map/inner_items.cov-map similarity index 100% rename from tests/coverage-map/status-quo/inner_items.cov-map rename to tests/coverage-map/inner_items.cov-map diff --git a/tests/coverage-map/status-quo/inner_items.rs b/tests/coverage-map/inner_items.rs similarity index 100% rename from tests/coverage-map/status-quo/inner_items.rs rename to tests/coverage-map/inner_items.rs diff --git a/tests/coverage-map/status-quo/issue-83601.cov-map b/tests/coverage-map/issue-83601.cov-map similarity index 100% rename from tests/coverage-map/status-quo/issue-83601.cov-map rename to tests/coverage-map/issue-83601.cov-map diff --git a/tests/coverage-map/status-quo/issue-83601.rs b/tests/coverage-map/issue-83601.rs similarity index 100% rename from tests/coverage-map/status-quo/issue-83601.rs rename to tests/coverage-map/issue-83601.rs diff --git a/tests/coverage-map/status-quo/issue-84561.cov-map b/tests/coverage-map/issue-84561.cov-map similarity index 100% rename from tests/coverage-map/status-quo/issue-84561.cov-map rename to tests/coverage-map/issue-84561.cov-map diff --git a/tests/coverage-map/status-quo/issue-84561.rs b/tests/coverage-map/issue-84561.rs similarity index 100% rename from tests/coverage-map/status-quo/issue-84561.rs rename to tests/coverage-map/issue-84561.rs diff --git a/tests/coverage-map/status-quo/issue-93054.cov-map b/tests/coverage-map/issue-93054.cov-map similarity index 100% rename from tests/coverage-map/status-quo/issue-93054.cov-map rename to tests/coverage-map/issue-93054.cov-map diff --git a/tests/coverage-map/status-quo/issue-93054.rs b/tests/coverage-map/issue-93054.rs similarity index 100% rename from tests/coverage-map/status-quo/issue-93054.rs rename to tests/coverage-map/issue-93054.rs diff --git a/tests/coverage-map/status-quo/lazy_boolean.cov-map b/tests/coverage-map/lazy_boolean.cov-map similarity index 100% rename from tests/coverage-map/status-quo/lazy_boolean.cov-map rename to tests/coverage-map/lazy_boolean.cov-map diff --git a/tests/coverage-map/status-quo/lazy_boolean.rs b/tests/coverage-map/lazy_boolean.rs similarity index 100% rename from tests/coverage-map/status-quo/lazy_boolean.rs rename to tests/coverage-map/lazy_boolean.rs diff --git a/tests/coverage-map/status-quo/loop_break_value.cov-map b/tests/coverage-map/loop_break_value.cov-map similarity index 100% rename from tests/coverage-map/status-quo/loop_break_value.cov-map rename to tests/coverage-map/loop_break_value.cov-map diff --git a/tests/coverage-map/status-quo/loop_break_value.rs b/tests/coverage-map/loop_break_value.rs similarity index 100% rename from tests/coverage-map/status-quo/loop_break_value.rs rename to tests/coverage-map/loop_break_value.rs diff --git a/tests/coverage-map/status-quo/loops_branches.cov-map b/tests/coverage-map/loops_branches.cov-map similarity index 100% rename from tests/coverage-map/status-quo/loops_branches.cov-map rename to tests/coverage-map/loops_branches.cov-map diff --git a/tests/coverage-map/status-quo/loops_branches.rs b/tests/coverage-map/loops_branches.rs similarity index 100% rename from tests/coverage-map/status-quo/loops_branches.rs rename to tests/coverage-map/loops_branches.rs diff --git a/tests/coverage-map/status-quo/match_or_pattern.cov-map b/tests/coverage-map/match_or_pattern.cov-map similarity index 100% rename from tests/coverage-map/status-quo/match_or_pattern.cov-map rename to tests/coverage-map/match_or_pattern.cov-map diff --git a/tests/coverage-map/status-quo/match_or_pattern.rs b/tests/coverage-map/match_or_pattern.rs similarity index 100% rename from tests/coverage-map/status-quo/match_or_pattern.rs rename to tests/coverage-map/match_or_pattern.rs diff --git a/tests/coverage-map/status-quo/nested_loops.cov-map b/tests/coverage-map/nested_loops.cov-map similarity index 100% rename from tests/coverage-map/status-quo/nested_loops.cov-map rename to tests/coverage-map/nested_loops.cov-map diff --git a/tests/coverage-map/status-quo/nested_loops.rs b/tests/coverage-map/nested_loops.rs similarity index 100% rename from tests/coverage-map/status-quo/nested_loops.rs rename to tests/coverage-map/nested_loops.rs diff --git a/tests/coverage-map/status-quo/no_cov_crate.cov-map b/tests/coverage-map/no_cov_crate.cov-map similarity index 100% rename from tests/coverage-map/status-quo/no_cov_crate.cov-map rename to tests/coverage-map/no_cov_crate.cov-map diff --git a/tests/coverage-map/status-quo/no_cov_crate.rs b/tests/coverage-map/no_cov_crate.rs similarity index 100% rename from tests/coverage-map/status-quo/no_cov_crate.rs rename to tests/coverage-map/no_cov_crate.rs diff --git a/tests/coverage-map/status-quo/overflow.cov-map b/tests/coverage-map/overflow.cov-map similarity index 100% rename from tests/coverage-map/status-quo/overflow.cov-map rename to tests/coverage-map/overflow.cov-map diff --git a/tests/coverage-map/status-quo/overflow.rs b/tests/coverage-map/overflow.rs similarity index 100% rename from tests/coverage-map/status-quo/overflow.rs rename to tests/coverage-map/overflow.rs diff --git a/tests/coverage-map/status-quo/panic_unwind.cov-map b/tests/coverage-map/panic_unwind.cov-map similarity index 100% rename from tests/coverage-map/status-quo/panic_unwind.cov-map rename to tests/coverage-map/panic_unwind.cov-map diff --git a/tests/coverage-map/status-quo/panic_unwind.rs b/tests/coverage-map/panic_unwind.rs similarity index 100% rename from tests/coverage-map/status-quo/panic_unwind.rs rename to tests/coverage-map/panic_unwind.rs diff --git a/tests/coverage-map/status-quo/partial_eq.cov-map b/tests/coverage-map/partial_eq.cov-map similarity index 100% rename from tests/coverage-map/status-quo/partial_eq.cov-map rename to tests/coverage-map/partial_eq.cov-map diff --git a/tests/coverage-map/status-quo/partial_eq.rs b/tests/coverage-map/partial_eq.rs similarity index 100% rename from tests/coverage-map/status-quo/partial_eq.rs rename to tests/coverage-map/partial_eq.rs diff --git a/tests/coverage-map/status-quo/simple_loop.cov-map b/tests/coverage-map/simple_loop.cov-map similarity index 100% rename from tests/coverage-map/status-quo/simple_loop.cov-map rename to tests/coverage-map/simple_loop.cov-map diff --git a/tests/coverage-map/status-quo/simple_loop.rs b/tests/coverage-map/simple_loop.rs similarity index 100% rename from tests/coverage-map/status-quo/simple_loop.rs rename to tests/coverage-map/simple_loop.rs diff --git a/tests/coverage-map/status-quo/simple_match.cov-map b/tests/coverage-map/simple_match.cov-map similarity index 100% rename from tests/coverage-map/status-quo/simple_match.cov-map rename to tests/coverage-map/simple_match.cov-map diff --git a/tests/coverage-map/status-quo/simple_match.rs b/tests/coverage-map/simple_match.rs similarity index 100% rename from tests/coverage-map/status-quo/simple_match.rs rename to tests/coverage-map/simple_match.rs diff --git a/tests/coverage-map/status-quo/sort_groups.cov-map b/tests/coverage-map/sort_groups.cov-map similarity index 100% rename from tests/coverage-map/status-quo/sort_groups.cov-map rename to tests/coverage-map/sort_groups.cov-map diff --git a/tests/coverage-map/status-quo/sort_groups.rs b/tests/coverage-map/sort_groups.rs similarity index 100% rename from tests/coverage-map/status-quo/sort_groups.rs rename to tests/coverage-map/sort_groups.rs diff --git a/tests/coverage-map/status-quo/test_harness.cov-map b/tests/coverage-map/test_harness.cov-map similarity index 100% rename from tests/coverage-map/status-quo/test_harness.cov-map rename to tests/coverage-map/test_harness.cov-map diff --git a/tests/coverage-map/status-quo/test_harness.rs b/tests/coverage-map/test_harness.rs similarity index 100% rename from tests/coverage-map/status-quo/test_harness.rs rename to tests/coverage-map/test_harness.rs diff --git a/tests/coverage-map/status-quo/tight_inf_loop.cov-map b/tests/coverage-map/tight_inf_loop.cov-map similarity index 100% rename from tests/coverage-map/status-quo/tight_inf_loop.cov-map rename to tests/coverage-map/tight_inf_loop.cov-map diff --git a/tests/coverage-map/status-quo/tight_inf_loop.rs b/tests/coverage-map/tight_inf_loop.rs similarity index 100% rename from tests/coverage-map/status-quo/tight_inf_loop.rs rename to tests/coverage-map/tight_inf_loop.rs diff --git a/tests/coverage-map/status-quo/try_error_result.cov-map b/tests/coverage-map/try_error_result.cov-map similarity index 100% rename from tests/coverage-map/status-quo/try_error_result.cov-map rename to tests/coverage-map/try_error_result.cov-map diff --git a/tests/coverage-map/status-quo/try_error_result.rs b/tests/coverage-map/try_error_result.rs similarity index 100% rename from tests/coverage-map/status-quo/try_error_result.rs rename to tests/coverage-map/try_error_result.rs diff --git a/tests/coverage-map/status-quo/unused.cov-map b/tests/coverage-map/unused.cov-map similarity index 100% rename from tests/coverage-map/status-quo/unused.cov-map rename to tests/coverage-map/unused.cov-map diff --git a/tests/coverage-map/status-quo/unused.rs b/tests/coverage-map/unused.rs similarity index 100% rename from tests/coverage-map/status-quo/unused.rs rename to tests/coverage-map/unused.rs diff --git a/tests/coverage-map/status-quo/while.cov-map b/tests/coverage-map/while.cov-map similarity index 100% rename from tests/coverage-map/status-quo/while.cov-map rename to tests/coverage-map/while.cov-map diff --git a/tests/coverage-map/status-quo/while.rs b/tests/coverage-map/while.rs similarity index 100% rename from tests/coverage-map/status-quo/while.rs rename to tests/coverage-map/while.rs diff --git a/tests/coverage-map/status-quo/while_early_ret.cov-map b/tests/coverage-map/while_early_ret.cov-map similarity index 100% rename from tests/coverage-map/status-quo/while_early_ret.cov-map rename to tests/coverage-map/while_early_ret.cov-map diff --git a/tests/coverage-map/status-quo/while_early_ret.rs b/tests/coverage-map/while_early_ret.rs similarity index 100% rename from tests/coverage-map/status-quo/while_early_ret.rs rename to tests/coverage-map/while_early_ret.rs diff --git a/tests/coverage-map/status-quo/yield.cov-map b/tests/coverage-map/yield.cov-map similarity index 100% rename from tests/coverage-map/status-quo/yield.cov-map rename to tests/coverage-map/yield.cov-map diff --git a/tests/coverage-map/status-quo/yield.rs b/tests/coverage-map/yield.rs similarity index 100% rename from tests/coverage-map/status-quo/yield.rs rename to tests/coverage-map/yield.rs From 4b76b97bc8c7a9bf4e9d9e43f02c03b2dce23a57 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sat, 28 Oct 2023 21:27:23 +1100 Subject: [PATCH 299/435] coverage: Copy all remaining coverage-map tests into run-coverage --- tests/run-coverage/long_and_wide.coverage | 151 ++++++++++++++++++++++ tests/run-coverage/long_and_wide.rs | 150 +++++++++++++++++++++ tests/run-coverage/trivial.coverage | 4 + tests/run-coverage/trivial.rs | 3 + 4 files changed, 308 insertions(+) create mode 100644 tests/run-coverage/long_and_wide.coverage create mode 100644 tests/run-coverage/long_and_wide.rs create mode 100644 tests/run-coverage/trivial.coverage create mode 100644 tests/run-coverage/trivial.rs diff --git a/tests/run-coverage/long_and_wide.coverage b/tests/run-coverage/long_and_wide.coverage new file mode 100644 index 000000000000..d7d29ca40cdd --- /dev/null +++ b/tests/run-coverage/long_and_wide.coverage @@ -0,0 +1,151 @@ + LL| |// compile-flags: --edition=2021 + LL| |// ignore-tidy-linelength + LL| | + LL| |// This file deliberately contains line and column numbers larger than 127, + LL| |// to verify that `coverage-dump`'s ULEB128 parser can handle them. + LL| | + LL| 1|fn main() { + LL| 1| wide_function(); + LL| 1| long_function(); + LL| 1| far_function(); + LL| 1|} + LL| | + LL| |#[rustfmt::skip] + LL| 1|fn wide_function() { /* */ (); } + LL| | + LL| 1|fn long_function() { + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1|} + LL| | + LL| 1|fn far_function() {} + diff --git a/tests/run-coverage/long_and_wide.rs b/tests/run-coverage/long_and_wide.rs new file mode 100644 index 000000000000..a7cbcd480279 --- /dev/null +++ b/tests/run-coverage/long_and_wide.rs @@ -0,0 +1,150 @@ +// compile-flags: --edition=2021 +// ignore-tidy-linelength + +// This file deliberately contains line and column numbers larger than 127, +// to verify that `coverage-dump`'s ULEB128 parser can handle them. + +fn main() { + wide_function(); + long_function(); + far_function(); +} + +#[rustfmt::skip] +fn wide_function() { /* */ (); } + +fn long_function() { + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // +} + +fn far_function() {} diff --git a/tests/run-coverage/trivial.coverage b/tests/run-coverage/trivial.coverage new file mode 100644 index 000000000000..4f417979ef97 --- /dev/null +++ b/tests/run-coverage/trivial.coverage @@ -0,0 +1,4 @@ + LL| |// compile-flags: --edition=2021 + LL| | + LL| 1|fn main() {} + diff --git a/tests/run-coverage/trivial.rs b/tests/run-coverage/trivial.rs new file mode 100644 index 000000000000..d0a9b44fb360 --- /dev/null +++ b/tests/run-coverage/trivial.rs @@ -0,0 +1,3 @@ +// compile-flags: --edition=2021 + +fn main() {} From 211d4cee8eb0ef2e3dcf5426c143cecce76570cb Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sat, 28 Oct 2023 21:29:37 +1100 Subject: [PATCH 300/435] coverage: Copy all remaining run-coverage tests into coverage-map These multi-file tests were not copied over in #114843 because they weren't working, but it turns out that they just need the correct crate-type. --- src/tools/compiletest/src/runtest.rs | 2 +- .../auxiliary/inline_always_with_dead_code.rs | 22 ++++ .../auxiliary/unused_mod_helper.rs | 4 + tests/coverage-map/auxiliary/used_crate.rs | 103 ++++++++++++++++++ .../auxiliary/used_inline_crate.rs | 85 +++++++++++++++ tests/coverage-map/issue-85461.cov-map | 8 ++ tests/coverage-map/issue-85461.rs | 11 ++ tests/coverage-map/unused_mod.cov-map | 16 +++ tests/coverage-map/unused_mod.rs | 6 + tests/coverage-map/uses_crate.cov-map | 40 +++++++ tests/coverage-map/uses_crate.rs | 19 ++++ tests/coverage-map/uses_inline_crate.cov-map | 55 ++++++++++ tests/coverage-map/uses_inline_crate.rs | 22 ++++ 13 files changed, 392 insertions(+), 1 deletion(-) create mode 100644 tests/coverage-map/auxiliary/inline_always_with_dead_code.rs create mode 100644 tests/coverage-map/auxiliary/unused_mod_helper.rs create mode 100644 tests/coverage-map/auxiliary/used_crate.rs create mode 100644 tests/coverage-map/auxiliary/used_inline_crate.rs create mode 100644 tests/coverage-map/issue-85461.cov-map create mode 100644 tests/coverage-map/issue-85461.rs create mode 100644 tests/coverage-map/unused_mod.cov-map create mode 100644 tests/coverage-map/unused_mod.rs create mode 100644 tests/coverage-map/uses_crate.cov-map create mode 100644 tests/coverage-map/uses_crate.rs create mode 100644 tests/coverage-map/uses_inline_crate.cov-map create mode 100644 tests/coverage-map/uses_inline_crate.rs diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 4c6f46ef0dce..c9bc858b8e91 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2193,7 +2193,7 @@ impl<'test> TestCx<'test> { || self.is_vxworks_pure_static() || self.config.target.contains("bpf") || !self.config.target_cfg().dynamic_linking - || self.config.mode == RunCoverage + || matches!(self.config.mode, CoverageMap | RunCoverage) { // We primarily compile all auxiliary libraries as dynamic libraries // to avoid code size bloat and large binaries as much as possible diff --git a/tests/coverage-map/auxiliary/inline_always_with_dead_code.rs b/tests/coverage-map/auxiliary/inline_always_with_dead_code.rs new file mode 100644 index 000000000000..9dc50dae25ae --- /dev/null +++ b/tests/coverage-map/auxiliary/inline_always_with_dead_code.rs @@ -0,0 +1,22 @@ +// compile-flags: -Cinstrument-coverage -Ccodegen-units=4 -Copt-level=0 + +#![allow(dead_code)] + +mod foo { + #[inline(always)] + pub fn called() {} + + fn uncalled() {} +} + +pub mod bar { + pub fn call_me() { + super::foo::called(); + } +} + +pub mod baz { + pub fn call_me() { + super::foo::called(); + } +} diff --git a/tests/coverage-map/auxiliary/unused_mod_helper.rs b/tests/coverage-map/auxiliary/unused_mod_helper.rs new file mode 100644 index 000000000000..88c5dac65cb5 --- /dev/null +++ b/tests/coverage-map/auxiliary/unused_mod_helper.rs @@ -0,0 +1,4 @@ +#[allow(dead_code)] +pub fn never_called_function() { + println!("I am never called"); +} diff --git a/tests/coverage-map/auxiliary/used_crate.rs b/tests/coverage-map/auxiliary/used_crate.rs new file mode 100644 index 000000000000..c086ef21e1a9 --- /dev/null +++ b/tests/coverage-map/auxiliary/used_crate.rs @@ -0,0 +1,103 @@ +#![allow(unused_assignments, unused_variables)] +// Verify that coverage works with optimizations: +// compile-flags: -C opt-level=3 + +use std::fmt::Debug; + +pub fn used_function() { + // Initialize test constants in a way that cannot be determined at compile time, to ensure + // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from + // dependent conditions. + let is_true = std::env::args().len() == 1; + let mut countdown = 0; + if is_true { + countdown = 10; + } + use_this_lib_crate(); +} + +pub fn used_only_from_bin_crate_generic_function(arg: T) { + println!("used_only_from_bin_crate_generic_function with {:?}", arg); +} +// Expect for above function: `Unexecuted instantiation` (see below) +pub fn used_only_from_this_lib_crate_generic_function(arg: T) { + println!("used_only_from_this_lib_crate_generic_function with {:?}", arg); +} + +pub fn used_from_bin_crate_and_lib_crate_generic_function(arg: T) { + println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg); +} + +pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function(arg: T) { + println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg); +} + +pub fn unused_generic_function(arg: T) { + println!("unused_generic_function with {:?}", arg); +} + +pub fn unused_function() { + let is_true = std::env::args().len() == 1; + let mut countdown = 2; + if !is_true { + countdown = 20; + } +} + +#[allow(dead_code)] +fn unused_private_function() { + let is_true = std::env::args().len() == 1; + let mut countdown = 2; + if !is_true { + countdown = 20; + } +} + +fn use_this_lib_crate() { + used_from_bin_crate_and_lib_crate_generic_function("used from library used_crate.rs"); + used_with_same_type_from_bin_crate_and_lib_crate_generic_function( + "used from library used_crate.rs", + ); + let some_vec = vec![5, 6, 7, 8]; + used_only_from_this_lib_crate_generic_function(some_vec); + used_only_from_this_lib_crate_generic_function("used ONLY from library used_crate.rs"); +} + +// FIXME(#79651): "Unexecuted instantiation" errors appear in coverage results, +// for example: +// +// | Unexecuted instantiation: used_crate::used_only_from_bin_crate_generic_function::<_> +// +// These notices appear when `llvm-cov` shows instantiations. This may be a +// default option, but it can be suppressed with: +// +// ```shell +// $ `llvm-cov show --show-instantiations=0 ...` +// ``` +// +// The notice is triggered because the function is unused by the library itself, +// and when the library is compiled, a synthetic function is generated, so +// unused function coverage can be reported. Coverage can be skipped for unused +// generic functions with: +// +// ```shell +// $ `rustc -Zunstable-options -C instrument-coverage=except-unused-generics ...` +// ``` +// +// Even though this function is used by `uses_crate.rs` (and +// counted), with substitutions for `T`, those instantiations are only generated +// when the generic function is actually used (from the binary, not from this +// library crate). So the test result shows coverage for all instantiated +// versions and their generic type substitutions, plus the `Unexecuted +// instantiation` message for the non-substituted version. This is valid, but +// unfortunately a little confusing. +// +// The library crate has its own coverage map, and the only way to show unused +// coverage of a generic function is to include the generic function in the +// coverage map, marked as an "unused function". If the library were used by +// another binary that never used this generic function, then it would be valid +// to show the unused generic, with unknown substitution (`_`). +// +// The alternative is to exclude all generics from being included in the "unused +// functions" list, which would then omit coverage results for +// `unused_generic_function()`, below. diff --git a/tests/coverage-map/auxiliary/used_inline_crate.rs b/tests/coverage-map/auxiliary/used_inline_crate.rs new file mode 100644 index 000000000000..e8929de6b360 --- /dev/null +++ b/tests/coverage-map/auxiliary/used_inline_crate.rs @@ -0,0 +1,85 @@ +#![allow(unused_assignments, unused_variables)] +// Verify that coverage works with optimizations: +// compile-flags: -C opt-level=3 + +use std::fmt::Debug; + +pub fn used_function() { + // Initialize test constants in a way that cannot be determined at compile time, to ensure + // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from + // dependent conditions. + let is_true = std::env::args().len() == 1; + let mut countdown = 0; + if is_true { + countdown = 10; + } + use_this_lib_crate(); +} + +#[inline(always)] +pub fn used_inline_function() { + // Initialize test constants in a way that cannot be determined at compile time, to ensure + // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from + // dependent conditions. + let is_true = std::env::args().len() == 1; + let mut countdown = 0; + if is_true { + countdown = 10; + } + use_this_lib_crate(); +} + +#[inline(always)] +pub fn used_only_from_bin_crate_generic_function(arg: T) { + println!("used_only_from_bin_crate_generic_function with {:?}", arg); +} +// Expect for above function: `Unexecuted instantiation` (see notes in `used_crate.rs`) + +#[inline(always)] +pub fn used_only_from_this_lib_crate_generic_function(arg: T) { + println!("used_only_from_this_lib_crate_generic_function with {:?}", arg); +} + +#[inline(always)] +pub fn used_from_bin_crate_and_lib_crate_generic_function(arg: T) { + println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg); +} + +#[inline(always)] +pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function(arg: T) { + println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg); +} + +#[inline(always)] +pub fn unused_generic_function(arg: T) { + println!("unused_generic_function with {:?}", arg); +} + +#[inline(always)] +pub fn unused_function() { + let is_true = std::env::args().len() == 1; + let mut countdown = 2; + if !is_true { + countdown = 20; + } +} + +#[inline(always)] +#[allow(dead_code)] +fn unused_private_function() { + let is_true = std::env::args().len() == 1; + let mut countdown = 2; + if !is_true { + countdown = 20; + } +} + +fn use_this_lib_crate() { + used_from_bin_crate_and_lib_crate_generic_function("used from library used_crate.rs"); + used_with_same_type_from_bin_crate_and_lib_crate_generic_function( + "used from library used_crate.rs", + ); + let some_vec = vec![5, 6, 7, 8]; + used_only_from_this_lib_crate_generic_function(some_vec); + used_only_from_this_lib_crate_generic_function("used ONLY from library used_crate.rs"); +} diff --git a/tests/coverage-map/issue-85461.cov-map b/tests/coverage-map/issue-85461.cov-map new file mode 100644 index 000000000000..d1c449b9a355 --- /dev/null +++ b/tests/coverage-map/issue-85461.cov-map @@ -0,0 +1,8 @@ +Function name: issue_85461::main +Raw bytes (9): 0x[01, 01, 00, 01, 01, 08, 01, 03, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 8, 1) to (start + 3, 2) + diff --git a/tests/coverage-map/issue-85461.rs b/tests/coverage-map/issue-85461.rs new file mode 100644 index 000000000000..9d4c90a827ee --- /dev/null +++ b/tests/coverage-map/issue-85461.rs @@ -0,0 +1,11 @@ +// Regression test for #85461: MSVC sometimes fail to link with dead code and #[inline(always)] + +// aux-build:inline_always_with_dead_code.rs +extern crate inline_always_with_dead_code; + +use inline_always_with_dead_code::{bar, baz}; + +fn main() { + bar::call_me(); + baz::call_me(); +} diff --git a/tests/coverage-map/unused_mod.cov-map b/tests/coverage-map/unused_mod.cov-map new file mode 100644 index 000000000000..241cb2610ffc --- /dev/null +++ b/tests/coverage-map/unused_mod.cov-map @@ -0,0 +1,16 @@ +Function name: unused_mod::main +Raw bytes (9): 0x[01, 02, 00, 01, 01, 04, 01, 02, 02] +Number of files: 1 +- file 0 => global file 2 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 4, 1) to (start + 2, 2) + +Function name: unused_mod::unused_module::never_called_function (unused) +Raw bytes (9): 0x[01, 01, 00, 01, 00, 02, 01, 02, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Zero) at (prev + 2, 1) to (start + 2, 2) + diff --git a/tests/coverage-map/unused_mod.rs b/tests/coverage-map/unused_mod.rs new file mode 100644 index 000000000000..6e62839c9985 --- /dev/null +++ b/tests/coverage-map/unused_mod.rs @@ -0,0 +1,6 @@ +#[path = "auxiliary/unused_mod_helper.rs"] +mod unused_module; + +fn main() { + println!("hello world!"); +} diff --git a/tests/coverage-map/uses_crate.cov-map b/tests/coverage-map/uses_crate.cov-map new file mode 100644 index 000000000000..9c06eab70050 --- /dev/null +++ b/tests/coverage-map/uses_crate.cov-map @@ -0,0 +1,40 @@ +Function name: used_crate::used_from_bin_crate_and_lib_crate_generic_function::> +Raw bytes (9): 0x[01, 01, 00, 01, 01, 1b, 01, 02, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 27, 1) to (start + 2, 2) + +Function name: used_crate::used_only_from_bin_crate_generic_function::<&alloc::vec::Vec> +Raw bytes (9): 0x[01, 01, 00, 01, 01, 13, 01, 02, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 19, 1) to (start + 2, 2) + +Function name: used_crate::used_only_from_bin_crate_generic_function::<&str> +Raw bytes (9): 0x[01, 01, 00, 01, 01, 13, 01, 02, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 19, 1) to (start + 2, 2) + +Function name: used_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function::<&str> +Raw bytes (9): 0x[01, 01, 00, 01, 01, 1f, 01, 02, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 31, 1) to (start + 2, 2) + +Function name: uses_crate::main +Raw bytes (9): 0x[01, 02, 00, 01, 01, 0c, 01, 07, 02] +Number of files: 1 +- file 0 => global file 2 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 12, 1) to (start + 7, 2) + diff --git a/tests/coverage-map/uses_crate.rs b/tests/coverage-map/uses_crate.rs new file mode 100644 index 000000000000..ab203ad781d6 --- /dev/null +++ b/tests/coverage-map/uses_crate.rs @@ -0,0 +1,19 @@ +// This test was failing on Linux for a while due to #110393 somehow making +// the unused functions not instrumented, but it seems to be fine now. + +// Validates coverage now works with optimizations +// compile-flags: -C opt-level=3 + +#![allow(unused_assignments, unused_variables)] + +// aux-build:used_crate.rs +extern crate used_crate; + +fn main() { + used_crate::used_function(); + let some_vec = vec![1, 2, 3, 4]; + used_crate::used_only_from_bin_crate_generic_function(&some_vec); + used_crate::used_only_from_bin_crate_generic_function("used from bin uses_crate.rs"); + used_crate::used_from_bin_crate_and_lib_crate_generic_function(some_vec); + used_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function("interesting?"); +} diff --git a/tests/coverage-map/uses_inline_crate.cov-map b/tests/coverage-map/uses_inline_crate.cov-map new file mode 100644 index 000000000000..6b621825c886 --- /dev/null +++ b/tests/coverage-map/uses_inline_crate.cov-map @@ -0,0 +1,55 @@ +Function name: used_inline_crate::used_from_bin_crate_and_lib_crate_generic_function::> +Raw bytes (9): 0x[01, 01, 00, 01, 01, 2c, 01, 02, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 44, 1) to (start + 2, 2) + +Function name: used_inline_crate::used_inline_function +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 14, 01, 06, 0f, 05, 06, 10, 02, 06, 02, 02, 06, 00, 07, 07, 01, 05, 01, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 2 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +- expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 20, 1) to (start + 6, 15) +- Code(Counter(1)) at (prev + 6, 16) to (start + 2, 6) +- Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7) + = (c0 - c1) +- Code(Expression(1, Add)) at (prev + 1, 5) to (start + 1, 2) + = (c1 + (c0 - c1)) + +Function name: used_inline_crate::used_only_from_bin_crate_generic_function::<&alloc::vec::Vec> +Raw bytes (9): 0x[01, 01, 00, 01, 01, 21, 01, 02, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 33, 1) to (start + 2, 2) + +Function name: used_inline_crate::used_only_from_bin_crate_generic_function::<&str> +Raw bytes (9): 0x[01, 01, 00, 01, 01, 21, 01, 02, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 33, 1) to (start + 2, 2) + +Function name: used_inline_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function::<&str> +Raw bytes (9): 0x[01, 01, 00, 01, 01, 31, 01, 02, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 49, 1) to (start + 2, 2) + +Function name: uses_inline_crate::main +Raw bytes (9): 0x[01, 02, 00, 01, 01, 0c, 01, 0a, 02] +Number of files: 1 +- file 0 => global file 2 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 12, 1) to (start + 10, 2) + diff --git a/tests/coverage-map/uses_inline_crate.rs b/tests/coverage-map/uses_inline_crate.rs new file mode 100644 index 000000000000..d7b4c3c057f4 --- /dev/null +++ b/tests/coverage-map/uses_inline_crate.rs @@ -0,0 +1,22 @@ +// This test was failing on Linux for a while due to #110393 somehow making +// the unused functions not instrumented, but it seems to be fine now. + +// Validates coverage now works with optimizations +// compile-flags: -C opt-level=3 + +#![allow(unused_assignments, unused_variables)] + +// aux-build:used_inline_crate.rs +extern crate used_inline_crate; + +fn main() { + used_inline_crate::used_function(); + used_inline_crate::used_inline_function(); + let some_vec = vec![1, 2, 3, 4]; + used_inline_crate::used_only_from_bin_crate_generic_function(&some_vec); + used_inline_crate::used_only_from_bin_crate_generic_function("used from bin uses_crate.rs"); + used_inline_crate::used_from_bin_crate_and_lib_crate_generic_function(some_vec); + used_inline_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function( + "interesting?", + ); +} From e585a992300093c13e477f2eb7e66842d9275131 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 2 Nov 2023 13:07:57 +1100 Subject: [PATCH 301/435] coverage: Give each coverage test mode a separate output directory When multiple test modes share the same test directory, this will allow them to avoid interfering with each others' files and timestamps. --- src/tools/compiletest/src/common.rs | 12 +++++++++++- src/tools/compiletest/src/runtest.rs | 2 +- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 0e1bf0c6c2dc..a908218fff14 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -78,7 +78,7 @@ impl Default for Mode { } impl Mode { - pub fn disambiguator(self) -> &'static str { + pub fn aux_dir_disambiguator(self) -> &'static str { // Pretty-printing tests could run concurrently, and if they do, // they need to keep their output segregated. match self { @@ -86,6 +86,15 @@ impl Mode { _ => "", } } + + pub fn output_dir_disambiguator(self) -> &'static str { + // Coverage tests use the same test files for multiple test modes, + // so each mode should have a separate output directory. + match self { + CoverageMap | RunCoverage => self.to_str(), + _ => "", + } + } } string_enum! { @@ -699,6 +708,7 @@ pub fn output_testname_unique( let mode = config.compare_mode.as_ref().map_or("", |m| m.to_str()); let debugger = config.debugger.as_ref().map_or("", |m| m.to_str()); PathBuf::from(&testpaths.file.file_stem().unwrap()) + .with_extra_extension(config.mode.output_dir_disambiguator()) .with_extra_extension(revision.unwrap_or("")) .with_extra_extension(mode) .with_extra_extension(debugger) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index c9bc858b8e91..748ee2fe052e 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2720,7 +2720,7 @@ impl<'test> TestCx<'test> { fn aux_output_dir_name(&self) -> PathBuf { self.output_base_dir() .join("auxiliary") - .with_extra_extension(self.config.mode.disambiguator()) + .with_extra_extension(self.config.mode.aux_dir_disambiguator()) } /// Generates a unique name for the test, such as `testname.revision.mode`. From 3509aed632dd7badac18b071bcd7e1ca53f9d1c6 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 1 Nov 2023 20:02:09 +1100 Subject: [PATCH 302/435] coverage: Add `./x.py test coverage`, an alias for `coverage-map` and `run-coverage` --- src/bootstrap/src/core/build_steps/test.rs | 50 ++++++++++++++++++++++ src/bootstrap/src/core/builder.rs | 1 + 2 files changed, 51 insertions(+) diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index e2b515a30867..c964d220cc3d 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -1349,6 +1349,56 @@ host_test!(RunMakeFullDeps { default_test!(Assembly { path: "tests/assembly", mode: "assembly", suite: "assembly" }); +/// Custom test step that is responsible for running the coverage tests +/// in multiple different modes. +/// +/// Each individual mode also has its own alias that will run the tests in +/// just that mode. +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct Coverage { + pub compiler: Compiler, + pub target: TargetSelection, +} + +impl Coverage { + const SUITE: &'static str = "coverage"; +} + +impl Step for Coverage { + type Output = (); + const DEFAULT: bool = false; + const ONLY_HOSTS: bool = false; + + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + run.alias(Self::SUITE) + } + + fn make_run(run: RunConfig<'_>) { + let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple()); + + run.builder.ensure(Coverage { compiler, target: run.target }); + } + + fn run(self, builder: &Builder<'_>) { + builder.ensure(Compiletest { + compiler: self.compiler, + target: self.target, + mode: "coverage-map", + suite: "coverage-map", + path: "tests/coverage-map", + compare_mode: None, + }); + builder.ensure(Compiletest { + compiler: self.compiler, + target: self.target, + mode: "run-coverage", + suite: "run-coverage", + path: "tests/run-coverage", + compare_mode: None, + }); + } +} + default_test!(CoverageMap { path: "tests/coverage-map", mode: "coverage-map", diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs index 44cdbe38de36..38eb46332738 100644 --- a/src/bootstrap/src/core/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -727,6 +727,7 @@ impl<'a> Builder<'a> { test::Tidy, test::Ui, test::RunPassValgrind, + test::Coverage, test::CoverageMap, test::RunCoverage, test::MirOpt, From aea7c27eae5e34b11c64ec6d11c75627ef24f8b1 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 1 Nov 2023 21:23:46 +1100 Subject: [PATCH 303/435] coverage: Set up a macro for declaring unified coverage test suites --- src/bootstrap/src/core/build_steps/test.rs | 53 ++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index c964d220cc3d..758a801f8a76 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -1305,6 +1305,47 @@ macro_rules! test_definitions { }; } +/// Declares an alias for running the [`Coverage`] tests in only one mode. +/// Adapted from [`test_definitions`]. +macro_rules! coverage_test_alias { + ($name:ident { + alias_and_mode: $alias_and_mode:expr, + default: $default:expr, + only_hosts: $only_hosts:expr $(,)? + }) => { + #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] + pub struct $name { + pub compiler: Compiler, + pub target: TargetSelection, + } + + impl $name { + const MODE: &'static str = $alias_and_mode; + } + + impl Step for $name { + type Output = (); + const DEFAULT: bool = $default; + const ONLY_HOSTS: bool = $only_hosts; + + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + run.alias($alias_and_mode) + } + + fn make_run(run: RunConfig<'_>) { + let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple()); + + run.builder.ensure($name { compiler, target: run.target }); + } + + fn run(self, builder: &Builder<'_>) { + Coverage { compiler: self.compiler, target: self.target } + .run_unified_suite(builder, Self::MODE) + } + } + }; +} + default_test!(Ui { path: "tests/ui", mode: "ui", suite: "ui" }); default_test!(RunPassValgrind { @@ -1361,7 +1402,19 @@ pub struct Coverage { } impl Coverage { + const PATH: &'static str = "tests/coverage"; const SUITE: &'static str = "coverage"; + + fn run_unified_suite(&self, builder: &Builder<'_>, mode: &'static str) { + builder.ensure(Compiletest { + compiler: self.compiler, + target: self.target, + mode, + suite: Self::SUITE, + path: Self::PATH, + compare_mode: None, + }) + } } impl Step for Coverage { From e9d04c5e2444526ffde83662f2d57fa35c772891 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 1 Nov 2023 21:26:53 +1100 Subject: [PATCH 304/435] coverage: Migrate `tests/run-coverage` into `tests/coverage` --- src/bootstrap/src/core/build_steps/test.rs | 16 +++++++--------- tests/{run-coverage => coverage}/abort.coverage | 0 tests/{run-coverage => coverage}/abort.rs | 0 tests/{run-coverage => coverage}/assert.coverage | 0 tests/{run-coverage => coverage}/assert.rs | 0 tests/{run-coverage => coverage}/async.coverage | 0 tests/{run-coverage => coverage}/async.rs | 0 tests/{run-coverage => coverage}/async2.coverage | 0 tests/{run-coverage => coverage}/async2.rs | 0 .../auxiliary/inline_always_with_dead_code.rs | 0 .../auxiliary/unused_mod_helper.rs | 0 .../auxiliary/used_crate.rs | 0 .../auxiliary/used_inline_crate.rs | 0 .../bad_counter_ids.coverage | 0 .../bad_counter_ids.rs | 0 .../{run-coverage => coverage}/closure.coverage | 0 tests/{run-coverage => coverage}/closure.rs | 0 .../closure_bug.coverage | 0 tests/{run-coverage => coverage}/closure_bug.rs | 0 .../closure_macro.coverage | 0 .../{run-coverage => coverage}/closure_macro.rs | 0 .../closure_macro_async.coverage | 0 .../closure_macro_async.rs | 0 .../conditions.coverage | 0 tests/{run-coverage => coverage}/conditions.rs | 0 .../{run-coverage => coverage}/continue.coverage | 0 tests/{run-coverage => coverage}/continue.rs | 0 .../coroutine.coverage | 0 tests/{run-coverage => coverage}/coroutine.rs | 0 .../dead_code.coverage | 0 tests/{run-coverage => coverage}/dead_code.rs | 0 .../drop_trait.coverage | 0 tests/{run-coverage => coverage}/drop_trait.rs | 0 .../fn_sig_into_try.coverage | 0 .../fn_sig_into_try.rs | 0 .../{run-coverage => coverage}/generics.coverage | 0 tests/{run-coverage => coverage}/generics.rs | 0 tests/{run-coverage => coverage}/if.coverage | 0 tests/{run-coverage => coverage}/if.rs | 0 .../{run-coverage => coverage}/if_else.coverage | 0 tests/{run-coverage => coverage}/if_else.rs | 0 .../inline-dead.coverage | 0 tests/{run-coverage => coverage}/inline-dead.rs | 0 tests/{run-coverage => coverage}/inline.coverage | 0 tests/{run-coverage => coverage}/inline.rs | 0 .../inner_items.coverage | 0 tests/{run-coverage => coverage}/inner_items.rs | 0 .../issue-83601.coverage | 0 tests/{run-coverage => coverage}/issue-83601.rs | 0 .../issue-84561.coverage | 0 tests/{run-coverage => coverage}/issue-84561.rs | 0 .../issue-85461.coverage | 0 tests/{run-coverage => coverage}/issue-85461.rs | 0 .../issue-93054.coverage | 0 tests/{run-coverage => coverage}/issue-93054.rs | 0 .../lazy_boolean.coverage | 0 tests/{run-coverage => coverage}/lazy_boolean.rs | 0 .../long_and_wide.coverage | 0 .../{run-coverage => coverage}/long_and_wide.rs | 0 .../loop_break_value.coverage | 0 .../loop_break_value.rs | 0 .../loops_branches.coverage | 0 .../{run-coverage => coverage}/loops_branches.rs | 0 .../match_or_pattern.coverage | 0 .../match_or_pattern.rs | 0 .../nested_loops.coverage | 0 tests/{run-coverage => coverage}/nested_loops.rs | 0 .../no_cov_crate.coverage | 0 tests/{run-coverage => coverage}/no_cov_crate.rs | 0 .../{run-coverage => coverage}/overflow.coverage | 0 tests/{run-coverage => coverage}/overflow.rs | 0 .../panic_unwind.coverage | 0 tests/{run-coverage => coverage}/panic_unwind.rs | 0 .../partial_eq.coverage | 0 tests/{run-coverage => coverage}/partial_eq.rs | 0 .../simple_loop.coverage | 0 tests/{run-coverage => coverage}/simple_loop.rs | 0 .../simple_match.coverage | 0 tests/{run-coverage => coverage}/simple_match.rs | 0 .../sort_groups.coverage | 0 tests/{run-coverage => coverage}/sort_groups.rs | 0 .../test_harness.coverage | 0 tests/{run-coverage => coverage}/test_harness.rs | 0 .../tight_inf_loop.coverage | 0 .../{run-coverage => coverage}/tight_inf_loop.rs | 0 .../{run-coverage => coverage}/trivial.coverage | 0 tests/{run-coverage => coverage}/trivial.rs | 0 .../try_error_result.coverage | 0 .../try_error_result.rs | 0 .../unreachable.coverage | 0 tests/{run-coverage => coverage}/unreachable.rs | 0 tests/{run-coverage => coverage}/unused.coverage | 0 tests/{run-coverage => coverage}/unused.rs | 0 .../unused_mod.coverage | 0 tests/{run-coverage => coverage}/unused_mod.rs | 0 .../uses_crate.coverage | 0 tests/{run-coverage => coverage}/uses_crate.rs | 0 .../uses_inline_crate.coverage | 0 .../uses_inline_crate.rs | 0 tests/{run-coverage => coverage}/while.coverage | 0 tests/{run-coverage => coverage}/while.rs | 0 .../while_early_ret.coverage | 0 .../while_early_ret.rs | 0 tests/{run-coverage => coverage}/yield.coverage | 0 tests/{run-coverage => coverage}/yield.rs | 0 105 files changed, 7 insertions(+), 9 deletions(-) rename tests/{run-coverage => coverage}/abort.coverage (100%) rename tests/{run-coverage => coverage}/abort.rs (100%) rename tests/{run-coverage => coverage}/assert.coverage (100%) rename tests/{run-coverage => coverage}/assert.rs (100%) rename tests/{run-coverage => coverage}/async.coverage (100%) rename tests/{run-coverage => coverage}/async.rs (100%) rename tests/{run-coverage => coverage}/async2.coverage (100%) rename tests/{run-coverage => coverage}/async2.rs (100%) rename tests/{run-coverage => coverage}/auxiliary/inline_always_with_dead_code.rs (100%) rename tests/{run-coverage => coverage}/auxiliary/unused_mod_helper.rs (100%) rename tests/{run-coverage => coverage}/auxiliary/used_crate.rs (100%) rename tests/{run-coverage => coverage}/auxiliary/used_inline_crate.rs (100%) rename tests/{run-coverage => coverage}/bad_counter_ids.coverage (100%) rename tests/{run-coverage => coverage}/bad_counter_ids.rs (100%) rename tests/{run-coverage => coverage}/closure.coverage (100%) rename tests/{run-coverage => coverage}/closure.rs (100%) rename tests/{run-coverage => coverage}/closure_bug.coverage (100%) rename tests/{run-coverage => coverage}/closure_bug.rs (100%) rename tests/{run-coverage => coverage}/closure_macro.coverage (100%) rename tests/{run-coverage => coverage}/closure_macro.rs (100%) rename tests/{run-coverage => coverage}/closure_macro_async.coverage (100%) rename tests/{run-coverage => coverage}/closure_macro_async.rs (100%) rename tests/{run-coverage => coverage}/conditions.coverage (100%) rename tests/{run-coverage => coverage}/conditions.rs (100%) rename tests/{run-coverage => coverage}/continue.coverage (100%) rename tests/{run-coverage => coverage}/continue.rs (100%) rename tests/{run-coverage => coverage}/coroutine.coverage (100%) rename tests/{run-coverage => coverage}/coroutine.rs (100%) rename tests/{run-coverage => coverage}/dead_code.coverage (100%) rename tests/{run-coverage => coverage}/dead_code.rs (100%) rename tests/{run-coverage => coverage}/drop_trait.coverage (100%) rename tests/{run-coverage => coverage}/drop_trait.rs (100%) rename tests/{run-coverage => coverage}/fn_sig_into_try.coverage (100%) rename tests/{run-coverage => coverage}/fn_sig_into_try.rs (100%) rename tests/{run-coverage => coverage}/generics.coverage (100%) rename tests/{run-coverage => coverage}/generics.rs (100%) rename tests/{run-coverage => coverage}/if.coverage (100%) rename tests/{run-coverage => coverage}/if.rs (100%) rename tests/{run-coverage => coverage}/if_else.coverage (100%) rename tests/{run-coverage => coverage}/if_else.rs (100%) rename tests/{run-coverage => coverage}/inline-dead.coverage (100%) rename tests/{run-coverage => coverage}/inline-dead.rs (100%) rename tests/{run-coverage => coverage}/inline.coverage (100%) rename tests/{run-coverage => coverage}/inline.rs (100%) rename tests/{run-coverage => coverage}/inner_items.coverage (100%) rename tests/{run-coverage => coverage}/inner_items.rs (100%) rename tests/{run-coverage => coverage}/issue-83601.coverage (100%) rename tests/{run-coverage => coverage}/issue-83601.rs (100%) rename tests/{run-coverage => coverage}/issue-84561.coverage (100%) rename tests/{run-coverage => coverage}/issue-84561.rs (100%) rename tests/{run-coverage => coverage}/issue-85461.coverage (100%) rename tests/{run-coverage => coverage}/issue-85461.rs (100%) rename tests/{run-coverage => coverage}/issue-93054.coverage (100%) rename tests/{run-coverage => coverage}/issue-93054.rs (100%) rename tests/{run-coverage => coverage}/lazy_boolean.coverage (100%) rename tests/{run-coverage => coverage}/lazy_boolean.rs (100%) rename tests/{run-coverage => coverage}/long_and_wide.coverage (100%) rename tests/{run-coverage => coverage}/long_and_wide.rs (100%) rename tests/{run-coverage => coverage}/loop_break_value.coverage (100%) rename tests/{run-coverage => coverage}/loop_break_value.rs (100%) rename tests/{run-coverage => coverage}/loops_branches.coverage (100%) rename tests/{run-coverage => coverage}/loops_branches.rs (100%) rename tests/{run-coverage => coverage}/match_or_pattern.coverage (100%) rename tests/{run-coverage => coverage}/match_or_pattern.rs (100%) rename tests/{run-coverage => coverage}/nested_loops.coverage (100%) rename tests/{run-coverage => coverage}/nested_loops.rs (100%) rename tests/{run-coverage => coverage}/no_cov_crate.coverage (100%) rename tests/{run-coverage => coverage}/no_cov_crate.rs (100%) rename tests/{run-coverage => coverage}/overflow.coverage (100%) rename tests/{run-coverage => coverage}/overflow.rs (100%) rename tests/{run-coverage => coverage}/panic_unwind.coverage (100%) rename tests/{run-coverage => coverage}/panic_unwind.rs (100%) rename tests/{run-coverage => coverage}/partial_eq.coverage (100%) rename tests/{run-coverage => coverage}/partial_eq.rs (100%) rename tests/{run-coverage => coverage}/simple_loop.coverage (100%) rename tests/{run-coverage => coverage}/simple_loop.rs (100%) rename tests/{run-coverage => coverage}/simple_match.coverage (100%) rename tests/{run-coverage => coverage}/simple_match.rs (100%) rename tests/{run-coverage => coverage}/sort_groups.coverage (100%) rename tests/{run-coverage => coverage}/sort_groups.rs (100%) rename tests/{run-coverage => coverage}/test_harness.coverage (100%) rename tests/{run-coverage => coverage}/test_harness.rs (100%) rename tests/{run-coverage => coverage}/tight_inf_loop.coverage (100%) rename tests/{run-coverage => coverage}/tight_inf_loop.rs (100%) rename tests/{run-coverage => coverage}/trivial.coverage (100%) rename tests/{run-coverage => coverage}/trivial.rs (100%) rename tests/{run-coverage => coverage}/try_error_result.coverage (100%) rename tests/{run-coverage => coverage}/try_error_result.rs (100%) rename tests/{run-coverage => coverage}/unreachable.coverage (100%) rename tests/{run-coverage => coverage}/unreachable.rs (100%) rename tests/{run-coverage => coverage}/unused.coverage (100%) rename tests/{run-coverage => coverage}/unused.rs (100%) rename tests/{run-coverage => coverage}/unused_mod.coverage (100%) rename tests/{run-coverage => coverage}/unused_mod.rs (100%) rename tests/{run-coverage => coverage}/uses_crate.coverage (100%) rename tests/{run-coverage => coverage}/uses_crate.rs (100%) rename tests/{run-coverage => coverage}/uses_inline_crate.coverage (100%) rename tests/{run-coverage => coverage}/uses_inline_crate.rs (100%) rename tests/{run-coverage => coverage}/while.coverage (100%) rename tests/{run-coverage => coverage}/while.rs (100%) rename tests/{run-coverage => coverage}/while_early_ret.coverage (100%) rename tests/{run-coverage => coverage}/while_early_ret.rs (100%) rename tests/{run-coverage => coverage}/yield.coverage (100%) rename tests/{run-coverage => coverage}/yield.rs (100%) diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 758a801f8a76..11c9e1c7bc25 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -1441,14 +1441,7 @@ impl Step for Coverage { path: "tests/coverage-map", compare_mode: None, }); - builder.ensure(Compiletest { - compiler: self.compiler, - target: self.target, - mode: "run-coverage", - suite: "run-coverage", - path: "tests/run-coverage", - compare_mode: None, - }); + self.run_unified_suite(builder, RunCoverage::MODE); } } @@ -1458,7 +1451,12 @@ default_test!(CoverageMap { suite: "coverage-map" }); -host_test!(RunCoverage { path: "tests/run-coverage", mode: "run-coverage", suite: "run-coverage" }); +coverage_test_alias!(RunCoverage { + alias_and_mode: "run-coverage", + default: true, + only_hosts: true, +}); + host_test!(RunCoverageRustdoc { path: "tests/run-coverage-rustdoc", mode: "run-coverage", diff --git a/tests/run-coverage/abort.coverage b/tests/coverage/abort.coverage similarity index 100% rename from tests/run-coverage/abort.coverage rename to tests/coverage/abort.coverage diff --git a/tests/run-coverage/abort.rs b/tests/coverage/abort.rs similarity index 100% rename from tests/run-coverage/abort.rs rename to tests/coverage/abort.rs diff --git a/tests/run-coverage/assert.coverage b/tests/coverage/assert.coverage similarity index 100% rename from tests/run-coverage/assert.coverage rename to tests/coverage/assert.coverage diff --git a/tests/run-coverage/assert.rs b/tests/coverage/assert.rs similarity index 100% rename from tests/run-coverage/assert.rs rename to tests/coverage/assert.rs diff --git a/tests/run-coverage/async.coverage b/tests/coverage/async.coverage similarity index 100% rename from tests/run-coverage/async.coverage rename to tests/coverage/async.coverage diff --git a/tests/run-coverage/async.rs b/tests/coverage/async.rs similarity index 100% rename from tests/run-coverage/async.rs rename to tests/coverage/async.rs diff --git a/tests/run-coverage/async2.coverage b/tests/coverage/async2.coverage similarity index 100% rename from tests/run-coverage/async2.coverage rename to tests/coverage/async2.coverage diff --git a/tests/run-coverage/async2.rs b/tests/coverage/async2.rs similarity index 100% rename from tests/run-coverage/async2.rs rename to tests/coverage/async2.rs diff --git a/tests/run-coverage/auxiliary/inline_always_with_dead_code.rs b/tests/coverage/auxiliary/inline_always_with_dead_code.rs similarity index 100% rename from tests/run-coverage/auxiliary/inline_always_with_dead_code.rs rename to tests/coverage/auxiliary/inline_always_with_dead_code.rs diff --git a/tests/run-coverage/auxiliary/unused_mod_helper.rs b/tests/coverage/auxiliary/unused_mod_helper.rs similarity index 100% rename from tests/run-coverage/auxiliary/unused_mod_helper.rs rename to tests/coverage/auxiliary/unused_mod_helper.rs diff --git a/tests/run-coverage/auxiliary/used_crate.rs b/tests/coverage/auxiliary/used_crate.rs similarity index 100% rename from tests/run-coverage/auxiliary/used_crate.rs rename to tests/coverage/auxiliary/used_crate.rs diff --git a/tests/run-coverage/auxiliary/used_inline_crate.rs b/tests/coverage/auxiliary/used_inline_crate.rs similarity index 100% rename from tests/run-coverage/auxiliary/used_inline_crate.rs rename to tests/coverage/auxiliary/used_inline_crate.rs diff --git a/tests/run-coverage/bad_counter_ids.coverage b/tests/coverage/bad_counter_ids.coverage similarity index 100% rename from tests/run-coverage/bad_counter_ids.coverage rename to tests/coverage/bad_counter_ids.coverage diff --git a/tests/run-coverage/bad_counter_ids.rs b/tests/coverage/bad_counter_ids.rs similarity index 100% rename from tests/run-coverage/bad_counter_ids.rs rename to tests/coverage/bad_counter_ids.rs diff --git a/tests/run-coverage/closure.coverage b/tests/coverage/closure.coverage similarity index 100% rename from tests/run-coverage/closure.coverage rename to tests/coverage/closure.coverage diff --git a/tests/run-coverage/closure.rs b/tests/coverage/closure.rs similarity index 100% rename from tests/run-coverage/closure.rs rename to tests/coverage/closure.rs diff --git a/tests/run-coverage/closure_bug.coverage b/tests/coverage/closure_bug.coverage similarity index 100% rename from tests/run-coverage/closure_bug.coverage rename to tests/coverage/closure_bug.coverage diff --git a/tests/run-coverage/closure_bug.rs b/tests/coverage/closure_bug.rs similarity index 100% rename from tests/run-coverage/closure_bug.rs rename to tests/coverage/closure_bug.rs diff --git a/tests/run-coverage/closure_macro.coverage b/tests/coverage/closure_macro.coverage similarity index 100% rename from tests/run-coverage/closure_macro.coverage rename to tests/coverage/closure_macro.coverage diff --git a/tests/run-coverage/closure_macro.rs b/tests/coverage/closure_macro.rs similarity index 100% rename from tests/run-coverage/closure_macro.rs rename to tests/coverage/closure_macro.rs diff --git a/tests/run-coverage/closure_macro_async.coverage b/tests/coverage/closure_macro_async.coverage similarity index 100% rename from tests/run-coverage/closure_macro_async.coverage rename to tests/coverage/closure_macro_async.coverage diff --git a/tests/run-coverage/closure_macro_async.rs b/tests/coverage/closure_macro_async.rs similarity index 100% rename from tests/run-coverage/closure_macro_async.rs rename to tests/coverage/closure_macro_async.rs diff --git a/tests/run-coverage/conditions.coverage b/tests/coverage/conditions.coverage similarity index 100% rename from tests/run-coverage/conditions.coverage rename to tests/coverage/conditions.coverage diff --git a/tests/run-coverage/conditions.rs b/tests/coverage/conditions.rs similarity index 100% rename from tests/run-coverage/conditions.rs rename to tests/coverage/conditions.rs diff --git a/tests/run-coverage/continue.coverage b/tests/coverage/continue.coverage similarity index 100% rename from tests/run-coverage/continue.coverage rename to tests/coverage/continue.coverage diff --git a/tests/run-coverage/continue.rs b/tests/coverage/continue.rs similarity index 100% rename from tests/run-coverage/continue.rs rename to tests/coverage/continue.rs diff --git a/tests/run-coverage/coroutine.coverage b/tests/coverage/coroutine.coverage similarity index 100% rename from tests/run-coverage/coroutine.coverage rename to tests/coverage/coroutine.coverage diff --git a/tests/run-coverage/coroutine.rs b/tests/coverage/coroutine.rs similarity index 100% rename from tests/run-coverage/coroutine.rs rename to tests/coverage/coroutine.rs diff --git a/tests/run-coverage/dead_code.coverage b/tests/coverage/dead_code.coverage similarity index 100% rename from tests/run-coverage/dead_code.coverage rename to tests/coverage/dead_code.coverage diff --git a/tests/run-coverage/dead_code.rs b/tests/coverage/dead_code.rs similarity index 100% rename from tests/run-coverage/dead_code.rs rename to tests/coverage/dead_code.rs diff --git a/tests/run-coverage/drop_trait.coverage b/tests/coverage/drop_trait.coverage similarity index 100% rename from tests/run-coverage/drop_trait.coverage rename to tests/coverage/drop_trait.coverage diff --git a/tests/run-coverage/drop_trait.rs b/tests/coverage/drop_trait.rs similarity index 100% rename from tests/run-coverage/drop_trait.rs rename to tests/coverage/drop_trait.rs diff --git a/tests/run-coverage/fn_sig_into_try.coverage b/tests/coverage/fn_sig_into_try.coverage similarity index 100% rename from tests/run-coverage/fn_sig_into_try.coverage rename to tests/coverage/fn_sig_into_try.coverage diff --git a/tests/run-coverage/fn_sig_into_try.rs b/tests/coverage/fn_sig_into_try.rs similarity index 100% rename from tests/run-coverage/fn_sig_into_try.rs rename to tests/coverage/fn_sig_into_try.rs diff --git a/tests/run-coverage/generics.coverage b/tests/coverage/generics.coverage similarity index 100% rename from tests/run-coverage/generics.coverage rename to tests/coverage/generics.coverage diff --git a/tests/run-coverage/generics.rs b/tests/coverage/generics.rs similarity index 100% rename from tests/run-coverage/generics.rs rename to tests/coverage/generics.rs diff --git a/tests/run-coverage/if.coverage b/tests/coverage/if.coverage similarity index 100% rename from tests/run-coverage/if.coverage rename to tests/coverage/if.coverage diff --git a/tests/run-coverage/if.rs b/tests/coverage/if.rs similarity index 100% rename from tests/run-coverage/if.rs rename to tests/coverage/if.rs diff --git a/tests/run-coverage/if_else.coverage b/tests/coverage/if_else.coverage similarity index 100% rename from tests/run-coverage/if_else.coverage rename to tests/coverage/if_else.coverage diff --git a/tests/run-coverage/if_else.rs b/tests/coverage/if_else.rs similarity index 100% rename from tests/run-coverage/if_else.rs rename to tests/coverage/if_else.rs diff --git a/tests/run-coverage/inline-dead.coverage b/tests/coverage/inline-dead.coverage similarity index 100% rename from tests/run-coverage/inline-dead.coverage rename to tests/coverage/inline-dead.coverage diff --git a/tests/run-coverage/inline-dead.rs b/tests/coverage/inline-dead.rs similarity index 100% rename from tests/run-coverage/inline-dead.rs rename to tests/coverage/inline-dead.rs diff --git a/tests/run-coverage/inline.coverage b/tests/coverage/inline.coverage similarity index 100% rename from tests/run-coverage/inline.coverage rename to tests/coverage/inline.coverage diff --git a/tests/run-coverage/inline.rs b/tests/coverage/inline.rs similarity index 100% rename from tests/run-coverage/inline.rs rename to tests/coverage/inline.rs diff --git a/tests/run-coverage/inner_items.coverage b/tests/coverage/inner_items.coverage similarity index 100% rename from tests/run-coverage/inner_items.coverage rename to tests/coverage/inner_items.coverage diff --git a/tests/run-coverage/inner_items.rs b/tests/coverage/inner_items.rs similarity index 100% rename from tests/run-coverage/inner_items.rs rename to tests/coverage/inner_items.rs diff --git a/tests/run-coverage/issue-83601.coverage b/tests/coverage/issue-83601.coverage similarity index 100% rename from tests/run-coverage/issue-83601.coverage rename to tests/coverage/issue-83601.coverage diff --git a/tests/run-coverage/issue-83601.rs b/tests/coverage/issue-83601.rs similarity index 100% rename from tests/run-coverage/issue-83601.rs rename to tests/coverage/issue-83601.rs diff --git a/tests/run-coverage/issue-84561.coverage b/tests/coverage/issue-84561.coverage similarity index 100% rename from tests/run-coverage/issue-84561.coverage rename to tests/coverage/issue-84561.coverage diff --git a/tests/run-coverage/issue-84561.rs b/tests/coverage/issue-84561.rs similarity index 100% rename from tests/run-coverage/issue-84561.rs rename to tests/coverage/issue-84561.rs diff --git a/tests/run-coverage/issue-85461.coverage b/tests/coverage/issue-85461.coverage similarity index 100% rename from tests/run-coverage/issue-85461.coverage rename to tests/coverage/issue-85461.coverage diff --git a/tests/run-coverage/issue-85461.rs b/tests/coverage/issue-85461.rs similarity index 100% rename from tests/run-coverage/issue-85461.rs rename to tests/coverage/issue-85461.rs diff --git a/tests/run-coverage/issue-93054.coverage b/tests/coverage/issue-93054.coverage similarity index 100% rename from tests/run-coverage/issue-93054.coverage rename to tests/coverage/issue-93054.coverage diff --git a/tests/run-coverage/issue-93054.rs b/tests/coverage/issue-93054.rs similarity index 100% rename from tests/run-coverage/issue-93054.rs rename to tests/coverage/issue-93054.rs diff --git a/tests/run-coverage/lazy_boolean.coverage b/tests/coverage/lazy_boolean.coverage similarity index 100% rename from tests/run-coverage/lazy_boolean.coverage rename to tests/coverage/lazy_boolean.coverage diff --git a/tests/run-coverage/lazy_boolean.rs b/tests/coverage/lazy_boolean.rs similarity index 100% rename from tests/run-coverage/lazy_boolean.rs rename to tests/coverage/lazy_boolean.rs diff --git a/tests/run-coverage/long_and_wide.coverage b/tests/coverage/long_and_wide.coverage similarity index 100% rename from tests/run-coverage/long_and_wide.coverage rename to tests/coverage/long_and_wide.coverage diff --git a/tests/run-coverage/long_and_wide.rs b/tests/coverage/long_and_wide.rs similarity index 100% rename from tests/run-coverage/long_and_wide.rs rename to tests/coverage/long_and_wide.rs diff --git a/tests/run-coverage/loop_break_value.coverage b/tests/coverage/loop_break_value.coverage similarity index 100% rename from tests/run-coverage/loop_break_value.coverage rename to tests/coverage/loop_break_value.coverage diff --git a/tests/run-coverage/loop_break_value.rs b/tests/coverage/loop_break_value.rs similarity index 100% rename from tests/run-coverage/loop_break_value.rs rename to tests/coverage/loop_break_value.rs diff --git a/tests/run-coverage/loops_branches.coverage b/tests/coverage/loops_branches.coverage similarity index 100% rename from tests/run-coverage/loops_branches.coverage rename to tests/coverage/loops_branches.coverage diff --git a/tests/run-coverage/loops_branches.rs b/tests/coverage/loops_branches.rs similarity index 100% rename from tests/run-coverage/loops_branches.rs rename to tests/coverage/loops_branches.rs diff --git a/tests/run-coverage/match_or_pattern.coverage b/tests/coverage/match_or_pattern.coverage similarity index 100% rename from tests/run-coverage/match_or_pattern.coverage rename to tests/coverage/match_or_pattern.coverage diff --git a/tests/run-coverage/match_or_pattern.rs b/tests/coverage/match_or_pattern.rs similarity index 100% rename from tests/run-coverage/match_or_pattern.rs rename to tests/coverage/match_or_pattern.rs diff --git a/tests/run-coverage/nested_loops.coverage b/tests/coverage/nested_loops.coverage similarity index 100% rename from tests/run-coverage/nested_loops.coverage rename to tests/coverage/nested_loops.coverage diff --git a/tests/run-coverage/nested_loops.rs b/tests/coverage/nested_loops.rs similarity index 100% rename from tests/run-coverage/nested_loops.rs rename to tests/coverage/nested_loops.rs diff --git a/tests/run-coverage/no_cov_crate.coverage b/tests/coverage/no_cov_crate.coverage similarity index 100% rename from tests/run-coverage/no_cov_crate.coverage rename to tests/coverage/no_cov_crate.coverage diff --git a/tests/run-coverage/no_cov_crate.rs b/tests/coverage/no_cov_crate.rs similarity index 100% rename from tests/run-coverage/no_cov_crate.rs rename to tests/coverage/no_cov_crate.rs diff --git a/tests/run-coverage/overflow.coverage b/tests/coverage/overflow.coverage similarity index 100% rename from tests/run-coverage/overflow.coverage rename to tests/coverage/overflow.coverage diff --git a/tests/run-coverage/overflow.rs b/tests/coverage/overflow.rs similarity index 100% rename from tests/run-coverage/overflow.rs rename to tests/coverage/overflow.rs diff --git a/tests/run-coverage/panic_unwind.coverage b/tests/coverage/panic_unwind.coverage similarity index 100% rename from tests/run-coverage/panic_unwind.coverage rename to tests/coverage/panic_unwind.coverage diff --git a/tests/run-coverage/panic_unwind.rs b/tests/coverage/panic_unwind.rs similarity index 100% rename from tests/run-coverage/panic_unwind.rs rename to tests/coverage/panic_unwind.rs diff --git a/tests/run-coverage/partial_eq.coverage b/tests/coverage/partial_eq.coverage similarity index 100% rename from tests/run-coverage/partial_eq.coverage rename to tests/coverage/partial_eq.coverage diff --git a/tests/run-coverage/partial_eq.rs b/tests/coverage/partial_eq.rs similarity index 100% rename from tests/run-coverage/partial_eq.rs rename to tests/coverage/partial_eq.rs diff --git a/tests/run-coverage/simple_loop.coverage b/tests/coverage/simple_loop.coverage similarity index 100% rename from tests/run-coverage/simple_loop.coverage rename to tests/coverage/simple_loop.coverage diff --git a/tests/run-coverage/simple_loop.rs b/tests/coverage/simple_loop.rs similarity index 100% rename from tests/run-coverage/simple_loop.rs rename to tests/coverage/simple_loop.rs diff --git a/tests/run-coverage/simple_match.coverage b/tests/coverage/simple_match.coverage similarity index 100% rename from tests/run-coverage/simple_match.coverage rename to tests/coverage/simple_match.coverage diff --git a/tests/run-coverage/simple_match.rs b/tests/coverage/simple_match.rs similarity index 100% rename from tests/run-coverage/simple_match.rs rename to tests/coverage/simple_match.rs diff --git a/tests/run-coverage/sort_groups.coverage b/tests/coverage/sort_groups.coverage similarity index 100% rename from tests/run-coverage/sort_groups.coverage rename to tests/coverage/sort_groups.coverage diff --git a/tests/run-coverage/sort_groups.rs b/tests/coverage/sort_groups.rs similarity index 100% rename from tests/run-coverage/sort_groups.rs rename to tests/coverage/sort_groups.rs diff --git a/tests/run-coverage/test_harness.coverage b/tests/coverage/test_harness.coverage similarity index 100% rename from tests/run-coverage/test_harness.coverage rename to tests/coverage/test_harness.coverage diff --git a/tests/run-coverage/test_harness.rs b/tests/coverage/test_harness.rs similarity index 100% rename from tests/run-coverage/test_harness.rs rename to tests/coverage/test_harness.rs diff --git a/tests/run-coverage/tight_inf_loop.coverage b/tests/coverage/tight_inf_loop.coverage similarity index 100% rename from tests/run-coverage/tight_inf_loop.coverage rename to tests/coverage/tight_inf_loop.coverage diff --git a/tests/run-coverage/tight_inf_loop.rs b/tests/coverage/tight_inf_loop.rs similarity index 100% rename from tests/run-coverage/tight_inf_loop.rs rename to tests/coverage/tight_inf_loop.rs diff --git a/tests/run-coverage/trivial.coverage b/tests/coverage/trivial.coverage similarity index 100% rename from tests/run-coverage/trivial.coverage rename to tests/coverage/trivial.coverage diff --git a/tests/run-coverage/trivial.rs b/tests/coverage/trivial.rs similarity index 100% rename from tests/run-coverage/trivial.rs rename to tests/coverage/trivial.rs diff --git a/tests/run-coverage/try_error_result.coverage b/tests/coverage/try_error_result.coverage similarity index 100% rename from tests/run-coverage/try_error_result.coverage rename to tests/coverage/try_error_result.coverage diff --git a/tests/run-coverage/try_error_result.rs b/tests/coverage/try_error_result.rs similarity index 100% rename from tests/run-coverage/try_error_result.rs rename to tests/coverage/try_error_result.rs diff --git a/tests/run-coverage/unreachable.coverage b/tests/coverage/unreachable.coverage similarity index 100% rename from tests/run-coverage/unreachable.coverage rename to tests/coverage/unreachable.coverage diff --git a/tests/run-coverage/unreachable.rs b/tests/coverage/unreachable.rs similarity index 100% rename from tests/run-coverage/unreachable.rs rename to tests/coverage/unreachable.rs diff --git a/tests/run-coverage/unused.coverage b/tests/coverage/unused.coverage similarity index 100% rename from tests/run-coverage/unused.coverage rename to tests/coverage/unused.coverage diff --git a/tests/run-coverage/unused.rs b/tests/coverage/unused.rs similarity index 100% rename from tests/run-coverage/unused.rs rename to tests/coverage/unused.rs diff --git a/tests/run-coverage/unused_mod.coverage b/tests/coverage/unused_mod.coverage similarity index 100% rename from tests/run-coverage/unused_mod.coverage rename to tests/coverage/unused_mod.coverage diff --git a/tests/run-coverage/unused_mod.rs b/tests/coverage/unused_mod.rs similarity index 100% rename from tests/run-coverage/unused_mod.rs rename to tests/coverage/unused_mod.rs diff --git a/tests/run-coverage/uses_crate.coverage b/tests/coverage/uses_crate.coverage similarity index 100% rename from tests/run-coverage/uses_crate.coverage rename to tests/coverage/uses_crate.coverage diff --git a/tests/run-coverage/uses_crate.rs b/tests/coverage/uses_crate.rs similarity index 100% rename from tests/run-coverage/uses_crate.rs rename to tests/coverage/uses_crate.rs diff --git a/tests/run-coverage/uses_inline_crate.coverage b/tests/coverage/uses_inline_crate.coverage similarity index 100% rename from tests/run-coverage/uses_inline_crate.coverage rename to tests/coverage/uses_inline_crate.coverage diff --git a/tests/run-coverage/uses_inline_crate.rs b/tests/coverage/uses_inline_crate.rs similarity index 100% rename from tests/run-coverage/uses_inline_crate.rs rename to tests/coverage/uses_inline_crate.rs diff --git a/tests/run-coverage/while.coverage b/tests/coverage/while.coverage similarity index 100% rename from tests/run-coverage/while.coverage rename to tests/coverage/while.coverage diff --git a/tests/run-coverage/while.rs b/tests/coverage/while.rs similarity index 100% rename from tests/run-coverage/while.rs rename to tests/coverage/while.rs diff --git a/tests/run-coverage/while_early_ret.coverage b/tests/coverage/while_early_ret.coverage similarity index 100% rename from tests/run-coverage/while_early_ret.coverage rename to tests/coverage/while_early_ret.coverage diff --git a/tests/run-coverage/while_early_ret.rs b/tests/coverage/while_early_ret.rs similarity index 100% rename from tests/run-coverage/while_early_ret.rs rename to tests/coverage/while_early_ret.rs diff --git a/tests/run-coverage/yield.coverage b/tests/coverage/yield.coverage similarity index 100% rename from tests/run-coverage/yield.coverage rename to tests/coverage/yield.coverage diff --git a/tests/run-coverage/yield.rs b/tests/coverage/yield.rs similarity index 100% rename from tests/run-coverage/yield.rs rename to tests/coverage/yield.rs From 49127c64d6998526d9f723a653312d0cf5310454 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 1 Nov 2023 21:28:53 +1100 Subject: [PATCH 305/435] coverage: Migrate `tests/coverage-map` into `tests/coverage` --- src/bootstrap/src/core/build_steps/test.rs | 18 +- tests/coverage-map/abort.rs | 66 ------ tests/coverage-map/assert.rs | 32 --- tests/coverage-map/async.rs | 128 ---------- tests/coverage-map/async2.rs | 57 ----- .../auxiliary/inline_always_with_dead_code.rs | 22 -- .../auxiliary/unused_mod_helper.rs | 4 - tests/coverage-map/auxiliary/used_crate.rs | 103 -------- .../auxiliary/used_inline_crate.rs | 85 ------- tests/coverage-map/bad_counter_ids.rs | 66 ------ tests/coverage-map/closure.rs | 220 ------------------ tests/coverage-map/closure_bug.rs | 44 ---- tests/coverage-map/closure_macro.rs | 40 ---- tests/coverage-map/closure_macro_async.rs | 77 ------ tests/coverage-map/conditions.rs | 86 ------- tests/coverage-map/continue.rs | 69 ------ tests/coverage-map/coroutine.rs | 30 --- tests/coverage-map/dead_code.rs | 37 --- tests/coverage-map/drop_trait.rs | 33 --- tests/coverage-map/fn_sig_into_try.rs | 41 ---- tests/coverage-map/generics.rs | 44 ---- tests/coverage-map/if.rs | 28 --- tests/coverage-map/if_else.rs | 40 ---- tests/coverage-map/inline-dead.rs | 27 --- tests/coverage-map/inline.rs | 51 ---- tests/coverage-map/inner_items.rs | 57 ----- tests/coverage-map/issue-83601.rs | 14 -- tests/coverage-map/issue-84561.rs | 182 --------------- tests/coverage-map/issue-85461.rs | 11 - tests/coverage-map/issue-93054.rs | 30 --- tests/coverage-map/lazy_boolean.rs | 61 ----- tests/coverage-map/long_and_wide.rs | 150 ------------ tests/coverage-map/loop_break_value.rs | 13 -- tests/coverage-map/loops_branches.rs | 60 ----- tests/coverage-map/match_or_pattern.rs | 43 ---- tests/coverage-map/nested_loops.rs | 25 -- tests/coverage-map/no_cov_crate.rs | 88 ------- tests/coverage-map/overflow.rs | 64 ----- tests/coverage-map/panic_unwind.rs | 31 --- tests/coverage-map/partial_eq.rs | 46 ---- tests/coverage-map/simple_loop.rs | 35 --- tests/coverage-map/simple_match.rs | 43 ---- tests/coverage-map/sort_groups.rs | 23 -- tests/coverage-map/test_harness.rs | 10 - tests/coverage-map/tight_inf_loop.rs | 5 - tests/coverage-map/trivial.rs | 3 - tests/coverage-map/try_error_result.rs | 118 ---------- tests/coverage-map/unreachable.rs | 37 --- tests/coverage-map/unused.rs | 41 ---- tests/coverage-map/unused_mod.rs | 6 - tests/coverage-map/uses_crate.rs | 19 -- tests/coverage-map/uses_inline_crate.rs | 22 -- tests/coverage-map/while.rs | 5 - tests/coverage-map/while_early_ret.rs | 42 ---- tests/coverage-map/yield.rs | 37 --- tests/{coverage-map => coverage}/README.md | 0 .../{coverage-map => coverage}/abort.cov-map | 0 .../{coverage-map => coverage}/assert.cov-map | 0 .../{coverage-map => coverage}/async.cov-map | 0 .../{coverage-map => coverage}/async2.cov-map | 0 .../bad_counter_ids.cov-map | 0 .../closure.cov-map | 0 .../closure_bug.cov-map | 0 .../closure_macro.cov-map | 0 .../closure_macro_async.cov-map | 0 .../conditions.cov-map | 0 .../continue.cov-map | 0 .../coroutine.cov-map | 0 .../dead_code.cov-map | 0 .../drop_trait.cov-map | 0 .../fn_sig_into_try.cov-map | 0 .../generics.cov-map | 0 tests/{coverage-map => coverage}/if.cov-map | 0 .../if_else.cov-map | 0 .../inline-dead.cov-map | 0 .../{coverage-map => coverage}/inline.cov-map | 0 .../inner_items.cov-map | 0 .../issue-83601.cov-map | 0 .../issue-84561.cov-map | 0 .../issue-85461.cov-map | 0 .../issue-93054.cov-map | 0 .../lazy_boolean.cov-map | 0 .../long_and_wide.cov-map | 0 .../loop_break_value.cov-map | 0 .../loops_branches.cov-map | 0 .../match_or_pattern.cov-map | 0 .../nested_loops.cov-map | 0 .../no_cov_crate.cov-map | 0 .../overflow.cov-map | 0 .../panic_unwind.cov-map | 0 .../partial_eq.cov-map | 0 .../simple_loop.cov-map | 0 .../simple_match.cov-map | 0 .../sort_groups.cov-map | 0 .../test_harness.cov-map | 0 .../tight_inf_loop.cov-map | 0 .../trivial.cov-map | 0 .../try_error_result.cov-map | 0 .../unreachable.cov-map | 0 .../{coverage-map => coverage}/unused.cov-map | 0 .../unused_mod.cov-map | 0 .../uses_crate.cov-map | 0 .../uses_inline_crate.cov-map | 0 .../{coverage-map => coverage}/while.cov-map | 0 .../while_early_ret.cov-map | 0 .../{coverage-map => coverage}/yield.cov-map | 0 106 files changed, 5 insertions(+), 2764 deletions(-) delete mode 100644 tests/coverage-map/abort.rs delete mode 100644 tests/coverage-map/assert.rs delete mode 100644 tests/coverage-map/async.rs delete mode 100644 tests/coverage-map/async2.rs delete mode 100644 tests/coverage-map/auxiliary/inline_always_with_dead_code.rs delete mode 100644 tests/coverage-map/auxiliary/unused_mod_helper.rs delete mode 100644 tests/coverage-map/auxiliary/used_crate.rs delete mode 100644 tests/coverage-map/auxiliary/used_inline_crate.rs delete mode 100644 tests/coverage-map/bad_counter_ids.rs delete mode 100644 tests/coverage-map/closure.rs delete mode 100644 tests/coverage-map/closure_bug.rs delete mode 100644 tests/coverage-map/closure_macro.rs delete mode 100644 tests/coverage-map/closure_macro_async.rs delete mode 100644 tests/coverage-map/conditions.rs delete mode 100644 tests/coverage-map/continue.rs delete mode 100644 tests/coverage-map/coroutine.rs delete mode 100644 tests/coverage-map/dead_code.rs delete mode 100644 tests/coverage-map/drop_trait.rs delete mode 100644 tests/coverage-map/fn_sig_into_try.rs delete mode 100644 tests/coverage-map/generics.rs delete mode 100644 tests/coverage-map/if.rs delete mode 100644 tests/coverage-map/if_else.rs delete mode 100644 tests/coverage-map/inline-dead.rs delete mode 100644 tests/coverage-map/inline.rs delete mode 100644 tests/coverage-map/inner_items.rs delete mode 100644 tests/coverage-map/issue-83601.rs delete mode 100644 tests/coverage-map/issue-84561.rs delete mode 100644 tests/coverage-map/issue-85461.rs delete mode 100644 tests/coverage-map/issue-93054.rs delete mode 100644 tests/coverage-map/lazy_boolean.rs delete mode 100644 tests/coverage-map/long_and_wide.rs delete mode 100644 tests/coverage-map/loop_break_value.rs delete mode 100644 tests/coverage-map/loops_branches.rs delete mode 100644 tests/coverage-map/match_or_pattern.rs delete mode 100644 tests/coverage-map/nested_loops.rs delete mode 100644 tests/coverage-map/no_cov_crate.rs delete mode 100644 tests/coverage-map/overflow.rs delete mode 100644 tests/coverage-map/panic_unwind.rs delete mode 100644 tests/coverage-map/partial_eq.rs delete mode 100644 tests/coverage-map/simple_loop.rs delete mode 100644 tests/coverage-map/simple_match.rs delete mode 100644 tests/coverage-map/sort_groups.rs delete mode 100644 tests/coverage-map/test_harness.rs delete mode 100644 tests/coverage-map/tight_inf_loop.rs delete mode 100644 tests/coverage-map/trivial.rs delete mode 100644 tests/coverage-map/try_error_result.rs delete mode 100644 tests/coverage-map/unreachable.rs delete mode 100644 tests/coverage-map/unused.rs delete mode 100644 tests/coverage-map/unused_mod.rs delete mode 100644 tests/coverage-map/uses_crate.rs delete mode 100644 tests/coverage-map/uses_inline_crate.rs delete mode 100644 tests/coverage-map/while.rs delete mode 100644 tests/coverage-map/while_early_ret.rs delete mode 100644 tests/coverage-map/yield.rs rename tests/{coverage-map => coverage}/README.md (100%) rename tests/{coverage-map => coverage}/abort.cov-map (100%) rename tests/{coverage-map => coverage}/assert.cov-map (100%) rename tests/{coverage-map => coverage}/async.cov-map (100%) rename tests/{coverage-map => coverage}/async2.cov-map (100%) rename tests/{coverage-map => coverage}/bad_counter_ids.cov-map (100%) rename tests/{coverage-map => coverage}/closure.cov-map (100%) rename tests/{coverage-map => coverage}/closure_bug.cov-map (100%) rename tests/{coverage-map => coverage}/closure_macro.cov-map (100%) rename tests/{coverage-map => coverage}/closure_macro_async.cov-map (100%) rename tests/{coverage-map => coverage}/conditions.cov-map (100%) rename tests/{coverage-map => coverage}/continue.cov-map (100%) rename tests/{coverage-map => coverage}/coroutine.cov-map (100%) rename tests/{coverage-map => coverage}/dead_code.cov-map (100%) rename tests/{coverage-map => coverage}/drop_trait.cov-map (100%) rename tests/{coverage-map => coverage}/fn_sig_into_try.cov-map (100%) rename tests/{coverage-map => coverage}/generics.cov-map (100%) rename tests/{coverage-map => coverage}/if.cov-map (100%) rename tests/{coverage-map => coverage}/if_else.cov-map (100%) rename tests/{coverage-map => coverage}/inline-dead.cov-map (100%) rename tests/{coverage-map => coverage}/inline.cov-map (100%) rename tests/{coverage-map => coverage}/inner_items.cov-map (100%) rename tests/{coverage-map => coverage}/issue-83601.cov-map (100%) rename tests/{coverage-map => coverage}/issue-84561.cov-map (100%) rename tests/{coverage-map => coverage}/issue-85461.cov-map (100%) rename tests/{coverage-map => coverage}/issue-93054.cov-map (100%) rename tests/{coverage-map => coverage}/lazy_boolean.cov-map (100%) rename tests/{coverage-map => coverage}/long_and_wide.cov-map (100%) rename tests/{coverage-map => coverage}/loop_break_value.cov-map (100%) rename tests/{coverage-map => coverage}/loops_branches.cov-map (100%) rename tests/{coverage-map => coverage}/match_or_pattern.cov-map (100%) rename tests/{coverage-map => coverage}/nested_loops.cov-map (100%) rename tests/{coverage-map => coverage}/no_cov_crate.cov-map (100%) rename tests/{coverage-map => coverage}/overflow.cov-map (100%) rename tests/{coverage-map => coverage}/panic_unwind.cov-map (100%) rename tests/{coverage-map => coverage}/partial_eq.cov-map (100%) rename tests/{coverage-map => coverage}/simple_loop.cov-map (100%) rename tests/{coverage-map => coverage}/simple_match.cov-map (100%) rename tests/{coverage-map => coverage}/sort_groups.cov-map (100%) rename tests/{coverage-map => coverage}/test_harness.cov-map (100%) rename tests/{coverage-map => coverage}/tight_inf_loop.cov-map (100%) rename tests/{coverage-map => coverage}/trivial.cov-map (100%) rename tests/{coverage-map => coverage}/try_error_result.cov-map (100%) rename tests/{coverage-map => coverage}/unreachable.cov-map (100%) rename tests/{coverage-map => coverage}/unused.cov-map (100%) rename tests/{coverage-map => coverage}/unused_mod.cov-map (100%) rename tests/{coverage-map => coverage}/uses_crate.cov-map (100%) rename tests/{coverage-map => coverage}/uses_inline_crate.cov-map (100%) rename tests/{coverage-map => coverage}/while.cov-map (100%) rename tests/{coverage-map => coverage}/while_early_ret.cov-map (100%) rename tests/{coverage-map => coverage}/yield.cov-map (100%) diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 11c9e1c7bc25..da4b135083c6 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -1433,24 +1433,16 @@ impl Step for Coverage { } fn run(self, builder: &Builder<'_>) { - builder.ensure(Compiletest { - compiler: self.compiler, - target: self.target, - mode: "coverage-map", - suite: "coverage-map", - path: "tests/coverage-map", - compare_mode: None, - }); + self.run_unified_suite(builder, CoverageMap::MODE); self.run_unified_suite(builder, RunCoverage::MODE); } } -default_test!(CoverageMap { - path: "tests/coverage-map", - mode: "coverage-map", - suite: "coverage-map" +coverage_test_alias!(CoverageMap { + alias_and_mode: "coverage-map", + default: true, + only_hosts: false, }); - coverage_test_alias!(RunCoverage { alias_and_mode: "run-coverage", default: true, diff --git a/tests/coverage-map/abort.rs b/tests/coverage-map/abort.rs deleted file mode 100644 index 98264bdc1afe..000000000000 --- a/tests/coverage-map/abort.rs +++ /dev/null @@ -1,66 +0,0 @@ -#![feature(c_unwind)] -#![allow(unused_assignments)] - -extern "C" fn might_abort(should_abort: bool) { - if should_abort { - println!("aborting..."); - panic!("panics and aborts"); - } else { - println!("Don't Panic"); - } -} - -fn main() -> Result<(), u8> { - let mut countdown = 10; - while countdown > 0 { - if countdown < 5 { - might_abort(false); - } - // See discussion (below the `Notes` section) on coverage results for the closing brace. - if countdown < 5 { might_abort(false); } // Counts for different regions on one line. - // For the following example, the closing brace is the last character on the line. - // This shows the character after the closing brace is highlighted, even if that next - // character is a newline. - if countdown < 5 { might_abort(false); } - countdown -= 1; - } - Ok(()) -} - -// Notes: -// 1. Compare this program and its coverage results to those of the similar tests -// `panic_unwind.rs` and `try_error_result.rs`. -// 2. This test confirms the coverage generated when a program includes `UnwindAction::Terminate`. -// 3. The test does not invoke the abort. By executing to a successful completion, the coverage -// results show where the program did and did not execute. -// 4. If the program actually aborted, the coverage counters would not be saved (which "works as -// intended"). Coverage results would show no executed coverage regions. -// 6. If `should_abort` is `true` and the program aborts, the program exits with a `132` status -// (on Linux at least). - -/* - -Expect the following coverage results: - -```text - 16| 11| while countdown > 0 { - 17| 10| if countdown < 5 { - 18| 4| might_abort(false); - 19| 6| } -``` - -This is actually correct. - -The condition `countdown < 5` executed 10 times (10 loop iterations). - -It evaluated to `true` 4 times, and executed the `might_abort()` call. - -It skipped the body of the `might_abort()` call 6 times. If an `if` does not include an explicit -`else`, the coverage implementation injects a counter, at the character immediately after the `if`s -closing brace, to count the "implicit" `else`. This is the only way to capture the coverage of the -non-true condition. - -As another example of why this is important, say the condition was `countdown < 50`, which is always -`true`. In that case, we wouldn't have a test for what happens if `might_abort()` is not called. -The closing brace would have a count of `0`, highlighting the missed coverage. -*/ diff --git a/tests/coverage-map/assert.rs b/tests/coverage-map/assert.rs deleted file mode 100644 index 85e6662a6adc..000000000000 --- a/tests/coverage-map/assert.rs +++ /dev/null @@ -1,32 +0,0 @@ -#![allow(unused_assignments)] -// failure-status: 101 - -fn might_fail_assert(one_plus_one: u32) { - println!("does 1 + 1 = {}?", one_plus_one); - assert_eq!(1 + 1, one_plus_one, "the argument was wrong"); -} - -fn main() -> Result<(), u8> { - let mut countdown = 10; - while countdown > 0 { - if countdown == 1 { - might_fail_assert(3); - } else if countdown < 5 { - might_fail_assert(2); - } - countdown -= 1; - } - Ok(()) -} - -// Notes: -// 1. Compare this program and its coverage results to those of the very similar test -// `panic_unwind.rs`, and similar tests `abort.rs` and `try_error_result.rs`. -// 2. This test confirms the coverage generated when a program passes or fails an `assert!()` or -// related `assert_*!()` macro. -// 3. Notably, the `assert` macros *do not* generate `TerminatorKind::Assert`. The macros produce -// conditional expressions, `TerminatorKind::SwitchInt` branches, and a possible call to -// `begin_panic_fmt()` (that begins a panic unwind, if the assertion test fails). -// 4. `TerminatoKind::Assert` is, however, also present in the MIR generated for this test -// (and in many other coverage tests). The `Assert` terminator is typically generated by the -// Rust compiler to check for runtime failures, such as numeric overflows. diff --git a/tests/coverage-map/async.rs b/tests/coverage-map/async.rs deleted file mode 100644 index efd9e62d64e1..000000000000 --- a/tests/coverage-map/async.rs +++ /dev/null @@ -1,128 +0,0 @@ -#![allow(unused_assignments, dead_code)] - -// compile-flags: --edition=2018 -C opt-level=1 - -async fn c(x: u8) -> u8 { - if x == 8 { - 1 - } else { - 0 - } -} - -async fn d() -> u8 { 1 } - -async fn e() -> u8 { 1 } // unused function; executor does not block on `g()` - -async fn f() -> u8 { 1 } - -async fn foo() -> [bool; 10] { [false; 10] } // unused function; executor does not block on `h()` - -pub async fn g(x: u8) { - match x { - y if e().await == y => (), - y if f().await == y => (), - _ => (), - } -} - -async fn h(x: usize) { // The function signature is counted when called, but the body is not - // executed (not awaited) so the open brace has a `0` count (at least when - // displayed with `llvm-cov show` in color-mode). - match x { - y if foo().await[y] => (), - _ => (), - } -} - -async fn i(x: u8) { // line coverage is 1, but there are 2 regions: - // (a) the function signature, counted when the function is called; and - // (b) the open brace for the function body, counted once when the body is - // executed asynchronously. - match x { - y if c(x).await == y + 1 => { d().await; } - y if f().await == y + 1 => (), - _ => (), - } -} - -fn j(x: u8) { - // non-async versions of `c()`, `d()`, and `f()` to make it similar to async `i()`. - fn c(x: u8) -> u8 { - if x == 8 { - 1 // This line appears covered, but the 1-character expression span covering the `1` - // is not executed. (`llvm-cov show` displays a `^0` below the `1` ). This is because - // `fn j()` executes the open brace for the function body, followed by the function's - // first executable statement, `match x`. Inner function declarations are not - // "visible" to the MIR for `j()`, so the code region counts all lines between the - // open brace and the first statement as executed, which is, in a sense, true. - // `llvm-cov show` overcomes this kind of situation by showing the actual counts - // of the enclosed coverages, (that is, the `1` expression was not executed, and - // accurately displays a `0`). - } else { - 0 - } - } - fn d() -> u8 { 1 } // inner function is defined in-line, but the function is not executed - fn f() -> u8 { 1 } - match x { - y if c(x) == y + 1 => { d(); } - y if f() == y + 1 => (), - _ => (), - } -} - -fn k(x: u8) { // unused function - match x { - 1 => (), - 2 => (), - _ => (), - } -} - -fn l(x: u8) { - match x { - 1 => (), - 2 => (), - _ => (), - } -} - -async fn m(x: u8) -> u8 { x - 1 } - -fn main() { - let _ = g(10); - let _ = h(9); - let mut future = Box::pin(i(8)); - j(7); - l(6); - let _ = m(5); - executor::block_on(future.as_mut()); -} - -mod executor { - use core::{ - future::Future, - pin::Pin, - task::{Context, Poll, RawWaker, RawWakerVTable, Waker}, - }; - - pub fn block_on(mut future: F) -> F::Output { - let mut future = unsafe { Pin::new_unchecked(&mut future) }; - use std::hint::unreachable_unchecked; - static VTABLE: RawWakerVTable = RawWakerVTable::new( - |_| unsafe { unreachable_unchecked() }, // clone - |_| unsafe { unreachable_unchecked() }, // wake - |_| unsafe { unreachable_unchecked() }, // wake_by_ref - |_| (), - ); - let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) }; - let mut context = Context::from_waker(&waker); - - loop { - if let Poll::Ready(val) = future.as_mut().poll(&mut context) { - break val; - } - } - } -} diff --git a/tests/coverage-map/async2.rs b/tests/coverage-map/async2.rs deleted file mode 100644 index 2884ff297aff..000000000000 --- a/tests/coverage-map/async2.rs +++ /dev/null @@ -1,57 +0,0 @@ -// compile-flags: --edition=2018 - -fn non_async_func() { - println!("non_async_func was covered"); - let b = true; - if b { - println!("non_async_func println in block"); - } -} - -async fn async_func() { - println!("async_func was covered"); - let b = true; - if b { - println!("async_func println in block"); - } -} - -async fn async_func_just_println() { - println!("async_func_just_println was covered"); -} - -fn main() { - println!("codecovsample::main"); - - non_async_func(); - - executor::block_on(async_func()); - executor::block_on(async_func_just_println()); -} - -mod executor { - use core::{ - future::Future, - pin::Pin, - task::{Context, Poll, RawWaker, RawWakerVTable, Waker}, - }; - - pub fn block_on(mut future: F) -> F::Output { - let mut future = unsafe { Pin::new_unchecked(&mut future) }; - use std::hint::unreachable_unchecked; - static VTABLE: RawWakerVTable = RawWakerVTable::new( - |_| unsafe { unreachable_unchecked() }, // clone - |_| unsafe { unreachable_unchecked() }, // wake - |_| unsafe { unreachable_unchecked() }, // wake_by_ref - |_| (), - ); - let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) }; - let mut context = Context::from_waker(&waker); - - loop { - if let Poll::Ready(val) = future.as_mut().poll(&mut context) { - break val; - } - } - } -} diff --git a/tests/coverage-map/auxiliary/inline_always_with_dead_code.rs b/tests/coverage-map/auxiliary/inline_always_with_dead_code.rs deleted file mode 100644 index 9dc50dae25ae..000000000000 --- a/tests/coverage-map/auxiliary/inline_always_with_dead_code.rs +++ /dev/null @@ -1,22 +0,0 @@ -// compile-flags: -Cinstrument-coverage -Ccodegen-units=4 -Copt-level=0 - -#![allow(dead_code)] - -mod foo { - #[inline(always)] - pub fn called() {} - - fn uncalled() {} -} - -pub mod bar { - pub fn call_me() { - super::foo::called(); - } -} - -pub mod baz { - pub fn call_me() { - super::foo::called(); - } -} diff --git a/tests/coverage-map/auxiliary/unused_mod_helper.rs b/tests/coverage-map/auxiliary/unused_mod_helper.rs deleted file mode 100644 index 88c5dac65cb5..000000000000 --- a/tests/coverage-map/auxiliary/unused_mod_helper.rs +++ /dev/null @@ -1,4 +0,0 @@ -#[allow(dead_code)] -pub fn never_called_function() { - println!("I am never called"); -} diff --git a/tests/coverage-map/auxiliary/used_crate.rs b/tests/coverage-map/auxiliary/used_crate.rs deleted file mode 100644 index c086ef21e1a9..000000000000 --- a/tests/coverage-map/auxiliary/used_crate.rs +++ /dev/null @@ -1,103 +0,0 @@ -#![allow(unused_assignments, unused_variables)] -// Verify that coverage works with optimizations: -// compile-flags: -C opt-level=3 - -use std::fmt::Debug; - -pub fn used_function() { - // Initialize test constants in a way that cannot be determined at compile time, to ensure - // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from - // dependent conditions. - let is_true = std::env::args().len() == 1; - let mut countdown = 0; - if is_true { - countdown = 10; - } - use_this_lib_crate(); -} - -pub fn used_only_from_bin_crate_generic_function(arg: T) { - println!("used_only_from_bin_crate_generic_function with {:?}", arg); -} -// Expect for above function: `Unexecuted instantiation` (see below) -pub fn used_only_from_this_lib_crate_generic_function(arg: T) { - println!("used_only_from_this_lib_crate_generic_function with {:?}", arg); -} - -pub fn used_from_bin_crate_and_lib_crate_generic_function(arg: T) { - println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg); -} - -pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function(arg: T) { - println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg); -} - -pub fn unused_generic_function(arg: T) { - println!("unused_generic_function with {:?}", arg); -} - -pub fn unused_function() { - let is_true = std::env::args().len() == 1; - let mut countdown = 2; - if !is_true { - countdown = 20; - } -} - -#[allow(dead_code)] -fn unused_private_function() { - let is_true = std::env::args().len() == 1; - let mut countdown = 2; - if !is_true { - countdown = 20; - } -} - -fn use_this_lib_crate() { - used_from_bin_crate_and_lib_crate_generic_function("used from library used_crate.rs"); - used_with_same_type_from_bin_crate_and_lib_crate_generic_function( - "used from library used_crate.rs", - ); - let some_vec = vec![5, 6, 7, 8]; - used_only_from_this_lib_crate_generic_function(some_vec); - used_only_from_this_lib_crate_generic_function("used ONLY from library used_crate.rs"); -} - -// FIXME(#79651): "Unexecuted instantiation" errors appear in coverage results, -// for example: -// -// | Unexecuted instantiation: used_crate::used_only_from_bin_crate_generic_function::<_> -// -// These notices appear when `llvm-cov` shows instantiations. This may be a -// default option, but it can be suppressed with: -// -// ```shell -// $ `llvm-cov show --show-instantiations=0 ...` -// ``` -// -// The notice is triggered because the function is unused by the library itself, -// and when the library is compiled, a synthetic function is generated, so -// unused function coverage can be reported. Coverage can be skipped for unused -// generic functions with: -// -// ```shell -// $ `rustc -Zunstable-options -C instrument-coverage=except-unused-generics ...` -// ``` -// -// Even though this function is used by `uses_crate.rs` (and -// counted), with substitutions for `T`, those instantiations are only generated -// when the generic function is actually used (from the binary, not from this -// library crate). So the test result shows coverage for all instantiated -// versions and their generic type substitutions, plus the `Unexecuted -// instantiation` message for the non-substituted version. This is valid, but -// unfortunately a little confusing. -// -// The library crate has its own coverage map, and the only way to show unused -// coverage of a generic function is to include the generic function in the -// coverage map, marked as an "unused function". If the library were used by -// another binary that never used this generic function, then it would be valid -// to show the unused generic, with unknown substitution (`_`). -// -// The alternative is to exclude all generics from being included in the "unused -// functions" list, which would then omit coverage results for -// `unused_generic_function()`, below. diff --git a/tests/coverage-map/auxiliary/used_inline_crate.rs b/tests/coverage-map/auxiliary/used_inline_crate.rs deleted file mode 100644 index e8929de6b360..000000000000 --- a/tests/coverage-map/auxiliary/used_inline_crate.rs +++ /dev/null @@ -1,85 +0,0 @@ -#![allow(unused_assignments, unused_variables)] -// Verify that coverage works with optimizations: -// compile-flags: -C opt-level=3 - -use std::fmt::Debug; - -pub fn used_function() { - // Initialize test constants in a way that cannot be determined at compile time, to ensure - // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from - // dependent conditions. - let is_true = std::env::args().len() == 1; - let mut countdown = 0; - if is_true { - countdown = 10; - } - use_this_lib_crate(); -} - -#[inline(always)] -pub fn used_inline_function() { - // Initialize test constants in a way that cannot be determined at compile time, to ensure - // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from - // dependent conditions. - let is_true = std::env::args().len() == 1; - let mut countdown = 0; - if is_true { - countdown = 10; - } - use_this_lib_crate(); -} - -#[inline(always)] -pub fn used_only_from_bin_crate_generic_function(arg: T) { - println!("used_only_from_bin_crate_generic_function with {:?}", arg); -} -// Expect for above function: `Unexecuted instantiation` (see notes in `used_crate.rs`) - -#[inline(always)] -pub fn used_only_from_this_lib_crate_generic_function(arg: T) { - println!("used_only_from_this_lib_crate_generic_function with {:?}", arg); -} - -#[inline(always)] -pub fn used_from_bin_crate_and_lib_crate_generic_function(arg: T) { - println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg); -} - -#[inline(always)] -pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function(arg: T) { - println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg); -} - -#[inline(always)] -pub fn unused_generic_function(arg: T) { - println!("unused_generic_function with {:?}", arg); -} - -#[inline(always)] -pub fn unused_function() { - let is_true = std::env::args().len() == 1; - let mut countdown = 2; - if !is_true { - countdown = 20; - } -} - -#[inline(always)] -#[allow(dead_code)] -fn unused_private_function() { - let is_true = std::env::args().len() == 1; - let mut countdown = 2; - if !is_true { - countdown = 20; - } -} - -fn use_this_lib_crate() { - used_from_bin_crate_and_lib_crate_generic_function("used from library used_crate.rs"); - used_with_same_type_from_bin_crate_and_lib_crate_generic_function( - "used from library used_crate.rs", - ); - let some_vec = vec![5, 6, 7, 8]; - used_only_from_this_lib_crate_generic_function(some_vec); - used_only_from_this_lib_crate_generic_function("used ONLY from library used_crate.rs"); -} diff --git a/tests/coverage-map/bad_counter_ids.rs b/tests/coverage-map/bad_counter_ids.rs deleted file mode 100644 index ef5460102b70..000000000000 --- a/tests/coverage-map/bad_counter_ids.rs +++ /dev/null @@ -1,66 +0,0 @@ -#![feature(coverage_attribute)] -// compile-flags: --edition=2021 -Copt-level=0 -Zmir-opt-level=3 - -// Regression test for . -// -// If some coverage counters were removed by MIR optimizations, we need to take -// care not to refer to those counter IDs in coverage mappings, and instead -// replace them with a constant zero value. If we don't, `llvm-cov` might see -// a too-large counter ID and silently discard the entire function from its -// coverage reports. - -#[derive(Debug, PartialEq, Eq)] -struct Foo(u32); - -fn eq_good() { - println!("a"); - assert_eq!(Foo(1), Foo(1)); -} - -fn eq_good_message() { - println!("b"); - assert_eq!(Foo(1), Foo(1), "message b"); -} - -fn ne_good() { - println!("c"); - assert_ne!(Foo(1), Foo(3)); -} - -fn ne_good_message() { - println!("d"); - assert_ne!(Foo(1), Foo(3), "message d"); -} - -fn eq_bad() { - println!("e"); - assert_eq!(Foo(1), Foo(3)); -} - -fn eq_bad_message() { - println!("f"); - assert_eq!(Foo(1), Foo(3), "message f"); -} - -fn ne_bad() { - println!("g"); - assert_ne!(Foo(1), Foo(1)); -} - -fn ne_bad_message() { - println!("h"); - assert_ne!(Foo(1), Foo(1), "message h"); -} - -#[coverage(off)] -fn main() { - eq_good(); - eq_good_message(); - ne_good(); - ne_good_message(); - - assert!(std::panic::catch_unwind(eq_bad).is_err()); - assert!(std::panic::catch_unwind(eq_bad_message).is_err()); - assert!(std::panic::catch_unwind(ne_bad).is_err()); - assert!(std::panic::catch_unwind(ne_bad_message).is_err()); -} diff --git a/tests/coverage-map/closure.rs b/tests/coverage-map/closure.rs deleted file mode 100644 index 16a2c4e33bd4..000000000000 --- a/tests/coverage-map/closure.rs +++ /dev/null @@ -1,220 +0,0 @@ -#![allow(unused_assignments, unused_variables)] -// compile-flags: -C opt-level=2 - -// This test used to be sensitive to certain coverage-specific hacks in -// `rustc_middle/mir/mono.rs`, but those hacks were later cleaned up by -// . - -fn main() { - // Initialize test constants in a way that cannot be determined at compile time, to ensure - // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from - // dependent conditions. - let is_true = std::env::args().len() == 1; - let is_false = !is_true; - - let mut some_string = Some(String::from("the string content")); - println!( - "The string or alt: {}" - , - some_string - . - unwrap_or_else - ( - || - { - let mut countdown = 0; - if is_false { - countdown = 10; - } - "alt string 1".to_owned() - } - ) - ); - - some_string = Some(String::from("the string content")); - let - a - = - || - { - let mut countdown = 0; - if is_false { - countdown = 10; - } - "alt string 2".to_owned() - }; - println!( - "The string or alt: {}" - , - some_string - . - unwrap_or_else - ( - a - ) - ); - - some_string = None; - println!( - "The string or alt: {}" - , - some_string - . - unwrap_or_else - ( - || - { - let mut countdown = 0; - if is_false { - countdown = 10; - } - "alt string 3".to_owned() - } - ) - ); - - some_string = None; - let - a - = - || - { - let mut countdown = 0; - if is_false { - countdown = 10; - } - "alt string 4".to_owned() - }; - println!( - "The string or alt: {}" - , - some_string - . - unwrap_or_else - ( - a - ) - ); - - let - quote_closure - = - |val| - { - let mut countdown = 0; - if is_false { - countdown = 10; - } - format!("'{}'", val) - }; - println!( - "Repeated, quoted string: {:?}" - , - std::iter::repeat("repeat me") - .take(5) - .map - ( - quote_closure - ) - .collect::>() - ); - - let - _unused_closure - = - | - mut countdown - | - { - if is_false { - countdown = 10; - } - "closure should be unused".to_owned() - }; - - let mut countdown = 10; - let _short_unused_closure = | _unused_arg: u8 | countdown += 1; - - - let short_used_covered_closure_macro = | used_arg: u8 | println!("called"); - let short_used_not_covered_closure_macro = | used_arg: u8 | println!("not called"); - let _short_unused_closure_macro = | _unused_arg: u8 | println!("not called"); - - - - - let _short_unused_closure_block = | _unused_arg: u8 | { println!("not called") }; - - let _shortish_unused_closure = | _unused_arg: u8 | { - println!("not called") - }; - - let _as_short_unused_closure = | - _unused_arg: u8 - | { println!("not called") }; - - let _almost_as_short_unused_closure = | - _unused_arg: u8 - | { println!("not called") } - ; - - - - - - let _short_unused_closure_line_break_no_block = | _unused_arg: u8 | -println!("not called") - ; - - let _short_unused_closure_line_break_no_block2 = - | _unused_arg: u8 | - println!( - "not called" - ) - ; - - let short_used_not_covered_closure_line_break_no_block_embedded_branch = - | _unused_arg: u8 | - println!( - "not called: {}", - if is_true { "check" } else { "me" } - ) - ; - - let short_used_not_covered_closure_line_break_block_embedded_branch = - | _unused_arg: u8 | - { - println!( - "not called: {}", - if is_true { "check" } else { "me" } - ) - } - ; - - let short_used_covered_closure_line_break_no_block_embedded_branch = - | _unused_arg: u8 | - println!( - "not called: {}", - if is_true { "check" } else { "me" } - ) - ; - - let short_used_covered_closure_line_break_block_embedded_branch = - | _unused_arg: u8 | - { - println!( - "not called: {}", - if is_true { "check" } else { "me" } - ) - } - ; - - if is_false { - short_used_not_covered_closure_macro(0); - short_used_not_covered_closure_line_break_no_block_embedded_branch(0); - short_used_not_covered_closure_line_break_block_embedded_branch(0); - } - short_used_covered_closure_macro(0); - short_used_covered_closure_line_break_no_block_embedded_branch(0); - short_used_covered_closure_line_break_block_embedded_branch(0); -} diff --git a/tests/coverage-map/closure_bug.rs b/tests/coverage-map/closure_bug.rs deleted file mode 100644 index 739bc5f0b51c..000000000000 --- a/tests/coverage-map/closure_bug.rs +++ /dev/null @@ -1,44 +0,0 @@ -// Regression test for #115930. -// All of these closures are identical, and should produce identical output in -// the coverage report. However, an unstable sort was causing them to be treated -// inconsistently when preparing coverage spans. - -fn main() { - let truthy = std::env::args().len() == 1; - - let a - = - | - | - if truthy { true } else { false }; - - a(); - if truthy { a(); } - - let b - = - | - | - if truthy { true } else { false }; - - b(); - if truthy { b(); } - - let c - = - | - | - if truthy { true } else { false }; - - c(); - if truthy { c(); } - - let d - = - | - | - if truthy { true } else { false }; - - d(); - if truthy { d(); } -} diff --git a/tests/coverage-map/closure_macro.rs b/tests/coverage-map/closure_macro.rs deleted file mode 100644 index 9b289141c2e5..000000000000 --- a/tests/coverage-map/closure_macro.rs +++ /dev/null @@ -1,40 +0,0 @@ -// compile-flags: --edition=2018 -#![feature(coverage_attribute)] - -macro_rules! bail { - ($msg:literal $(,)?) => { - if $msg.len() > 0 { - println!("no msg"); - } else { - println!($msg); - } - return Err(String::from($msg)); - }; -} - -macro_rules! on_error { - ($value:expr, $error_message:expr) => { - $value.or_else(|e| { // FIXME(85000): no coverage in closure macros - let message = format!($error_message, e); - if message.len() > 0 { - println!("{}", message); - Ok(String::from("ok")) - } else { - bail!("error"); - } - }) - }; -} - -fn load_configuration_files() -> Result { - Ok(String::from("config")) -} - -pub fn main() -> Result<(), String> { - println!("Starting service"); - let config = on_error!(load_configuration_files(), "Error loading configs: {}")?; - - let startup_delay_duration = String::from("arg"); - let _ = (config, startup_delay_duration); - Ok(()) -} diff --git a/tests/coverage-map/closure_macro_async.rs b/tests/coverage-map/closure_macro_async.rs deleted file mode 100644 index b4275599e599..000000000000 --- a/tests/coverage-map/closure_macro_async.rs +++ /dev/null @@ -1,77 +0,0 @@ -// compile-flags: --edition=2018 -#![feature(coverage_attribute)] - -macro_rules! bail { - ($msg:literal $(,)?) => { - if $msg.len() > 0 { - println!("no msg"); - } else { - println!($msg); - } - return Err(String::from($msg)); - }; -} - -macro_rules! on_error { - ($value:expr, $error_message:expr) => { - $value.or_else(|e| { // FIXME(85000): no coverage in closure macros - let message = format!($error_message, e); - if message.len() > 0 { - println!("{}", message); - Ok(String::from("ok")) - } else { - bail!("error"); - } - }) - }; -} - -fn load_configuration_files() -> Result { - Ok(String::from("config")) -} - -pub async fn test() -> Result<(), String> { - println!("Starting service"); - let config = on_error!(load_configuration_files(), "Error loading configs: {}")?; - - let startup_delay_duration = String::from("arg"); - let _ = (config, startup_delay_duration); - Ok(()) -} - -#[coverage(off)] -fn main() { - executor::block_on(test()).unwrap(); -} - -mod executor { - use core::{ - future::Future, - pin::Pin, - task::{Context, Poll, RawWaker, RawWakerVTable, Waker}, - }; - - #[coverage(off)] - pub fn block_on(mut future: F) -> F::Output { - let mut future = unsafe { Pin::new_unchecked(&mut future) }; - use std::hint::unreachable_unchecked; - static VTABLE: RawWakerVTable = RawWakerVTable::new( - #[coverage(off)] - |_| unsafe { unreachable_unchecked() }, // clone - #[coverage(off)] - |_| unsafe { unreachable_unchecked() }, // wake - #[coverage(off)] - |_| unsafe { unreachable_unchecked() }, // wake_by_ref - #[coverage(off)] - |_| (), - ); - let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) }; - let mut context = Context::from_waker(&waker); - - loop { - if let Poll::Ready(val) = future.as_mut().poll(&mut context) { - break val; - } - } - } -} diff --git a/tests/coverage-map/conditions.rs b/tests/coverage-map/conditions.rs deleted file mode 100644 index fa7f2a116c21..000000000000 --- a/tests/coverage-map/conditions.rs +++ /dev/null @@ -1,86 +0,0 @@ -#![allow(unused_assignments, unused_variables)] - -fn main() { - let mut countdown = 0; - if true { - countdown = 10; - } - - const B: u32 = 100; - let x = if countdown > 7 { - countdown -= 4; - B - } else if countdown > 2 { - if countdown < 1 || countdown > 5 || countdown != 9 { - countdown = 0; - } - countdown -= 5; - countdown - } else { - return; - }; - - let mut countdown = 0; - if true { - countdown = 10; - } - - if countdown > 7 { - countdown -= 4; - } else if countdown > 2 { - if countdown < 1 || countdown > 5 || countdown != 9 { - countdown = 0; - } - countdown -= 5; - } else { - return; - } - - if true { - let mut countdown = 0; - if true { - countdown = 10; - } - - if countdown > 7 { - countdown -= 4; - } - else if countdown > 2 { - if countdown < 1 || countdown > 5 || countdown != 9 { - countdown = 0; - } - countdown -= 5; - } else { - return; - } - } - - let mut countdown = 0; - if true { - countdown = 1; - } - - let z = if countdown > 7 { - countdown -= 4; - } else if countdown > 2 { - if countdown < 1 || countdown > 5 || countdown != 9 { - countdown = 0; - } - countdown -= 5; - } else { - let should_be_reachable = countdown; - println!("reached"); - return; - }; - - let w = if countdown > 7 { - countdown -= 4; - } else if countdown > 2 { - if countdown < 1 || countdown > 5 || countdown != 9 { - countdown = 0; - } - countdown -= 5; - } else { - return; - }; -} diff --git a/tests/coverage-map/continue.rs b/tests/coverage-map/continue.rs deleted file mode 100644 index 624aa98341b8..000000000000 --- a/tests/coverage-map/continue.rs +++ /dev/null @@ -1,69 +0,0 @@ -#![allow(unused_assignments, unused_variables)] - -fn main() { - let is_true = std::env::args().len() == 1; - - let mut x = 0; - for _ in 0..10 { - match is_true { - true => { - continue; - } - _ => { - x = 1; - } - } - x = 3; - } - for _ in 0..10 { - match is_true { - false => { - x = 1; - } - _ => { - continue; - } - } - x = 3; - } - for _ in 0..10 { - match is_true { - true => { - x = 1; - } - _ => { - continue; - } - } - x = 3; - } - for _ in 0..10 { - if is_true { - continue; - } - x = 3; - } - for _ in 0..10 { - match is_true { - false => { - x = 1; - } - _ => { - let _ = x; - } - } - x = 3; - } - for _ in 0..10 { - match is_true { - false => { - x = 1; - } - _ => { - break; - } - } - x = 3; - } - let _ = x; -} diff --git a/tests/coverage-map/coroutine.rs b/tests/coverage-map/coroutine.rs deleted file mode 100644 index 86d19af6f4f0..000000000000 --- a/tests/coverage-map/coroutine.rs +++ /dev/null @@ -1,30 +0,0 @@ -#![feature(coroutines, coroutine_trait)] - -use std::ops::{Coroutine, CoroutineState}; -use std::pin::Pin; - -// The following implementation of a function called from a `yield` statement -// (apparently requiring the Result and the `String` type or constructor) -// creates conditions where the `coroutine::StateTransform` MIR transform will -// drop all `Counter` `Coverage` statements from a MIR. `simplify.rs` has logic -// to handle this condition, and still report dead block coverage. -fn get_u32(val: bool) -> Result { - if val { Ok(1) } else { Err(String::from("some error")) } -} - -fn main() { - let is_true = std::env::args().len() == 1; - let mut coroutine = || { - yield get_u32(is_true); - return "foo"; - }; - - match Pin::new(&mut coroutine).resume(()) { - CoroutineState::Yielded(Ok(1)) => {} - _ => panic!("unexpected return from resume"), - } - match Pin::new(&mut coroutine).resume(()) { - CoroutineState::Complete("foo") => {} - _ => panic!("unexpected return from resume"), - } -} diff --git a/tests/coverage-map/dead_code.rs b/tests/coverage-map/dead_code.rs deleted file mode 100644 index 3492712a6f98..000000000000 --- a/tests/coverage-map/dead_code.rs +++ /dev/null @@ -1,37 +0,0 @@ -#![allow(dead_code, unused_assignments, unused_variables)] - -pub fn unused_pub_fn_not_in_library() { - // Initialize test constants in a way that cannot be determined at compile time, to ensure - // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from - // dependent conditions. - let is_true = std::env::args().len() == 1; - - let mut countdown = 0; - if is_true { - countdown = 10; - } -} - -fn unused_fn() { - // Initialize test constants in a way that cannot be determined at compile time, to ensure - // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from - // dependent conditions. - let is_true = std::env::args().len() == 1; - - let mut countdown = 0; - if is_true { - countdown = 10; - } -} - -fn main() { - // Initialize test constants in a way that cannot be determined at compile time, to ensure - // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from - // dependent conditions. - let is_true = std::env::args().len() == 1; - - let mut countdown = 0; - if is_true { - countdown = 10; - } -} diff --git a/tests/coverage-map/drop_trait.rs b/tests/coverage-map/drop_trait.rs deleted file mode 100644 index 7b062719c6b0..000000000000 --- a/tests/coverage-map/drop_trait.rs +++ /dev/null @@ -1,33 +0,0 @@ -#![allow(unused_assignments)] -// failure-status: 1 - -struct Firework { - strength: i32, -} - -impl Drop for Firework { - fn drop(&mut self) { - println!("BOOM times {}!!!", self.strength); - } -} - -fn main() -> Result<(), u8> { - let _firecracker = Firework { strength: 1 }; - - let _tnt = Firework { strength: 100 }; - - if true { - println!("Exiting with error..."); - return Err(1); - } - - let _ = Firework { strength: 1000 }; - - Ok(()) -} - -// Expected program output: -// Exiting with error... -// BOOM times 100!!! -// BOOM times 1!!! -// Error: 1 diff --git a/tests/coverage-map/fn_sig_into_try.rs b/tests/coverage-map/fn_sig_into_try.rs deleted file mode 100644 index 92850c8a188f..000000000000 --- a/tests/coverage-map/fn_sig_into_try.rs +++ /dev/null @@ -1,41 +0,0 @@ -#![feature(coverage_attribute)] -// compile-flags: --edition=2021 - -// Regression test for inconsistent handling of function signature spans that -// are followed by code using the `?` operator. -// -// For each of these similar functions, the line containing the function -// signature should be handled in the same way. - -fn a() -> Option -{ - Some(7i32); - Some(0) -} - -fn b() -> Option -{ - Some(7i32)?; - Some(0) -} - -fn c() -> Option -{ - let _ = Some(7i32)?; - Some(0) -} - -fn d() -> Option -{ - let _: () = (); - Some(7i32)?; - Some(0) -} - -#[coverage(off)] -fn main() { - a(); - b(); - c(); - d(); -} diff --git a/tests/coverage-map/generics.rs b/tests/coverage-map/generics.rs deleted file mode 100644 index bf4c2d8d6853..000000000000 --- a/tests/coverage-map/generics.rs +++ /dev/null @@ -1,44 +0,0 @@ -#![allow(unused_assignments)] -// failure-status: 1 - -struct Firework where T: Copy + std::fmt::Display { - strength: T, -} - -impl Firework where T: Copy + std::fmt::Display { - #[inline(always)] - fn set_strength(&mut self, new_strength: T) { - self.strength = new_strength; - } -} - -impl Drop for Firework where T: Copy + std::fmt::Display { - #[inline(always)] - fn drop(&mut self) { - println!("BOOM times {}!!!", self.strength); - } -} - -fn main() -> Result<(), u8> { - let mut firecracker = Firework { strength: 1 }; - firecracker.set_strength(2); - - let mut tnt = Firework { strength: 100.1 }; - tnt.set_strength(200.1); - tnt.set_strength(300.3); - - if true { - println!("Exiting with error..."); - return Err(1); - } - - let _ = Firework { strength: 1000 }; - - Ok(()) -} - -// Expected program output: -// Exiting with error... -// BOOM times 100!!! -// BOOM times 1!!! -// Error: 1 diff --git a/tests/coverage-map/if.rs b/tests/coverage-map/if.rs deleted file mode 100644 index 8ad5042ff7ba..000000000000 --- a/tests/coverage-map/if.rs +++ /dev/null @@ -1,28 +0,0 @@ -#![allow(unused_assignments, unused_variables)] - -fn main() { - // Initialize test constants in a way that cannot be determined at compile time, to ensure - // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from - // dependent conditions. - let - is_true - = - std::env::args().len() - == - 1 - ; - let - mut - countdown - = - 0 - ; - if - is_true - { - countdown - = - 10 - ; - } -} diff --git a/tests/coverage-map/if_else.rs b/tests/coverage-map/if_else.rs deleted file mode 100644 index 3244e1e3afd2..000000000000 --- a/tests/coverage-map/if_else.rs +++ /dev/null @@ -1,40 +0,0 @@ -#![allow(unused_assignments, unused_variables)] - -fn main() { - // Initialize test constants in a way that cannot be determined at compile time, to ensure - // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from - // dependent conditions. - let is_true = std::env::args().len() == 1; - - let mut countdown = 0; - if - is_true - { - countdown - = - 10 - ; - } - else // Note coverage region difference without semicolon - { - countdown - = - 100 - } - - if - is_true - { - countdown - = - 10 - ; - } - else - { - countdown - = - 100 - ; - } -} diff --git a/tests/coverage-map/inline-dead.rs b/tests/coverage-map/inline-dead.rs deleted file mode 100644 index 854fa0629675..000000000000 --- a/tests/coverage-map/inline-dead.rs +++ /dev/null @@ -1,27 +0,0 @@ -// Regression test for issue #98833. -// compile-flags: -Zinline-mir -Cdebug-assertions=off - -fn main() { - println!("{}", live::()); - - let f = |x: bool| { - debug_assert!( - x - ); - }; - f(false); -} - -#[inline] -fn live() -> u32 { - if B { - dead() - } else { - 0 - } -} - -#[inline] -fn dead() -> u32 { - 42 -} diff --git a/tests/coverage-map/inline.rs b/tests/coverage-map/inline.rs deleted file mode 100644 index 9cfab9ddbadf..000000000000 --- a/tests/coverage-map/inline.rs +++ /dev/null @@ -1,51 +0,0 @@ -// compile-flags: -Zinline-mir - -use std::fmt::Display; - -fn main() { - permutations(&['a', 'b', 'c']); -} - -#[inline(always)] -fn permutations(xs: &[T]) { - let mut ys = xs.to_owned(); - permutate(&mut ys, 0); -} - -fn permutate(xs: &mut [T], k: usize) { - let n = length(xs); - if k == n { - display(xs); - } else if k < n { - for i in k..n { - swap(xs, i, k); - permutate(xs, k + 1); - swap(xs, i, k); - } - } else { - error(); - } -} - -fn length(xs: &[T]) -> usize { - xs.len() -} - -#[inline] -fn swap(xs: &mut [T], i: usize, j: usize) { - let t = xs[i]; - xs[i] = xs[j]; - xs[j] = t; -} - -fn display(xs: &[T]) { - for x in xs { - print!("{}", x); - } - println!(); -} - -#[inline(always)] -fn error() { - panic!("error"); -} diff --git a/tests/coverage-map/inner_items.rs b/tests/coverage-map/inner_items.rs deleted file mode 100644 index bcb62b3031cd..000000000000 --- a/tests/coverage-map/inner_items.rs +++ /dev/null @@ -1,57 +0,0 @@ -#![allow(unused_assignments, unused_variables, dead_code)] - -fn main() { - // Initialize test constants in a way that cannot be determined at compile time, to ensure - // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from - // dependent conditions. - let is_true = std::env::args().len() == 1; - - let mut countdown = 0; - if is_true { - countdown = 10; - } - - mod in_mod { - const IN_MOD_CONST: u32 = 1000; - } - - fn in_func(a: u32) { - let b = 1; - let c = a + b; - println!("c = {}", c) - } - - struct InStruct { - in_struct_field: u32, - } - - const IN_CONST: u32 = 1234; - - trait InTrait { - fn trait_func(&mut self, incr: u32); - - fn default_trait_func(&mut self) { - in_func(IN_CONST); - self.trait_func(IN_CONST); - } - } - - impl InTrait for InStruct { - fn trait_func(&mut self, incr: u32) { - self.in_struct_field += incr; - in_func(self.in_struct_field); - } - } - - type InType = String; - - if is_true { - in_func(countdown); - } - - let mut val = InStruct { - in_struct_field: 101, - }; - - val.default_trait_func(); -} diff --git a/tests/coverage-map/issue-83601.rs b/tests/coverage-map/issue-83601.rs deleted file mode 100644 index 0b72a81947cc..000000000000 --- a/tests/coverage-map/issue-83601.rs +++ /dev/null @@ -1,14 +0,0 @@ -// Shows that rust-lang/rust/83601 is resolved - -#[derive(Debug, PartialEq, Eq)] -struct Foo(u32); - -fn main() { - let bar = Foo(1); - assert_eq!(bar, Foo(1)); - let baz = Foo(0); - assert_ne!(baz, Foo(1)); - println!("{:?}", Foo(1)); - println!("{:?}", bar); - println!("{:?}", baz); -} diff --git a/tests/coverage-map/issue-84561.rs b/tests/coverage-map/issue-84561.rs deleted file mode 100644 index facf5b5b4cfb..000000000000 --- a/tests/coverage-map/issue-84561.rs +++ /dev/null @@ -1,182 +0,0 @@ -// This demonstrated Issue #84561: function-like macros produce unintuitive coverage results. - -// failure-status: 101 -#[derive(PartialEq, Eq)] -struct Foo(u32); -fn test3() { - let is_true = std::env::args().len() == 1; - let bar = Foo(1); - assert_eq!(bar, Foo(1)); - let baz = Foo(0); - assert_ne!(baz, Foo(1)); - println!("{:?}", Foo(1)); - println!("{:?}", bar); - println!("{:?}", baz); - - assert_eq!(Foo(1), Foo(1)); - assert_ne!(Foo(0), Foo(1)); - assert_eq!(Foo(2), Foo(2)); - let bar = Foo(0); - assert_ne!(bar, Foo(3)); - assert_ne!(Foo(0), Foo(4)); - assert_eq!(Foo(3), Foo(3), "with a message"); - println!("{:?}", bar); - println!("{:?}", Foo(1)); - - assert_ne!(Foo(0), Foo(5), "{}", if is_true { "true message" } else { "false message" }); - assert_ne!( - Foo(0) - , - Foo(5) - , - "{}" - , - if - is_true - { - "true message" - } else { - "false message" - } - ); - - let is_true = std::env::args().len() == 1; - - assert_eq!( - Foo(1), - Foo(1) - ); - assert_ne!( - Foo(0), - Foo(1) - ); - assert_eq!( - Foo(2), - Foo(2) - ); - let bar = Foo(1); - assert_ne!( - bar, - Foo(3) - ); - if is_true { - assert_ne!( - Foo(0), - Foo(4) - ); - } else { - assert_eq!( - Foo(3), - Foo(3) - ); - } - if is_true { - assert_ne!( - Foo(0), - Foo(4), - "with a message" - ); - } else { - assert_eq!( - Foo(3), - Foo(3), - "with a message" - ); - } - assert_ne!( - if is_true { - Foo(0) - } else { - Foo(1) - }, - Foo(5) - ); - assert_ne!( - Foo(5), - if is_true { - Foo(0) - } else { - Foo(1) - } - ); - assert_ne!( - if is_true { - assert_eq!( - Foo(3), - Foo(3) - ); - Foo(0) - } else { - assert_ne!( - if is_true { - Foo(0) - } else { - Foo(1) - }, - Foo(5) - ); - Foo(1) - }, - Foo(5), - "with a message" - ); - assert_eq!( - Foo(1), - Foo(3), - "this assert should fail" - ); - assert_eq!( - Foo(3), - Foo(3), - "this assert should not be reached" - ); -} - -impl std::fmt::Debug for Foo { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(f, "try and succeed")?; - Ok(()) - } -} - -static mut DEBUG_LEVEL_ENABLED: bool = false; - -macro_rules! debug { - ($($arg:tt)+) => ( - if unsafe { DEBUG_LEVEL_ENABLED } { - println!($($arg)+); - } - ); -} - -fn test1() { - debug!("debug is enabled"); - debug!("debug is enabled"); - let _ = 0; - debug!("debug is enabled"); - unsafe { - DEBUG_LEVEL_ENABLED = true; - } - debug!("debug is enabled"); -} - -macro_rules! call_debug { - ($($arg:tt)+) => ( - fn call_print(s: &str) { - print!("{}", s); - } - - call_print("called from call_debug: "); - debug!($($arg)+); - ); -} - -fn test2() { - call_debug!("debug is enabled"); -} - -fn main() { - test1(); - test2(); - test3(); -} diff --git a/tests/coverage-map/issue-85461.rs b/tests/coverage-map/issue-85461.rs deleted file mode 100644 index 9d4c90a827ee..000000000000 --- a/tests/coverage-map/issue-85461.rs +++ /dev/null @@ -1,11 +0,0 @@ -// Regression test for #85461: MSVC sometimes fail to link with dead code and #[inline(always)] - -// aux-build:inline_always_with_dead_code.rs -extern crate inline_always_with_dead_code; - -use inline_always_with_dead_code::{bar, baz}; - -fn main() { - bar::call_me(); - baz::call_me(); -} diff --git a/tests/coverage-map/issue-93054.rs b/tests/coverage-map/issue-93054.rs deleted file mode 100644 index da546cfeef85..000000000000 --- a/tests/coverage-map/issue-93054.rs +++ /dev/null @@ -1,30 +0,0 @@ -#![allow(dead_code, unreachable_code)] - -// Regression test for #93054: Functions using uninhabited types often only have a single, -// unreachable basic block which doesn't get instrumented. This should not cause llvm-cov to fail. -// Since these kinds functions can't be invoked anyway, it's ok to not have coverage data for them. - -// compile-flags: --edition=2021 - -enum Never {} - -impl Never { - fn foo(self) { - match self {} - make().map(|never| match never {}); - } - - fn bar(&self) { - match *self {} - } -} - -async fn foo2(never: Never) { - match never {} -} - -fn make() -> Option { - None -} - -fn main() {} diff --git a/tests/coverage-map/lazy_boolean.rs b/tests/coverage-map/lazy_boolean.rs deleted file mode 100644 index bb6219e851c8..000000000000 --- a/tests/coverage-map/lazy_boolean.rs +++ /dev/null @@ -1,61 +0,0 @@ -#![allow(unused_assignments, unused_variables)] - -fn main() { - // Initialize test constants in a way that cannot be determined at compile time, to ensure - // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from - // dependent conditions. - let is_true = std::env::args().len() == 1; - - let (mut a, mut b, mut c) = (0, 0, 0); - if is_true { - a = 1; - b = 10; - c = 100; - } - let - somebool - = - a < b - || - b < c - ; - let - somebool - = - b < a - || - b < c - ; - let somebool = a < b && b < c; - let somebool = b < a && b < c; - - if - ! - is_true - { - a = 2 - ; - } - - if - is_true - { - b = 30 - ; - } - else - { - c = 400 - ; - } - - if !is_true { - a = 2; - } - - if is_true { - b = 30; - } else { - c = 400; - } -} diff --git a/tests/coverage-map/long_and_wide.rs b/tests/coverage-map/long_and_wide.rs deleted file mode 100644 index a7cbcd480279..000000000000 --- a/tests/coverage-map/long_and_wide.rs +++ /dev/null @@ -1,150 +0,0 @@ -// compile-flags: --edition=2021 -// ignore-tidy-linelength - -// This file deliberately contains line and column numbers larger than 127, -// to verify that `coverage-dump`'s ULEB128 parser can handle them. - -fn main() { - wide_function(); - long_function(); - far_function(); -} - -#[rustfmt::skip] -fn wide_function() { /* */ (); } - -fn long_function() { - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // -} - -fn far_function() {} diff --git a/tests/coverage-map/loop_break_value.rs b/tests/coverage-map/loop_break_value.rs deleted file mode 100644 index dbc4fad7a231..000000000000 --- a/tests/coverage-map/loop_break_value.rs +++ /dev/null @@ -1,13 +0,0 @@ -#![allow(unused_assignments, unused_variables)] - -fn main() { - let result - = - loop - { - break - 10 - ; - } - ; -} diff --git a/tests/coverage-map/loops_branches.rs b/tests/coverage-map/loops_branches.rs deleted file mode 100644 index f3a343bcc1f4..000000000000 --- a/tests/coverage-map/loops_branches.rs +++ /dev/null @@ -1,60 +0,0 @@ -#![allow(unused_assignments, unused_variables, while_true)] - -// This test confirms that (1) unexecuted infinite loops are handled correctly by the -// InstrumentCoverage MIR pass; and (2) Counter Expressions that subtract from zero can be dropped. - -struct DebugTest; - -impl std::fmt::Debug for DebugTest { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - if true { - if false { - while true {} - } - write!(f, "cool")?; - } else { - } - - for i in 0..10 { - if true { - if false { - while true {} - } - write!(f, "cool")?; - } else { - } - } - Ok(()) - } -} - -struct DisplayTest; - -impl std::fmt::Display for DisplayTest { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - if false { - } else { - if false { - while true {} - } - write!(f, "cool")?; - } - for i in 0..10 { - if false { - } else { - if false { - while true {} - } - write!(f, "cool")?; - } - } - Ok(()) - } -} - -fn main() { - let debug_test = DebugTest; - println!("{:?}", debug_test); - let display_test = DisplayTest; - println!("{}", display_test); -} diff --git a/tests/coverage-map/match_or_pattern.rs b/tests/coverage-map/match_or_pattern.rs deleted file mode 100644 index ab7aee51d1bc..000000000000 --- a/tests/coverage-map/match_or_pattern.rs +++ /dev/null @@ -1,43 +0,0 @@ -fn main() { - // Initialize test constants in a way that cannot be determined at compile time, to ensure - // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from - // dependent conditions. - let is_true = std::env::args().len() == 1; - - let mut a: u8 = 0; - let mut b: u8 = 0; - if is_true { - a = 2; - b = 0; - } - match (a, b) { - // Or patterns generate MIR `SwitchInt` with multiple targets to the same `BasicBlock`. - // This test confirms a fix for Issue #79569. - (0 | 1, 2 | 3) => {} - _ => {} - } - if is_true { - a = 0; - b = 0; - } - match (a, b) { - (0 | 1, 2 | 3) => {} - _ => {} - } - if is_true { - a = 2; - b = 2; - } - match (a, b) { - (0 | 1, 2 | 3) => {} - _ => {} - } - if is_true { - a = 0; - b = 2; - } - match (a, b) { - (0 | 1, 2 | 3) => {} - _ => {} - } -} diff --git a/tests/coverage-map/nested_loops.rs b/tests/coverage-map/nested_loops.rs deleted file mode 100644 index 4c7c78427965..000000000000 --- a/tests/coverage-map/nested_loops.rs +++ /dev/null @@ -1,25 +0,0 @@ -fn main() { - let is_true = std::env::args().len() == 1; - let mut countdown = 10; - - 'outer: while countdown > 0 { - let mut a = 100; - let mut b = 100; - for _ in 0..50 { - if a < 30 { - break; - } - a -= 5; - b -= 5; - if b < 90 { - a -= 10; - if is_true { - break 'outer; - } else { - a -= 2; - } - } - } - countdown -= 1; - } -} diff --git a/tests/coverage-map/no_cov_crate.rs b/tests/coverage-map/no_cov_crate.rs deleted file mode 100644 index e12e4bc55e3e..000000000000 --- a/tests/coverage-map/no_cov_crate.rs +++ /dev/null @@ -1,88 +0,0 @@ -// Enables `coverage(off)` on the entire crate -#![feature(coverage_attribute)] - -#[coverage(off)] -fn do_not_add_coverage_1() { - println!("called but not covered"); -} - -fn do_not_add_coverage_2() { - #![coverage(off)] - println!("called but not covered"); -} - -#[coverage(off)] -#[allow(dead_code)] -fn do_not_add_coverage_not_called() { - println!("not called and not covered"); -} - -fn add_coverage_1() { - println!("called and covered"); -} - -fn add_coverage_2() { - println!("called and covered"); -} - -#[allow(dead_code)] -fn add_coverage_not_called() { - println!("not called but covered"); -} - -// FIXME: These test-cases illustrate confusing results of nested functions. -// See https://github.com/rust-lang/rust/issues/93319 -mod nested_fns { - #[coverage(off)] - pub fn outer_not_covered(is_true: bool) { - fn inner(is_true: bool) { - if is_true { - println!("called and covered"); - } else { - println!("absolutely not covered"); - } - } - println!("called but not covered"); - inner(is_true); - } - - pub fn outer(is_true: bool) { - println!("called and covered"); - inner_not_covered(is_true); - - #[coverage(off)] - fn inner_not_covered(is_true: bool) { - if is_true { - println!("called but not covered"); - } else { - println!("absolutely not covered"); - } - } - } - - pub fn outer_both_covered(is_true: bool) { - println!("called and covered"); - inner(is_true); - - fn inner(is_true: bool) { - if is_true { - println!("called and covered"); - } else { - println!("absolutely not covered"); - } - } - } -} - -fn main() { - let is_true = std::env::args().len() == 1; - - do_not_add_coverage_1(); - do_not_add_coverage_2(); - add_coverage_1(); - add_coverage_2(); - - nested_fns::outer_not_covered(is_true); - nested_fns::outer(is_true); - nested_fns::outer_both_covered(is_true); -} diff --git a/tests/coverage-map/overflow.rs b/tests/coverage-map/overflow.rs deleted file mode 100644 index 1c40771b2747..000000000000 --- a/tests/coverage-map/overflow.rs +++ /dev/null @@ -1,64 +0,0 @@ -#![allow(unused_assignments)] -// compile-flags: -Coverflow-checks=yes -// failure-status: 101 - -fn might_overflow(to_add: u32) -> u32 { - if to_add > 5 { - println!("this will probably overflow"); - } - let add_to = u32::MAX - 5; - println!("does {} + {} overflow?", add_to, to_add); - let result = to_add + add_to; - println!("continuing after overflow check"); - result -} - -fn main() -> Result<(), u8> { - let mut countdown = 10; - while countdown > 0 { - if countdown == 1 { - let result = might_overflow(10); - println!("Result: {}", result); - } else if countdown < 5 { - let result = might_overflow(1); - println!("Result: {}", result); - } - countdown -= 1; - } - Ok(()) -} - -// Notes: -// 1. Compare this program and its coverage results to those of the very similar test `assert.rs`, -// and similar tests `panic_unwind.rs`, abort.rs` and `try_error_result.rs`. -// 2. This test confirms the coverage generated when a program passes or fails a -// compiler-generated `TerminatorKind::Assert` (based on an overflow check, in this case). -// 3. Similar to how the coverage instrumentation handles `TerminatorKind::Call`, -// compiler-generated assertion failures are assumed to be a symptom of a program bug, not -// expected behavior. To simplify the coverage graphs and keep instrumented programs as -// small and fast as possible, `Assert` terminators are assumed to always succeed, and -// therefore are considered "non-branching" terminators. So, an `Assert` terminator does not -// get its own coverage counter. -// 4. After an unhandled panic or failed Assert, coverage results may not always be intuitive. -// In this test, the final count for the statements after the `if` block in `might_overflow()` -// is 4, even though the lines after `to_add + add_to` were executed only 3 times. Depending -// on the MIR graph and the structure of the code, this count could have been 3 (which might -// have been valid for the overflowed add `+`, but should have been 4 for the lines before -// the overflow. The reason for this potential uncertainty is, a `CounterKind` is incremented -// via StatementKind::Counter at the end of the block, but (as in the case in this test), -// a CounterKind::Expression is always evaluated. In this case, the expression was based on -// a `Counter` incremented as part of the evaluation of the `if` expression, which was -// executed, and counted, 4 times, before reaching the overflow add. - -// If the program did not overflow, the coverage for `might_overflow()` would look like this: -// -// 4| |fn might_overflow(to_add: u32) -> u32 { -// 5| 4| if to_add > 5 { -// 6| 0| println!("this will probably overflow"); -// 7| 4| } -// 8| 4| let add_to = u32::MAX - 5; -// 9| 4| println!("does {} + {} overflow?", add_to, to_add); -// 10| 4| let result = to_add + add_to; -// 11| 4| println!("continuing after overflow check"); -// 12| 4| result -// 13| 4|} diff --git a/tests/coverage-map/panic_unwind.rs b/tests/coverage-map/panic_unwind.rs deleted file mode 100644 index 638d2eb6aaaf..000000000000 --- a/tests/coverage-map/panic_unwind.rs +++ /dev/null @@ -1,31 +0,0 @@ -#![allow(unused_assignments)] -// failure-status: 101 - -fn might_panic(should_panic: bool) { - if should_panic { - println!("panicking..."); - panic!("panics"); - } else { - println!("Don't Panic"); - } -} - -fn main() -> Result<(), u8> { - let mut countdown = 10; - while countdown > 0 { - if countdown == 1 { - might_panic(true); - } else if countdown < 5 { - might_panic(false); - } - countdown -= 1; - } - Ok(()) -} - -// Notes: -// 1. Compare this program and its coverage results to those of the similar tests `abort.rs` and -// `try_error_result.rs`. -// 2. Since the `panic_unwind.rs` test is allowed to unwind, it is also allowed to execute the -// normal program exit cleanup, including writing out the current values of the coverage -// counters. diff --git a/tests/coverage-map/partial_eq.rs b/tests/coverage-map/partial_eq.rs deleted file mode 100644 index dd8b42c18cea..000000000000 --- a/tests/coverage-map/partial_eq.rs +++ /dev/null @@ -1,46 +0,0 @@ -// This test confirms an earlier problem was resolved, supporting the MIR graph generated by the -// structure of this test. - -#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] -pub struct Version { - major: usize, - minor: usize, - patch: usize, -} - -impl Version { - pub fn new(major: usize, minor: usize, patch: usize) -> Self { - Self { - major, - minor, - patch, - } - } -} - -fn main() { - let version_3_2_1 = Version::new(3, 2, 1); - let version_3_3_0 = Version::new(3, 3, 0); - - println!("{:?} < {:?} = {}", version_3_2_1, version_3_3_0, version_3_2_1 < version_3_3_0); -} - -/* - -This test verifies a bug was fixed that otherwise generated this error: - -thread 'rustc' panicked at 'No counters provided the source_hash for function: - Instance { - def: Item(WithOptConstParam { - did: DefId(0:101 ~ autocfg[c44a]::version::{impl#2}::partial_cmp), - const_param_did: None - }), - args: [] - }' -The `PartialOrd` derived by `Version` happened to generate a MIR that generated coverage -without a code region associated with any `Counter`. Code regions were associated with at least -one expression, which is allowed, but the `function_source_hash` was only passed to the codegen -(coverage mapgen) phase from a `Counter`s code region. A new method was added to pass the -`function_source_hash` without a code region, if necessary. - -*/ diff --git a/tests/coverage-map/simple_loop.rs b/tests/coverage-map/simple_loop.rs deleted file mode 100644 index 6f7f23475b82..000000000000 --- a/tests/coverage-map/simple_loop.rs +++ /dev/null @@ -1,35 +0,0 @@ -#![allow(unused_assignments)] - -fn main() { - // Initialize test constants in a way that cannot be determined at compile time, to ensure - // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from - // dependent conditions. - let is_true = std::env::args().len() == 1; - - let mut countdown = 0; - - if - is_true - { - countdown - = - 10 - ; - } - - loop - { - if - countdown - == - 0 - { - break - ; - } - countdown - -= - 1 - ; - } -} diff --git a/tests/coverage-map/simple_match.rs b/tests/coverage-map/simple_match.rs deleted file mode 100644 index be99e59a8268..000000000000 --- a/tests/coverage-map/simple_match.rs +++ /dev/null @@ -1,43 +0,0 @@ -#![allow(unused_assignments, unused_variables)] - -fn main() { - // Initialize test constants in a way that cannot be determined at compile time, to ensure - // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from - // dependent conditions. - let is_true = std::env::args().len() == 1; - - let mut countdown = 1; - if is_true { - countdown = 0; - } - - for - _ - in - 0..2 - { - let z - ; - match - countdown - { - x - if - x - < - 1 - => - { - z = countdown - ; - let y = countdown - ; - countdown = 10 - ; - } - _ - => - {} - } - } -} diff --git a/tests/coverage-map/sort_groups.rs b/tests/coverage-map/sort_groups.rs deleted file mode 100644 index 5adbbc6a87d1..000000000000 --- a/tests/coverage-map/sort_groups.rs +++ /dev/null @@ -1,23 +0,0 @@ -// compile-flags: --edition=2021 - -// Demonstrate that `sort_subviews.py` can sort instantiation groups into a -// predictable order, while preserving their heterogeneous contents. - -fn main() { - let cond = std::env::args().len() > 1; - generic_fn::<()>(cond); - generic_fn::<&'static str>(!cond); - if std::hint::black_box(false) { - generic_fn::(cond); - } - generic_fn::(cond); - other_fn(); -} - -fn generic_fn(cond: bool) { - if cond { - println!("{}", std::any::type_name::()); - } -} - -fn other_fn() {} diff --git a/tests/coverage-map/test_harness.rs b/tests/coverage-map/test_harness.rs deleted file mode 100644 index 12a755734c19..000000000000 --- a/tests/coverage-map/test_harness.rs +++ /dev/null @@ -1,10 +0,0 @@ -// Verify that the entry point injected by the test harness doesn't cause -// weird artifacts in the coverage report (e.g. issue #10749). - -// compile-flags: --test - -#[allow(dead_code)] -fn unused() {} - -#[test] -fn my_test() {} diff --git a/tests/coverage-map/tight_inf_loop.rs b/tests/coverage-map/tight_inf_loop.rs deleted file mode 100644 index cef99027aaa4..000000000000 --- a/tests/coverage-map/tight_inf_loop.rs +++ /dev/null @@ -1,5 +0,0 @@ -fn main() { - if false { - loop {} - } -} diff --git a/tests/coverage-map/trivial.rs b/tests/coverage-map/trivial.rs deleted file mode 100644 index d0a9b44fb360..000000000000 --- a/tests/coverage-map/trivial.rs +++ /dev/null @@ -1,3 +0,0 @@ -// compile-flags: --edition=2021 - -fn main() {} diff --git a/tests/coverage-map/try_error_result.rs b/tests/coverage-map/try_error_result.rs deleted file mode 100644 index 557cbf22bfad..000000000000 --- a/tests/coverage-map/try_error_result.rs +++ /dev/null @@ -1,118 +0,0 @@ -#![allow(unused_assignments)] -// failure-status: 1 - -fn call(return_error: bool) -> Result<(), ()> { - if return_error { - Err(()) - } else { - Ok(()) - } -} - -fn test1() -> Result<(), ()> { - let mut - countdown = 10 - ; - for - _ - in - 0..10 - { - countdown - -= 1 - ; - if - countdown < 5 - { - call(/*return_error=*/ true)?; - call(/*return_error=*/ false)?; - } - else - { - call(/*return_error=*/ false)?; - } - } - Ok(()) -} - -struct Thing1; -impl Thing1 { - fn get_thing_2(&self, return_error: bool) -> Result { - if return_error { - Err(()) - } else { - Ok(Thing2 {}) - } - } -} - -struct Thing2; -impl Thing2 { - fn call(&self, return_error: bool) -> Result { - if return_error { - Err(()) - } else { - Ok(57) - } - } -} - -fn test2() -> Result<(), ()> { - let thing1 = Thing1{}; - let mut - countdown = 10 - ; - for - _ - in - 0..10 - { - countdown - -= 1 - ; - if - countdown < 5 - { - thing1.get_thing_2(/*err=*/ false)?.call(/*err=*/ true).expect_err("call should fail"); - thing1 - . - get_thing_2(/*return_error=*/ false) - ? - . - call(/*return_error=*/ true) - . - expect_err( - "call should fail" - ); - let val = thing1.get_thing_2(/*return_error=*/ true)?.call(/*return_error=*/ true)?; - assert_eq!(val, 57); - let val = thing1.get_thing_2(/*return_error=*/ true)?.call(/*return_error=*/ false)?; - assert_eq!(val, 57); - } - else - { - let val = thing1.get_thing_2(/*return_error=*/ false)?.call(/*return_error=*/ false)?; - assert_eq!(val, 57); - let val = thing1 - .get_thing_2(/*return_error=*/ false)? - .call(/*return_error=*/ false)?; - assert_eq!(val, 57); - let val = thing1 - .get_thing_2(/*return_error=*/ false) - ? - .call(/*return_error=*/ false) - ? - ; - assert_eq!(val, 57); - } - } - Ok(()) -} - -fn main() -> Result<(), ()> { - test1().expect_err("test1 should fail"); - test2() - ? - ; - Ok(()) -} diff --git a/tests/coverage-map/unreachable.rs b/tests/coverage-map/unreachable.rs deleted file mode 100644 index 6385bfa160d7..000000000000 --- a/tests/coverage-map/unreachable.rs +++ /dev/null @@ -1,37 +0,0 @@ -#![feature(core_intrinsics)] -#![feature(coverage_attribute)] -// compile-flags: --edition=2021 - -// -// If we instrument a function for coverage, but all of its counter-increment -// statements are removed by MIR optimizations, LLVM will think it isn't -// instrumented and it will disappear from coverage maps and coverage reports. -// Most MIR opts won't cause this because they tend not to remove statements -// from bb0, but `UnreachablePropagation` can do so if it sees that bb0 ends -// with `TerminatorKind::Unreachable`. - -use std::hint::{black_box, unreachable_unchecked}; - -static UNREACHABLE_CLOSURE: fn() = || unsafe { unreachable_unchecked() }; - -fn unreachable_function() { - unsafe { unreachable_unchecked() } -} - -// Use an intrinsic to more reliably trigger unreachable-propagation. -fn unreachable_intrinsic() { - unsafe { std::intrinsics::unreachable() } -} - -#[coverage(off)] -fn main() { - if black_box(false) { - UNREACHABLE_CLOSURE(); - } - if black_box(false) { - unreachable_function(); - } - if black_box(false) { - unreachable_intrinsic(); - } -} diff --git a/tests/coverage-map/unused.rs b/tests/coverage-map/unused.rs deleted file mode 100644 index d985af135470..000000000000 --- a/tests/coverage-map/unused.rs +++ /dev/null @@ -1,41 +0,0 @@ -#![allow(dead_code, unused_assignments, unused_must_use, unused_variables)] - -fn foo(x: T) { - let mut i = 0; - while i < 10 { - i != 0 || i != 0; - i += 1; - } -} - -fn unused_template_func(x: T) { - let mut i = 0; - while i < 10 { - i != 0 || i != 0; - i += 1; - } -} - -fn unused_func(mut a: u32) { - if a != 0 { - a += 1; - } -} - -fn unused_func2(mut a: u32) { - if a != 0 { - a += 1; - } -} - -fn unused_func3(mut a: u32) { - if a != 0 { - a += 1; - } -} - -fn main() -> Result<(), u8> { - foo::(0); - foo::(0.0); - Ok(()) -} diff --git a/tests/coverage-map/unused_mod.rs b/tests/coverage-map/unused_mod.rs deleted file mode 100644 index 6e62839c9985..000000000000 --- a/tests/coverage-map/unused_mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -#[path = "auxiliary/unused_mod_helper.rs"] -mod unused_module; - -fn main() { - println!("hello world!"); -} diff --git a/tests/coverage-map/uses_crate.rs b/tests/coverage-map/uses_crate.rs deleted file mode 100644 index ab203ad781d6..000000000000 --- a/tests/coverage-map/uses_crate.rs +++ /dev/null @@ -1,19 +0,0 @@ -// This test was failing on Linux for a while due to #110393 somehow making -// the unused functions not instrumented, but it seems to be fine now. - -// Validates coverage now works with optimizations -// compile-flags: -C opt-level=3 - -#![allow(unused_assignments, unused_variables)] - -// aux-build:used_crate.rs -extern crate used_crate; - -fn main() { - used_crate::used_function(); - let some_vec = vec![1, 2, 3, 4]; - used_crate::used_only_from_bin_crate_generic_function(&some_vec); - used_crate::used_only_from_bin_crate_generic_function("used from bin uses_crate.rs"); - used_crate::used_from_bin_crate_and_lib_crate_generic_function(some_vec); - used_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function("interesting?"); -} diff --git a/tests/coverage-map/uses_inline_crate.rs b/tests/coverage-map/uses_inline_crate.rs deleted file mode 100644 index d7b4c3c057f4..000000000000 --- a/tests/coverage-map/uses_inline_crate.rs +++ /dev/null @@ -1,22 +0,0 @@ -// This test was failing on Linux for a while due to #110393 somehow making -// the unused functions not instrumented, but it seems to be fine now. - -// Validates coverage now works with optimizations -// compile-flags: -C opt-level=3 - -#![allow(unused_assignments, unused_variables)] - -// aux-build:used_inline_crate.rs -extern crate used_inline_crate; - -fn main() { - used_inline_crate::used_function(); - used_inline_crate::used_inline_function(); - let some_vec = vec![1, 2, 3, 4]; - used_inline_crate::used_only_from_bin_crate_generic_function(&some_vec); - used_inline_crate::used_only_from_bin_crate_generic_function("used from bin uses_crate.rs"); - used_inline_crate::used_from_bin_crate_and_lib_crate_generic_function(some_vec); - used_inline_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function( - "interesting?", - ); -} diff --git a/tests/coverage-map/while.rs b/tests/coverage-map/while.rs deleted file mode 100644 index 781b90b35663..000000000000 --- a/tests/coverage-map/while.rs +++ /dev/null @@ -1,5 +0,0 @@ -fn main() { - let num = 9; - while num >= 10 { - } -} diff --git a/tests/coverage-map/while_early_ret.rs b/tests/coverage-map/while_early_ret.rs deleted file mode 100644 index b2f0eee2cc0f..000000000000 --- a/tests/coverage-map/while_early_ret.rs +++ /dev/null @@ -1,42 +0,0 @@ -#![allow(unused_assignments)] -// failure-status: 1 - -fn main() -> Result<(), u8> { - let mut countdown = 10; - while - countdown - > - 0 - { - if - countdown - < - 5 - { - return - if - countdown - > - 8 - { - Ok(()) - } - else - { - Err(1) - } - ; - } - countdown - -= - 1 - ; - } - Ok(()) -} - -// ISSUE(77553): Originally, this test had `Err(1)` on line 22 (instead of `Ok(())`) and -// `std::process::exit(2)` on line 26 (instead of `Err(1)`); and this worked as expected on Linux -// and MacOS. But on Windows (MSVC, at least), the call to `std::process::exit()` exits the program -// without saving the InstrProf coverage counters. The use of `std::process:exit()` is not critical -// to the coverage test for early returns, but this is a limitation that should be fixed. diff --git a/tests/coverage-map/yield.rs b/tests/coverage-map/yield.rs deleted file mode 100644 index b7e2ba31b59c..000000000000 --- a/tests/coverage-map/yield.rs +++ /dev/null @@ -1,37 +0,0 @@ -#![feature(coroutines, coroutine_trait)] -#![allow(unused_assignments)] - -use std::ops::{Coroutine, CoroutineState}; -use std::pin::Pin; - -fn main() { - let mut coroutine = || { - yield 1; - return "foo"; - }; - - match Pin::new(&mut coroutine).resume(()) { - CoroutineState::Yielded(1) => {} - _ => panic!("unexpected value from resume"), - } - match Pin::new(&mut coroutine).resume(()) { - CoroutineState::Complete("foo") => {} - _ => panic!("unexpected value from resume"), - } - - let mut coroutine = || { - yield 1; - yield 2; - yield 3; - return "foo"; - }; - - match Pin::new(&mut coroutine).resume(()) { - CoroutineState::Yielded(1) => {} - _ => panic!("unexpected value from resume"), - } - match Pin::new(&mut coroutine).resume(()) { - CoroutineState::Yielded(2) => {} - _ => panic!("unexpected value from resume"), - } -} diff --git a/tests/coverage-map/README.md b/tests/coverage/README.md similarity index 100% rename from tests/coverage-map/README.md rename to tests/coverage/README.md diff --git a/tests/coverage-map/abort.cov-map b/tests/coverage/abort.cov-map similarity index 100% rename from tests/coverage-map/abort.cov-map rename to tests/coverage/abort.cov-map diff --git a/tests/coverage-map/assert.cov-map b/tests/coverage/assert.cov-map similarity index 100% rename from tests/coverage-map/assert.cov-map rename to tests/coverage/assert.cov-map diff --git a/tests/coverage-map/async.cov-map b/tests/coverage/async.cov-map similarity index 100% rename from tests/coverage-map/async.cov-map rename to tests/coverage/async.cov-map diff --git a/tests/coverage-map/async2.cov-map b/tests/coverage/async2.cov-map similarity index 100% rename from tests/coverage-map/async2.cov-map rename to tests/coverage/async2.cov-map diff --git a/tests/coverage-map/bad_counter_ids.cov-map b/tests/coverage/bad_counter_ids.cov-map similarity index 100% rename from tests/coverage-map/bad_counter_ids.cov-map rename to tests/coverage/bad_counter_ids.cov-map diff --git a/tests/coverage-map/closure.cov-map b/tests/coverage/closure.cov-map similarity index 100% rename from tests/coverage-map/closure.cov-map rename to tests/coverage/closure.cov-map diff --git a/tests/coverage-map/closure_bug.cov-map b/tests/coverage/closure_bug.cov-map similarity index 100% rename from tests/coverage-map/closure_bug.cov-map rename to tests/coverage/closure_bug.cov-map diff --git a/tests/coverage-map/closure_macro.cov-map b/tests/coverage/closure_macro.cov-map similarity index 100% rename from tests/coverage-map/closure_macro.cov-map rename to tests/coverage/closure_macro.cov-map diff --git a/tests/coverage-map/closure_macro_async.cov-map b/tests/coverage/closure_macro_async.cov-map similarity index 100% rename from tests/coverage-map/closure_macro_async.cov-map rename to tests/coverage/closure_macro_async.cov-map diff --git a/tests/coverage-map/conditions.cov-map b/tests/coverage/conditions.cov-map similarity index 100% rename from tests/coverage-map/conditions.cov-map rename to tests/coverage/conditions.cov-map diff --git a/tests/coverage-map/continue.cov-map b/tests/coverage/continue.cov-map similarity index 100% rename from tests/coverage-map/continue.cov-map rename to tests/coverage/continue.cov-map diff --git a/tests/coverage-map/coroutine.cov-map b/tests/coverage/coroutine.cov-map similarity index 100% rename from tests/coverage-map/coroutine.cov-map rename to tests/coverage/coroutine.cov-map diff --git a/tests/coverage-map/dead_code.cov-map b/tests/coverage/dead_code.cov-map similarity index 100% rename from tests/coverage-map/dead_code.cov-map rename to tests/coverage/dead_code.cov-map diff --git a/tests/coverage-map/drop_trait.cov-map b/tests/coverage/drop_trait.cov-map similarity index 100% rename from tests/coverage-map/drop_trait.cov-map rename to tests/coverage/drop_trait.cov-map diff --git a/tests/coverage-map/fn_sig_into_try.cov-map b/tests/coverage/fn_sig_into_try.cov-map similarity index 100% rename from tests/coverage-map/fn_sig_into_try.cov-map rename to tests/coverage/fn_sig_into_try.cov-map diff --git a/tests/coverage-map/generics.cov-map b/tests/coverage/generics.cov-map similarity index 100% rename from tests/coverage-map/generics.cov-map rename to tests/coverage/generics.cov-map diff --git a/tests/coverage-map/if.cov-map b/tests/coverage/if.cov-map similarity index 100% rename from tests/coverage-map/if.cov-map rename to tests/coverage/if.cov-map diff --git a/tests/coverage-map/if_else.cov-map b/tests/coverage/if_else.cov-map similarity index 100% rename from tests/coverage-map/if_else.cov-map rename to tests/coverage/if_else.cov-map diff --git a/tests/coverage-map/inline-dead.cov-map b/tests/coverage/inline-dead.cov-map similarity index 100% rename from tests/coverage-map/inline-dead.cov-map rename to tests/coverage/inline-dead.cov-map diff --git a/tests/coverage-map/inline.cov-map b/tests/coverage/inline.cov-map similarity index 100% rename from tests/coverage-map/inline.cov-map rename to tests/coverage/inline.cov-map diff --git a/tests/coverage-map/inner_items.cov-map b/tests/coverage/inner_items.cov-map similarity index 100% rename from tests/coverage-map/inner_items.cov-map rename to tests/coverage/inner_items.cov-map diff --git a/tests/coverage-map/issue-83601.cov-map b/tests/coverage/issue-83601.cov-map similarity index 100% rename from tests/coverage-map/issue-83601.cov-map rename to tests/coverage/issue-83601.cov-map diff --git a/tests/coverage-map/issue-84561.cov-map b/tests/coverage/issue-84561.cov-map similarity index 100% rename from tests/coverage-map/issue-84561.cov-map rename to tests/coverage/issue-84561.cov-map diff --git a/tests/coverage-map/issue-85461.cov-map b/tests/coverage/issue-85461.cov-map similarity index 100% rename from tests/coverage-map/issue-85461.cov-map rename to tests/coverage/issue-85461.cov-map diff --git a/tests/coverage-map/issue-93054.cov-map b/tests/coverage/issue-93054.cov-map similarity index 100% rename from tests/coverage-map/issue-93054.cov-map rename to tests/coverage/issue-93054.cov-map diff --git a/tests/coverage-map/lazy_boolean.cov-map b/tests/coverage/lazy_boolean.cov-map similarity index 100% rename from tests/coverage-map/lazy_boolean.cov-map rename to tests/coverage/lazy_boolean.cov-map diff --git a/tests/coverage-map/long_and_wide.cov-map b/tests/coverage/long_and_wide.cov-map similarity index 100% rename from tests/coverage-map/long_and_wide.cov-map rename to tests/coverage/long_and_wide.cov-map diff --git a/tests/coverage-map/loop_break_value.cov-map b/tests/coverage/loop_break_value.cov-map similarity index 100% rename from tests/coverage-map/loop_break_value.cov-map rename to tests/coverage/loop_break_value.cov-map diff --git a/tests/coverage-map/loops_branches.cov-map b/tests/coverage/loops_branches.cov-map similarity index 100% rename from tests/coverage-map/loops_branches.cov-map rename to tests/coverage/loops_branches.cov-map diff --git a/tests/coverage-map/match_or_pattern.cov-map b/tests/coverage/match_or_pattern.cov-map similarity index 100% rename from tests/coverage-map/match_or_pattern.cov-map rename to tests/coverage/match_or_pattern.cov-map diff --git a/tests/coverage-map/nested_loops.cov-map b/tests/coverage/nested_loops.cov-map similarity index 100% rename from tests/coverage-map/nested_loops.cov-map rename to tests/coverage/nested_loops.cov-map diff --git a/tests/coverage-map/no_cov_crate.cov-map b/tests/coverage/no_cov_crate.cov-map similarity index 100% rename from tests/coverage-map/no_cov_crate.cov-map rename to tests/coverage/no_cov_crate.cov-map diff --git a/tests/coverage-map/overflow.cov-map b/tests/coverage/overflow.cov-map similarity index 100% rename from tests/coverage-map/overflow.cov-map rename to tests/coverage/overflow.cov-map diff --git a/tests/coverage-map/panic_unwind.cov-map b/tests/coverage/panic_unwind.cov-map similarity index 100% rename from tests/coverage-map/panic_unwind.cov-map rename to tests/coverage/panic_unwind.cov-map diff --git a/tests/coverage-map/partial_eq.cov-map b/tests/coverage/partial_eq.cov-map similarity index 100% rename from tests/coverage-map/partial_eq.cov-map rename to tests/coverage/partial_eq.cov-map diff --git a/tests/coverage-map/simple_loop.cov-map b/tests/coverage/simple_loop.cov-map similarity index 100% rename from tests/coverage-map/simple_loop.cov-map rename to tests/coverage/simple_loop.cov-map diff --git a/tests/coverage-map/simple_match.cov-map b/tests/coverage/simple_match.cov-map similarity index 100% rename from tests/coverage-map/simple_match.cov-map rename to tests/coverage/simple_match.cov-map diff --git a/tests/coverage-map/sort_groups.cov-map b/tests/coverage/sort_groups.cov-map similarity index 100% rename from tests/coverage-map/sort_groups.cov-map rename to tests/coverage/sort_groups.cov-map diff --git a/tests/coverage-map/test_harness.cov-map b/tests/coverage/test_harness.cov-map similarity index 100% rename from tests/coverage-map/test_harness.cov-map rename to tests/coverage/test_harness.cov-map diff --git a/tests/coverage-map/tight_inf_loop.cov-map b/tests/coverage/tight_inf_loop.cov-map similarity index 100% rename from tests/coverage-map/tight_inf_loop.cov-map rename to tests/coverage/tight_inf_loop.cov-map diff --git a/tests/coverage-map/trivial.cov-map b/tests/coverage/trivial.cov-map similarity index 100% rename from tests/coverage-map/trivial.cov-map rename to tests/coverage/trivial.cov-map diff --git a/tests/coverage-map/try_error_result.cov-map b/tests/coverage/try_error_result.cov-map similarity index 100% rename from tests/coverage-map/try_error_result.cov-map rename to tests/coverage/try_error_result.cov-map diff --git a/tests/coverage-map/unreachable.cov-map b/tests/coverage/unreachable.cov-map similarity index 100% rename from tests/coverage-map/unreachable.cov-map rename to tests/coverage/unreachable.cov-map diff --git a/tests/coverage-map/unused.cov-map b/tests/coverage/unused.cov-map similarity index 100% rename from tests/coverage-map/unused.cov-map rename to tests/coverage/unused.cov-map diff --git a/tests/coverage-map/unused_mod.cov-map b/tests/coverage/unused_mod.cov-map similarity index 100% rename from tests/coverage-map/unused_mod.cov-map rename to tests/coverage/unused_mod.cov-map diff --git a/tests/coverage-map/uses_crate.cov-map b/tests/coverage/uses_crate.cov-map similarity index 100% rename from tests/coverage-map/uses_crate.cov-map rename to tests/coverage/uses_crate.cov-map diff --git a/tests/coverage-map/uses_inline_crate.cov-map b/tests/coverage/uses_inline_crate.cov-map similarity index 100% rename from tests/coverage-map/uses_inline_crate.cov-map rename to tests/coverage/uses_inline_crate.cov-map diff --git a/tests/coverage-map/while.cov-map b/tests/coverage/while.cov-map similarity index 100% rename from tests/coverage-map/while.cov-map rename to tests/coverage/while.cov-map diff --git a/tests/coverage-map/while_early_ret.cov-map b/tests/coverage/while_early_ret.cov-map similarity index 100% rename from tests/coverage-map/while_early_ret.cov-map rename to tests/coverage/while_early_ret.cov-map diff --git a/tests/coverage-map/yield.cov-map b/tests/coverage/yield.cov-map similarity index 100% rename from tests/coverage-map/yield.cov-map rename to tests/coverage/yield.cov-map From 4e6f438d2ace2f5297cea2d3e331c6dccd4e18c2 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 1 Nov 2023 21:07:07 +1100 Subject: [PATCH 306/435] coverage: Register `test::Coverage` as the test suite for `tests/coverage` This restores the ability to run a coverage test by specifying its path, e.g. `./x.py test tests/coverage/if.rs`. This runs the test in both modes. --- src/bootstrap/src/core/build_steps/test.rs | 3 ++- tests/coverage/README.md | 17 ++++++++++------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index da4b135083c6..39667d16b7b6 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -1423,7 +1423,7 @@ impl Step for Coverage { const ONLY_HOSTS: bool = false; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.alias(Self::SUITE) + run.suite_path(Self::PATH) } fn make_run(run: RunConfig<'_>) { @@ -1438,6 +1438,7 @@ impl Step for Coverage { } } +// Aliases for running the coverage tests in only one mode. coverage_test_alias!(CoverageMap { alias_and_mode: "coverage-map", default: true, diff --git a/tests/coverage/README.md b/tests/coverage/README.md index 146fbff5b204..f1e403c65e35 100644 --- a/tests/coverage/README.md +++ b/tests/coverage/README.md @@ -1,13 +1,16 @@ -Many of these tests were copied from `tests/run-coverage` in order to -capture the current behavior of the instrumentor on non-trivial programs. -The actual mappings have not been closely inspected. +The tests in this directory are shared by two different test modes, and can be +run in multiple different ways: + +- `./x.py test coverage-map` (compiles to LLVM IR and checks coverage mappings) +- `./x.py test run-coverage` (runs a test binary and checks its coverage report) +- `./x.py test coverage` (runs both `coverage-map` and `run-coverage`) ## Maintenance note These tests can be sensitive to small changes in MIR spans or MIR control flow, especially in HIR-to-MIR lowering or MIR optimizations. -If you haven't touched the coverage code directly, and the `run-coverage` test -suite still works, then it should usually be OK to just `--bless` these -coverage mapping tests as necessary, without worrying too much about the exact -changes. +If you haven't touched the coverage code directly, and the tests still pass in +`run-coverage` mode, then it should usually be OK to just re-bless the mappings +as necessary with `./x.py test coverage-map --bless`, without worrying too much +about the exact changes. From f926031ea50ef58c1c8bfccd98da73d86d5fc937 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 21 Oct 2023 01:18:41 +0000 Subject: [PATCH 307/435] When not finding assoc fn on type, look for builder fn When we have a resolution error when looking at a fully qualified path on a type, look for all associated functions on inherent impls that return `Self` and mention them to the user. Fix #69512. --- .../rustc_hir_typeck/src/method/suggest.rs | 88 +++++++++++++++++++ tests/ui/atomic-from-mut-not-available.stderr | 4 + tests/ui/parser/emoji-identifiers.stderr | 6 ++ tests/ui/resolve/fn-new-doesnt-exist.rs | 5 ++ tests/ui/resolve/fn-new-doesnt-exist.stderr | 14 +++ tests/ui/resolve/issue-82865.stderr | 7 ++ tests/ui/suggestions/deref-path-method.stderr | 7 ++ tests/ui/suggestions/issue-109291.stderr | 7 ++ 8 files changed, 138 insertions(+) create mode 100644 tests/ui/resolve/fn-new-doesnt-exist.rs create mode 100644 tests/ui/resolve/fn-new-doesnt-exist.stderr diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 12cc5ed2f1a5..87dfcf09cdd3 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -409,6 +409,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.downgrade_to_delayed_bug(); } + self.find_builder_fn(&mut err, rcvr_ty, source); if tcx.ty_is_opaque_future(rcvr_ty) && item_name.name == sym::poll { err.help(format!( "method `poll` found on `Pin<&mut {ty_str}>`, \ @@ -1407,6 +1408,93 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } + /// Look at all the associated functions without receivers in the type's inherent impls + /// to look for builders that return `Self`, `Option` or `Result`. + fn find_builder_fn(&self, err: &mut Diagnostic, rcvr_ty: Ty<'tcx>, source: SelfSource<'tcx>) { + let ty::Adt(adt_def, _) = rcvr_ty.kind() else { + return; + }; + let SelfSource::QPath(ty) = source else { + return; + }; + let hir = self.tcx.hir(); + if let Some(Node::Pat(_)) = hir.find(hir.parent_id(ty.hir_id)) { + // Do not suggest a fn call when a pattern is expected. + return; + } + let mut items = self + .tcx + .inherent_impls(adt_def.did()) + .iter() + .flat_map(|i| self.tcx.associated_items(i).in_definition_order()) + // Only assoc fn with no receivers. + .filter(|item| matches!(item.kind, ty::AssocKind::Fn) && !item.fn_has_self_parameter) + .filter_map(|item| { + // Only assoc fns that return `Self`, `Option` or `Result`. + let ret_ty = self.tcx.fn_sig(item.def_id).skip_binder().output(); + let ret_ty = self.tcx.erase_late_bound_regions(ret_ty); + let ty::Adt(def, args) = ret_ty.kind() else { + return None; + }; + // Check for `-> Self` + if self.can_eq(self.param_env, ret_ty, rcvr_ty) { + return Some((item.def_id, ret_ty)); + } + // Check for `-> Option` or `-> Result` + if ![self.tcx.lang_items().option_type(), self.tcx.get_diagnostic_item(sym::Result)] + .contains(&Some(def.did())) + { + return None; + } + let arg = args.get(0)?.expect_ty(); + if self.can_eq(self.param_env, rcvr_ty, arg) { + Some((item.def_id, ret_ty)) + } else { + None + } + }) + .collect::>(); + let post = if items.len() > 5 { + let items_len = items.len(); + items.truncate(4); + format!("\nand {} others", items_len - 4) + } else { + String::new() + }; + match &items[..] { + [] => {} + [(def_id, ret_ty)] => { + err.span_note( + self.tcx.def_span(def_id), + format!( + "if you're trying to build a new `{rcvr_ty}`, consider using `{}` which \ + returns `{ret_ty}`", + self.tcx.def_path_str(def_id), + ), + ); + } + _ => { + let span: MultiSpan = items + .iter() + .map(|(def_id, _)| self.tcx.def_span(def_id)) + .collect::>() + .into(); + err.span_note( + span, + format!( + "if you're trying to build a new `{rcvr_ty}` consider using one of the \ + following associated functions:\n{}{post}", + items + .iter() + .map(|(def_id, _ret_ty)| self.tcx.def_path_str(def_id)) + .collect::>() + .join("\n") + ), + ); + } + } + } + /// Suggest calling `Ty::method` if `.method()` isn't found because the method /// doesn't take a `self` receiver. fn suggest_associated_call_syntax( diff --git a/tests/ui/atomic-from-mut-not-available.stderr b/tests/ui/atomic-from-mut-not-available.stderr index d1ebca8a29e9..c15d19b1594d 100644 --- a/tests/ui/atomic-from-mut-not-available.stderr +++ b/tests/ui/atomic-from-mut-not-available.stderr @@ -3,6 +3,10 @@ error[E0599]: no function or associated item named `from_mut` found for struct ` | LL | core::sync::atomic::AtomicU64::from_mut(&mut 0u64); | ^^^^^^^^ function or associated item not found in `AtomicU64` + | +note: if you're trying to build a new `AtomicU64`, consider using `AtomicU64::new` which returns `AtomicU64` + --> $SRC_DIR/core/src/sync/atomic.rs:LL:COL + = note: this error originates in the macro `atomic_int` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/tests/ui/parser/emoji-identifiers.stderr b/tests/ui/parser/emoji-identifiers.stderr index e645b68ba87c..8250dd1ea2e9 100644 --- a/tests/ui/parser/emoji-identifiers.stderr +++ b/tests/ui/parser/emoji-identifiers.stderr @@ -75,6 +75,12 @@ LL | 👀::full_of✨() | | | function or associated item not found in `👀` | help: there is an associated function with a similar name: `full_of_✨` + | +note: if you're trying to build a new `👀`, consider using `👀::full_of_✨` which returns `👀` + --> $DIR/emoji-identifiers.rs:4:5 + | +LL | fn full_of_✨() -> 👀 { + | ^^^^^^^^^^^^^^^^^^^^^ error[E0425]: cannot find function `i_like_to_😄_a_lot` in this scope --> $DIR/emoji-identifiers.rs:13:13 diff --git a/tests/ui/resolve/fn-new-doesnt-exist.rs b/tests/ui/resolve/fn-new-doesnt-exist.rs new file mode 100644 index 000000000000..4f6290808fc0 --- /dev/null +++ b/tests/ui/resolve/fn-new-doesnt-exist.rs @@ -0,0 +1,5 @@ +use std::net::TcpStream; + +fn main() { + let stream = TcpStream::new(); //~ ERROR no function or associated item named `new` found +} diff --git a/tests/ui/resolve/fn-new-doesnt-exist.stderr b/tests/ui/resolve/fn-new-doesnt-exist.stderr new file mode 100644 index 000000000000..39adc0fde44e --- /dev/null +++ b/tests/ui/resolve/fn-new-doesnt-exist.stderr @@ -0,0 +1,14 @@ +error[E0599]: no function or associated item named `new` found for struct `TcpStream` in the current scope + --> $DIR/fn-new-doesnt-exist.rs:4:28 + | +LL | let stream = TcpStream::new(); + | ^^^ function or associated item not found in `TcpStream` + | +note: if you're trying to build a new `TcpStream` consider using one of the following associated functions: + TcpStream::connect + TcpStream::connect_timeout + --> $SRC_DIR/std/src/net/tcp.rs:LL:COL + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/resolve/issue-82865.stderr b/tests/ui/resolve/issue-82865.stderr index 730fd6d60264..9d0439d9d876 100644 --- a/tests/ui/resolve/issue-82865.stderr +++ b/tests/ui/resolve/issue-82865.stderr @@ -15,6 +15,13 @@ LL | Box::z LL | mac!(); | ------ in this macro invocation | +note: if you're trying to build a new `Box<_, _>` consider using one of the following associated functions: + Box::::new + Box::::new_uninit + Box::::new_zeroed + Box::::try_new + and 18 others + --> $SRC_DIR/alloc/src/boxed.rs:LL:COL = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/ui/suggestions/deref-path-method.stderr b/tests/ui/suggestions/deref-path-method.stderr index 1cc37d61151c..0372a7e6cc0a 100644 --- a/tests/ui/suggestions/deref-path-method.stderr +++ b/tests/ui/suggestions/deref-path-method.stderr @@ -4,6 +4,13 @@ error[E0599]: no function or associated item named `contains` found for struct ` LL | Vec::contains(&vec, &0); | ^^^^^^^^ function or associated item not found in `Vec<_, _>` | +note: if you're trying to build a new `Vec<_, _>` consider using one of the following associated functions: + Vec::::new + Vec::::with_capacity + Vec::::from_raw_parts + Vec::::new_in + and 2 others + --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL help: the function `contains` is implemented on `[_]` | LL | <[_]>::contains(&vec, &0); diff --git a/tests/ui/suggestions/issue-109291.stderr b/tests/ui/suggestions/issue-109291.stderr index 4ef5948d9bf2..644841fdf7ed 100644 --- a/tests/ui/suggestions/issue-109291.stderr +++ b/tests/ui/suggestions/issue-109291.stderr @@ -6,6 +6,13 @@ LL | println!("Custom backtrace: {}", std::backtrace::Backtrace::forced_capt | | | function or associated item not found in `Backtrace` | help: there is an associated function with a similar name: `force_capture` + | +note: if you're trying to build a new `Backtrace` consider using one of the following associated functions: + Backtrace::capture + Backtrace::force_capture + Backtrace::disabled + Backtrace::create + --> $SRC_DIR/std/src/backtrace.rs:LL:COL error: aborting due to previous error From aae391cf6880cc19d2fa543cb3de67ffbb26d01c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 28 Sep 2023 18:49:39 +0000 Subject: [PATCH 308/435] Apply structured suggestion that allows test to work since 1.64 Close #73497. --- src/tools/tidy/src/ui_tests.rs | 2 +- ...k-underscore-lifetime-in-return-trait-object.fixed | 11 +++++++++++ ...ick-underscore-lifetime-in-return-trait-object.rs} | 1 + ...underscore-lifetime-in-return-trait-object.stderr} | 2 +- 4 files changed, 14 insertions(+), 2 deletions(-) create mode 100644 tests/ui/suggestions/lifetimes/suggest-using-tick-underscore-lifetime-in-return-trait-object.fixed rename tests/ui/{issues/issue-16922.rs => suggestions/lifetimes/suggest-using-tick-underscore-lifetime-in-return-trait-object.rs} (92%) rename tests/ui/{issues/issue-16922.stderr => suggestions/lifetimes/suggest-using-tick-underscore-lifetime-in-return-trait-object.stderr} (87%) diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index 7e24793adee0..dfa386b49de7 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -10,7 +10,7 @@ use std::path::{Path, PathBuf}; const ENTRY_LIMIT: usize = 900; // FIXME: The following limits should be reduced eventually. -const ISSUES_ENTRY_LIMIT: usize = 1854; +const ISSUES_ENTRY_LIMIT: usize = 1852; const ROOT_ENTRY_LIMIT: usize = 867; const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[ diff --git a/tests/ui/suggestions/lifetimes/suggest-using-tick-underscore-lifetime-in-return-trait-object.fixed b/tests/ui/suggestions/lifetimes/suggest-using-tick-underscore-lifetime-in-return-trait-object.fixed new file mode 100644 index 000000000000..84315ad91732 --- /dev/null +++ b/tests/ui/suggestions/lifetimes/suggest-using-tick-underscore-lifetime-in-return-trait-object.fixed @@ -0,0 +1,11 @@ +// run-rustfix +use std::any::Any; + +fn foo(value: &T) -> Box { + Box::new(value) as Box + //~^ ERROR lifetime may not live long enough +} + +fn main() { + let _ = foo(&5); +} diff --git a/tests/ui/issues/issue-16922.rs b/tests/ui/suggestions/lifetimes/suggest-using-tick-underscore-lifetime-in-return-trait-object.rs similarity index 92% rename from tests/ui/issues/issue-16922.rs rename to tests/ui/suggestions/lifetimes/suggest-using-tick-underscore-lifetime-in-return-trait-object.rs index bbbbf72dbd5d..fa7e72ff2a73 100644 --- a/tests/ui/issues/issue-16922.rs +++ b/tests/ui/suggestions/lifetimes/suggest-using-tick-underscore-lifetime-in-return-trait-object.rs @@ -1,3 +1,4 @@ +// run-rustfix use std::any::Any; fn foo(value: &T) -> Box { diff --git a/tests/ui/issues/issue-16922.stderr b/tests/ui/suggestions/lifetimes/suggest-using-tick-underscore-lifetime-in-return-trait-object.stderr similarity index 87% rename from tests/ui/issues/issue-16922.stderr rename to tests/ui/suggestions/lifetimes/suggest-using-tick-underscore-lifetime-in-return-trait-object.stderr index 9d9f32a97c06..dc5817bfe0f5 100644 --- a/tests/ui/issues/issue-16922.stderr +++ b/tests/ui/suggestions/lifetimes/suggest-using-tick-underscore-lifetime-in-return-trait-object.stderr @@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/issue-16922.rs:4:5 + --> $DIR/suggest-using-tick-underscore-lifetime-in-return-trait-object.rs:5:5 | LL | fn foo(value: &T) -> Box { | - let's call the lifetime of this reference `'1` From 88a37acb26a58472a124e38a8b63d27c204ca5a8 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 7 Nov 2023 03:43:08 +0000 Subject: [PATCH 309/435] Yeet MethodCallComponents --- compiler/rustc_hir_typeck/src/expr.rs | 6 +- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 3 +- compiler/rustc_hir_typeck/src/method/mod.rs | 2 +- .../rustc_hir_typeck/src/method/suggest.rs | 161 +++++++++--------- compiler/rustc_hir_typeck/src/pat.rs | 8 +- 5 files changed, 90 insertions(+), 90 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index bb21b027cc9f..92501fb0a83c 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -13,7 +13,7 @@ use crate::errors::{ YieldExprOutsideOfCoroutine, }; use crate::fatally_break_rust; -use crate::method::{MethodCallComponents, SelfSource}; +use crate::method::SelfSource; use crate::type_error_struct; use crate::Expectation::{self, ExpectCastableToType, ExpectHasType, NoExpectation}; use crate::{ @@ -512,7 +512,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> Ty<'tcx> { let tcx = self.tcx; let (res, opt_ty, segs) = - self.resolve_ty_and_res_fully_qualified_call(qpath, expr.hir_id, expr.span); + self.resolve_ty_and_res_fully_qualified_call(qpath, expr.hir_id, expr.span, Some(args)); let ty = match res { Res::Err => { self.suggest_assoc_method_call(segs); @@ -1332,7 +1332,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { segment.ident, SelfSource::MethodCall(rcvr), error, - Some(MethodCallComponents { receiver: rcvr, args, full_expr: expr }), + Some(args), expected, false, ) { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index b5a07f0d3e9e..750ed2c34913 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -797,6 +797,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { qpath: &'tcx QPath<'tcx>, hir_id: hir::HirId, span: Span, + args: Option<&'tcx [hir::Expr<'tcx>]>, ) -> (Res, Option>, &'tcx [hir::PathSegment<'tcx>]) { debug!( "resolve_ty_and_res_fully_qualified_call: qpath={:?} hir_id={:?} span={:?}", @@ -898,7 +899,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { item_name, SelfSource::QPath(qself), error, - None, + args, Expectation::NoExpectation, trait_missing_method && span.edition().at_least_rust_2021(), // emits missing method for trait only after edition 2021 ) { diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs index 86a0e95de1da..d69d2529b18d 100644 --- a/compiler/rustc_hir_typeck/src/method/mod.rs +++ b/compiler/rustc_hir_typeck/src/method/mod.rs @@ -7,7 +7,7 @@ mod prelude2021; pub mod probe; mod suggest; -pub use self::suggest::{MethodCallComponents, SelfSource}; +pub use self::suggest::SelfSource; pub use self::MethodError::*; use crate::errors::OpMethodGenericParams; diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 87dfcf09cdd3..426cec11d0e6 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -50,15 +50,6 @@ use rustc_hir::intravisit::Visitor; use std::cmp::{self, Ordering}; use std::iter; -/// After identifying that `full_expr` is a method call, we use this type to keep the expression's -/// components readily available to us to point at the right place in diagnostics. -#[derive(Debug, Clone, Copy)] -pub struct MethodCallComponents<'tcx> { - pub receiver: &'tcx hir::Expr<'tcx>, - pub args: &'tcx [hir::Expr<'tcx>], - pub full_expr: &'tcx hir::Expr<'tcx>, -} - impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn is_fn_ty(&self, ty: Ty<'tcx>, span: Span) -> bool { let tcx = self.tcx; @@ -124,7 +115,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { item_name: Ident, source: SelfSource<'tcx>, error: MethodError<'tcx>, - args: Option>, + args: Option<&'tcx [hir::Expr<'tcx>]>, expected: Expectation<'tcx>, trait_missing_method: bool, ) -> Option> { @@ -167,6 +158,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.note_candidates_on_method_error( rcvr_ty, item_name, + source, args, span, &mut err, @@ -266,23 +258,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn suggest_missing_writer( &self, rcvr_ty: Ty<'tcx>, - args: MethodCallComponents<'tcx>, + rcvr_expr: &hir::Expr<'tcx>, ) -> DiagnosticBuilder<'_, ErrorGuaranteed> { let (ty_str, _ty_file) = self.tcx.short_ty_string(rcvr_ty); let mut err = struct_span_err!( self.tcx.sess, - args.receiver.span, + rcvr_expr.span, E0599, "cannot write into `{}`", ty_str ); err.span_note( - args.receiver.span, + rcvr_expr.span, "must implement `io::Write`, `fmt::Write`, or have a `write_fmt` method", ); - if let ExprKind::Lit(_) = args.receiver.kind { + if let ExprKind::Lit(_) = rcvr_expr.kind { err.span_help( - args.receiver.span.shrink_to_lo(), + rcvr_expr.span.shrink_to_lo(), "a writer is needed before this format string", ); }; @@ -296,7 +288,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { rcvr_ty: Ty<'tcx>, item_name: Ident, source: SelfSource<'tcx>, - args: Option>, + args: Option<&'tcx [hir::Expr<'tcx>]>, sugg_span: Span, no_match_data: &mut NoMatchData<'tcx>, expected: Expectation<'tcx>, @@ -377,23 +369,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { tcx.is_diagnostic_item(sym::write_macro, def_id) || tcx.is_diagnostic_item(sym::writeln_macro, def_id) }) && item_name.name == Symbol::intern("write_fmt"); - let mut err = if is_write && let Some(args) = args { - self.suggest_missing_writer(rcvr_ty, args) - } else { - tcx.sess.create_err(NoAssociatedItem { - span, - item_kind, - item_name, - ty_prefix: if trait_missing_method { - // FIXME(mu001999) E0599 maybe not suitable here because it is for types - Cow::from("trait") - } else { - rcvr_ty.prefix_string(self.tcx) - }, - ty_str: ty_str_reported, - trait_missing_method, - }) - }; + let mut err = + if is_write && let SelfSource::MethodCall(rcvr_expr) = source + { + self.suggest_missing_writer(rcvr_ty, rcvr_expr) + } else { + tcx.sess.create_err(NoAssociatedItem { + span, + item_kind, + item_name, + ty_prefix: if trait_missing_method { + // FIXME(mu001999) E0599 maybe not suitable here because it is for types + Cow::from("trait") + } else { + rcvr_ty.prefix_string(self.tcx) + }, + ty_str: ty_str_reported, + trait_missing_method, + }) + }; if tcx.sess.source_map().is_multiline(sugg_span) { err.span_label(sugg_span.with_hi(span.lo()), ""); } @@ -409,7 +403,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.downgrade_to_delayed_bug(); } - self.find_builder_fn(&mut err, rcvr_ty, source); + if matches!(source, SelfSource::QPath(_)) && args.is_some() { + self.find_builder_fn(&mut err, rcvr_ty); + } + if tcx.ty_is_opaque_future(rcvr_ty) && item_name.name == sym::poll { err.help(format!( "method `poll` found on `Pin<&mut {ty_str}>`, \ @@ -523,6 +520,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.note_candidates_on_method_error( rcvr_ty, item_name, + source, args, span, &mut err, @@ -533,6 +531,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.note_candidates_on_method_error( rcvr_ty, item_name, + source, args, span, &mut err, @@ -976,7 +975,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { unsatisfied_bounds = true; } } else if let ty::Adt(def, targs) = rcvr_ty.kind() - && let Some(args) = args + && let SelfSource::MethodCall(rcvr_expr) = source { // This is useful for methods on arbitrary self types that might have a simple // mutability difference, like calling a method on `Pin<&mut Self>` that is on @@ -999,8 +998,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { rcvr_ty, &item_segment, span, - args.full_expr, - args.receiver, + tcx.hir().get_parent(rcvr_expr.hir_id).expect_expr(), + rcvr_expr, ) { err.span_note( tcx.def_span(method.def_id), @@ -1169,7 +1168,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span, rcvr_ty, item_name, - args.map(|MethodCallComponents { args, .. }| args.len() + 1), + args.map(|args| args.len() + 1), source, no_match_data.out_of_scope_traits.clone(), &unsatisfied_predicates, @@ -1250,7 +1249,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, rcvr_ty: Ty<'tcx>, item_name: Ident, - args: Option>, + self_source: SelfSource<'tcx>, + args: Option<&'tcx [hir::Expr<'tcx>]>, span: Span, err: &mut Diagnostic, sources: &mut Vec, @@ -1339,6 +1339,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Some(sugg) = print_disambiguation_help( item_name, args, + self_source, err, path, ty, @@ -1378,6 +1379,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Some(sugg) = print_disambiguation_help( item_name, args, + self_source, err, path, rcvr_ty, @@ -1410,18 +1412,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Look at all the associated functions without receivers in the type's inherent impls /// to look for builders that return `Self`, `Option` or `Result`. - fn find_builder_fn(&self, err: &mut Diagnostic, rcvr_ty: Ty<'tcx>, source: SelfSource<'tcx>) { + fn find_builder_fn(&self, err: &mut Diagnostic, rcvr_ty: Ty<'tcx>) { let ty::Adt(adt_def, _) = rcvr_ty.kind() else { return; }; - let SelfSource::QPath(ty) = source else { - return; - }; - let hir = self.tcx.hir(); - if let Some(Node::Pat(_)) = hir.find(hir.parent_id(ty.hir_id)) { - // Do not suggest a fn call when a pattern is expected. - return; - } let mut items = self .tcx .inherent_impls(adt_def.did()) @@ -1504,7 +1498,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { rcvr_ty: Ty<'tcx>, source: SelfSource<'tcx>, item_name: Ident, - args: Option>, + args: Option<&'tcx [hir::Expr<'tcx>]>, sugg_span: Span, ) { let mut has_unsuggestable_args = false; @@ -1578,38 +1572,40 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { None }; let mut applicability = Applicability::MachineApplicable; - let args = if let Some(MethodCallComponents { receiver, args, .. }) = args { - // The first arg is the same kind as the receiver - let explicit_args = if first_arg.is_some() { - std::iter::once(receiver).chain(args.iter()).collect::>() + let args = if let SelfSource::MethodCall(receiver) = source + && let Some(args) = args + { + // The first arg is the same kind as the receiver + let explicit_args = if first_arg.is_some() { + std::iter::once(receiver).chain(args.iter()).collect::>() + } else { + // There is no `Self` kind to infer the arguments from + if has_unsuggestable_args { + applicability = Applicability::HasPlaceholders; + } + args.iter().collect() + }; + format!( + "({}{})", + first_arg.unwrap_or(""), + explicit_args + .iter() + .map(|arg| self + .tcx + .sess + .source_map() + .span_to_snippet(arg.span) + .unwrap_or_else(|_| { + applicability = Applicability::HasPlaceholders; + "_".to_owned() + })) + .collect::>() + .join(", "), + ) } else { - // There is no `Self` kind to infer the arguments from - if has_unsuggestable_args { - applicability = Applicability::HasPlaceholders; - } - args.iter().collect() + applicability = Applicability::HasPlaceholders; + "(...)".to_owned() }; - format!( - "({}{})", - first_arg.unwrap_or(""), - explicit_args - .iter() - .map(|arg| self - .tcx - .sess - .source_map() - .span_to_snippet(arg.span) - .unwrap_or_else(|_| { - applicability = Applicability::HasPlaceholders; - "_".to_owned() - })) - .collect::>() - .join(", "), - ) - } else { - applicability = Applicability::HasPlaceholders; - "(...)".to_owned() - }; err.span_suggestion( sugg_span, "use associated function syntax instead", @@ -3268,7 +3264,8 @@ pub fn all_traits(tcx: TyCtxt<'_>) -> Vec { fn print_disambiguation_help<'tcx>( item_name: Ident, - args: Option>, + args: Option<&'tcx [hir::Expr<'tcx>]>, + source: SelfSource<'tcx>, err: &mut Diagnostic, trait_name: String, rcvr_ty: Ty<'_>, @@ -3281,7 +3278,9 @@ fn print_disambiguation_help<'tcx>( fn_has_self_parameter: bool, ) -> Option { Some( - if let (ty::AssocKind::Fn, Some(MethodCallComponents { receiver, args, .. })) = (kind, args) + if matches!(kind, ty::AssocKind::Fn) + && let SelfSource::MethodCall(receiver) = source + && let Some(args) = args { let args = format!( "({}{})", diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 50684482c0d5..b30f9b82fbbf 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -166,9 +166,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn check_pat(&self, pat: &'tcx Pat<'tcx>, expected: Ty<'tcx>, pat_info: PatInfo<'tcx, '_>) { let PatInfo { binding_mode: def_bm, top_info: ti, .. } = pat_info; let path_res = match &pat.kind { - PatKind::Path(qpath) => { - Some(self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span)) - } + PatKind::Path(qpath) => Some( + self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span, None), + ), _ => None, }; let adjust_mode = self.calc_adjust_mode(pat, path_res.map(|(res, ..)| res)); @@ -1060,7 +1060,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Resolve the path and check the definition for errors. let (res, opt_ty, segments) = - self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span); + self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span, None); if res == Res::Err { let e = tcx.sess.delay_span_bug(pat.span, "`Res::Err` but no error emitted"); self.set_tainted_by_errors(e); From 0add056dee57a0b56f3316596dcecb1bbde17a08 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 7 Nov 2023 05:22:20 +0000 Subject: [PATCH 310/435] Rework print_disambiguation_help --- .../rustc_hir_typeck/src/method/suggest.rs | 126 ++++++++---------- .../disambiguate-multiple-blanket-impl.stderr | 12 +- .../methods/disambiguate-multiple-impl.stderr | 8 +- .../disambiguate-multiple-trait-2.stderr | 28 ++-- .../disambiguate-multiple-trait.stderr | 12 +- ...method-ambig-two-traits-from-bounds.stderr | 8 +- ...e-trait-object-with-separate-params.stderr | 4 +- tests/ui/span/issue-37767.stderr | 8 +- 8 files changed, 93 insertions(+), 113 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 426cec11d0e6..b1a2df8ace40 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -34,7 +34,7 @@ use rustc_middle::ty::{self, GenericArgKind, Ty, TyCtxt, TypeVisitableExt}; use rustc_span::def_id::DefIdSet; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::Symbol; -use rustc_span::{edit_distance, source_map, ExpnKind, FileName, MacroKind, Span}; +use rustc_span::{edit_distance, ExpnKind, FileName, MacroKind, Span}; use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::error_reporting::on_unimplemented::OnUnimplementedNote; use rustc_trait_selection::traits::error_reporting::on_unimplemented::TypeErrCtxtExt as _; @@ -1320,39 +1320,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } if let Some(sugg_span) = sugg_span && let Some(trait_ref) = self.tcx.impl_trait_ref(impl_did) - { - let path = self.tcx.def_path_str(trait_ref.skip_binder().def_id); - - let ty = match item.kind { - ty::AssocKind::Const | ty::AssocKind::Type => impl_ty, - ty::AssocKind::Fn => self - .tcx - .fn_sig(item.def_id) - .instantiate_identity() - .inputs() - .skip_binder() - .get(0) - .filter(|ty| ty.is_ref() && !rcvr_ty.is_ref()) - .copied() - .unwrap_or(rcvr_ty), - }; - if let Some(sugg) = print_disambiguation_help( - item_name, - args, - self_source, + && let Some(sugg) = print_disambiguation_help( + self.tcx, err, - path, - ty, - Some(impl_ty), - item.kind, - self.tcx.def_kind_descr(item.kind.as_def_kind(), item.def_id), - sugg_span, + self_source, + args, + trait_ref.instantiate( + self.tcx, + self.fresh_args_for_item(sugg_span, impl_did) + ).with_self_ty(self.tcx, rcvr_ty), idx, - self.tcx.sess.source_map(), - item.fn_has_self_parameter, - ) { - suggs.push(sugg); - } + sugg_span, + item, + ) + { + suggs.push(sugg); } } CandidateSource::Trait(trait_did) => { @@ -1374,25 +1356,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.span_note(item_span, msg); None }; - if let Some(sugg_span) = sugg_span { - let path = self.tcx.def_path_str(trait_did); - if let Some(sugg) = print_disambiguation_help( - item_name, - args, - self_source, + if let Some(sugg_span) = sugg_span + && let Some(sugg) = print_disambiguation_help( + self.tcx, err, - path, - rcvr_ty, - None, - item.kind, - self.tcx.def_kind_descr(item.kind.as_def_kind(), item.def_id), - sugg_span, + self_source, + args, + ty::TraitRef::new( + self.tcx, + trait_did, + self.fresh_args_for_item(sugg_span, trait_did) + ).with_self_ty(self.tcx, rcvr_ty), idx, - self.tcx.sess.source_map(), - item.fn_has_self_parameter, - ) { - suggs.push(sugg); - } + sugg_span, + item, + ) + { + suggs.push(sugg); } } } @@ -3263,59 +3243,59 @@ pub fn all_traits(tcx: TyCtxt<'_>) -> Vec { } fn print_disambiguation_help<'tcx>( - item_name: Ident, - args: Option<&'tcx [hir::Expr<'tcx>]>, - source: SelfSource<'tcx>, + tcx: TyCtxt<'tcx>, err: &mut Diagnostic, - trait_name: String, - rcvr_ty: Ty<'_>, - impl_self_ty: Option>, - kind: ty::AssocKind, - def_kind_descr: &'static str, + source: SelfSource<'tcx>, + args: Option<&'tcx [hir::Expr<'tcx>]>, + trait_ref: ty::TraitRef<'tcx>, + candidate_idx: Option, span: Span, - candidate: Option, - source_map: &source_map::SourceMap, - fn_has_self_parameter: bool, + item: ty::AssocItem, ) -> Option { + let trait_ref = if item.fn_has_self_parameter { + trait_ref.print_only_trait_name().to_string() + } else { + format!("<{} as {}>", trait_ref.args[0], trait_ref.print_only_trait_name()) + }; Some( - if matches!(kind, ty::AssocKind::Fn) + if matches!(item.kind, ty::AssocKind::Fn) && let SelfSource::MethodCall(receiver) = source && let Some(args) = args { + let def_kind_descr = tcx.def_kind_descr(item.kind.as_def_kind(), item.def_id); + let item_name = item.ident(tcx); + let rcvr_ref = tcx.fn_sig(item.def_id).skip_binder().skip_binder().inputs()[0] + .ref_mutability() + .map_or("", |mutbl| mutbl.ref_prefix_str()); let args = format!( "({}{})", - rcvr_ty.ref_mutability().map_or("", |mutbl| mutbl.ref_prefix_str()), + rcvr_ref, std::iter::once(receiver) .chain(args.iter()) - .map(|arg| source_map + .map(|arg| tcx + .sess + .source_map() .span_to_snippet(arg.span) .unwrap_or_else(|_| { "_".to_owned() })) .collect::>() .join(", "), ); - let trait_name = if !fn_has_self_parameter && let Some(impl_self_ty) = impl_self_ty { - format!("<{impl_self_ty} as {trait_name}>") - } else { - trait_name - }; err.span_suggestion_verbose( span, format!( "disambiguate the {def_kind_descr} for {}", - if let Some(candidate) = candidate { + if let Some(candidate) = candidate_idx { format!("candidate #{candidate}") } else { "the candidate".to_string() }, ), - format!("{trait_name}::{item_name}{args}"), + format!("{trait_ref}::{item_name}{args}"), Applicability::HasPlaceholders, ); return None; - } else if let Some(impl_self_ty) = impl_self_ty { - format!("<{impl_self_ty} as {trait_name}>::") } else { - format!("{trait_name}::") + format!("{trait_ref}::") }, ) } diff --git a/tests/ui/methods/disambiguate-multiple-blanket-impl.stderr b/tests/ui/methods/disambiguate-multiple-blanket-impl.stderr index a9e9c679fdb6..ccdd9a95451b 100644 --- a/tests/ui/methods/disambiguate-multiple-blanket-impl.stderr +++ b/tests/ui/methods/disambiguate-multiple-blanket-impl.stderr @@ -29,10 +29,10 @@ LL | fn foo(&self) {} | ^^^^^^^^^^^^^ help: use fully-qualified syntax to disambiguate | -LL | ::foo(&s); - | ~~~~~~~~~~ -LL | ::foo(&s); - | ~~~~~~~~~~ +LL | A::foo(&s); + | ~~~ +LL | B::foo(&s); + | ~~~ error[E0034]: multiple applicable items in scope --> $DIR/disambiguate-multiple-blanket-impl.rs:33:8 @@ -52,9 +52,9 @@ LL | const CONST: usize = 2; | ^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax to disambiguate | -LL | ::CONST; +LL | ::CONST; | ~~~~~~~~~~ -LL | ::CONST; +LL | ::CONST; | ~~~~~~~~~~ error: aborting due to 3 previous errors diff --git a/tests/ui/methods/disambiguate-multiple-impl.stderr b/tests/ui/methods/disambiguate-multiple-impl.stderr index 901bfc30a3f2..4172120770c6 100644 --- a/tests/ui/methods/disambiguate-multiple-impl.stderr +++ b/tests/ui/methods/disambiguate-multiple-impl.stderr @@ -29,10 +29,10 @@ LL | fn foo(&self) {} | ^^^^^^^^^^^^^ help: use fully-qualified syntax to disambiguate | -LL | ::foo(&s); - | ~~~~~~~~~~ -LL | ::foo(&s); - | ~~~~~~~~~~ +LL | A::foo(&s); + | ~~~ +LL | B::foo(&s); + | ~~~ error[E0034]: multiple applicable items in scope --> $DIR/disambiguate-multiple-impl.rs:34:16 diff --git a/tests/ui/methods/disambiguate-multiple-trait-2.stderr b/tests/ui/methods/disambiguate-multiple-trait-2.stderr index 0f9c60ce243d..2778f254a561 100644 --- a/tests/ui/methods/disambiguate-multiple-trait-2.stderr +++ b/tests/ui/methods/disambiguate-multiple-trait-2.stderr @@ -37,12 +37,12 @@ LL | fn foo(&self); | ^^^^^^^^^^^^^^ help: disambiguate the method for candidate #1 | -LL | A::foo(t); - | ~~~~~~~~~ +LL | A::foo(&t); + | ~~~~~~~~~~ help: disambiguate the method for candidate #2 | -LL | B::foo(t); - | ~~~~~~~~~ +LL | B::foo(&t); + | ~~~~~~~~~~ error[E0034]: multiple applicable items in scope --> $DIR/disambiguate-multiple-trait-2.rs:20:16 @@ -62,10 +62,10 @@ LL | const CONST: usize; | ^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax to disambiguate | -LL | let _ = A::CONST; - | ~~~ -LL | let _ = B::CONST; - | ~~~ +LL | let _ = ::CONST; + | ~~~~~~~~~~ +LL | let _ = ::CONST; + | ~~~~~~~~~~ error[E0223]: ambiguous associated type --> $DIR/disambiguate-multiple-trait-2.rs:52:12 @@ -98,10 +98,10 @@ LL | fn foo(&self) {} | ^^^^^^^^^^^^^ help: use fully-qualified syntax to disambiguate | -LL | ::foo(&s); - | ~~~~~~~~~~ -LL | ::foo(&s); - | ~~~~~~~~~~ +LL | A::foo(&s); + | ~~~ +LL | B::foo(&s); + | ~~~ error[E0034]: multiple applicable items in scope --> $DIR/disambiguate-multiple-trait-2.rs:49:16 @@ -121,9 +121,9 @@ LL | const CONST: usize = 1; | ^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax to disambiguate | -LL | let _ = ::CONST; +LL | let _ = ::CONST; | ~~~~~~~~~~ -LL | let _ = ::CONST; +LL | let _ = ::CONST; | ~~~~~~~~~~ error: aborting due to 6 previous errors diff --git a/tests/ui/methods/disambiguate-multiple-trait.stderr b/tests/ui/methods/disambiguate-multiple-trait.stderr index 9a50d51245ba..e00498ca62b4 100644 --- a/tests/ui/methods/disambiguate-multiple-trait.stderr +++ b/tests/ui/methods/disambiguate-multiple-trait.stderr @@ -29,10 +29,10 @@ LL | fn foo(&self) {} | ^^^^^^^^^^^^^ help: use fully-qualified syntax to disambiguate | -LL | ::foo(&s); - | ~~~~~~~~~~ -LL | ::foo(&s); - | ~~~~~~~~~~ +LL | A::foo(&s); + | ~~~ +LL | B::foo(&s); + | ~~~ error[E0034]: multiple applicable items in scope --> $DIR/disambiguate-multiple-trait.rs:27:16 @@ -52,9 +52,9 @@ LL | const CONST: usize = 2; | ^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax to disambiguate | -LL | let _ = ::CONST; +LL | let _ = ::CONST; | ~~~~~~~~~~ -LL | let _ = ::CONST; +LL | let _ = ::CONST; | ~~~~~~~~~~ error: aborting due to 3 previous errors diff --git a/tests/ui/methods/method-ambig-two-traits-from-bounds.stderr b/tests/ui/methods/method-ambig-two-traits-from-bounds.stderr index 601e6bbb006f..9a84768a9f4a 100644 --- a/tests/ui/methods/method-ambig-two-traits-from-bounds.stderr +++ b/tests/ui/methods/method-ambig-two-traits-from-bounds.stderr @@ -16,12 +16,12 @@ LL | trait B { fn foo(&self); } | ^^^^^^^^^^^^^^ help: disambiguate the method for candidate #1 | -LL | A::foo(t); - | ~~~~~~~~~ +LL | A::foo(&t); + | ~~~~~~~~~~ help: disambiguate the method for candidate #2 | -LL | B::foo(t); - | ~~~~~~~~~ +LL | B::foo(&t); + | ~~~~~~~~~~ error: aborting due to previous error diff --git a/tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr b/tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr index 4e83e4b77f10..755179650bba 100644 --- a/tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr +++ b/tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr @@ -54,8 +54,8 @@ LL | let z = NuisanceFoo::foo(x); | ~~~~~~~~~~~~~~~~~~~ help: disambiguate the method for candidate #3 | -LL | let z = FinalFoo::foo(x); - | ~~~~~~~~~~~~~~~~ +LL | let z = FinalFoo::foo(&x); + | ~~~~~~~~~~~~~~~~~ error[E0308]: mismatched types --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:139:24 diff --git a/tests/ui/span/issue-37767.stderr b/tests/ui/span/issue-37767.stderr index b612fdf16fc8..457870821a19 100644 --- a/tests/ui/span/issue-37767.stderr +++ b/tests/ui/span/issue-37767.stderr @@ -16,12 +16,12 @@ LL | fn foo(&mut self) {} | ^^^^^^^^^^^^^^^^^ help: disambiguate the method for candidate #1 | -LL | A::foo(&a) - | ~~~~~~~~~~ +LL | A::foo(&mut a) + | ~~~~~~~~~~~~~~ help: disambiguate the method for candidate #2 | -LL | B::foo(&a) - | ~~~~~~~~~~ +LL | B::foo(&mut a) + | ~~~~~~~~~~~~~~ error[E0034]: multiple applicable items in scope --> $DIR/issue-37767.rs:22:7 From 13249b7dd9f6fb9acbd8629093226407d3a38690 Mon Sep 17 00:00:00 2001 From: roife Date: Tue, 7 Nov 2023 14:51:34 +0800 Subject: [PATCH 311/435] fix: correct a typo in a comment in base-db/lib.rs --- crates/base-db/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/base-db/src/lib.rs b/crates/base-db/src/lib.rs index af204e44e6ee..c5c4afa30f79 100644 --- a/crates/base-db/src/lib.rs +++ b/crates/base-db/src/lib.rs @@ -75,7 +75,7 @@ pub trait SourceDatabase: FileLoader + std::fmt::Debug { #[salsa::input] fn crate_graph(&self) -> Arc; - /// The crate graph. + /// The proc macros. #[salsa::input] fn proc_macros(&self) -> Arc; } From 61e38ceea7fb8dad16a0e1c42b70417b057e22a7 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 7 Nov 2023 08:59:16 +0000 Subject: [PATCH 312/435] Implement all SSE intrinsics used by the jpeg-decoder crate --- src/intrinsics/llvm_x86.rs | 71 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/src/intrinsics/llvm_x86.rs b/src/intrinsics/llvm_x86.rs index 9c415d468d87..622688fb82c1 100644 --- a/src/intrinsics/llvm_x86.rs +++ b/src/intrinsics/llvm_x86.rs @@ -413,6 +413,77 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( ret.place_lane(fx, out_lane_idx).write_cvalue(fx, res_lane); } } + + "llvm.x86.ssse3.pmul.hr.sw.128" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_mulhrs_epi16&ig_expand=4782 + intrinsic_args!(fx, args => (a, b); intrinsic); + + assert_eq!(a.layout(), b.layout()); + let layout = a.layout(); + + let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx); + let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx); + assert_eq!(lane_ty, fx.tcx.types.i16); + assert_eq!(ret_lane_ty, fx.tcx.types.i16); + assert_eq!(lane_count, ret_lane_count); + + let ret_lane_layout = fx.layout_of(fx.tcx.types.i16); + for out_lane_idx in 0..lane_count { + let a_lane = a.value_lane(fx, out_lane_idx).load_scalar(fx); + let a_lane = fx.bcx.ins().sextend(types::I32, a_lane); + let b_lane = b.value_lane(fx, out_lane_idx).load_scalar(fx); + let b_lane = fx.bcx.ins().sextend(types::I32, b_lane); + + let mul: Value = fx.bcx.ins().imul(a_lane, b_lane); + let shifted = fx.bcx.ins().ushr_imm(mul, 14); + let incremented = fx.bcx.ins().iadd_imm(shifted, 1); + let shifted_again = fx.bcx.ins().ushr_imm(incremented, 1); + + let res_lane = fx.bcx.ins().ireduce(types::I16, shifted_again); + let res_lane = CValue::by_val(res_lane, ret_lane_layout); + + ret.place_lane(fx, out_lane_idx).write_cvalue(fx, res_lane); + } + } + + "llvm.x86.sse2.packuswb.128" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_packus_epi16&ig_expand=4903 + intrinsic_args!(fx, args => (a, b); intrinsic); + + assert_eq!(a.layout(), b.layout()); + let layout = a.layout(); + + let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx); + let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx); + assert_eq!(lane_ty, fx.tcx.types.i16); + assert_eq!(ret_lane_ty, fx.tcx.types.u8); + assert_eq!(lane_count * 2, ret_lane_count); + + let zero = fx.bcx.ins().iconst(types::I16, 0); + let max_u8 = fx.bcx.ins().iconst(types::I16, 255); + let ret_lane_layout = fx.layout_of(fx.tcx.types.u8); + + for idx in 0..lane_count { + let lane = a.value_lane(fx, idx).load_scalar(fx); + let sat = fx.bcx.ins().smax(lane, zero); + let sat = fx.bcx.ins().umin(sat, max_u8); + let res = fx.bcx.ins().ireduce(types::I8, sat); + + let res_lane = CValue::by_val(res, ret_lane_layout); + ret.place_lane(fx, idx).write_cvalue(fx, res_lane); + } + + for idx in 0..lane_count { + let lane = b.value_lane(fx, idx).load_scalar(fx); + let sat = fx.bcx.ins().smax(lane, zero); + let sat = fx.bcx.ins().umin(sat, max_u8); + let res = fx.bcx.ins().ireduce(types::I8, sat); + + let res_lane = CValue::by_val(res, ret_lane_layout); + ret.place_lane(fx, lane_count + idx).write_cvalue(fx, res_lane); + } + } + _ => { fx.tcx .sess From 0a35232c8523968444bc8f86ed630d886cfe6525 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 7 Nov 2023 09:42:01 +0000 Subject: [PATCH 313/435] Implement all vendor intrinsics used by the httparse crate --- src/intrinsics/llvm_x86.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/intrinsics/llvm_x86.rs b/src/intrinsics/llvm_x86.rs index 622688fb82c1..6a91ce42fdf6 100644 --- a/src/intrinsics/llvm_x86.rs +++ b/src/intrinsics/llvm_x86.rs @@ -27,6 +27,16 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( crate::inline_asm::codegen_xgetbv(fx, xcr_no, ret); } + "llvm.x86.sse3.ldu.dq" | "llvm.x86.avx.ldu.dq.256" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_lddqu_si128&ig_expand=4009 + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_lddqu_si256&ig_expand=4010 + intrinsic_args!(fx, args => (ptr); intrinsic); + + // FIXME correctly handle unalignedness + let val = CValue::by_ref(Pointer::new(ptr.load_scalar(fx)), ret.layout()); + ret.write_cvalue(fx, val); + } + "llvm.x86.sse.cmp.ps" | "llvm.x86.sse2.cmp.pd" => { let (x, y, kind) = match args { [x, y, kind] => (x, y, kind), From eed89185bb88c75a4fd6d013b7368939bb03682e Mon Sep 17 00:00:00 2001 From: klensy Date: Tue, 7 Nov 2023 15:19:33 +0300 Subject: [PATCH 314/435] bump some deps drop num_cpus from rust-installer as not used update rayon, rayon-core, which drops it's deps on num_cpus and crossbeam-channel (for bootstrap too) (https://github.com/rayon-rs/rayon/blob/v1.8.0/RELEASES.md) update erro, which drops errno-dragonfly (https://github.com/lambda-fairy/rust-errno/blob/5341791935df601306ffc57a665763c4ecd72755/CHANGELOG.md) --- Cargo.lock | 26 +++++-------------- src/bootstrap/Cargo.lock | 40 +++-------------------------- src/tools/rust-installer/Cargo.toml | 1 - src/tools/tidy/src/deps.rs | 1 - 4 files changed, 10 insertions(+), 58 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e6c5de3ca6c4..55ed17ac256a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1281,25 +1281,14 @@ checksum = "88bffebc5d80432c9b140ee17875ff173a8ab62faad5b257da912bd2f6c1c0a1" [[package]] name = "errno" -version = "0.3.1" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" +checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860" dependencies = [ - "errno-dragonfly", "libc", "windows-sys 0.48.0", ] -[[package]] -name = "errno-dragonfly" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" -dependencies = [ - "cc", - "libc", -] - [[package]] name = "error_index_generator" version = "0.0.0" @@ -2055,7 +2044,6 @@ dependencies = [ "anyhow", "clap", "flate2", - "num_cpus", "rayon", "tar", "walkdir", @@ -3181,9 +3169,9 @@ dependencies = [ [[package]] name = "rayon" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" +checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" dependencies = [ "either", "rayon-core", @@ -3191,14 +3179,12 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" +checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" dependencies = [ - "crossbeam-channel", "crossbeam-deque", "crossbeam-utils", - "num_cpus", ] [[package]] diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock index 346bfb30fecf..57113b0ec62c 100644 --- a/src/bootstrap/Cargo.lock +++ b/src/bootstrap/Cargo.lock @@ -180,16 +180,6 @@ dependencies = [ "libc", ] -[[package]] -name = "crossbeam-channel" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" -dependencies = [ - "cfg-if", - "crossbeam-utils", -] - [[package]] name = "crossbeam-deque" version = "0.8.2" @@ -323,15 +313,6 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - [[package]] name = "hex" version = "0.4.3" @@ -443,16 +424,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "num_cpus" -version = "1.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" -dependencies = [ - "hermit-abi", - "libc", -] - [[package]] name = "object" version = "0.32.0" @@ -514,25 +485,22 @@ dependencies = [ [[package]] name = "rayon" -version = "1.6.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e060280438193c554f654141c9ea9417886713b7acd75974c85b18a69a88e0b" +checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" dependencies = [ - "crossbeam-deque", "either", "rayon-core", ] [[package]] name = "rayon-core" -version = "1.10.1" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cac410af5d00ab6884528b4ab69d1e8e146e8d471201800fa1b4524126de6ad3" +checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" dependencies = [ - "crossbeam-channel", "crossbeam-deque", "crossbeam-utils", - "num_cpus", ] [[package]] diff --git a/src/tools/rust-installer/Cargo.toml b/src/tools/rust-installer/Cargo.toml index 471f2b5ac73e..cdd867c5f157 100644 --- a/src/tools/rust-installer/Cargo.toml +++ b/src/tools/rust-installer/Cargo.toml @@ -16,7 +16,6 @@ rayon = "1.0" tar = "0.4.38" walkdir = "2" xz2 = "0.1.4" -num_cpus = "1" [dependencies.clap] features = ["derive"] diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index b10cccc79f6b..7ad75f089f30 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -228,7 +228,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "ena", "equivalent", "errno", - "errno-dragonfly", "expect-test", "fallible-iterator", // dependency of `thorin` "fastrand", From f2fd8ad788a8e90282e6aa0de44d037806b018ff Mon Sep 17 00:00:00 2001 From: Alex Macleod Date: Tue, 7 Nov 2023 13:21:04 +0000 Subject: [PATCH 315/435] Document clippy_config in nightly-rustc docs --- src/bootstrap/src/core/build_steps/doc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs index f2a185f70fe0..e3fd942fc380 100644 --- a/src/bootstrap/src/core/build_steps/doc.rs +++ b/src/bootstrap/src/core/build_steps/doc.rs @@ -887,7 +887,7 @@ tool_doc!( "src/tools/rustfmt", crates = ["rustfmt-nightly", "rustfmt-config_proc_macro"] ); -tool_doc!(Clippy, "clippy", "src/tools/clippy", crates = ["clippy_utils"]); +tool_doc!(Clippy, "clippy", "src/tools/clippy", crates = ["clippy_config", "clippy_utils"]); tool_doc!(Miri, "miri", "src/tools/miri", crates = ["miri"]); tool_doc!( Cargo, From ecf79a304a0676d2ca2d071127494e83e4aacb90 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 7 Nov 2023 13:32:11 +0000 Subject: [PATCH 316/435] Implement all vendor intrinsics used by the fimg crate --- src/intrinsics/llvm_x86.rs | 154 +++++++++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) diff --git a/src/intrinsics/llvm_x86.rs b/src/intrinsics/llvm_x86.rs index 6a91ce42fdf6..0d557469c778 100644 --- a/src/intrinsics/llvm_x86.rs +++ b/src/intrinsics/llvm_x86.rs @@ -494,6 +494,160 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( } } + "llvm.x86.avx2.packuswb" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_packus_epi16&ig_expand=4906 + intrinsic_args!(fx, args => (a, b); intrinsic); + + assert_eq!(a.layout(), b.layout()); + let layout = a.layout(); + + let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx); + let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx); + assert_eq!(lane_ty, fx.tcx.types.i16); + assert_eq!(ret_lane_ty, fx.tcx.types.u8); + assert_eq!(lane_count * 2, ret_lane_count); + + let zero = fx.bcx.ins().iconst(types::I16, 0); + let max_u8 = fx.bcx.ins().iconst(types::I16, 255); + let ret_lane_layout = fx.layout_of(fx.tcx.types.u8); + + for idx in 0..lane_count / 2 { + let lane = a.value_lane(fx, idx).load_scalar(fx); + let sat = fx.bcx.ins().smax(lane, zero); + let sat = fx.bcx.ins().umin(sat, max_u8); + let res = fx.bcx.ins().ireduce(types::I8, sat); + + let res_lane = CValue::by_val(res, ret_lane_layout); + ret.place_lane(fx, idx).write_cvalue(fx, res_lane); + } + + for idx in 0..lane_count / 2 { + let lane = b.value_lane(fx, idx).load_scalar(fx); + let sat = fx.bcx.ins().smax(lane, zero); + let sat = fx.bcx.ins().umin(sat, max_u8); + let res = fx.bcx.ins().ireduce(types::I8, sat); + + let res_lane = CValue::by_val(res, ret_lane_layout); + ret.place_lane(fx, lane_count / 2 + idx).write_cvalue(fx, res_lane); + } + + for idx in 0..lane_count / 2 { + let lane = a.value_lane(fx, idx).load_scalar(fx); + let sat = fx.bcx.ins().smax(lane, zero); + let sat = fx.bcx.ins().umin(sat, max_u8); + let res = fx.bcx.ins().ireduce(types::I8, sat); + + let res_lane = CValue::by_val(res, ret_lane_layout); + ret.place_lane(fx, lane_count / 2 * 2 + idx).write_cvalue(fx, res_lane); + } + + for idx in 0..lane_count / 2 { + let lane = b.value_lane(fx, idx).load_scalar(fx); + let sat = fx.bcx.ins().smax(lane, zero); + let sat = fx.bcx.ins().umin(sat, max_u8); + let res = fx.bcx.ins().ireduce(types::I8, sat); + + let res_lane = CValue::by_val(res, ret_lane_layout); + ret.place_lane(fx, lane_count / 2 * 3 + idx).write_cvalue(fx, res_lane); + } + } + + "llvm.x86.sse2.packssdw.128" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_packs_epi32&ig_expand=4889 + intrinsic_args!(fx, args => (a, b); intrinsic); + + assert_eq!(a.layout(), b.layout()); + let layout = a.layout(); + + let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx); + let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx); + assert_eq!(lane_ty, fx.tcx.types.i32); + assert_eq!(ret_lane_ty, fx.tcx.types.i16); + assert_eq!(lane_count * 2, ret_lane_count); + + let min_i16 = fx.bcx.ins().iconst(types::I32, i64::from(i16::MIN as u16)); + let max_i16 = fx.bcx.ins().iconst(types::I32, i64::from(i16::MAX as u16)); + let ret_lane_layout = fx.layout_of(fx.tcx.types.i16); + + for idx in 0..lane_count { + let lane = a.value_lane(fx, idx).load_scalar(fx); + let sat = fx.bcx.ins().smax(lane, min_i16); + let sat = fx.bcx.ins().umin(sat, max_i16); + let res = fx.bcx.ins().ireduce(types::I16, sat); + + let res_lane = CValue::by_val(res, ret_lane_layout); + ret.place_lane(fx, idx).write_cvalue(fx, res_lane); + } + + for idx in 0..lane_count { + let lane = b.value_lane(fx, idx).load_scalar(fx); + let sat = fx.bcx.ins().smax(lane, min_i16); + let sat = fx.bcx.ins().umin(sat, max_i16); + let res = fx.bcx.ins().ireduce(types::I16, sat); + + let res_lane = CValue::by_val(res, ret_lane_layout); + ret.place_lane(fx, lane_count + idx).write_cvalue(fx, res_lane); + } + } + + "llvm.x86.avx2.packssdw" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_packs_epi32&ig_expand=4892 + intrinsic_args!(fx, args => (a, b); intrinsic); + + assert_eq!(a.layout(), b.layout()); + let layout = a.layout(); + + let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx); + let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx); + assert_eq!(lane_ty, fx.tcx.types.i32); + assert_eq!(ret_lane_ty, fx.tcx.types.i16); + assert_eq!(lane_count * 2, ret_lane_count); + + let min_i16 = fx.bcx.ins().iconst(types::I32, i64::from(i16::MIN as u16)); + let max_i16 = fx.bcx.ins().iconst(types::I32, i64::from(i16::MAX as u16)); + let ret_lane_layout = fx.layout_of(fx.tcx.types.i16); + + for idx in 0..lane_count / 2 { + let lane = a.value_lane(fx, idx).load_scalar(fx); + let sat = fx.bcx.ins().smax(lane, min_i16); + let sat = fx.bcx.ins().umin(sat, max_i16); + let res = fx.bcx.ins().ireduce(types::I16, sat); + + let res_lane = CValue::by_val(res, ret_lane_layout); + ret.place_lane(fx, idx).write_cvalue(fx, res_lane); + } + + for idx in 0..lane_count / 2 { + let lane = b.value_lane(fx, idx).load_scalar(fx); + let sat = fx.bcx.ins().smax(lane, min_i16); + let sat = fx.bcx.ins().umin(sat, max_i16); + let res = fx.bcx.ins().ireduce(types::I16, sat); + + let res_lane = CValue::by_val(res, ret_lane_layout); + ret.place_lane(fx, lane_count / 2 + idx).write_cvalue(fx, res_lane); + } + + for idx in 0..lane_count / 2 { + let lane = a.value_lane(fx, idx).load_scalar(fx); + let sat = fx.bcx.ins().smax(lane, min_i16); + let sat = fx.bcx.ins().umin(sat, max_i16); + let res = fx.bcx.ins().ireduce(types::I16, sat); + + let res_lane = CValue::by_val(res, ret_lane_layout); + ret.place_lane(fx, lane_count / 2 * 2 + idx).write_cvalue(fx, res_lane); + } + + for idx in 0..lane_count / 2 { + let lane = b.value_lane(fx, idx).load_scalar(fx); + let sat = fx.bcx.ins().smax(lane, min_i16); + let sat = fx.bcx.ins().umin(sat, max_i16); + let res = fx.bcx.ins().ireduce(types::I16, sat); + + let res_lane = CValue::by_val(res, ret_lane_layout); + ret.place_lane(fx, lane_count / 2 * 3 + idx).write_cvalue(fx, res_lane); + } + } + _ => { fx.tcx .sess From d73eaaac5f89ccdb6a77089897fdac0948018d7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Thu, 21 Sep 2023 20:59:29 +0000 Subject: [PATCH 317/435] ci: bump gcc on dist x64 linux builder to 9.5 Support for `-fuse-ld=lld` was added in GCC 9 --- src/ci/docker/host-x86_64/dist-x86_64-linux/build-gcc.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-gcc.sh b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-gcc.sh index 3b3ec5da74bc..f64eb8ae638e 100755 --- a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-gcc.sh +++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-gcc.sh @@ -3,7 +3,7 @@ set -ex source shared.sh -GCC=8.5.0 +GCC=9.5.0 curl https://ftp.gnu.org/gnu/gcc/gcc-$GCC/gcc-$GCC.tar.xz | xzcat | tar xf - cd gcc-$GCC From 752a6132e5fd7a042430afd1c4a2c0dbfa5da59b Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Tue, 7 Nov 2023 16:40:26 +0100 Subject: [PATCH 318/435] llvm-wrapper: Remove include of non-existant Vectorize.h --- compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h | 1 - 1 file changed, 1 deletion(-) diff --git a/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h b/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h index 3f2bf2c9b444..142384e6d0ca 100644 --- a/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h +++ b/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h @@ -25,7 +25,6 @@ #include "llvm/Transforms/IPO.h" #include "llvm/Transforms/Instrumentation.h" #include "llvm/Transforms/Scalar.h" -#include "llvm/Transforms/Vectorize.h" #define LLVM_VERSION_GE(major, minor) \ (LLVM_VERSION_MAJOR > (major) || \ From 84abf837b82bdd3a91df0afd4f1debac6b5cc318 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 7 Nov 2023 17:29:29 +0100 Subject: [PATCH 319/435] manually bless a wasm-only test --- .../numbers-arithmetic/saturating-float-casts-wasm.stderr | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 tests/ui/numbers-arithmetic/saturating-float-casts-wasm.stderr diff --git a/tests/ui/numbers-arithmetic/saturating-float-casts-wasm.stderr b/tests/ui/numbers-arithmetic/saturating-float-casts-wasm.stderr new file mode 100644 index 000000000000..475b41388d3b --- /dev/null +++ b/tests/ui/numbers-arithmetic/saturating-float-casts-wasm.stderr @@ -0,0 +1,6 @@ +warning: unstable feature specified for `-Ctarget-feature`: `nontrapping-fptoint` + | + = note: this feature is not stably supported; its behavior can change in the future + +warning: 1 warning emitted + From f784fa7bd980916c235f5bd9bdbcf9389ea261f4 Mon Sep 17 00:00:00 2001 From: Alona Enraght-Moony Date: Tue, 7 Nov 2023 16:36:55 +0000 Subject: [PATCH 320/435] tests/rustdoc-json: Remove some needless uses of `#![no_core]`. Done by removing all uses of `#![no_core]`, and the reverting the ones that failed. More involved ones are in a later commit. --- tests/rustdoc-json/doc_hidden_failure.rs | 3 --- tests/rustdoc-json/enums/use_glob.rs | 3 --- tests/rustdoc-json/enums/use_variant.rs | 3 --- tests/rustdoc-json/fn_pointer/generics.rs | 3 --- tests/rustdoc-json/fns/extern_c_variadic.rs | 3 --- tests/rustdoc-json/fns/generic_args.rs | 3 --- tests/rustdoc-json/fns/generic_returns.rs | 3 --- tests/rustdoc-json/fns/generics.rs | 3 --- tests/rustdoc-json/glob_import.rs | 3 --- tests/rustdoc-json/impls/impl_item_visibility.rs | 7 +------ .../impls/impl_item_visibility_show_hidden.rs | 6 +----- .../impls/impl_item_visibility_show_private.rs | 6 +----- .../impls/issue-112852-dangling-trait-impl-id-3.rs | 3 --- tests/rustdoc-json/impls/local_for_local_primitive.rs | 2 -- tests/rustdoc-json/lifetime/longest.rs | 9 +++++---- tests/rustdoc-json/lifetime/outlives.rs | 3 --- tests/rustdoc-json/methods/abi.rs | 2 -- tests/rustdoc-json/primitives/primitive_overloading.rs | 6 +----- .../rustdoc-json/reexport/export_extern_crate_as_self.rs | 3 --- tests/rustdoc-json/reexport/glob_collision.rs | 3 --- tests/rustdoc-json/reexport/glob_extern.rs | 3 --- tests/rustdoc-json/reexport/glob_private.rs | 3 --- tests/rustdoc-json/reexport/in_root_and_mod.rs | 3 --- tests/rustdoc-json/reexport/in_root_and_mod_pub.rs | 3 --- tests/rustdoc-json/reexport/macro.rs | 3 --- tests/rustdoc-json/reexport/mod_not_included.rs | 3 --- tests/rustdoc-json/reexport/private_twice_one_inline.rs | 4 ---- tests/rustdoc-json/reexport/private_two_names.rs | 3 --- tests/rustdoc-json/reexport/pub_use_doc_hidden.rs | 3 --- tests/rustdoc-json/reexport/rename_private.rs | 3 --- tests/rustdoc-json/reexport/rename_public.rs | 3 --- tests/rustdoc-json/reexport/same_name_different_types.rs | 3 --- .../reexport/same_type_reexported_more_than_once.rs | 2 -- tests/rustdoc-json/reexport/simple_private.rs | 2 -- tests/rustdoc-json/reexport/simple_public.rs | 3 --- tests/rustdoc-json/return_private.rs | 3 --- tests/rustdoc-json/stripped_modules.rs | 3 --- tests/rustdoc-json/traits/private_supertrait.rs | 4 ---- tests/rustdoc-json/traits/supertrait.rs | 2 -- tests/rustdoc-json/type/inherent_associated_type.rs | 2 -- 40 files changed, 9 insertions(+), 126 deletions(-) diff --git a/tests/rustdoc-json/doc_hidden_failure.rs b/tests/rustdoc-json/doc_hidden_failure.rs index 0d2c6b2209bd..e2ce66c99e4c 100644 --- a/tests/rustdoc-json/doc_hidden_failure.rs +++ b/tests/rustdoc-json/doc_hidden_failure.rs @@ -1,8 +1,5 @@ // Regression test for . -#![feature(no_core)] -#![no_core] - mod auto { mod action_row { pub struct ActionRowBuilder; diff --git a/tests/rustdoc-json/enums/use_glob.rs b/tests/rustdoc-json/enums/use_glob.rs index 49990ec53315..bec89530b052 100644 --- a/tests/rustdoc-json/enums/use_glob.rs +++ b/tests/rustdoc-json/enums/use_glob.rs @@ -1,8 +1,5 @@ // Regression test for -#![feature(no_core)] -#![no_core] - // @set Color = "$.index[*][?(@.name == 'Color')].id" pub enum Color { Red, diff --git a/tests/rustdoc-json/enums/use_variant.rs b/tests/rustdoc-json/enums/use_variant.rs index 8190e1cbe81d..c7e0c21f1ef4 100644 --- a/tests/rustdoc-json/enums/use_variant.rs +++ b/tests/rustdoc-json/enums/use_variant.rs @@ -1,6 +1,3 @@ -#![feature(no_core)] -#![no_core] - // @set AlwaysNone = "$.index[*][?(@.name == 'AlwaysNone')].id" pub enum AlwaysNone { // @set None = "$.index[*][?(@.name == 'None')].id" diff --git a/tests/rustdoc-json/fn_pointer/generics.rs b/tests/rustdoc-json/fn_pointer/generics.rs index 3b82561ec7df..8b3a8c0a74eb 100644 --- a/tests/rustdoc-json/fn_pointer/generics.rs +++ b/tests/rustdoc-json/fn_pointer/generics.rs @@ -1,8 +1,5 @@ // ignore-tidy-linelength -#![feature(no_core)] -#![no_core] - // @count "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.decl.inputs[*]" 1 // @is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.decl.inputs[0][0]" '"val"' // @is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.decl.inputs[0][1].borrowed_ref.lifetime" \"\'c\" diff --git a/tests/rustdoc-json/fns/extern_c_variadic.rs b/tests/rustdoc-json/fns/extern_c_variadic.rs index d6ea343b9911..eef9ae99eb02 100644 --- a/tests/rustdoc-json/fns/extern_c_variadic.rs +++ b/tests/rustdoc-json/fns/extern_c_variadic.rs @@ -1,6 +1,3 @@ -#![feature(no_core)] -#![no_core] - extern "C" { // @is "$.index[*][?(@.name == 'not_variadic')].inner.function.decl.c_variadic" false pub fn not_variadic(_: i32); diff --git a/tests/rustdoc-json/fns/generic_args.rs b/tests/rustdoc-json/fns/generic_args.rs index 539d17f831eb..2f6cf3bf65a1 100644 --- a/tests/rustdoc-json/fns/generic_args.rs +++ b/tests/rustdoc-json/fns/generic_args.rs @@ -1,8 +1,5 @@ // ignore-tidy-linelength -#![feature(no_core)] -#![no_core] - // @set foo = "$.index[*][?(@.name=='Foo')].id" pub trait Foo {} diff --git a/tests/rustdoc-json/fns/generic_returns.rs b/tests/rustdoc-json/fns/generic_returns.rs index 27d842066f4e..8e82efef4beb 100644 --- a/tests/rustdoc-json/fns/generic_returns.rs +++ b/tests/rustdoc-json/fns/generic_returns.rs @@ -1,8 +1,5 @@ // ignore-tidy-linelength -#![feature(no_core)] -#![no_core] - // @count "$.index[*][?(@.name=='generic_returns')].inner.module.items[*]" 2 // @set foo = "$.index[*][?(@.name=='Foo')].id" diff --git a/tests/rustdoc-json/fns/generics.rs b/tests/rustdoc-json/fns/generics.rs index 5239a6f21f53..44dc6d854aa3 100644 --- a/tests/rustdoc-json/fns/generics.rs +++ b/tests/rustdoc-json/fns/generics.rs @@ -1,8 +1,5 @@ // ignore-tidy-linelength -#![feature(no_core)] -#![no_core] - // @set wham_id = "$.index[*][?(@.name=='Wham')].id" pub trait Wham {} diff --git a/tests/rustdoc-json/glob_import.rs b/tests/rustdoc-json/glob_import.rs index f37ce0abb414..7de1ed78f2ff 100644 --- a/tests/rustdoc-json/glob_import.rs +++ b/tests/rustdoc-json/glob_import.rs @@ -1,13 +1,10 @@ // This is a regression test for . -#![feature(no_core)] #![no_std] -#![no_core] // @has "$.index[*][?(@.name=='glob')]" // @has "$.index[*][?(@.inner.import)].inner.import.name" \"*\" - mod m1 { pub fn f() {} } diff --git a/tests/rustdoc-json/impls/impl_item_visibility.rs b/tests/rustdoc-json/impls/impl_item_visibility.rs index efa54d91dcaa..d3c15cd23e44 100644 --- a/tests/rustdoc-json/impls/impl_item_visibility.rs +++ b/tests/rustdoc-json/impls/impl_item_visibility.rs @@ -1,6 +1,3 @@ -#![feature(no_core)] -#![no_core] - pub struct Foo; /// impl Foo priv @@ -9,18 +6,16 @@ impl Foo { } // @!has '$.index[*][?(@.docs=="impl Foo priv")]' - /// impl Foo pub impl Foo { pub fn qux() {} } // @is '$.index[*][?(@.docs=="impl Foo pub")].visibility' '"default"' - /// impl Foo hidden impl Foo { #[doc(hidden)] - pub fn __quazl(){} + pub fn __quazl() {} } // FIXME(#111564): Is this the right behaviour? // @is '$.index[*][?(@.docs=="impl Foo hidden")].visibility' '"default"' diff --git a/tests/rustdoc-json/impls/impl_item_visibility_show_hidden.rs b/tests/rustdoc-json/impls/impl_item_visibility_show_hidden.rs index 3c6fefc4ca29..fa3a36df8563 100644 --- a/tests/rustdoc-json/impls/impl_item_visibility_show_hidden.rs +++ b/tests/rustdoc-json/impls/impl_item_visibility_show_hidden.rs @@ -1,6 +1,4 @@ // compile-flags: --document-hidden-items -#![feature(no_core)] -#![no_core] pub struct Foo; @@ -11,18 +9,16 @@ impl Foo { // FIXME(#111564): Is this the right behaviour? // @is '$.index[*][?(@.docs=="impl Foo priv")].visibility' '"default"' - /// impl Foo pub impl Foo { pub fn qux() {} } // @is '$.index[*][?(@.docs=="impl Foo pub")].visibility' '"default"' - /// impl Foo hidden impl Foo { #[doc(hidden)] - pub fn __quazl(){} + pub fn __quazl() {} } // FIXME(#111564): Is this the right behaviour? // @is '$.index[*][?(@.docs=="impl Foo hidden")].visibility' '"default"' diff --git a/tests/rustdoc-json/impls/impl_item_visibility_show_private.rs b/tests/rustdoc-json/impls/impl_item_visibility_show_private.rs index b98d1e4167ce..7c68a2412f36 100644 --- a/tests/rustdoc-json/impls/impl_item_visibility_show_private.rs +++ b/tests/rustdoc-json/impls/impl_item_visibility_show_private.rs @@ -1,6 +1,4 @@ // compile-flags: --document-private-items -#![feature(no_core)] -#![no_core] pub struct Foo; @@ -10,18 +8,16 @@ impl Foo { } // @is '$.index[*][?(@.docs=="impl Foo priv")].visibility' '"default"' - /// impl Foo pub impl Foo { pub fn qux() {} } // @is '$.index[*][?(@.docs=="impl Foo pub")].visibility' '"default"' - /// impl Foo hidden impl Foo { #[doc(hidden)] - pub fn __quazl(){} + pub fn __quazl() {} } // FIXME(#111564): Is this the right behaviour? // @is '$.index[*][?(@.docs=="impl Foo hidden")].visibility' '"default"' diff --git a/tests/rustdoc-json/impls/issue-112852-dangling-trait-impl-id-3.rs b/tests/rustdoc-json/impls/issue-112852-dangling-trait-impl-id-3.rs index fcd27ca4b7c5..836f1fe87da3 100644 --- a/tests/rustdoc-json/impls/issue-112852-dangling-trait-impl-id-3.rs +++ b/tests/rustdoc-json/impls/issue-112852-dangling-trait-impl-id-3.rs @@ -1,8 +1,5 @@ // compile-flags: --document-hidden-items -#![feature(no_core)] -#![no_core] - // @has "$.index[*][?(@.name == 'HiddenPubStruct')]" // @has "$.index[*][?(@.inner.impl)]" // @has "$.index[*][?(@.name=='PubTrait')]" diff --git a/tests/rustdoc-json/impls/local_for_local_primitive.rs b/tests/rustdoc-json/impls/local_for_local_primitive.rs index 769dd3f0a2c0..acc3a879fe1c 100644 --- a/tests/rustdoc-json/impls/local_for_local_primitive.rs +++ b/tests/rustdoc-json/impls/local_for_local_primitive.rs @@ -1,6 +1,4 @@ -#![feature(no_core)] #![feature(rustc_attrs)] -#![no_core] // @set Local = "$.index[*][?(@.name=='Local')].id" pub trait Local {} diff --git a/tests/rustdoc-json/lifetime/longest.rs b/tests/rustdoc-json/lifetime/longest.rs index dc28258a8b67..419b0b4fcab1 100644 --- a/tests/rustdoc-json/lifetime/longest.rs +++ b/tests/rustdoc-json/lifetime/longest.rs @@ -1,8 +1,5 @@ // ignore-tidy-linelength -#![feature(no_core)] -#![no_core] - // @is "$.index[*][?(@.name=='longest')].inner.function.generics.params[0].name" \"\'a\" // @is "$.index[*][?(@.name=='longest')].inner.function.generics.params[0].kind" '{"lifetime": {"outlives": []}}' // @is "$.index[*][?(@.name=='longest')].inner.function.generics.params[0].kind" '{"lifetime": {"outlives": []}}' @@ -26,5 +23,9 @@ // @is "$.index[*][?(@.name=='longest')].inner.function.decl.output.borrowed_ref.type.primitive" \"str\" pub fn longest<'a>(l: &'a str, r: &'a str) -> &'a str { - if l.len() > r.len() { l } else { r } + if l.len() > r.len() { + l + } else { + r + } } diff --git a/tests/rustdoc-json/lifetime/outlives.rs b/tests/rustdoc-json/lifetime/outlives.rs index 6e105b382b00..549e4c200dca 100644 --- a/tests/rustdoc-json/lifetime/outlives.rs +++ b/tests/rustdoc-json/lifetime/outlives.rs @@ -1,8 +1,5 @@ // ignore-tidy-linelength -#![feature(no_core)] -#![no_core] - // @count "$.index[*][?(@.name=='foo')].inner.function.generics.params[*]" 3 // @is "$.index[*][?(@.name=='foo')].inner.function.generics.where_predicates" [] // @is "$.index[*][?(@.name=='foo')].inner.function.generics.params[0].name" \"\'a\" diff --git a/tests/rustdoc-json/methods/abi.rs b/tests/rustdoc-json/methods/abi.rs index b8279298c1e7..917e9e0790c9 100644 --- a/tests/rustdoc-json/methods/abi.rs +++ b/tests/rustdoc-json/methods/abi.rs @@ -1,8 +1,6 @@ // ignore-tidy-linelength #![feature(abi_vectorcall)] -#![feature(no_core)] -#![no_core] // @has "$.index[*][?(@.name=='Foo')]" pub struct Foo; diff --git a/tests/rustdoc-json/primitives/primitive_overloading.rs b/tests/rustdoc-json/primitives/primitive_overloading.rs index 81e0acdc6e93..50e23fc06d3e 100644 --- a/tests/rustdoc-json/primitives/primitive_overloading.rs +++ b/tests/rustdoc-json/primitives/primitive_overloading.rs @@ -3,14 +3,10 @@ // Regression test for . #![feature(rustc_attrs)] -#![feature(no_core)] - -#![no_core] // @has "$.index[*][?(@.name=='usize')]" // @has "$.index[*][?(@.name=='prim')]" #[rustc_doc_primitive = "usize"] /// This is the built-in type `usize`. -mod prim { -} +mod prim {} diff --git a/tests/rustdoc-json/reexport/export_extern_crate_as_self.rs b/tests/rustdoc-json/reexport/export_extern_crate_as_self.rs index 37ca279b352c..a8f5500d6297 100644 --- a/tests/rustdoc-json/reexport/export_extern_crate_as_self.rs +++ b/tests/rustdoc-json/reexport/export_extern_crate_as_self.rs @@ -1,8 +1,5 @@ //! Regression test for -#![feature(no_core)] -#![no_core] - #![crate_name = "export_extern_crate_as_self"] // ignore-tidy-linelength diff --git a/tests/rustdoc-json/reexport/glob_collision.rs b/tests/rustdoc-json/reexport/glob_collision.rs index dee35ba78dc4..9a75f4c0cf38 100644 --- a/tests/rustdoc-json/reexport/glob_collision.rs +++ b/tests/rustdoc-json/reexport/glob_collision.rs @@ -1,8 +1,5 @@ // Regression test for https://github.com/rust-lang/rust/issues/100973 -#![feature(no_core)] -#![no_core] - // @set m1 = "$.index[*][?(@.name == 'm1' && @.inner.module)].id" // @is "$.index[*][?(@.name == 'm1')].inner.module.items" [] // @is "$.index[*][?(@.name == 'm1')].inner.module.is_stripped" true diff --git a/tests/rustdoc-json/reexport/glob_extern.rs b/tests/rustdoc-json/reexport/glob_extern.rs index 78edfaf0aa8d..ed0c4a420d48 100644 --- a/tests/rustdoc-json/reexport/glob_extern.rs +++ b/tests/rustdoc-json/reexport/glob_extern.rs @@ -1,8 +1,5 @@ // edition:2018 -#![no_core] -#![feature(no_core)] - // @is "$.index[*][?(@.name=='mod1')].inner.module.is_stripped" "true" mod mod1 { extern "C" { diff --git a/tests/rustdoc-json/reexport/glob_private.rs b/tests/rustdoc-json/reexport/glob_private.rs index ae4e87d23bc5..11ea5aa3522b 100644 --- a/tests/rustdoc-json/reexport/glob_private.rs +++ b/tests/rustdoc-json/reexport/glob_private.rs @@ -1,8 +1,5 @@ // edition:2018 -#![no_core] -#![feature(no_core)] - // @is "$.index[*][?(@.name=='mod1')].inner.module.is_stripped" "true" mod mod1 { // @is "$.index[*][?(@.name=='mod2')].inner.module.is_stripped" "true" diff --git a/tests/rustdoc-json/reexport/in_root_and_mod.rs b/tests/rustdoc-json/reexport/in_root_and_mod.rs index f81445bd48da..a4133e2f0c7d 100644 --- a/tests/rustdoc-json/reexport/in_root_and_mod.rs +++ b/tests/rustdoc-json/reexport/in_root_and_mod.rs @@ -1,6 +1,3 @@ -#![feature(no_core)] -#![no_core] - // @!has "$.index[*][?(@.name=='foo')]" mod foo { // @has "$.index[*][?(@.name=='Foo')]" diff --git a/tests/rustdoc-json/reexport/in_root_and_mod_pub.rs b/tests/rustdoc-json/reexport/in_root_and_mod_pub.rs index c5c41b25f7ec..37f7b26fc859 100644 --- a/tests/rustdoc-json/reexport/in_root_and_mod_pub.rs +++ b/tests/rustdoc-json/reexport/in_root_and_mod_pub.rs @@ -1,6 +1,3 @@ -#![feature(no_core)] -#![no_core] - pub mod foo { // @set bar_id = "$.index[*][?(@.name=='Bar')].id" // @ismany "$.index[*][?(@.name=='foo')].inner.module.items[*]" $bar_id diff --git a/tests/rustdoc-json/reexport/macro.rs b/tests/rustdoc-json/reexport/macro.rs index ac0632b98a95..be09cb47629d 100644 --- a/tests/rustdoc-json/reexport/macro.rs +++ b/tests/rustdoc-json/reexport/macro.rs @@ -1,8 +1,5 @@ // edition:2018 -#![no_core] -#![feature(no_core)] - // @set repro_id = "$.index[*][?(@.name=='repro')].id" #[macro_export] macro_rules! repro { diff --git a/tests/rustdoc-json/reexport/mod_not_included.rs b/tests/rustdoc-json/reexport/mod_not_included.rs index 1c49f213d1a7..bc072be81a31 100644 --- a/tests/rustdoc-json/reexport/mod_not_included.rs +++ b/tests/rustdoc-json/reexport/mod_not_included.rs @@ -1,8 +1,5 @@ // Regression test for https://github.com/rust-lang/rust/issues/101103 -#![feature(no_core)] -#![no_core] - mod m1 { pub fn x() {} } diff --git a/tests/rustdoc-json/reexport/private_twice_one_inline.rs b/tests/rustdoc-json/reexport/private_twice_one_inline.rs index 8c8152bd16c3..d7b766235578 100644 --- a/tests/rustdoc-json/reexport/private_twice_one_inline.rs +++ b/tests/rustdoc-json/reexport/private_twice_one_inline.rs @@ -4,12 +4,8 @@ // Test for the ICE in https://github.com/rust-lang/rust/issues/83057 // An external type re-exported with different attributes shouldn't cause an error -#![no_core] -#![feature(no_core)] - extern crate pub_struct as foo; #[doc(inline)] - // @set crate_use_id = "$.index[*][?(@.docs=='Hack A')].id" // @set foo_id = "$.index[*][?(@.docs=='Hack A')].inner.import.id" /// Hack A diff --git a/tests/rustdoc-json/reexport/private_two_names.rs b/tests/rustdoc-json/reexport/private_two_names.rs index cdcbf2a2bc86..e6f037eb4b38 100644 --- a/tests/rustdoc-json/reexport/private_two_names.rs +++ b/tests/rustdoc-json/reexport/private_two_names.rs @@ -3,9 +3,6 @@ // Test for the ICE in https://github.com/rust-lang/rust/issues/83720 // A pub-in-private type re-exported under two different names shouldn't cause an error -#![no_core] -#![feature(no_core)] - // @!has "$.index[*][?(@.name=='style')]" mod style { // @set color_struct_id = "$.index[*][?(@.inner.struct && @.name=='Color')].id" diff --git a/tests/rustdoc-json/reexport/pub_use_doc_hidden.rs b/tests/rustdoc-json/reexport/pub_use_doc_hidden.rs index a2a25d08448a..46c3da4c15b3 100644 --- a/tests/rustdoc-json/reexport/pub_use_doc_hidden.rs +++ b/tests/rustdoc-json/reexport/pub_use_doc_hidden.rs @@ -1,8 +1,5 @@ // Regression test for -#![feature(no_core)] -#![no_core] - mod repeat_n { #[doc(hidden)] pub struct RepeatN {} diff --git a/tests/rustdoc-json/reexport/rename_private.rs b/tests/rustdoc-json/reexport/rename_private.rs index 9114460231dc..3924282a49e5 100644 --- a/tests/rustdoc-json/reexport/rename_private.rs +++ b/tests/rustdoc-json/reexport/rename_private.rs @@ -1,8 +1,5 @@ // edition:2018 -#![no_core] -#![feature(no_core)] - // @!has "$.index[*][?(@.name=='inner')]" mod inner { // @has "$.index[*][?(@.name=='Public')]" diff --git a/tests/rustdoc-json/reexport/rename_public.rs b/tests/rustdoc-json/reexport/rename_public.rs index d0fd314bd8c9..636937874483 100644 --- a/tests/rustdoc-json/reexport/rename_public.rs +++ b/tests/rustdoc-json/reexport/rename_public.rs @@ -1,8 +1,5 @@ // edition:2018 -#![no_core] -#![feature(no_core)] - // @set inner_id = "$.index[*][?(@.name=='inner')].id" pub mod inner { // @set public_id = "$.index[*][?(@.name=='Public')].id" diff --git a/tests/rustdoc-json/reexport/same_name_different_types.rs b/tests/rustdoc-json/reexport/same_name_different_types.rs index 6a765b733016..42ba6c40019a 100644 --- a/tests/rustdoc-json/reexport/same_name_different_types.rs +++ b/tests/rustdoc-json/reexport/same_name_different_types.rs @@ -1,8 +1,5 @@ // Regression test for . -#![feature(no_core)] -#![no_core] - pub mod nested { // @set foo_struct = "$.index[*][?(@.docs == 'Foo the struct')].id" diff --git a/tests/rustdoc-json/reexport/same_type_reexported_more_than_once.rs b/tests/rustdoc-json/reexport/same_type_reexported_more_than_once.rs index a00547dc3481..1e1710e1c086 100644 --- a/tests/rustdoc-json/reexport/same_type_reexported_more_than_once.rs +++ b/tests/rustdoc-json/reexport/same_type_reexported_more_than_once.rs @@ -2,9 +2,7 @@ // Regression test for . -#![feature(no_core)] #![no_std] -#![no_core] mod inner { // @set trait_id = "$.index[*][?(@.name=='Trait')].id" diff --git a/tests/rustdoc-json/reexport/simple_private.rs b/tests/rustdoc-json/reexport/simple_private.rs index 462efee51bf4..2ca8c7fa6be6 100644 --- a/tests/rustdoc-json/reexport/simple_private.rs +++ b/tests/rustdoc-json/reexport/simple_private.rs @@ -1,6 +1,4 @@ // edition:2018 -#![no_core] -#![feature(no_core)] // @!has "$.index[*][?(@.name=='inner')]" mod inner { diff --git a/tests/rustdoc-json/reexport/simple_public.rs b/tests/rustdoc-json/reexport/simple_public.rs index 1373f96f87f0..04611eeb95ca 100644 --- a/tests/rustdoc-json/reexport/simple_public.rs +++ b/tests/rustdoc-json/reexport/simple_public.rs @@ -1,8 +1,5 @@ // edition:2018 -#![no_core] -#![feature(no_core)] - // @set inner_id = "$.index[*][?(@.name=='inner')].id" pub mod inner { diff --git a/tests/rustdoc-json/return_private.rs b/tests/rustdoc-json/return_private.rs index 0ce81b5e59fa..a9301b3fe4f3 100644 --- a/tests/rustdoc-json/return_private.rs +++ b/tests/rustdoc-json/return_private.rs @@ -1,9 +1,6 @@ // Regression test for . // ignore-tidy-linelength -#![feature(no_core)] -#![no_core] - mod secret { pub struct Secret; } diff --git a/tests/rustdoc-json/stripped_modules.rs b/tests/rustdoc-json/stripped_modules.rs index d2664b49e9c2..d5ab1173d924 100644 --- a/tests/rustdoc-json/stripped_modules.rs +++ b/tests/rustdoc-json/stripped_modules.rs @@ -1,6 +1,3 @@ -#![no_core] -#![feature(no_core)] - // @!has "$.index[*][?(@.name=='no_pub_inner')]" mod no_pub_inner { fn priv_inner() {} diff --git a/tests/rustdoc-json/traits/private_supertrait.rs b/tests/rustdoc-json/traits/private_supertrait.rs index 49238e5e88be..67b5a858ab76 100644 --- a/tests/rustdoc-json/traits/private_supertrait.rs +++ b/tests/rustdoc-json/traits/private_supertrait.rs @@ -1,9 +1,5 @@ // ignore-tidy-linelength -#![feature(no_core)] -#![no_core] - - // @!has "$.index[*][?(@.name == 'sealed')]" mod sealed { // @set sealed_id = "$.index[*][?(@.name=='Sealed')].id" diff --git a/tests/rustdoc-json/traits/supertrait.rs b/tests/rustdoc-json/traits/supertrait.rs index 2123ac40427e..6504467291d1 100644 --- a/tests/rustdoc-json/traits/supertrait.rs +++ b/tests/rustdoc-json/traits/supertrait.rs @@ -1,8 +1,6 @@ // ignore-tidy-linelength -#![feature(no_core)] #![feature(lang_items)] -#![no_core] // @set loud_id = "$.index[*][?(@.name=='Loud')].id" pub trait Loud {} diff --git a/tests/rustdoc-json/type/inherent_associated_type.rs b/tests/rustdoc-json/type/inherent_associated_type.rs index 64c6c53ce472..f86031479519 100644 --- a/tests/rustdoc-json/type/inherent_associated_type.rs +++ b/tests/rustdoc-json/type/inherent_associated_type.rs @@ -1,8 +1,6 @@ // ignore-tidy-linelength #![feature(inherent_associated_types)] -#![feature(no_core)] #![allow(incomplete_features)] -#![no_core] // @set OwnerMetadata = '$.index[*][?(@.name=="OwnerMetadata")].id' pub struct OwnerMetadata; From 0875f456f1081929db5aabf67ee7713dd77cd303 Mon Sep 17 00:00:00 2001 From: Alona Enraght-Moony Date: Tue, 7 Nov 2023 16:40:32 +0000 Subject: [PATCH 321/435] tests/rustdoc-json: Remove more needless uses of `#![no_core]`. These were'nt done with regex, but don't require changes to assertions. --- tests/rustdoc-json/enums/field_hidden.rs | 6 ------ tests/rustdoc-json/enums/kind.rs | 6 ------ tests/rustdoc-json/enums/tuple_fields_hidden.rs | 6 ------ tests/rustdoc-json/generic-associated-types/gats.rs | 9 --------- tests/rustdoc-json/non_lifetime_binders.rs | 11 +---------- tests/rustdoc-json/traits/supertrait.rs | 2 -- 6 files changed, 1 insertion(+), 39 deletions(-) diff --git a/tests/rustdoc-json/enums/field_hidden.rs b/tests/rustdoc-json/enums/field_hidden.rs index f24098580579..74d96248d5c7 100644 --- a/tests/rustdoc-json/enums/field_hidden.rs +++ b/tests/rustdoc-json/enums/field_hidden.rs @@ -1,11 +1,5 @@ // Regression test for . -#![no_core] -#![feature(no_core, lang_items)] - -#[lang = "sized"] -trait Sized {} - // @has "$.index[*][?(@.name=='ParseError')]" // @has "$.index[*][?(@.name=='UnexpectedEndTag')]" // @is "$.index[*][?(@.name=='UnexpectedEndTag')].inner.variant.kind.tuple" [null] diff --git a/tests/rustdoc-json/enums/kind.rs b/tests/rustdoc-json/enums/kind.rs index 777161c4e4ba..68483683464b 100644 --- a/tests/rustdoc-json/enums/kind.rs +++ b/tests/rustdoc-json/enums/kind.rs @@ -1,11 +1,5 @@ // ignore-tidy-linelength -#![feature(no_core, lang_items)] -#![no_core] - -#[lang = "sized"] -trait Sized {} - pub enum Foo { // @set Unit = "$.index[*][?(@.name=='Unit')].id" // @is "$.index[*][?(@.name=='Unit')].inner.variant.kind" '"plain"' diff --git a/tests/rustdoc-json/enums/tuple_fields_hidden.rs b/tests/rustdoc-json/enums/tuple_fields_hidden.rs index 34a4f4aec538..53cdf83ffa68 100644 --- a/tests/rustdoc-json/enums/tuple_fields_hidden.rs +++ b/tests/rustdoc-json/enums/tuple_fields_hidden.rs @@ -1,9 +1,3 @@ -#![feature(no_core, lang_items)] -#![no_core] - -#[lang = "sized"] -trait Sized {} - // @set 1.1.0 = "$.index[*][?(@.docs=='1.1.0')].id" // @set 2.1.0 = "$.index[*][?(@.docs=='2.1.0')].id" // @set 2.1.1 = "$.index[*][?(@.docs=='2.1.1')].id" diff --git a/tests/rustdoc-json/generic-associated-types/gats.rs b/tests/rustdoc-json/generic-associated-types/gats.rs index 9cfe649243f8..56d6e7a49dbd 100644 --- a/tests/rustdoc-json/generic-associated-types/gats.rs +++ b/tests/rustdoc-json/generic-associated-types/gats.rs @@ -1,14 +1,5 @@ // ignore-tidy-linelength -#![no_core] -#![feature(lang_items, no_core, arbitrary_self_types)] - -#[lang = "sized"] -pub trait Sized {} - -#[lang = "receiver"] -pub trait Receiver {} - pub trait Display {} pub trait LendingIterator { diff --git a/tests/rustdoc-json/non_lifetime_binders.rs b/tests/rustdoc-json/non_lifetime_binders.rs index cabee0b1caa5..d925fcd52215 100644 --- a/tests/rustdoc-json/non_lifetime_binders.rs +++ b/tests/rustdoc-json/non_lifetime_binders.rs @@ -3,18 +3,9 @@ #![feature(non_lifetime_binders)] #![allow(incomplete_features)] -#![no_core] -#![feature(lang_items, no_core)] - -#[lang = "sized"] -pub trait Sized {} - pub trait Trait {} -#[lang = "phantom_data"] -struct PhantomData; - -pub struct Wrapper(PhantomData); +pub struct Wrapper(std::marker::PhantomData); // @count "$.index[*][?(@.name=='foo')].inner.function.generics.where_predicates[0].bound_predicate.generic_params[*]" 2 // @is "$.index[*][?(@.name=='foo')].inner.function.generics.where_predicates[0].bound_predicate.generic_params[0].name" \"\'a\" diff --git a/tests/rustdoc-json/traits/supertrait.rs b/tests/rustdoc-json/traits/supertrait.rs index 6504467291d1..bbae3557cf9c 100644 --- a/tests/rustdoc-json/traits/supertrait.rs +++ b/tests/rustdoc-json/traits/supertrait.rs @@ -1,7 +1,5 @@ // ignore-tidy-linelength -#![feature(lang_items)] - // @set loud_id = "$.index[*][?(@.name=='Loud')].id" pub trait Loud {} From 434b69a1d670fb0b18a4dd121db0a445d74d34d4 Mon Sep 17 00:00:00 2001 From: Alona Enraght-Moony Date: Tue, 7 Nov 2023 16:56:03 +0000 Subject: [PATCH 322/435] tests/rustdoc-json: Rewrite tests no not use `#![no_core]`. --- .../rustdoc-json/impls/import_from_private.rs | 14 ++++----- .../issue-112852-dangling-trait-impl-id-2.rs | 8 ++--- .../issue-112852-dangling-trait-impl-id.rs | 12 ++++---- tests/rustdoc-json/impls/local_for_local.rs | 5 +--- tests/rustdoc-json/traits/implementors.rs | 29 +++++++++---------- 5 files changed, 31 insertions(+), 37 deletions(-) diff --git a/tests/rustdoc-json/impls/import_from_private.rs b/tests/rustdoc-json/impls/import_from_private.rs index d2b0665dcafa..3da03df2546c 100644 --- a/tests/rustdoc-json/impls/import_from_private.rs +++ b/tests/rustdoc-json/impls/import_from_private.rs @@ -1,14 +1,12 @@ // https://github.com/rust-lang/rust/issues/100252 -#![feature(no_core)] -#![no_core] - mod bar { - // @set baz = "$.index[*][?(@.inner.struct)].id" + // @set baz = "$.index[*][?(@.name == 'Baz')].id" pub struct Baz; - // @set impl = "$.index[*][?(@.inner.impl)].id" + // @set impl = "$.index[*][?(@.docs == 'impl')].id" + /// impl impl Baz { - // @set doit = "$.index[*][?(@.inner.function)].id" + // @set doit = "$.index[*][?(@.name == 'doit')].id" pub fn doit() {} } } @@ -18,5 +16,5 @@ pub use bar::Baz; // @is "$.index[*].inner.module.items[*]" $import // @is "$.index[*].inner.import.id" $baz -// @is "$.index[*].inner.struct.impls[*]" $impl -// @is "$.index[*].inner.impl.items[*]" $doit +// @has "$.index[*][?(@.name == 'Baz')].inner.struct.impls[*]" $impl +// @is "$.index[*][?(@.docs=='impl')].inner.impl.items[*]" $doit diff --git a/tests/rustdoc-json/impls/issue-112852-dangling-trait-impl-id-2.rs b/tests/rustdoc-json/impls/issue-112852-dangling-trait-impl-id-2.rs index d2ac316d47d4..7857626d66ed 100644 --- a/tests/rustdoc-json/impls/issue-112852-dangling-trait-impl-id-2.rs +++ b/tests/rustdoc-json/impls/issue-112852-dangling-trait-impl-id-2.rs @@ -1,7 +1,5 @@ -#![feature(no_core)] -#![no_core] - -// @count "$.index[*][?(@.inner.impl)]" 1 +// @has "$.index[*][?(@.docs=='Here')]" +// @!has "$.index[*][?(@.docs=='Not Here')]" // @!has "$.index[*][?(@.name == 'HiddenPubStruct')]" // @has "$.index[*][?(@.name == 'NotHiddenPubStruct')]" // @has "$.index[*][?(@.name=='PubTrait')]" @@ -11,5 +9,7 @@ pub trait PubTrait {} pub struct HiddenPubStruct; pub struct NotHiddenPubStruct; +/// Not Here impl PubTrait for HiddenPubStruct {} +/// Here impl PubTrait for NotHiddenPubStruct {} diff --git a/tests/rustdoc-json/impls/issue-112852-dangling-trait-impl-id.rs b/tests/rustdoc-json/impls/issue-112852-dangling-trait-impl-id.rs index 141c54a57dd1..97db9c93a0f2 100644 --- a/tests/rustdoc-json/impls/issue-112852-dangling-trait-impl-id.rs +++ b/tests/rustdoc-json/impls/issue-112852-dangling-trait-impl-id.rs @@ -1,21 +1,21 @@ -#![feature(no_core)] -#![no_core] - -// @count "$.index[*][?(@.inner.impl)]" 1 -// @!has "$.index[*][?(@.name == 'HiddenPubStruct')]" -// @has "$.index[*][?(@.name == 'NotHiddenPubStruct')]" // @has "$.index[*][?(@.name=='PubTrait')]" pub trait PubTrait {} #[doc(hidden)] pub mod hidden { + // @!has "$.index[*][?(@.name == 'HiddenPubStruct')]" pub struct HiddenPubStruct; + // @!has "$.index[*][?(@.docs == 'Not Here')]" + /// Not Here impl crate::PubTrait for HiddenPubStruct {} } pub mod not_hidden { + // @has "$.index[*][?(@.name == 'NotHiddenPubStruct')]" pub struct NotHiddenPubStruct; + // @has "$.index[*][?(@.docs == 'Here')]" + /// Here impl crate::PubTrait for NotHiddenPubStruct {} } diff --git a/tests/rustdoc-json/impls/local_for_local.rs b/tests/rustdoc-json/impls/local_for_local.rs index 37a720003295..015e89c22810 100644 --- a/tests/rustdoc-json/impls/local_for_local.rs +++ b/tests/rustdoc-json/impls/local_for_local.rs @@ -1,6 +1,3 @@ -#![feature(no_core)] -#![no_core] - // @set struct = "$.index[*][?(@.name=='Struct')].id" pub struct Struct; // @set trait = "$.index[*][?(@.name=='Trait')].id" @@ -9,7 +6,7 @@ pub trait Trait {} /// impl impl Trait for Struct {} -// @is "$.index[*][?(@.name=='Struct')].inner.struct.impls[*]" $impl +// @has "$.index[*][?(@.name=='Struct')].inner.struct.impls[*]" $impl // @is "$.index[*][?(@.name=='Trait')].inner.trait.implementations[*]" $impl // @is "$.index[*][?(@.docs=='impl')].inner.impl.trait.id" $trait // @is "$.index[*][?(@.docs=='impl')].inner.impl.for.resolved_path.id" $struct diff --git a/tests/rustdoc-json/traits/implementors.rs b/tests/rustdoc-json/traits/implementors.rs index 7d351ad61be2..c27553c75448 100644 --- a/tests/rustdoc-json/traits/implementors.rs +++ b/tests/rustdoc-json/traits/implementors.rs @@ -1,19 +1,18 @@ -#![feature(no_core)] -#![no_core] - -// @set wham = "$.index[*][?(@.name=='Wham')].id" -// @count "$.index[*][?(@.name=='Wham')].inner.trait.implementations[*]" 1 -// @set gmWham = "$.index[*][?(@.name=='Wham')].inner.trait.implementations[0]" pub trait Wham {} - -// @count "$.index[*][?(@.name=='GeorgeMichael')].inner.struct.impls[*]" 1 -// @is "$.index[*][?(@.name=='GeorgeMichael')].inner.struct.impls[0]" $gmWham -// @set gm = "$.index[*][?(@.name=='Wham')].id" - -// jsonpath_lib isnt expressive enough (for now) to get the "impl" item, so we -// just check it isn't pointing to the type, but when you port to jsondocck-ng -// check what the impl item is -// @!is "$.index[*][?(@.name=='Wham')].inner.trait.implementations[0]" $gm pub struct GeorgeMichael {} +/// Wham for George Michael impl Wham for GeorgeMichael {} + +// Find IDs. +// @set wham = "$.index[*][?(@.name=='Wham')].id" +// @set gmWham = "$.index[*][?(@.docs=='Wham for George Michael')].id" +// @set gm = "$.index[*][?(@.name=='GeorgeMichael')].id" + +// Both struct and trait point to impl. +// @has "$.index[*][?(@.name=='GeorgeMichael')].inner.struct.impls[*]" $gmWham +// @is "$.index[*][?(@.name=='Wham')].inner.trait.implementations[*]" $gmWham + +// Impl points to both struct and trait. +// @is "$.index[*][?(@.docs == 'Wham for George Michael')].inner.impl.trait.id" $wham +// @is "$.index[*][?(@.docs == 'Wham for George Michael')].inner.impl.for.resolved_path.id" $gm From 864973135a3449e2ce3be91d894509dfad2d94a6 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 7 Nov 2023 18:08:30 +0000 Subject: [PATCH 323/435] Implement all vendor intrinsics used by the simd-json crate --- src/intrinsics/llvm_x86.rs | 138 +++++++++++++++++++++++++++++++++++++ 1 file changed, 138 insertions(+) diff --git a/src/intrinsics/llvm_x86.rs b/src/intrinsics/llvm_x86.rs index 0d557469c778..4c536048626e 100644 --- a/src/intrinsics/llvm_x86.rs +++ b/src/intrinsics/llvm_x86.rs @@ -590,6 +590,44 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( } } + "llvm.x86.sse41.packusdw" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_packus_epi32&ig_expand=4912 + intrinsic_args!(fx, args => (a, b); intrinsic); + + assert_eq!(a.layout(), b.layout()); + let layout = a.layout(); + + let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx); + let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx); + assert_eq!(lane_ty, fx.tcx.types.i32); + assert_eq!(ret_lane_ty, fx.tcx.types.u16); + assert_eq!(lane_count * 2, ret_lane_count); + + let min_u16 = fx.bcx.ins().iconst(types::I32, i64::from(u16::MIN)); + let max_u16 = fx.bcx.ins().iconst(types::I32, i64::from(u16::MAX)); + let ret_lane_layout = fx.layout_of(fx.tcx.types.u16); + + for idx in 0..lane_count { + let lane = a.value_lane(fx, idx).load_scalar(fx); + let sat = fx.bcx.ins().umax(lane, min_u16); + let sat = fx.bcx.ins().umin(sat, max_u16); + let res = fx.bcx.ins().ireduce(types::I16, sat); + + let res_lane = CValue::by_val(res, ret_lane_layout); + ret.place_lane(fx, idx).write_cvalue(fx, res_lane); + } + + for idx in 0..lane_count { + let lane = b.value_lane(fx, idx).load_scalar(fx); + let sat = fx.bcx.ins().umax(lane, min_u16); + let sat = fx.bcx.ins().umin(sat, max_u16); + let res = fx.bcx.ins().ireduce(types::I16, sat); + + let res_lane = CValue::by_val(res, ret_lane_layout); + ret.place_lane(fx, lane_count + idx).write_cvalue(fx, res_lane); + } + } + "llvm.x86.avx2.packssdw" => { // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_packs_epi32&ig_expand=4892 intrinsic_args!(fx, args => (a, b); intrinsic); @@ -648,6 +686,106 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( } } + "llvm.x86.pclmulqdq" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_clmulepi64_si128&ig_expand=772 + intrinsic_args!(fx, args => (a, b, imm8); intrinsic); + + assert_eq!(a.layout(), b.layout()); + let layout = a.layout(); + + let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx); + let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx); + assert_eq!(lane_ty, fx.tcx.types.i64); + assert_eq!(ret_lane_ty, fx.tcx.types.i64); + assert_eq!(lane_count, 2); + assert_eq!(ret_lane_count, 2); + + let imm8 = imm8.load_scalar(fx); + + let control0 = fx.bcx.ins().band_imm(imm8, 0b0000_0001); + let a_lane0 = a.value_lane(fx, 0).load_scalar(fx); + let a_lane1 = a.value_lane(fx, 1).load_scalar(fx); + let temp1 = fx.bcx.ins().select(control0, a_lane1, a_lane0); + + let control4 = fx.bcx.ins().band_imm(imm8, 0b0001_0000); + let b_lane0 = b.value_lane(fx, 0).load_scalar(fx); + let b_lane1 = b.value_lane(fx, 1).load_scalar(fx); + let temp2 = fx.bcx.ins().select(control4, b_lane1, b_lane0); + + fn extract_bit(fx: &mut FunctionCx<'_, '_, '_>, val: Value, bit: i64) -> Value { + let tmp = fx.bcx.ins().ushr_imm(val, bit); + fx.bcx.ins().band_imm(tmp, 1) + } + + let mut res1 = fx.bcx.ins().iconst(types::I64, 0); + for i in 0..=63 { + let x = extract_bit(fx, temp1, 0); + let y = extract_bit(fx, temp2, i); + let mut temp = fx.bcx.ins().band(x, y); + for j in 1..=i { + let x = extract_bit(fx, temp1, j); + let y = extract_bit(fx, temp2, i - j); + let z = fx.bcx.ins().band(x, y); + temp = fx.bcx.ins().bxor(temp, z); + } + let temp = fx.bcx.ins().ishl_imm(temp, i); + res1 = fx.bcx.ins().bor(res1, temp); + } + ret.place_lane(fx, 0).to_ptr().store(fx, res1, MemFlags::trusted()); + + let mut res2 = fx.bcx.ins().iconst(types::I64, 0); + for i in 64..=127 { + let mut temp = fx.bcx.ins().iconst(types::I64, 0); + for j in i - 63..=63 { + let x = extract_bit(fx, temp1, j); + let y = extract_bit(fx, temp2, i - j); + let z = fx.bcx.ins().band(x, y); + temp = fx.bcx.ins().bxor(temp, z); + } + let temp = fx.bcx.ins().ishl_imm(temp, i); + res2 = fx.bcx.ins().bor(res2, temp); + } + ret.place_lane(fx, 1).to_ptr().store(fx, res2, MemFlags::trusted()); + } + + "llvm.x86.avx.ptestz.256" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_testz_si256&ig_expand=6945 + intrinsic_args!(fx, args => (a, b); intrinsic); + + assert_eq!(a.layout(), b.layout()); + let layout = a.layout(); + + let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx); + assert_eq!(lane_ty, fx.tcx.types.i64); + assert_eq!(ret.layout().ty, fx.tcx.types.i32); + assert_eq!(lane_count, 4); + + let a_lane0 = a.value_lane(fx, 0).load_scalar(fx); + let a_lane1 = a.value_lane(fx, 1).load_scalar(fx); + let a_lane2 = a.value_lane(fx, 2).load_scalar(fx); + let a_lane3 = a.value_lane(fx, 3).load_scalar(fx); + let b_lane0 = b.value_lane(fx, 0).load_scalar(fx); + let b_lane1 = b.value_lane(fx, 1).load_scalar(fx); + let b_lane2 = b.value_lane(fx, 2).load_scalar(fx); + let b_lane3 = b.value_lane(fx, 3).load_scalar(fx); + + let zero0 = fx.bcx.ins().band(a_lane0, b_lane0); + let zero1 = fx.bcx.ins().band(a_lane1, b_lane1); + let zero2 = fx.bcx.ins().band(a_lane2, b_lane2); + let zero3 = fx.bcx.ins().band(a_lane3, b_lane3); + + let all_zero0 = fx.bcx.ins().bor(zero0, zero1); + let all_zero1 = fx.bcx.ins().bor(zero2, zero3); + let all_zero = fx.bcx.ins().bor(all_zero0, all_zero1); + + let res = fx.bcx.ins().icmp_imm(IntCC::Equal, all_zero, 0); + let res = CValue::by_val( + fx.bcx.ins().uextend(types::I32, res), + fx.layout_of(fx.tcx.types.i32), + ); + ret.write_cvalue(fx, res); + } + _ => { fx.tcx .sess From 1d1fe9a2052ef89ef6efb414f32dfb5151652560 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Tue, 7 Nov 2023 18:24:07 +0000 Subject: [PATCH 324/435] add note to remember to update a url when bumping to gcc 10.1.0 --- src/ci/docker/host-x86_64/dist-x86_64-linux/build-gcc.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-gcc.sh b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-gcc.sh index f64eb8ae638e..e939a5d7eac4 100755 --- a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-gcc.sh +++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-gcc.sh @@ -3,6 +3,7 @@ set -ex source shared.sh +# Note: in the future when bumping to version 10.1.0, also take care of the sed block below. GCC=9.5.0 curl https://ftp.gnu.org/gnu/gcc/gcc-$GCC/gcc-$GCC.tar.xz | xzcat | tar xf - @@ -22,6 +23,11 @@ cd gcc-$GCC # latter host is presented to `wget`! Therefore, we choose to download from the insecure HTTP server # instead here. # +# Note: in version 10.1.0, the URL used in `download_prerequisites` has changed from using FTP to +# using HTTP. When bumping to that gcc version, we can likely remove the sed replacement below, or +# the expression will need to be updated. That new URL is available at: +# https://github.com/gcc-mirror/gcc/blob/6e6e3f144a33ae504149dc992453b4f6dea12fdb/contrib/download_prerequisites#L35 +# sed -i'' 's|ftp://gcc\.gnu\.org/|https://gcc.gnu.org/|g' ./contrib/download_prerequisites ./contrib/download_prerequisites From eca9a1533f4bf2848a34723410d9ae2f1e76975d Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Tue, 7 Nov 2023 20:03:07 +0000 Subject: [PATCH 325/435] Add an explanation for `transmute_unchecked` --- compiler/rustc_middle/src/query/erase.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index deefd438c4ad..b96281b86455 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -30,6 +30,13 @@ pub fn erase(src: T) -> Erase { }; Erased::<::Result> { + // `transmute_unchecked` is needed here because it does not have `transmute`'s size check + // (and thus allows to transmute between `T` and `MaybeUninit`) (we do the size + // check ourselves in the `const` block above). + // + // `transmute_copy` is also commonly used for this (and it would work here since + // `EraseType: Copy`), but `transmute_unchecked` better explains the intent. + // // SAFETY: It is safe to transmute to MaybeUninit for types with the same sizes. data: unsafe { transmute_unchecked::>(src) }, } @@ -39,6 +46,8 @@ pub fn erase(src: T) -> Erase { #[inline(always)] pub fn restore(value: Erase) -> T { let value: Erased<::Result> = value; + // See comment in `erase` for why we use `transmute_unchecked`. + // // SAFETY: Due to the use of impl Trait in `Erase` the only way to safely create an instance // of `Erase` is to call `erase`, so we know that `value.data` is a valid instance of `T` of // the right size. From 0ba7d19769c068729761eba72e779b53101a19bc Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 7 Nov 2023 21:14:38 +0000 Subject: [PATCH 326/435] Build pre-coroutine-transform coroutine body --- compiler/rustc_mir_build/src/build/mod.rs | 12 +----------- .../ui/mir/build-async-error-body-correctly.rs | 8 ++++++++ .../mir/build-async-error-body-correctly.stderr | 17 +++++++++++++++++ 3 files changed, 26 insertions(+), 11 deletions(-) create mode 100644 tests/ui/mir/build-async-error-body-correctly.rs create mode 100644 tests/ui/mir/build-async-error-body-correctly.stderr diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index 7c729016521b..886d805454db 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -656,17 +656,7 @@ fn construct_error(tcx: TyCtxt<'_>, def_id: LocalDefId, guar: ErrorGuaranteed) - let args = args.as_coroutine(); let yield_ty = args.yield_ty(); let return_ty = args.return_ty(); - let self_ty = Ty::new_adt( - tcx, - tcx.adt_def(tcx.lang_items().pin_type().unwrap()), - tcx.mk_args(&[Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, coroutine_ty).into()]), - ); - let coroutine_state = Ty::new_adt( - tcx, - tcx.adt_def(tcx.lang_items().coroutine_state().unwrap()), - tcx.mk_args(&[yield_ty.into(), return_ty.into()]), - ); - (vec![self_ty, args.resume_ty()], coroutine_state, Some(yield_ty)) + (vec![coroutine_ty, args.resume_ty()], return_ty, Some(yield_ty)) } dk => bug!("{:?} is not a body: {:?}", def_id, dk), }; diff --git a/tests/ui/mir/build-async-error-body-correctly.rs b/tests/ui/mir/build-async-error-body-correctly.rs new file mode 100644 index 000000000000..1787f80c07e5 --- /dev/null +++ b/tests/ui/mir/build-async-error-body-correctly.rs @@ -0,0 +1,8 @@ +// edition: 2021 + +async fn asyncfn() { + let binding = match true {}; + //~^ ERROR non-exhaustive patterns: type `bool` is non-empty +} + +fn main() {} diff --git a/tests/ui/mir/build-async-error-body-correctly.stderr b/tests/ui/mir/build-async-error-body-correctly.stderr new file mode 100644 index 000000000000..3d18c249afe2 --- /dev/null +++ b/tests/ui/mir/build-async-error-body-correctly.stderr @@ -0,0 +1,17 @@ +error[E0004]: non-exhaustive patterns: type `bool` is non-empty + --> $DIR/build-async-error-body-correctly.rs:4:25 + | +LL | let binding = match true {}; + | ^^^^ + | + = note: the matched value is of type `bool` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ let binding = match true { +LL + _ => todo!(), +LL ~ }; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0004`. From 102384523a32f54b813fdfdc49758a090cb82766 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Sun, 15 Oct 2023 12:48:06 +0000 Subject: [PATCH 327/435] Document how rust atomics work wrt mixed-sized and non-atomic accesses --- library/core/src/sync/atomic.rs | 124 +++++++++++++++++++++----------- 1 file changed, 81 insertions(+), 43 deletions(-) diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index de41bd1a1167..a5be33c7f56c 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -4,26 +4,12 @@ //! threads, and are the building blocks of other concurrent //! types. //! -//! Rust atomics currently follow the same rules as [C++20 atomics][cpp], specifically `atomic_ref`. -//! Basically, creating a *shared reference* to one of the Rust atomic types corresponds to creating -//! an `atomic_ref` in C++; the `atomic_ref` is destroyed when the lifetime of the shared reference -//! ends. (A Rust atomic type that is exclusively owned or behind a mutable reference does *not* -//! correspond to an "atomic object" in C++, since it can be accessed via non-atomic operations.) -//! //! This module defines atomic versions of a select number of primitive //! types, including [`AtomicBool`], [`AtomicIsize`], [`AtomicUsize`], //! [`AtomicI8`], [`AtomicU16`], etc. //! Atomic types present operations that, when used correctly, synchronize //! updates between threads. //! -//! Each method takes an [`Ordering`] which represents the strength of -//! the memory barrier for that operation. These orderings are the -//! same as the [C++20 atomic orderings][1]. For more information see the [nomicon][2]. -//! -//! [cpp]: https://en.cppreference.com/w/cpp/atomic -//! [1]: https://en.cppreference.com/w/cpp/atomic/memory_order -//! [2]: ../../../nomicon/atomics.html -//! //! Atomic variables are safe to share between threads (they implement [`Sync`]) //! but they do not themselves provide the mechanism for sharing and follow the //! [threading model](../../../std/thread/index.html#the-threading-model) of Rust. @@ -36,6 +22,75 @@ //! the constant initializers like [`AtomicBool::new`]. Atomic statics //! are often used for lazy global initialization. //! +//! ## Memory model for atomic accesses +//! +//! Rust atomics currently follow the same rules as [C++20 atomics][cpp], specifically `atomic_ref`. +//! Basically, creating a *shared reference* to one of the Rust atomic types corresponds to creating +//! an `atomic_ref` in C++; the `atomic_ref` is destroyed when the lifetime of the shared reference +//! ends. (A Rust atomic type that is exclusively owned or behind a mutable reference does *not* +//! correspond to an "atomic object" in C++, since it can be accessed via non-atomic operations.) +//! +//! [cpp]: https://en.cppreference.com/w/cpp/atomic +//! +//! Each method takes an [`Ordering`] which represents the strength of +//! the memory barrier for that operation. These orderings are the +//! same as the [C++20 atomic orderings][1]. For more information see the [nomicon][2]. +//! +//! [1]: https://en.cppreference.com/w/cpp/atomic/memory_order +//! [2]: ../../../nomicon/atomics.html +//! +//! Since C++ does not support mixing atomic and non-atomic accesses, or non-synchronized +//! different-sized accesses to the same data, Rust does not support those operations either. +//! Note that both of those restrictions only apply if the accesses are non-synchronized. +//! +//! ```rust,no_run undefined_behavior +//! use std::sync::atomic::{AtomicU16, AtomicU8, Ordering}; +//! use std::mem::transmute; +//! use std::thread; +//! +//! let atomic = AtomicU16::new(0); +//! +//! thread::scope(|s| { +//! // This is UB: mixing atomic and non-atomic accesses +//! s.spawn(|| atomic.store(1, Ordering::Relaxed)); +//! s.spawn(|| unsafe { atomic.as_ptr().write(2) }); +//! }); +//! +//! thread::scope(|s| { +//! // This is UB: even reads are not allowed to be mixed +//! s.spawn(|| atomic.load(Ordering::Relaxed)); +//! s.spawn(|| unsafe { atomic.as_ptr().read() }); +//! }); +//! +//! thread::scope(|s| { +//! // This is fine, `join` synchronizes the code in a way such that atomic +//! // and non-atomic accesses can't happen "at the same time" +//! let handle = s.spawn(|| atomic.store(1, Ordering::Relaxed)); +//! handle.join().unwrap(); +//! s.spawn(|| unsafe { atomic.as_ptr().write(2) }); +//! }); +//! +//! thread::scope(|s| { +//! // This is UB: using different-sized atomic accesses to the same data +//! s.spawn(|| atomic.store(1, Ordering::Relaxed)); +//! s.spawn(|| unsafe { +//! let differently_sized = transmute::<&AtomicU16, &AtomicU8>(&atomic); +//! differently_sized.store(2, Ordering::Relaxed); +//! }); +//! }); +//! +//! thread::scope(|s| { +//! // This is fine, `join` synchronizes the code in a way such that +//! // differently-sized accesses can't happen "at the same time" +//! let handle = s.spawn(|| atomic.store(1, Ordering::Relaxed)); +//! handle.join().unwrap(); +//! s.spawn(|| unsafe { +//! let differently_sized = transmute::<&AtomicU16, &AtomicU8>(&atomic); +//! differently_sized.store(2, Ordering::Relaxed); +//! }); +//! }); +//! ``` +//! //! # Portability //! //! All atomic types in this module are guaranteed to be [lock-free] if they're @@ -349,16 +404,12 @@ impl AtomicBool { /// * `ptr` must be aligned to `align_of::()` (note that on some platforms this can /// be bigger than `align_of::()`). /// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`. - /// * Non-atomic accesses to the value behind `ptr` must have a happens-before relationship - /// with atomic accesses via the returned value (or vice-versa). - /// * In other words, time periods where the value is accessed atomically may not overlap - /// with periods where the value is accessed non-atomically. - /// * This requirement is trivially satisfied if `ptr` is never used non-atomically for the - /// duration of lifetime `'a`. Most use cases should be able to follow this guideline. - /// * This requirement is also trivially satisfied if all accesses (atomic or not) are done - /// from the same thread. + /// * You must adhere to the [Memory model for atomic accesses]. In particular, it is not + /// allowed to mix atomic and non-atomic accesses, or atomic accesses of different sizes, + /// without synchronization. /// /// [valid]: crate::ptr#safety + /// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses #[stable(feature = "atomic_from_ptr", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_atomic_from_ptr", issue = "108652")] pub const unsafe fn from_ptr<'a>(ptr: *mut bool) -> &'a AtomicBool { @@ -1151,18 +1202,12 @@ impl AtomicPtr { /// * `ptr` must be aligned to `align_of::>()` (note that on some platforms this /// can be bigger than `align_of::<*mut T>()`). /// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`. - /// * Non-atomic accesses to the value behind `ptr` must have a happens-before relationship - /// with atomic accesses via the returned value (or vice-versa). - /// * In other words, time periods where the value is accessed atomically may not overlap - /// with periods where the value is accessed non-atomically. - /// * This requirement is trivially satisfied if `ptr` is never used non-atomically for the - /// duration of lifetime `'a`. Most use cases should be able to follow this guideline. - /// * This requirement is also trivially satisfied if all accesses (atomic or not) are done - /// from the same thread. - /// * This method should not be used to create overlapping or mixed-size atomic accesses, as - /// these are not supported by the memory model. + /// * You must adhere to the [Memory model for atomic accesses]. In particular, it is not + /// allowed to mix atomic and non-atomic accesses, or atomic accesses of different sizes, + /// without synchronization. /// /// [valid]: crate::ptr#safety + /// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses #[stable(feature = "atomic_from_ptr", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_atomic_from_ptr", issue = "108652")] pub const unsafe fn from_ptr<'a>(ptr: *mut *mut T) -> &'a AtomicPtr { @@ -2133,19 +2178,12 @@ macro_rules! atomic_int { `align_of::<", stringify!($atomic_type), ">()` (note that on some platforms this \ can be bigger than `align_of::<", stringify!($int_type), ">()`).")] /// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`. - /// * Non-atomic accesses to the value behind `ptr` must have a happens-before - /// relationship with atomic accesses via the returned value (or vice-versa). - /// * In other words, time periods where the value is accessed atomically may not - /// overlap with periods where the value is accessed non-atomically. - /// * This requirement is trivially satisfied if `ptr` is never used non-atomically - /// for the duration of lifetime `'a`. Most use cases should be able to follow - /// this guideline. - /// * This requirement is also trivially satisfied if all accesses (atomic or not) are - /// done from the same thread. - /// * This method should not be used to create overlapping or mixed-size atomic - /// accesses, as these are not supported by the memory model. + /// * You must adhere to the [Memory model for atomic accesses]. In particular, it is not + /// allowed to mix atomic and non-atomic accesses, or atomic accesses of different sizes, + /// without synchronization. /// /// [valid]: crate::ptr#safety + /// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses #[stable(feature = "atomic_from_ptr", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_atomic_from_ptr", issue = "108652")] pub const unsafe fn from_ptr<'a>(ptr: *mut $int_type) -> &'a $atomic_type { From 1086b294c26a55542b65377970fc0ba23b61d7bd Mon Sep 17 00:00:00 2001 From: hkalbasi Date: Wed, 8 Nov 2023 01:16:47 +0330 Subject: [PATCH 328/435] update rustc dependencies --- Cargo.lock | 34 ++++++++++++++++++++++------ crates/hir-def/src/data/adt.rs | 2 +- crates/rustc-dependencies/Cargo.toml | 6 ++--- 3 files changed, 31 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0a3d38645f52..fcb188c0dfab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1454,12 +1454,12 @@ dependencies = [ [[package]] name = "ra-ap-rustc_abi" -version = "0.14.0" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a51b7a02377b3246ec5c095b852b5cf1678bd9ed6b572b2a79efbf7ad711c292" +checksum = "7082716cb2bbcd8b5f062fe950cbbc87f3aba022d6da4168db35af6732a7f15d" dependencies = [ "bitflags 1.3.2", - "ra-ap-rustc_index", + "ra-ap-rustc_index 0.18.0", "tracing", ] @@ -1473,6 +1473,16 @@ dependencies = [ "smallvec", ] +[[package]] +name = "ra-ap-rustc_index" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19e14b1fc835d6992b128a03a3f3a8365ba9f03e1c656a1670305f63f30d786d" +dependencies = [ + "arrayvec", + "smallvec", +] + [[package]] name = "ra-ap-rustc_lexer" version = "0.14.0" @@ -1483,14 +1493,24 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "ra-ap-rustc_lexer" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1762abb25eb1e37c1823f62b5da0821bbcd870812318db084c9516c2f78d2dcd" +dependencies = [ + "unicode-properties", + "unicode-xid", +] + [[package]] name = "ra-ap-rustc_parse_format" version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "207b5ac1a21d4926695e03b605ffb9f63d4968e0488e9197c04c512c37303aa7" dependencies = [ - "ra-ap-rustc_index", - "ra-ap-rustc_lexer", + "ra-ap-rustc_index 0.14.0", + "ra-ap-rustc_lexer 0.14.0", ] [[package]] @@ -1614,8 +1634,8 @@ name = "rustc-dependencies" version = "0.0.0" dependencies = [ "ra-ap-rustc_abi", - "ra-ap-rustc_index", - "ra-ap-rustc_lexer", + "ra-ap-rustc_index 0.18.0", + "ra-ap-rustc_lexer 0.18.0", "ra-ap-rustc_parse_format", ] diff --git a/crates/hir-def/src/data/adt.rs b/crates/hir-def/src/data/adt.rs index 76c8d9a0c367..b163112db918 100644 --- a/crates/hir-def/src/data/adt.rs +++ b/crates/hir-def/src/data/adt.rs @@ -178,7 +178,7 @@ fn parse_repr_tt(tt: &Subtree) -> Option { } } - Some(ReprOptions { int, align: max_align, pack: min_pack, flags }) + Some(ReprOptions { int, align: max_align, pack: min_pack, flags, field_shuffle_seed: 0 }) } impl StructData { diff --git a/crates/rustc-dependencies/Cargo.toml b/crates/rustc-dependencies/Cargo.toml index 7ead3d84cd3c..a313507bff31 100644 --- a/crates/rustc-dependencies/Cargo.toml +++ b/crates/rustc-dependencies/Cargo.toml @@ -11,10 +11,10 @@ authors.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -ra-ap-rustc_lexer = { version = "0.14.0" } +ra-ap-rustc_lexer = { version = "0.18.0" } ra-ap-rustc_parse_format = { version = "0.14.0", default-features = false } -ra-ap-rustc_index = { version = "0.14.0", default-features = false } -ra-ap-rustc_abi = { version = "0.14.0", default-features = false } +ra-ap-rustc_index = { version = "0.18.0", default-features = false } +ra-ap-rustc_abi = { version = "0.18.0", default-features = false } [features] in-rust-tree = [] From 1b3733e5a4b625a8b4aa78ed31e90c756b0bc048 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 6 Nov 2023 13:06:40 +1100 Subject: [PATCH 329/435] rustc: minor changes suggested by clippy perf lints. --- compiler/rustc_errors/src/emitter.rs | 6 +----- compiler/rustc_middle/src/ty/diagnostics.rs | 2 +- compiler/rustc_resolve/src/diagnostics.rs | 2 +- compiler/rustc_session/src/config.rs | 2 +- 4 files changed, 4 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 6d95fbcfad00..68dba8602912 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -2362,11 +2362,7 @@ impl FileWithAnnotatedLines { let label = label.as_ref().map(|m| { normalize_whitespace( - &emitter - .translate_message(m, &args) - .map_err(Report::new) - .unwrap() - .to_string(), + &emitter.translate_message(m, &args).map_err(Report::new).unwrap(), ) }); diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index 77a50fa9276d..0094825fc70d 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -274,7 +274,7 @@ pub fn suggest_constraining_type_params<'a>( span, if span_to_replace.is_some() { constraint.clone() - } else if constraint.starts_with("<") { + } else if constraint.starts_with('<') { constraint.to_string() } else if bound_list_non_empty { format!(" + {constraint}") diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index edcc22d56c68..93db6cfc4635 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1545,7 +1545,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let (span, sugg, post) = if let SuggestionTarget::SimilarlyNamed = suggestion.target && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) && let Some(span) = suggestion.span - && let Some(candidate) = suggestion.candidate.as_str().strip_prefix("_") + && let Some(candidate) = suggestion.candidate.as_str().strip_prefix('_') && snippet == candidate { // When the suggested binding change would be from `x` to `_x`, suggest changing the diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index c94e0d0ed394..930fb693eb6d 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -2477,7 +2477,7 @@ pub fn parse_externs( let mut error = handler.early_struct_error(format!( "crate name `{name}` passed to `--extern` is not a valid ASCII identifier" )); - let adjusted_name = name.replace("-", "_"); + let adjusted_name = name.replace('-', "_"); if crate::utils::is_ascii_ident(&adjusted_name) { error.help(format!( "consider replacing the dashes with underscores: `{adjusted_name}`" From e8cf29b584ce684351ceacbf7e06be6c0874c9be Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 6 Nov 2023 13:27:38 +1100 Subject: [PATCH 330/435] rustdoc: minor changes suggested by clippy perf lints. --- src/librustdoc/clean/inline.rs | 2 +- src/librustdoc/clean/types.rs | 1 + src/librustdoc/clean/utils.rs | 2 +- src/librustdoc/html/render/write_shared.rs | 15 ++++++--------- .../passes/lint/redundant_explicit_links.rs | 2 +- 5 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 013814b1f7dc..974ba1e3bd93 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -599,7 +599,7 @@ fn build_module_items( let prim_ty = clean::PrimitiveType::from(p); items.push(clean::Item { name: None, - attrs: Box::new(clean::Attributes::default()), + attrs: Box::default(), // We can use the item's `DefId` directly since the only information ever used // from it is `DefId.krate`. item_id: ItemId::DefId(did), diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index a718cb37d89f..88ee4e3a2abd 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1327,6 +1327,7 @@ impl WherePredicate { pub(crate) enum GenericParamDefKind { Lifetime { outlives: ThinVec }, Type { did: DefId, bounds: ThinVec, default: Option>, synthetic: bool }, + // Option> makes this type smaller than `Option` would. Const { ty: Box, default: Option>, is_host_effect: bool }, } diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index dea7bfaf7e22..ca1b782492c4 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -588,7 +588,7 @@ pub(crate) fn has_doc_flag(tcx: TyCtxt<'_>, did: DefId, flag: Symbol) -> bool { /// Set by `bootstrap::Builder::doc_rust_lang_org_channel` in order to keep tests passing on beta/stable. pub(crate) const DOC_RUST_LANG_ORG_CHANNEL: &str = env!("DOC_RUST_LANG_ORG_CHANNEL"); pub(crate) static DOC_CHANNEL: Lazy<&'static str> = - Lazy::new(|| DOC_RUST_LANG_ORG_CHANNEL.rsplit("/").filter(|c| !c.is_empty()).next().unwrap()); + Lazy::new(|| DOC_RUST_LANG_ORG_CHANNEL.rsplit('/').filter(|c| !c.is_empty()).next().unwrap()); /// Render a sequence of macro arms in a format suitable for displaying to the user /// as part of an item declaration. diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index 3e58dd96ed92..d2c7c578c083 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs @@ -356,15 +356,12 @@ if (typeof exports !== 'undefined') {exports.searchIndex = searchIndex}; let content = format!( "