diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index 6f956c3bcc1ce..7407dfc455d84 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -152,7 +152,8 @@ pub fn target_machine_factory( let features = features.join(","); let features = CString::new(features).unwrap(); let abi = SmallCStr::new(&sess.target.llvm_abiname); - let trap_unreachable = sess.target.trap_unreachable; + let trap_unreachable = + sess.opts.debugging_opts.trap_unreachable.unwrap_or(sess.target.trap_unreachable); let emit_stack_size_section = sess.opts.debugging_opts.emit_stack_sizes; let asm_comments = sess.asm_comments(); diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 1fc2d281e7935..92262050b8c1b 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -547,7 +547,7 @@ fn test_debugging_options_tracking_hash() { tracked!(debug_macros, true); tracked!(dep_info_omit_d_target, true); tracked!(dual_proc_macros, true); - tracked!(fewer_names, true); + tracked!(fewer_names, Some(true)); tracked!(force_overflow_checks, Some(true)); tracked!(force_unstable_if_unmarked, true); tracked!(fuel, Some(("abc".to_string(), 99))); @@ -592,6 +592,7 @@ fn test_debugging_options_tracking_hash() { tracked!(thinlto, Some(true)); tracked!(tune_cpu, Some(String::from("abc"))); tracked!(tls_model, Some(TlsModel::GeneralDynamic)); + tracked!(trap_unreachable, Some(false)); tracked!(treat_err_as_bug, Some(1)); tracked!(unleash_the_miri_inside_of_you, true); tracked!(use_ctors_section, Some(true)); diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 67491b5bf7e4e..a0d5b61e8bd1b 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -481,6 +481,7 @@ impl<'a> Resolver<'a> { name )); } + err.help("use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions"); err } diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 1cd3d11e32153..731bbf029fa31 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -900,7 +900,7 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "emits a future-incompatibility report for lints (RFC 2834)"), emit_stack_sizes: bool = (false, parse_bool, [UNTRACKED], "emit a section containing stack size metadata (default: no)"), - fewer_names: bool = (false, parse_bool, [TRACKED], + fewer_names: Option = (None, parse_opt_bool, [TRACKED], "reduce memory use by retaining fewer names within compilation artifacts (LLVM-IR) \ (default: no)"), force_overflow_checks: Option = (None, parse_opt_bool, [TRACKED], @@ -1113,6 +1113,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "choose the TLS model to use (`rustc --print tls-models` for details)"), trace_macros: bool = (false, parse_bool, [UNTRACKED], "for every macro invocation, print its name and arguments (default: no)"), + trap_unreachable: Option = (None, parse_opt_bool, [TRACKED], + "generate trap instructions for unreachable intrinsics (default: use target setting, usually yes)"), treat_err_as_bug: Option = (None, parse_treat_err_as_bug, [TRACKED], "treat error number `val` that occurs as bug"), trim_diagnostic_paths: bool = (true, parse_bool, [UNTRACKED], diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 419d1447764ec..5dddf0eb72ea6 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -734,12 +734,15 @@ impl Session { self.opts.cg.panic.unwrap_or(self.target.panic_strategy) } pub fn fewer_names(&self) -> bool { - let more_names = self.opts.output_types.contains_key(&OutputType::LlvmAssembly) - || self.opts.output_types.contains_key(&OutputType::Bitcode) - // AddressSanitizer and MemorySanitizer use alloca name when reporting an issue. - || self.opts.debugging_opts.sanitizer.intersects(SanitizerSet::ADDRESS | SanitizerSet::MEMORY); - - self.opts.debugging_opts.fewer_names || !more_names + if let Some(fewer_names) = self.opts.debugging_opts.fewer_names { + fewer_names + } else { + let more_names = self.opts.output_types.contains_key(&OutputType::LlvmAssembly) + || self.opts.output_types.contains_key(&OutputType::Bitcode) + // AddressSanitizer and MemorySanitizer use alloca name when reporting an issue. + || self.opts.debugging_opts.sanitizer.intersects(SanitizerSet::ADDRESS | SanitizerSet::MEMORY); + !more_names + } } pub fn unstable_options(&self) -> bool { diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index 5dffe5107b581..aeca801a4ee00 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -329,7 +329,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) { ), ) .note("the only supported types are integers, `bool` and `char`") - .note("more complex types are supported with `#[feature(const_generics)]`") + .help("more complex types are supported with `#[feature(const_generics)]`") .emit() } }; diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs index eb32cef24a1ea..bd2ad257402fa 100644 --- a/library/alloc/src/collections/btree/map.rs +++ b/library/alloc/src/collections/btree/map.rs @@ -458,7 +458,7 @@ impl fmt::Debug for RangeMut<'_, K, V> { } impl BTreeMap { - /// Makes a new empty BTreeMap. + /// Makes a new, empty `BTreeMap`. /// /// Does not allocate anything on its own. /// @@ -1924,7 +1924,7 @@ impl Hash for BTreeMap { #[stable(feature = "rust1", since = "1.0.0")] impl Default for BTreeMap { - /// Creates an empty `BTreeMap`. + /// Creates an empty `BTreeMap`. fn default() -> BTreeMap { BTreeMap::new() } diff --git a/library/alloc/src/collections/btree/node.rs b/library/alloc/src/collections/btree/node.rs index e3e555a72de02..6a8be441513a0 100644 --- a/library/alloc/src/collections/btree/node.rs +++ b/library/alloc/src/collections/btree/node.rs @@ -112,20 +112,8 @@ impl InternalNode { /// /// However, `BoxedNode` contains no information as to which of the two types /// of nodes it actually contains, and, partially due to this lack of information, -/// has no destructor. -struct BoxedNode { - ptr: NonNull>, -} - -impl BoxedNode { - fn from_owned(ptr: NonNull>) -> Self { - BoxedNode { ptr } - } - - fn as_ptr(&self) -> NonNull> { - self.ptr - } -} +/// is not a separate type and has no destructor. +type BoxedNode = NonNull>; /// An owned tree. /// @@ -168,11 +156,6 @@ impl NodeRef { pub fn borrow_valmut(&mut self) -> NodeRef, K, V, Type> { NodeRef { height: self.height, node: self.node, _marker: PhantomData } } - - /// Packs the reference, aware of type and height, into a type-agnostic pointer. - fn into_boxed_node(self) -> BoxedNode { - BoxedNode::from_owned(self.node) - } } impl NodeRef { @@ -181,7 +164,7 @@ impl NodeRef { /// and is the opposite of `pop_internal_level`. pub fn push_internal_level(&mut self) -> NodeRef, K, V, marker::Internal> { let mut new_node = Box::new(unsafe { InternalNode::new() }); - new_node.edges[0].write(BoxedNode::from_owned(self.node)); + new_node.edges[0].write(self.node); let mut new_root = NodeRef::from_new_internal(new_node, self.height + 1); new_root.borrow_mut().first_edge().correct_parent_link(); *self = new_root.forget_type(); @@ -288,13 +271,6 @@ unsafe impl<'a, K: Send + 'a, V: Send + 'a, Type> Send for NodeRef Send for NodeRef, K, V, Type> {} unsafe impl Send for NodeRef {} -impl NodeRef { - /// Unpack a node reference that was packed by `Root::into_boxed_node`. - fn from_boxed_node(boxed_node: BoxedNode, height: usize) -> Self { - NodeRef { height, node: boxed_node.as_ptr(), _marker: PhantomData } - } -} - impl NodeRef { /// Unpack a node reference that was packed as `NodeRef::parent`. fn from_internal(node: NonNull>, height: usize) -> Self { @@ -695,7 +671,7 @@ impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::Internal> { unsafe { self.reborrow_mut().into_key_area_mut_at(idx).write(key); self.reborrow_mut().into_val_area_mut_at(idx).write(val); - self.reborrow_mut().into_edge_area_mut_at(idx + 1).write(edge.into_boxed_node()); + self.reborrow_mut().into_edge_area_mut_at(idx + 1).write(edge.node); Handle::new_edge(self.reborrow_mut(), idx + 1).correct_parent_link(); } } @@ -710,7 +686,7 @@ impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::Internal> { *self.reborrow_mut().into_len_mut() += 1; slice_insert(self.reborrow_mut().into_key_area_slice(), 0, key); slice_insert(self.reborrow_mut().into_val_area_slice(), 0, val); - slice_insert(self.reborrow_mut().into_edge_area_slice(), 0, edge.into_boxed_node()); + slice_insert(self.reborrow_mut().into_edge_area_slice(), 0, edge.node); } self.correct_all_childrens_parent_links(); @@ -732,8 +708,8 @@ impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::LeafOrInternal> { let edge = match self.reborrow_mut().force() { ForceResult::Leaf(_) => None, ForceResult::Internal(internal) => { - let boxed_node = ptr::read(internal.reborrow().edge_at(idx + 1)); - let mut edge = Root::from_boxed_node(boxed_node, internal.height - 1); + let node = ptr::read(internal.reborrow().edge_at(idx + 1)); + let mut edge = Root { node, height: internal.height - 1, _marker: PhantomData }; // In practice, clearing the parent is a waste of time, because we will // insert the node elsewhere and set its parent link again. edge.borrow_mut().clear_parent_link(); @@ -760,9 +736,8 @@ impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::LeafOrInternal> { let edge = match self.reborrow_mut().force() { ForceResult::Leaf(_) => None, ForceResult::Internal(mut internal) => { - let boxed_node = - slice_remove(internal.reborrow_mut().into_edge_area_slice(), 0); - let mut edge = Root::from_boxed_node(boxed_node, internal.height - 1); + let node = slice_remove(internal.reborrow_mut().into_edge_area_slice(), 0); + let mut edge = Root { node, height: internal.height - 1, _marker: PhantomData }; // In practice, clearing the parent is a waste of time, because we will // insert the node elsewhere and set its parent link again. edge.borrow_mut().clear_parent_link(); @@ -1041,12 +1016,11 @@ impl<'a, K: 'a, V: 'a> Handle, K, V, marker::Internal>, debug_assert!(self.node.len() < CAPACITY); debug_assert!(edge.height == self.node.height - 1); - let boxed_node = edge.into_boxed_node(); unsafe { *self.node.reborrow_mut().into_len_mut() += 1; slice_insert(self.node.reborrow_mut().into_key_area_slice(), self.idx, key); slice_insert(self.node.reborrow_mut().into_val_area_slice(), self.idx, val); - slice_insert(self.node.reborrow_mut().into_edge_area_slice(), self.idx + 1, boxed_node); + slice_insert(self.node.reborrow_mut().into_edge_area_slice(), self.idx + 1, edge.node); self.node.correct_childrens_parent_links((self.idx + 1)..=self.node.len()); } @@ -1135,8 +1109,8 @@ impl Handle, marke // reference (Rust issue #73987) and invalidate any other references // to or inside the array, should any be around. let parent_ptr = NodeRef::as_internal_ptr(&self.node); - let boxed_node = unsafe { (*parent_ptr).edges.get_unchecked(self.idx).assume_init_read() }; - NodeRef::from_boxed_node(boxed_node, self.node.height - 1) + let node = unsafe { (*parent_ptr).edges.get_unchecked(self.idx).assume_init_read() }; + NodeRef { node, height: self.node.height - 1, _marker: PhantomData } } } diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs index 1a807100653bc..f4046e87b99a8 100644 --- a/library/alloc/src/collections/btree/set.rs +++ b/library/alloc/src/collections/btree/set.rs @@ -220,7 +220,9 @@ impl fmt::Debug for Union<'_, T> { const ITER_PERFORMANCE_TIPPING_SIZE_DIFF: usize = 16; impl BTreeSet { - /// Makes a new `BTreeSet` with a reasonable choice of B. + /// Makes a new, empty `BTreeSet`. + /// + /// Does not allocate anything on its own. /// /// # Examples /// @@ -1121,7 +1123,7 @@ impl<'a, T: 'a + Ord + Copy> Extend<&'a T> for BTreeSet { #[stable(feature = "rust1", since = "1.0.0")] impl Default for BTreeSet { - /// Makes an empty `BTreeSet` with a reasonable choice of B. + /// Creates an empty `BTreeSet`. fn default() -> BTreeSet { BTreeSet::new() } diff --git a/library/std/src/keyword_docs.rs b/library/std/src/keyword_docs.rs index b990b78570393..80b74a9ba9b09 100644 --- a/library/std/src/keyword_docs.rs +++ b/library/std/src/keyword_docs.rs @@ -1739,7 +1739,7 @@ mod super_keyword {} /// /// # Differences between the 2015 and 2018 editions /// -/// In the 2015 edition parameters pattern where not needed for traits: +/// In the 2015 edition the parameters pattern was not needed for traits: /// /// ```rust,edition2015 /// trait Tr { diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index 57013e9194bc1..dd19861573667 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -18,4 +18,5 @@ - [Known Issues](targets/known-issues.md) - [Profile-guided Optimization](profile-guided-optimization.md) - [Linker-plugin based LTO](linker-plugin-lto.md) +- [Exploit Mitigations](exploit-mitigations.md) - [Contributing to `rustc`](contributing.md) diff --git a/src/doc/rustc/src/exploit-mitigations.md b/src/doc/rustc/src/exploit-mitigations.md new file mode 100644 index 0000000000000..44d5d9564f267 --- /dev/null +++ b/src/doc/rustc/src/exploit-mitigations.md @@ -0,0 +1,693 @@ +# 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 is for software engineers working with the Rust programming +language, and assumes prior knowledge of the Rust programming language and +its toolchain. + + +## Introduction + +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. + +Parts of the Rust standard library are implemented as safe abstractions over +unsafe code (and historically have been vulnerable to memory corruption[7]). +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. + +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 + +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 +programs for the Linux operating system on the AMD64 architecture and +equivalent. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Exploit mitigation + Supported and enabled by default + Since +
Position-independent executable + Yes + 0.12.0 (2014-10-09) +
Integer overflow checks + Yes (enabled when debug assertions are enabled, and disabled when debug assertions are disabled) + 1.1.0 (2015-06-25) +
Non-executable memory regions + Yes + 1.8.0 (2016-04-14) +
Stack clashing protection + Yes + 1.20.0 (2017-08-31) +
Read-only relocations and immediate binding + Yes + 1.21.0 (2017-10-12) +
Heap corruption protection + Yes + 1.32.0 (2019-01-17) (via operating system default or specified allocator) +
Stack smashing protection + No + +
Forward-edge control flow protection + No + +
Backward-edge control flow protection (e.g., shadow and safe stack) + No + +
+ +1\. See + +for a list of targets and their default options. + + +### Position-independent executable + +Position-independent executable increases the difficulty of the use of code +reuse exploitation techniques, such as return-oriented programming (ROP) and +variants, by generating position-independent code for the executable, and +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]. + +```text +$ readelf -h target/release/hello-rust | grep Type: + Type: DYN (Shared object file) +``` +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). + + +### Integer overflow checks + +Integer overflow checks protects programs from undefined and unintended +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]. + +```compile_fail +fn main() { + let u: u8 = 255; + println!("u: {}", u + 1); +} +``` +Fig. 2. hello-rust-integer program. + +```text +$ cargo run + Compiling hello-rust-integer v0.1.0 (/home/rcvalle/hello-rust-integer) + Finished dev [unoptimized + debuginfo] target(s) in 0.23s + Running `target/debug/hello-rust-integer` +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 +enabled. + +```text +$ cargo run --release + Compiling hello-rust-integer v0.1.0 (/home/rcvalle/hello-rust-integer) + Finished release [optimized] target(s) in 0.23s + Running `target/release/hello-rust-integer` +u: 0 +``` +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. + +2\. See +for more information on the checked, overflowing, saturating, and wrapping +methods (using u32 as an example). + + +### Non-executable memory regions + +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. + +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]. + +```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 +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 +`PT_GNU_STACK` in the program header table indicates non-executable memory +regions are not enabled for a given binary. + +3\. See the Appendix section for more information on why it +affects other memory regions besides the stack. + + +### Stack clashing protection + +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”. + +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(); +} +``` +Fig 7. Modified hello-rust. + +![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. + +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 + +**Read-only relocations** protect segments containing relocations and +relocation information (i.e., `.init_array`, `.fini_array`, `.dynamic`, and +`.got`) from being overwritten by marking these segments read only. This is +also referred to as “partial RELRO”. + +The Rust compiler supports read-only relocations, and enables it by default +since version 1.21.0 (2017-10-12)[30], [31]. + +```text +$ readelf -l target/release/hello-rust | grep GNU_RELRO + GNU_RELRO 0x000000000002ee00 0x000000000002fe00 0x000000000002fe00 +``` +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. + +**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”. + +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 + 0x000000000000001e (FLAGS) BIND_NOW +``` +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. + +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). + +4\. And the `DF_1_NOW` flag for some link editors. + + +### 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. + +[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. + +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]. + +```ignore +fn main() { + let mut x = Box::new([0; 1024]); + + for i in 0..1026 { + unsafe { + let elem = x.get_unchecked_mut(i); + *elem = 0x4141414141414141u64; + } + } +} +``` +Fig. 11. hello-rust-heap program. + +```text +$ cargo run + Compiling hello-rust-heap v0.1.0 (/home/rcvalle/hello-rust-heap) + Finished dev [unoptimized + debuginfo] target(s) in 0.25s + Running `target/debug/hello-rust-heap` +free(): invalid next size (normal) +Aborted +``` +Fig. 12. Build and execution of hello-rust-heap with debug assertions +enabled. + +```text +$ cargo run --release + Compiling hello-rust-heap v0.1.0 (/home/rcvalle/hello-rust-heap) + Finished release [optimized] target(s) in 0.25s + Running `target/release/hello-rust-heap` +free(): invalid next size (normal) +Aborted +``` +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. + + +### 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)”. + +The Rust compiler does not support stack smashing protection. However, more +comprehensive alternatives to stack smashing protection exist, such as +shadow and safe stack (see backward-edge control flow protection). + +![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 only cross references to +`__stack_chk_fail` in hello-rust are from the statically-linked libbacktrace +library (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)”. + +Newer processors provide hardware assistance for forward-edge control flow +protection, such as ARM Branch Target Identification (BTI), ARM Pointer +Authentication, and Intel Indirect Branch Tracking (IBT) as part of Intel +Control-flow Enforcement Technology (CET). However, ARM BTI and Intel IBT +-based implementations are less comprehensive than software-based +implementations such as [LLVM ControlFlowIntegrity +(CFI)](https://clang.llvm.org/docs/ControlFlowIntegrity.html), and the +commercially available [grsecurity/PaX Reuse Attack Protector +(RAP)](https://grsecurity.net/rap_faq). + +The Rust compiler does not support forward-edge control flow protection on +Linux6. There is work currently ongoing to add support +for the [sanitizers](https://github.com/google/sanitizers)[40], which may or +may not include support for LLVM CFI. + +```text +$ readelf -s target/release/hello-rust | grep __cfi_init +``` +Fig. 15. Checking if LLVM CFI is enabled for a given binary. + +The presence of 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 the `__cfi_init` +symbol (and references to `__cfi_check`) indicates that LLVM CFI is not +enabled for a given binary (see Fig. 15). + +6\. It supports Control Flow Guard (CFG) on Windows (see +). + + +### 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”). + +**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. + +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. + +The Rust compiler does not support shadow or safe stack. There is work +currently ongoing to add support for the sanitizers[40], which may or may +not include support for safe stack7. + +```text +$ 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. 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. + + +## Appendix + +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. + +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). + +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 + +1. D. Hosfelt. “Fearless security: memory safety.” Mozilla Hacks. + . + +2. D. Hosfelt. “Fearless security: thread safety.” Mozilla Hacks. + . + +3. S. Klabnik and C. Nichols. “What Is Ownership?.” The Rust Programming + Language. . + +4. S. Klabnik and C. Nichols. “References and Borrowing.” The Rust + Programming Language. + . + +5. S. Klabnik and C. Nichols. “The Slice Type.” The Rust Programming + Language. . + +6. S. Klabnik and C. Nichols. “Unsafe Rust.” The Rust Programming Language. + . + +7. S. Davidoff. “How Rust’s standard library was vulnerable for years and + nobody noticed.” Medium. + . + +8. “Improper restriction of operations within the bounds of a memory buffer + (CWE-119).” MITRE CWE List. + . + +9. “Concurrency issues (CWE-557).” MITRE CWE List. + . + +10. K. McAllister. “Memory exploit mitigations #15179.” GitHub. + . + +11. K. McAllister. “RFC: Memory exploit mitigation #145.” GitHub. + . + +12. K. McAllister. “RFC: Memory exploit mitigation.” GitHub. + . + +13. D. Micay. “Enable PIE by default on Linux for full ASLR #16340.” GitHub. + . + +14. N. Matsakis. “Integer overflow #560.” GitHub. + . + +15. G. Lehel and N. Matsakis. “Integer overflow.” GitHub. + . + +16. A. Turon. “Tracking issue for integer overflow (RFC 560) #22020.” + GitHub. . + +17. H. Wilson. “Myths and legends about integer overflow in Rust.” Huon on + the Internet. + . + +18. B. Anderson. “Stabilize -C overflow-checks #1535.” GitHub. + . + +19. B. Anderson. “Stable overflow checks.” GitHub. + . + +20. N. Froyd. “Add -C overflow-checks option #40037.” GitHub. + . + +21. R. Á. de Espíndola. “rustc requires executable stack #798.” GitHub. + . + +22. A. Seipp. “Make sure librustrt.so is linked with a non-executable stack. + #1066.” GitHub. . + +23. D. Micay. “Rust binaries should not have an executable stack #5643.” + GitHub. . + +24. D. Micay. “Mark the assembly object stacks as non-executable #5647.” + GitHub. . + +25. A. Clark. “Explicitly disable stack execution on linux and bsd #30859.” + GitHub. . + +26. “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. + . + +29. A. Crichton. “Add \_\_rust\_probestack intrinsic #175.” GitHub. + . + +30. B. Anderson. “Consider applying -Wl,-z,relro or -Wl,-z,relro,-z,now by + default #29877.” GitHub. . + +31. J. Löthberg. “Add support for full RELRO #43170.” GitHub. + . + +32. N. Matsakis. “Allocators in Rust.” Baby Steps. + . + +33. A. Crichton. “RFC: Allow changing the default allocator #1183.” GitHub. + . + +34. A. Crichton. “RFC: Swap out jemalloc.” GitHub. + . + +35. A. Crichton. “Tracking issue for changing the global, default allocator + (RFC 1974) #27389.” GitHub. + . + +36. S. Fackler. “Prepare global allocators for stabilization #1974.” GitHub. + . + +37. A. Crichton. “RFC: Global allocators.” GitHub. + . + +38. B. Anderson. “Switch the default global allocator to System, remove + alloc\_jemalloc, use jemallocator in rustc #36963.” GitHub. + . + +39. A. Crichton. “Remove the alloc\_jemalloc crate #55238.” GitHub. + . + +40. J. Aparicio. 2017. “Tracking issue for sanitizer support #39699.” + . diff --git a/src/doc/rustc/src/images/image1.png b/src/doc/rustc/src/images/image1.png new file mode 100644 index 0000000000000..ee2d3fd4f43c6 Binary files /dev/null and b/src/doc/rustc/src/images/image1.png differ diff --git a/src/doc/rustc/src/images/image2.png b/src/doc/rustc/src/images/image2.png new file mode 100644 index 0000000000000..03061e1f0b12d Binary files /dev/null and b/src/doc/rustc/src/images/image2.png differ diff --git a/src/doc/rustc/src/images/image3.png b/src/doc/rustc/src/images/image3.png new file mode 100644 index 0000000000000..a49e14b5ed222 Binary files /dev/null and b/src/doc/rustc/src/images/image3.png differ diff --git a/src/etc/gdb_providers.py b/src/etc/gdb_providers.py index b5ade324bba10..b74d47a80027a 100644 --- a/src/etc/gdb_providers.py +++ b/src/etc/gdb_providers.py @@ -216,6 +216,10 @@ def cast_to_internal(node): internal_type = lookup_type(internal_type_name) return node.cast(internal_type.pointer()) + if node_ptr.type.name.startswith("alloc::collections::btree::node::BoxedNode<"): + # BACKCOMPAT: rust 1.49 + node_ptr = node_ptr["ptr"] + node_ptr = unwrap_unique_or_non_null(node_ptr) leaf = node_ptr.dereference() keys = leaf["keys"] vals = leaf["vals"] @@ -224,9 +228,8 @@ def cast_to_internal(node): for i in xrange(0, length + 1): if height > 0: - boxed_child_node = edges[i]["value"]["value"] - child_node = unwrap_unique_or_non_null(boxed_child_node["ptr"]) - for child in children_of_node(child_node, height - 1): + child_ptr = edges[i]["value"]["value"] + for child in children_of_node(child_ptr, height - 1): yield child if i < length: # Avoid "Cannot perform pointer math on incomplete type" on zero-sized arrays. @@ -239,9 +242,6 @@ def cast_to_internal(node): if root.type.name.startswith("core::option::Option<"): root = root.cast(gdb.lookup_type(root.type.name[21:-1])) node_ptr = root["node"] - if node_ptr.type.name.startswith("alloc::collections::btree::node::BoxedNode<"): - node_ptr = node_ptr["ptr"] - node_ptr = unwrap_unique_or_non_null(node_ptr) height = root["height"] for child in children_of_node(node_ptr, height): yield child diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index d58a88957df22..e76ca1022a943 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -234,9 +234,8 @@ impl Clean for doctree::Module<'_> { items.extend(self.fns.iter().map(|x| x.clean(cx))); items.extend(self.foreigns.iter().map(|x| x.clean(cx))); items.extend(self.mods.iter().map(|x| x.clean(cx))); - items.extend(self.items.iter().map(|x| x.clean(cx))); + items.extend(self.items.iter().map(|x| x.clean(cx)).flatten()); items.extend(self.traits.iter().map(|x| x.clean(cx))); - items.extend(self.impls.iter().flat_map(|x| x.clean(cx))); items.extend(self.macros.iter().map(|x| x.clean(cx))); items.extend(self.proc_macros.iter().map(|x| x.clean(cx))); @@ -1922,8 +1921,8 @@ impl Clean for hir::BareFnTy<'_> { } } -impl Clean for (&hir::Item<'_>, Option) { - fn clean(&self, cx: &DocContext<'_>) -> Item { +impl Clean> for (&hir::Item<'_>, Option) { + fn clean(&self, cx: &DocContext<'_>) -> Vec { use hir::ItemKind; let (item, renamed) = self; @@ -1977,10 +1976,11 @@ impl Clean for (&hir::Item<'_>, Option) { fields: variant_data.fields().clean(cx), fields_stripped: false, }), + ItemKind::Impl { .. } => return clean_impl(item, cx), _ => unreachable!("not yet converted"), }; - Item::from_def_id_and_parts(def_id, Some(name), kind, cx) + vec![Item::from_def_id_and_parts(def_id, Some(name), kind, cx)] } } @@ -2005,57 +2005,53 @@ impl Clean for ty::ImplPolarity { } } -impl Clean> for doctree::Impl<'_> { - fn clean(&self, cx: &DocContext<'_>) -> Vec { - let mut ret = Vec::new(); - let trait_ = self.trait_.clean(cx); - let items = self.items.iter().map(|ii| ii.clean(cx)).collect::>(); - let def_id = cx.tcx.hir().local_def_id(self.id); - - // If this impl block is an implementation of the Deref trait, then we - // need to try inlining the target's inherent impl blocks as well. - if trait_.def_id() == cx.tcx.lang_items().deref_trait() { - build_deref_target_impls(cx, &items, &mut ret); +fn clean_impl(impl_: &hir::Item<'_>, cx: &DocContext<'_>) -> Vec { + let mut ret = Vec::new(); + let (trait_, items, for_, unsafety, generics) = match &impl_.kind { + hir::ItemKind::Impl { of_trait, items, self_ty, unsafety, generics, .. } => { + (of_trait, items, self_ty, *unsafety, generics) } - - let provided: FxHashSet = trait_ - .def_id() - .map(|did| { - cx.tcx.provided_trait_methods(did).map(|meth| meth.ident.to_string()).collect() - }) - .unwrap_or_default(); - - let for_ = self.for_.clean(cx); - let type_alias = for_.def_id().and_then(|did| match cx.tcx.def_kind(did) { - DefKind::TyAlias => Some(cx.tcx.type_of(did).clean(cx)), - _ => None, + _ => unreachable!(), + }; + let trait_ = trait_.clean(cx); + let items = items.iter().map(|ii| cx.tcx.hir().impl_item(ii.id).clean(cx)).collect::>(); + let def_id = cx.tcx.hir().local_def_id(impl_.hir_id); + + // If this impl block is an implementation of the Deref trait, then we + // need to try inlining the target's inherent impl blocks as well. + if trait_.def_id() == cx.tcx.lang_items().deref_trait() { + build_deref_target_impls(cx, &items, &mut ret); + } + + let provided: FxHashSet = trait_ + .def_id() + .map(|did| cx.tcx.provided_trait_methods(did).map(|meth| meth.ident.to_string()).collect()) + .unwrap_or_default(); + + let for_ = for_.clean(cx); + let type_alias = for_.def_id().and_then(|did| match cx.tcx.def_kind(did) { + DefKind::TyAlias => Some(cx.tcx.type_of(did).clean(cx)), + _ => None, + }); + let make_item = |trait_: Option, for_: Type, items: Vec| { + let kind = ImplItem(Impl { + unsafety, + generics: generics.clean(cx), + provided_trait_methods: provided.clone(), + trait_, + for_, + items, + polarity: Some(cx.tcx.impl_polarity(def_id).clean(cx)), + synthetic: false, + blanket_impl: None, }); - let make_item = |trait_: Option, for_: Type, items: Vec| Item { - name: None, - attrs: self.attrs.clean(cx), - source: self.span.clean(cx), - def_id: def_id.to_def_id(), - visibility: self.vis.clean(cx), - stability: cx.stability(self.id), - deprecation: cx.deprecation(self.id).clean(cx), - kind: ImplItem(Impl { - unsafety: self.unsafety, - generics: self.generics.clean(cx), - provided_trait_methods: provided.clone(), - trait_, - for_, - items, - polarity: Some(cx.tcx.impl_polarity(def_id).clean(cx)), - synthetic: false, - blanket_impl: None, - }), - }; - if let Some(type_alias) = type_alias { - ret.push(make_item(trait_.clone(), type_alias, items.clone())); - } - ret.push(make_item(trait_, for_, items)); - ret + Item::from_hir_id_and_parts(impl_.hir_id, None, kind, cx) + }; + if let Some(type_alias) = type_alias { + ret.push(make_item(trait_.clone(), type_alias, items.clone())); } + ret.push(make_item(trait_, for_, items)); + ret } impl Clean> for doctree::ExternCrate<'_> { diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 413f5bdf5214b..b7cc0f1945911 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -1,4 +1,3 @@ -use rustc_attr as attr; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::{self, Lrc}; use rustc_driver::abort_on_err; @@ -156,21 +155,6 @@ impl<'tcx> DocContext<'tcx> { def_id.as_local().map(|def_id| self.tcx.hir().local_def_id_to_hir_id(def_id)) } } - - crate fn stability(&self, id: HirId) -> Option { - self.tcx - .hir() - .opt_local_def_id(id) - .and_then(|def_id| self.tcx.lookup_stability(def_id.to_def_id())) - .cloned() - } - - crate fn deprecation(&self, id: HirId) -> Option { - self.tcx - .hir() - .opt_local_def_id(id) - .and_then(|def_id| self.tcx.lookup_deprecation(def_id.to_def_id())) - } } /// Creates a new diagnostic `Handler` that can be used to emit warnings and errors. diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs index d56328cc2aa08..4d2fe04123bc2 100644 --- a/src/librustdoc/doctree.rs +++ b/src/librustdoc/doctree.rs @@ -23,7 +23,6 @@ crate struct Module<'hir> { // (item, renamed) crate items: Vec<(&'hir hir::Item<'hir>, Option)>, crate traits: Vec>, - crate impls: Vec>, crate foreigns: Vec>, crate macros: Vec, crate proc_macros: Vec, @@ -44,7 +43,6 @@ impl Module<'hir> { mods: Vec::new(), items: Vec::new(), traits: Vec::new(), - impls: Vec::new(), foreigns: Vec::new(), macros: Vec::new(), proc_macros: Vec::new(), @@ -89,22 +87,6 @@ crate struct Trait<'hir> { crate id: hir::HirId, } -#[derive(Debug)] -crate struct Impl<'hir> { - crate unsafety: hir::Unsafety, - crate polarity: hir::ImplPolarity, - crate defaultness: hir::Defaultness, - crate constness: hir::Constness, - crate generics: &'hir hir::Generics<'hir>, - crate trait_: &'hir Option>, - crate for_: &'hir hir::Ty<'hir>, - crate items: Vec<&'hir hir::ImplItem<'hir>>, - crate attrs: &'hir [ast::Attribute], - crate span: Span, - crate vis: &'hir hir::Visibility<'hir>, - crate id: hir::HirId, -} - crate struct ForeignItem<'hir> { crate id: hir::HirId, crate name: Symbol, diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs index a72860ef0a8fd..285fabdc37230 100644 --- a/src/librustdoc/fold.rs +++ b/src/librustdoc/fold.rs @@ -16,7 +16,7 @@ impl StripItem { crate trait DocFolder: Sized { fn fold_item(&mut self, item: Item) -> Option { - self.fold_item_recur(item) + Some(self.fold_item_recur(item)) } /// don't override! @@ -71,15 +71,12 @@ crate trait DocFolder: Sized { } /// don't override! - fn fold_item_recur(&mut self, item: Item) -> Option { - let Item { attrs, name, source, visibility, def_id, kind, stability, deprecation } = item; - - let kind = match kind { + fn fold_item_recur(&mut self, mut item: Item) -> Item { + item.kind = match item.kind { StrippedItem(box i) => StrippedItem(box self.fold_inner_recur(i)), - _ => self.fold_inner_recur(kind), + _ => self.fold_inner_recur(item.kind), }; - - Some(Item { attrs, name, source, kind, visibility, stability, deprecation, def_id }) + item } fn fold_mod(&mut self, m: Module) -> Module { diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index 917c1a95fdbf5..39b750279ac5b 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -421,55 +421,52 @@ impl DocFolder for Cache { // Once we've recursively found all the generics, hoard off all the // implementations elsewhere. - let ret = self.fold_item_recur(item).and_then(|item| { - if let clean::Item { kind: clean::ImplItem(_), .. } = item { - // Figure out the id of this impl. This may map to a - // primitive rather than always to a struct/enum. - // Note: matching twice to restrict the lifetime of the `i` borrow. - let mut dids = FxHashSet::default(); - if let clean::Item { kind: clean::ImplItem(ref i), .. } = item { - match i.for_ { - clean::ResolvedPath { did, .. } - | clean::BorrowedRef { - type_: box clean::ResolvedPath { did, .. }, .. - } => { - dids.insert(did); - } - ref t => { - let did = t - .primitive_type() - .and_then(|t| self.primitive_locations.get(&t).cloned()); + let item = self.fold_item_recur(item); + let ret = if let clean::Item { kind: clean::ImplItem(_), .. } = item { + // Figure out the id of this impl. This may map to a + // primitive rather than always to a struct/enum. + // Note: matching twice to restrict the lifetime of the `i` borrow. + let mut dids = FxHashSet::default(); + if let clean::Item { kind: clean::ImplItem(ref i), .. } = item { + match i.for_ { + clean::ResolvedPath { did, .. } + | clean::BorrowedRef { type_: box clean::ResolvedPath { did, .. }, .. } => { + dids.insert(did); + } + ref t => { + let did = t + .primitive_type() + .and_then(|t| self.primitive_locations.get(&t).cloned()); - if let Some(did) = did { - dids.insert(did); - } + if let Some(did) = did { + dids.insert(did); } } + } - if let Some(generics) = i.trait_.as_ref().and_then(|t| t.generics()) { - for bound in generics { - if let Some(did) = bound.def_id() { - dids.insert(did); - } + if let Some(generics) = i.trait_.as_ref().and_then(|t| t.generics()) { + for bound in generics { + if let Some(did) = bound.def_id() { + dids.insert(did); } } - } else { - unreachable!() - }; - let impl_item = Impl { impl_item: item }; - if impl_item.trait_did().map_or(true, |d| self.traits.contains_key(&d)) { - for did in dids { - self.impls.entry(did).or_insert(vec![]).push(impl_item.clone()); - } - } else { - let trait_did = impl_item.trait_did().expect("no trait did"); - self.orphan_trait_impls.push((trait_did, dids, impl_item)); } - None } else { - Some(item) + unreachable!() + }; + let impl_item = Impl { impl_item: item }; + if impl_item.trait_did().map_or(true, |d| self.traits.contains_key(&d)) { + for did in dids { + self.impls.entry(did).or_insert(vec![]).push(impl_item.clone()); + } + } else { + let trait_did = impl_item.trait_did().expect("no trait did"); + self.orphan_trait_impls.push((trait_did, dids, impl_item)); } - }); + None + } else { + Some(item) + }; if pushed { self.stack.pop().expect("stack already empty"); diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs index 0f82649409f36..e7b5a90d84df0 100644 --- a/src/librustdoc/html/sources.rs +++ b/src/librustdoc/html/sources.rs @@ -60,7 +60,7 @@ impl<'a> DocFolder for SourceCollector<'a> { } }; } - self.fold_item_recur(item) + Some(self.fold_item_recur(item)) } } diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs index aca218e538165..3f9978c8fca84 100644 --- a/src/librustdoc/passes/calculate_doc_coverage.rs +++ b/src/librustdoc/passes/calculate_doc_coverage.rs @@ -268,6 +268,6 @@ impl<'a, 'b> fold::DocFolder for CoverageCalculator<'a, 'b> { } } - self.fold_item_recur(i) + Some(self.fold_item_recur(i)) } } diff --git a/src/librustdoc/passes/check_code_block_syntax.rs b/src/librustdoc/passes/check_code_block_syntax.rs index a48fa738e3b72..0c76dc571beee 100644 --- a/src/librustdoc/passes/check_code_block_syntax.rs +++ b/src/librustdoc/passes/check_code_block_syntax.rs @@ -105,7 +105,7 @@ impl<'a, 'tcx> DocFolder for SyntaxChecker<'a, 'tcx> { } } - self.fold_item_recur(item) + Some(self.fold_item_recur(item)) } } diff --git a/src/librustdoc/passes/collapse_docs.rs b/src/librustdoc/passes/collapse_docs.rs index 1f9f5c58e5a93..e1ba75baa0fa4 100644 --- a/src/librustdoc/passes/collapse_docs.rs +++ b/src/librustdoc/passes/collapse_docs.rs @@ -23,7 +23,7 @@ struct Collapser; impl fold::DocFolder for Collapser { fn fold_item(&mut self, mut i: Item) -> Option { i.attrs.collapse_doc_comments(); - self.fold_item_recur(i) + Some(self.fold_item_recur(i)) } } diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index fd09ba04b3db9..6aa46b24a0e96 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -858,7 +858,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { // we don't display docs on `extern crate` items anyway, so don't process them. clean::ExternCrateItem(..) => { debug!("ignoring extern crate item {:?}", item.def_id); - return self.fold_item_recur(item); + return Some(self.fold_item_recur(item)); } clean::ImportItem(Import { kind: clean::ImportKind::Simple(ref name, ..), .. }) => { Some(name.clone()) @@ -958,7 +958,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { } } - if item.is_mod() { + Some(if item.is_mod() { if !item.attrs.inner_docs { self.mod_ids.push(item.def_id); } @@ -968,7 +968,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { ret } else { self.fold_item_recur(item) - } + }) } } @@ -1022,7 +1022,7 @@ impl LinkCollector<'_, '_> { (link.trim(), None) }; - if path_str.contains(|ch: char| !(ch.is_alphanumeric() || ":_<>, ".contains(ch))) { + if path_str.contains(|ch: char| !(ch.is_alphanumeric() || ":_<>, !".contains(ch))) { return None; } diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs index 2946db1f46206..4c3defabc3294 100644 --- a/src/librustdoc/passes/collect_trait_impls.rs +++ b/src/librustdoc/passes/collect_trait_impls.rs @@ -133,7 +133,7 @@ impl<'a, 'tcx> DocFolder for SyntheticImplCollector<'a, 'tcx> { } } - self.fold_item_recur(i) + Some(self.fold_item_recur(i)) } } @@ -152,7 +152,7 @@ impl DocFolder for ItemCollector { fn fold_item(&mut self, i: Item) -> Option { self.items.insert(i.def_id); - self.fold_item_recur(i) + Some(self.fold_item_recur(i)) } } diff --git a/src/librustdoc/passes/doc_test_lints.rs b/src/librustdoc/passes/doc_test_lints.rs index 60fe8080f56b4..299a73c8a0112 100644 --- a/src/librustdoc/passes/doc_test_lints.rs +++ b/src/librustdoc/passes/doc_test_lints.rs @@ -41,7 +41,7 @@ impl<'a, 'tcx> DocFolder for PrivateItemDocTestLinter<'a, 'tcx> { look_for_tests(&cx, &dox, &item); - self.fold_item_recur(item) + Some(self.fold_item_recur(item)) } } diff --git a/src/librustdoc/passes/html_tags.rs b/src/librustdoc/passes/html_tags.rs index 70748633117fb..a7a1ba1118d1f 100644 --- a/src/librustdoc/passes/html_tags.rs +++ b/src/librustdoc/passes/html_tags.rs @@ -178,7 +178,7 @@ impl<'a, 'tcx> DocFolder for InvalidHtmlTagsLinter<'a, 'tcx> { Some(hir_id) => hir_id, None => { // If non-local, no need to check anything. - return self.fold_item_recur(item); + return Some(self.fold_item_recur(item)); } }; let dox = item.attrs.collapsed_doc_value().unwrap_or_default(); @@ -223,6 +223,6 @@ impl<'a, 'tcx> DocFolder for InvalidHtmlTagsLinter<'a, 'tcx> { } } - self.fold_item_recur(item) + Some(self.fold_item_recur(item)) } } diff --git a/src/librustdoc/passes/non_autolinks.rs b/src/librustdoc/passes/non_autolinks.rs index c9c49968b93e1..1f411b997f802 100644 --- a/src/librustdoc/passes/non_autolinks.rs +++ b/src/librustdoc/passes/non_autolinks.rs @@ -68,7 +68,7 @@ impl<'a, 'tcx> DocFolder for NonAutolinksLinter<'a, 'tcx> { Some(hir_id) => hir_id, None => { // If non-local, no need to check anything. - return self.fold_item_recur(item); + return Some(self.fold_item_recur(item)); } }; let dox = item.attrs.collapsed_doc_value().unwrap_or_default(); @@ -133,6 +133,6 @@ impl<'a, 'tcx> DocFolder for NonAutolinksLinter<'a, 'tcx> { } } - self.fold_item_recur(item) + Some(self.fold_item_recur(item)) } } diff --git a/src/librustdoc/passes/propagate_doc_cfg.rs b/src/librustdoc/passes/propagate_doc_cfg.rs index fbfc693c5347d..6722d7c2fc9fe 100644 --- a/src/librustdoc/passes/propagate_doc_cfg.rs +++ b/src/librustdoc/passes/propagate_doc_cfg.rs @@ -39,6 +39,6 @@ impl DocFolder for CfgPropagator { let result = self.fold_item_recur(item); self.parent_cfg = old_parent_cfg; - result + Some(result) } } diff --git a/src/librustdoc/passes/strip_hidden.rs b/src/librustdoc/passes/strip_hidden.rs index 6da753ea6e695..6b59eb8cf288a 100644 --- a/src/librustdoc/passes/strip_hidden.rs +++ b/src/librustdoc/passes/strip_hidden.rs @@ -47,7 +47,7 @@ impl<'a> DocFolder for Stripper<'a> { // strip things like impl methods but when doing so // we must not add any items to the `retained` set. let old = mem::replace(&mut self.update_retained, false); - let ret = StripItem(self.fold_item_recur(i).unwrap()).strip(); + let ret = StripItem(self.fold_item_recur(i)).strip(); self.update_retained = old; return ret; } @@ -58,6 +58,6 @@ impl<'a> DocFolder for Stripper<'a> { self.retained.insert(i.def_id); } } - self.fold_item_recur(i) + Some(self.fold_item_recur(i)) } } diff --git a/src/librustdoc/passes/stripper.rs b/src/librustdoc/passes/stripper.rs index eb5a61a9d202a..444fd593ec9c9 100644 --- a/src/librustdoc/passes/stripper.rs +++ b/src/librustdoc/passes/stripper.rs @@ -22,7 +22,7 @@ impl<'a> DocFolder for Stripper<'a> { let old = mem::replace(&mut self.update_retained, false); let ret = self.fold_item_recur(i); self.update_retained = old; - return ret; + return Some(ret); } // These items can all get re-exported clean::OpaqueTyItem(..) @@ -59,7 +59,7 @@ impl<'a> DocFolder for Stripper<'a> { if i.def_id.is_local() && !i.visibility.is_public() { debug!("Stripper: stripping module {:?}", i.name); let old = mem::replace(&mut self.update_retained, false); - let ret = StripItem(self.fold_item_recur(i).unwrap()).strip(); + let ret = StripItem(self.fold_item_recur(i)).strip(); self.update_retained = old; return ret; } @@ -107,12 +107,10 @@ impl<'a> DocFolder for Stripper<'a> { self.fold_item_recur(i) }; - if let Some(ref i) = i { - if self.update_retained { - self.retained.insert(i.def_id); - } + if self.update_retained { + self.retained.insert(i.def_id); } - i + Some(i) } } @@ -153,7 +151,7 @@ impl<'a> DocFolder for ImplStripper<'a> { } } } - self.fold_item_recur(i) + Some(self.fold_item_recur(i)) } } @@ -164,7 +162,7 @@ impl DocFolder for ImportStripper { fn fold_item(&mut self, i: Item) -> Option { match i.kind { clean::ExternCrateItem(..) | clean::ImportItem(..) if !i.visibility.is_public() => None, - _ => self.fold_item_recur(i), + _ => Some(self.fold_item_recur(i)), } } } diff --git a/src/librustdoc/passes/unindent_comments.rs b/src/librustdoc/passes/unindent_comments.rs index eb2f066bbdebb..d0345d1e48cb5 100644 --- a/src/librustdoc/passes/unindent_comments.rs +++ b/src/librustdoc/passes/unindent_comments.rs @@ -23,7 +23,7 @@ struct CommentCleaner; impl fold::DocFolder for CommentCleaner { fn fold_item(&mut self, mut i: Item) -> Option { i.attrs.unindent_doc_comments(); - self.fold_item_recur(i) + Some(self.fold_item_recur(i)) } } diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index c55e5f7690c14..37050a57ca017 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -401,37 +401,11 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { }; om.traits.push(t); } - hir::ItemKind::Impl { - unsafety, - polarity, - defaultness, - constness, - defaultness_span: _, - ref generics, - ref of_trait, - self_ty, - ref items, - } => { + hir::ItemKind::Impl { ref of_trait, .. } => { // Don't duplicate impls when inlining or if it's implementing a trait, we'll pick // them up regardless of where they're located. if !self.inlining && of_trait.is_none() { - let items = - items.iter().map(|item| self.cx.tcx.hir().impl_item(item.id)).collect(); - let i = Impl { - unsafety, - polarity, - defaultness, - constness, - generics, - trait_: of_trait, - for_: self_ty, - items, - attrs: &item.attrs, - id: item.hir_id, - span: item.span, - vis: &item.vis, - }; - om.impls.push(i); + om.items.push((item, None)); } } } diff --git a/src/test/codegen/fewer-names.rs b/src/test/codegen/fewer-names.rs new file mode 100644 index 0000000000000..53a926d49efe7 --- /dev/null +++ b/src/test/codegen/fewer-names.rs @@ -0,0 +1,20 @@ +// no-system-llvm +// compile-flags: -Coverflow-checks=no -O +// revisions: YES NO +// [YES]compile-flags: -Zfewer-names=yes +// [NO] compile-flags: -Zfewer-names=no +#![crate_type = "lib"] + +#[no_mangle] +pub fn sum(x: u32, y: u32) -> u32 { +// YES-LABEL: define i32 @sum(i32 %0, i32 %1) +// YES-NEXT: %3 = add i32 %1, %0 +// YES-NEXT: ret i32 %3 + +// NO-LABEL: define i32 @sum(i32 %x, i32 %y) +// NO-NEXT: start: +// NO-NEXT: %z = add i32 %y, %x +// NO-NEXT: ret i32 %z + let z = x + y; + z +} diff --git a/src/test/rustdoc-ui/intra-link-errors.stderr b/src/test/rustdoc-ui/intra-link-errors.stderr index 31e7fc48afde5..be98cac94ece7 100644 --- a/src/test/rustdoc-ui/intra-link-errors.stderr +++ b/src/test/rustdoc-ui/intra-link-errors.stderr @@ -106,6 +106,15 @@ LL | /// [S!] | this link resolves to the struct `S`, which is not in the macro namespace | help: to link to the struct, prefix with `struct@`: `struct@S` +error: unresolved link to `S::h` + --> $DIR/intra-link-errors.rs:78:6 + | +LL | /// [type@S::h] + | ^^^^^^^^^ + | | + | this link resolves to the associated function `h`, which is not in the type namespace + | help: to link to the associated function, add parentheses: `S::h()` + error: unresolved link to `T::g` --> $DIR/intra-link-errors.rs:86:6 | @@ -121,15 +130,6 @@ error: unresolved link to `T::h` LL | /// [T::h!] | ^^^^^ the trait `T` has no macro named `h` -error: unresolved link to `S::h` - --> $DIR/intra-link-errors.rs:78:6 - | -LL | /// [type@S::h] - | ^^^^^^^^^ - | | - | this link resolves to the associated function `h`, which is not in the type namespace - | help: to link to the associated function, add parentheses: `S::h()` - error: unresolved link to `m` --> $DIR/intra-link-errors.rs:98:6 | diff --git a/src/test/rustdoc/intra-doc-link-generic-params.rs b/src/test/rustdoc/intra-doc-link-generic-params.rs index 7d7289437ff8a..1de6410f10c43 100644 --- a/src/test/rustdoc/intra-doc-link-generic-params.rs +++ b/src/test/rustdoc/intra-doc-link-generic-params.rs @@ -15,8 +15,11 @@ // @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/core/option/enum.Option.html"]' 'with the generic, Option' //! We should also try linking to [`Result`]; it has *two* generics! +//! And [`Result`] and [`Result`]. //! // @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/core/result/enum.Result.html"]' 'Result' +// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/core/result/enum.Result.html"]' 'Result' +// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/core/result/enum.Result.html"]' 'Result' //! Now let's test a trickier case: [`Vec::::new`], or you could write it //! [with parentheses as `Vec::::new()`][Vec::::new()]. diff --git a/src/test/ui/const-generics/array-size-in-generic-struct-param.min.stderr b/src/test/ui/const-generics/array-size-in-generic-struct-param.min.stderr index cfaacf7a5be33..73c9ea59c955b 100644 --- a/src/test/ui/const-generics/array-size-in-generic-struct-param.min.stderr +++ b/src/test/ui/const-generics/array-size-in-generic-struct-param.min.stderr @@ -5,6 +5,7 @@ LL | struct ArithArrayLen([u32; 0 + N]); | ^ cannot perform const operation using `N` | = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/array-size-in-generic-struct-param.rs:20:15 @@ -13,6 +14,7 @@ LL | arr: [u8; CFG.arr_size], | ^^^ cannot perform const operation using `CFG` | = help: const parameters may only be used as standalone arguments, i.e. `CFG` + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: `Config` is forbidden as the type of a const generic parameter --> $DIR/array-size-in-generic-struct-param.rs:18:21 @@ -21,7 +23,7 @@ LL | struct B { | ^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = note: more complex types are supported with `#[feature(const_generics)]` + = help: more complex types are supported with `#[feature(const_generics)]` error: aborting due to 3 previous errors diff --git a/src/test/ui/const-generics/const-arg-in-const-arg.min.stderr b/src/test/ui/const-generics/const-arg-in-const-arg.min.stderr index 7dfe250b78e00..042fa9ad958b1 100644 --- a/src/test/ui/const-generics/const-arg-in-const-arg.min.stderr +++ b/src/test/ui/const-generics/const-arg-in-const-arg.min.stderr @@ -5,6 +5,7 @@ LL | let _: [u8; foo::()]; | ^ cannot perform const operation using `T` | = note: type parameters may not be used in const expressions + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/const-arg-in-const-arg.rs:15:23 @@ -13,6 +14,7 @@ LL | let _: [u8; bar::()]; | ^ cannot perform const operation using `N` | = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/const-arg-in-const-arg.rs:25:23 @@ -21,6 +23,7 @@ LL | let _ = [0; bar::()]; | ^ cannot perform const operation using `N` | = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/const-arg-in-const-arg.rs:30:24 @@ -29,6 +32,7 @@ LL | let _: Foo<{ foo::() }>; | ^ cannot perform const operation using `T` | = note: type parameters may not be used in const expressions + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/const-arg-in-const-arg.rs:31:24 @@ -37,6 +41,7 @@ LL | let _: Foo<{ bar::() }>; | ^ cannot perform const operation using `N` | = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/const-arg-in-const-arg.rs:36:27 @@ -45,6 +50,7 @@ LL | let _ = Foo::<{ foo::() }>; | ^ cannot perform const operation using `T` | = note: type parameters may not be used in const expressions + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/const-arg-in-const-arg.rs:37:27 @@ -53,6 +59,7 @@ LL | let _ = Foo::<{ bar::() }>; | ^ cannot perform const operation using `N` | = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error[E0658]: a non-static lifetime is not allowed in a `const` --> $DIR/const-arg-in-const-arg.rs:16:23 diff --git a/src/test/ui/const-generics/const-argument-if-length.min.stderr b/src/test/ui/const-generics/const-argument-if-length.min.stderr index bce701ade8651..8a1074392a5cb 100644 --- a/src/test/ui/const-generics/const-argument-if-length.min.stderr +++ b/src/test/ui/const-generics/const-argument-if-length.min.stderr @@ -5,6 +5,7 @@ LL | pad: [u8; is_zst::()], | ^ cannot perform const operation using `T` | = note: type parameters may not be used in const expressions + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error[E0277]: the size for values of type `T` cannot be known at compilation time --> $DIR/const-argument-if-length.rs:17:12 diff --git a/src/test/ui/const-generics/const-param-before-other-params.min.stderr b/src/test/ui/const-generics/const-param-before-other-params.min.stderr index c7e6d1be42161..354c6d0615f1b 100644 --- a/src/test/ui/const-generics/const-param-before-other-params.min.stderr +++ b/src/test/ui/const-generics/const-param-before-other-params.min.stderr @@ -17,7 +17,7 @@ LL | fn bar(_: &'a ()) { | ^^ | = note: the only supported types are integers, `bool` and `char` - = note: more complex types are supported with `#[feature(const_generics)]` + = help: more complex types are supported with `#[feature(const_generics)]` error: `()` is forbidden as the type of a const generic parameter --> $DIR/const-param-before-other-params.rs:11:17 @@ -26,7 +26,7 @@ LL | fn foo(_: &T) {} | ^^ | = note: the only supported types are integers, `bool` and `char` - = note: more complex types are supported with `#[feature(const_generics)]` + = help: more complex types are supported with `#[feature(const_generics)]` error: aborting due to 4 previous errors diff --git a/src/test/ui/const-generics/const-param-elided-lifetime.min.stderr b/src/test/ui/const-generics/const-param-elided-lifetime.min.stderr index 81dbaee0ec514..ed30182690a7a 100644 --- a/src/test/ui/const-generics/const-param-elided-lifetime.min.stderr +++ b/src/test/ui/const-generics/const-param-elided-lifetime.min.stderr @@ -35,7 +35,7 @@ LL | struct A; | ^^^ | = note: the only supported types are integers, `bool` and `char` - = note: more complex types are supported with `#[feature(const_generics)]` + = help: more complex types are supported with `#[feature(const_generics)]` error: `&'static u8` is forbidden as the type of a const generic parameter --> $DIR/const-param-elided-lifetime.rs:16:15 @@ -44,7 +44,7 @@ LL | impl A { | ^^^ | = note: the only supported types are integers, `bool` and `char` - = note: more complex types are supported with `#[feature(const_generics)]` + = help: more complex types are supported with `#[feature(const_generics)]` error: `&'static u8` is forbidden as the type of a const generic parameter --> $DIR/const-param-elided-lifetime.rs:24:15 @@ -53,7 +53,7 @@ LL | impl B for A {} | ^^^ | = note: the only supported types are integers, `bool` and `char` - = note: more complex types are supported with `#[feature(const_generics)]` + = help: more complex types are supported with `#[feature(const_generics)]` error: `&'static u8` is forbidden as the type of a const generic parameter --> $DIR/const-param-elided-lifetime.rs:28:17 @@ -62,7 +62,7 @@ LL | fn bar() {} | ^^^ | = note: the only supported types are integers, `bool` and `char` - = note: more complex types are supported with `#[feature(const_generics)]` + = help: more complex types are supported with `#[feature(const_generics)]` error: `&'static u8` is forbidden as the type of a const generic parameter --> $DIR/const-param-elided-lifetime.rs:19:21 @@ -71,7 +71,7 @@ LL | fn foo(&self) {} | ^^^ | = note: the only supported types are integers, `bool` and `char` - = note: more complex types are supported with `#[feature(const_generics)]` + = help: more complex types are supported with `#[feature(const_generics)]` error: aborting due to 10 previous errors diff --git a/src/test/ui/const-generics/const-param-type-depends-on-const-param.min.stderr b/src/test/ui/const-generics/const-param-type-depends-on-const-param.min.stderr index b00a160787629..6b7a218ada5dd 100644 --- a/src/test/ui/const-generics/const-param-type-depends-on-const-param.min.stderr +++ b/src/test/ui/const-generics/const-param-type-depends-on-const-param.min.stderr @@ -17,7 +17,7 @@ LL | pub struct Dependent([(); N]); | ^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = note: more complex types are supported with `#[feature(const_generics)]` + = help: more complex types are supported with `#[feature(const_generics)]` error: `[u8; _]` is forbidden as the type of a const generic parameter --> $DIR/const-param-type-depends-on-const-param.rs:16:35 @@ -26,7 +26,7 @@ LL | pub struct SelfDependent; | ^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = note: more complex types are supported with `#[feature(const_generics)]` + = help: more complex types are supported with `#[feature(const_generics)]` error: aborting due to 4 previous errors diff --git a/src/test/ui/const-generics/const_evaluatable_checked/feature-gate-const_evaluatable_checked.min.stderr b/src/test/ui/const-generics/const_evaluatable_checked/feature-gate-const_evaluatable_checked.min.stderr index 359c2d2a22f02..573bc66b7c7e8 100644 --- a/src/test/ui/const-generics/const_evaluatable_checked/feature-gate-const_evaluatable_checked.min.stderr +++ b/src/test/ui/const-generics/const_evaluatable_checked/feature-gate-const_evaluatable_checked.min.stderr @@ -5,6 +5,7 @@ LL | type Arr = [u8; N - 1]; | ^ cannot perform const operation using `N` | = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: aborting due to previous error diff --git a/src/test/ui/const-generics/const_evaluatable_checked/simple.min.stderr b/src/test/ui/const-generics/const_evaluatable_checked/simple.min.stderr index 46485262cc46e..d476a7eb6455c 100644 --- a/src/test/ui/const-generics/const_evaluatable_checked/simple.min.stderr +++ b/src/test/ui/const-generics/const_evaluatable_checked/simple.min.stderr @@ -5,6 +5,7 @@ LL | fn test() -> [u8; N - 1] where [u8; N - 1]: Default { | ^ cannot perform const operation using `N` | = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/simple.rs:8:35 @@ -13,6 +14,7 @@ LL | fn test() -> [u8; N - 1] where [u8; N - 1]: Default { | ^ cannot perform const operation using `N` | = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: aborting due to 2 previous errors diff --git a/src/test/ui/const-generics/const_evaluatable_checked/simple_fail.min.stderr b/src/test/ui/const-generics/const_evaluatable_checked/simple_fail.min.stderr index 981d993f58976..bd81e0bc5a8cf 100644 --- a/src/test/ui/const-generics/const_evaluatable_checked/simple_fail.min.stderr +++ b/src/test/ui/const-generics/const_evaluatable_checked/simple_fail.min.stderr @@ -5,6 +5,7 @@ LL | type Arr = [u8; N - 1]; | ^ cannot perform const operation using `N` | = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: aborting due to previous error diff --git a/src/test/ui/const-generics/different_byref.min.stderr b/src/test/ui/const-generics/different_byref.min.stderr index 050b28abe5088..e5b393ffe99eb 100644 --- a/src/test/ui/const-generics/different_byref.min.stderr +++ b/src/test/ui/const-generics/different_byref.min.stderr @@ -5,7 +5,7 @@ LL | struct Const {} | ^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = note: more complex types are supported with `#[feature(const_generics)]` + = help: more complex types are supported with `#[feature(const_generics)]` error: aborting due to previous error diff --git a/src/test/ui/const-generics/forbid-non-structural_match-types.min.stderr b/src/test/ui/const-generics/forbid-non-structural_match-types.min.stderr index 40d8f44cafc04..014200178b9ca 100644 --- a/src/test/ui/const-generics/forbid-non-structural_match-types.min.stderr +++ b/src/test/ui/const-generics/forbid-non-structural_match-types.min.stderr @@ -5,7 +5,7 @@ LL | struct B; // ok | ^ | = note: the only supported types are integers, `bool` and `char` - = note: more complex types are supported with `#[feature(const_generics)]` + = help: more complex types are supported with `#[feature(const_generics)]` error: `C` is forbidden as the type of a const generic parameter --> $DIR/forbid-non-structural_match-types.rs:15:19 @@ -14,7 +14,7 @@ LL | struct D; | ^ | = note: the only supported types are integers, `bool` and `char` - = note: more complex types are supported with `#[feature(const_generics)]` + = help: more complex types are supported with `#[feature(const_generics)]` error[E0741]: `C` must be annotated with `#[derive(PartialEq, Eq)]` to be used as the type of a const parameter --> $DIR/forbid-non-structural_match-types.rs:15:19 diff --git a/src/test/ui/const-generics/generic-function-call-in-array-length.min.stderr b/src/test/ui/const-generics/generic-function-call-in-array-length.min.stderr index 84449018e4609..526f98fe8cd4f 100644 --- a/src/test/ui/const-generics/generic-function-call-in-array-length.min.stderr +++ b/src/test/ui/const-generics/generic-function-call-in-array-length.min.stderr @@ -5,6 +5,7 @@ LL | fn bar() -> [u32; foo(N)] { | ^ cannot perform const operation using `N` | = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/generic-function-call-in-array-length.rs:12:13 @@ -13,6 +14,7 @@ LL | [0; foo(N)] | ^ cannot perform const operation using `N` | = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: aborting due to 2 previous errors diff --git a/src/test/ui/const-generics/generic-sum-in-array-length.min.stderr b/src/test/ui/const-generics/generic-sum-in-array-length.min.stderr index d3f7143327ead..e531b612b5609 100644 --- a/src/test/ui/const-generics/generic-sum-in-array-length.min.stderr +++ b/src/test/ui/const-generics/generic-sum-in-array-length.min.stderr @@ -5,6 +5,7 @@ LL | fn foo(bar: [usize; A + B]) {} | ^ cannot perform const operation using `A` | = help: const parameters may only be used as standalone arguments, i.e. `A` + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/generic-sum-in-array-length.rs:7:57 @@ -13,6 +14,7 @@ LL | fn foo(bar: [usize; A + B]) {} | ^ cannot perform const operation using `B` | = help: const parameters may only be used as standalone arguments, i.e. `B` + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: aborting due to 2 previous errors diff --git a/src/test/ui/const-generics/intrinsics-type_name-as-const-argument.min.stderr b/src/test/ui/const-generics/intrinsics-type_name-as-const-argument.min.stderr index 20a8d9fdaab53..02467df193c39 100644 --- a/src/test/ui/const-generics/intrinsics-type_name-as-const-argument.min.stderr +++ b/src/test/ui/const-generics/intrinsics-type_name-as-const-argument.min.stderr @@ -5,6 +5,7 @@ LL | T: Trait<{std::intrinsics::type_name::()}> | ^ cannot perform const operation using `T` | = note: type parameters may not be used in const expressions + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: `&'static str` is forbidden as the type of a const generic parameter --> $DIR/intrinsics-type_name-as-const-argument.rs:10:22 @@ -13,7 +14,7 @@ LL | trait Trait {} | ^^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = note: more complex types are supported with `#[feature(const_generics)]` + = help: more complex types are supported with `#[feature(const_generics)]` error: aborting due to 2 previous errors diff --git a/src/test/ui/const-generics/issue-61522-array-len-succ.min.stderr b/src/test/ui/const-generics/issue-61522-array-len-succ.min.stderr index 526807f0a2474..2eaef95c23216 100644 --- a/src/test/ui/const-generics/issue-61522-array-len-succ.min.stderr +++ b/src/test/ui/const-generics/issue-61522-array-len-succ.min.stderr @@ -5,6 +5,7 @@ LL | pub struct MyArray([u8; COUNT + 1]); | ^^^^^ cannot perform const operation using `COUNT` | = help: const parameters may only be used as standalone arguments, i.e. `COUNT` + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/issue-61522-array-len-succ.rs:12:30 @@ -13,6 +14,7 @@ LL | fn inner(&self) -> &[u8; COUNT + 1] { | ^^^^^ cannot perform const operation using `COUNT` | = help: const parameters may only be used as standalone arguments, i.e. `COUNT` + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: aborting due to 2 previous errors diff --git a/src/test/ui/const-generics/issue-66596-impl-trait-for-str-const-arg.min.stderr b/src/test/ui/const-generics/issue-66596-impl-trait-for-str-const-arg.min.stderr index 786ded3c2fe42..1c2e7e069a181 100644 --- a/src/test/ui/const-generics/issue-66596-impl-trait-for-str-const-arg.min.stderr +++ b/src/test/ui/const-generics/issue-66596-impl-trait-for-str-const-arg.min.stderr @@ -5,7 +5,7 @@ LL | trait Trait { | ^^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = note: more complex types are supported with `#[feature(const_generics)]` + = help: more complex types are supported with `#[feature(const_generics)]` error: aborting due to previous error diff --git a/src/test/ui/const-generics/issue-67375.min.stderr b/src/test/ui/const-generics/issue-67375.min.stderr index 3c344edbf1d15..da96b5374a57d 100644 --- a/src/test/ui/const-generics/issue-67375.min.stderr +++ b/src/test/ui/const-generics/issue-67375.min.stderr @@ -5,6 +5,7 @@ LL | inner: [(); { [|_: &T| {}; 0].len() }], | ^ cannot perform const operation using `T` | = note: type parameters may not be used in const expressions + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error[E0392]: parameter `T` is never used --> $DIR/issue-67375.rs:7:12 diff --git a/src/test/ui/const-generics/issue-67945-1.min.stderr b/src/test/ui/const-generics/issue-67945-1.min.stderr index 804236c30bd81..8fea130baa57c 100644 --- a/src/test/ui/const-generics/issue-67945-1.min.stderr +++ b/src/test/ui/const-generics/issue-67945-1.min.stderr @@ -5,6 +5,7 @@ LL | let x: S = MaybeUninit::uninit(); | ^ cannot perform const operation using `S` | = note: type parameters may not be used in const expressions + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/issue-67945-1.rs:17:45 @@ -13,6 +14,7 @@ LL | let b = &*(&x as *const _ as *const S); | ^ cannot perform const operation using `S` | = note: type parameters may not be used in const expressions + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error[E0392]: parameter `S` is never used --> $DIR/issue-67945-1.rs:11:12 diff --git a/src/test/ui/const-generics/issue-67945-2.min.stderr b/src/test/ui/const-generics/issue-67945-2.min.stderr index 2de942c1220cd..50633772b75a9 100644 --- a/src/test/ui/const-generics/issue-67945-2.min.stderr +++ b/src/test/ui/const-generics/issue-67945-2.min.stderr @@ -5,6 +5,7 @@ LL | let x: S = MaybeUninit::uninit(); | ^ cannot perform const operation using `S` | = note: type parameters may not be used in const expressions + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/issue-67945-2.rs:15:45 @@ -13,6 +14,7 @@ LL | let b = &*(&x as *const _ as *const S); | ^ cannot perform const operation using `S` | = note: type parameters may not be used in const expressions + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error[E0392]: parameter `S` is never used --> $DIR/issue-67945-2.rs:9:12 diff --git a/src/test/ui/const-generics/issues/issue-61747.min.stderr b/src/test/ui/const-generics/issues/issue-61747.min.stderr index b176f9d1c75aa..1de9e71b6eb00 100644 --- a/src/test/ui/const-generics/issues/issue-61747.min.stderr +++ b/src/test/ui/const-generics/issues/issue-61747.min.stderr @@ -5,6 +5,7 @@ LL | fn successor() -> Const<{C + 1}> { | ^ cannot perform const operation using `C` | = help: const parameters may only be used as standalone arguments, i.e. `C` + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: aborting due to previous error diff --git a/src/test/ui/const-generics/issues/issue-61935.min.stderr b/src/test/ui/const-generics/issues/issue-61935.min.stderr index 9e31466259fd9..b1d92056a544c 100644 --- a/src/test/ui/const-generics/issues/issue-61935.min.stderr +++ b/src/test/ui/const-generics/issues/issue-61935.min.stderr @@ -5,6 +5,7 @@ LL | Self:FooImpl<{N==0}> | ^ cannot perform const operation using `N` | = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: aborting due to previous error diff --git a/src/test/ui/const-generics/issues/issue-62220.min.stderr b/src/test/ui/const-generics/issues/issue-62220.min.stderr index 3bd127ee74a59..b338cdb87e1e5 100644 --- a/src/test/ui/const-generics/issues/issue-62220.min.stderr +++ b/src/test/ui/const-generics/issues/issue-62220.min.stderr @@ -5,6 +5,7 @@ LL | pub type TruncatedVector = Vector; | ^ cannot perform const operation using `N` | = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: aborting due to previous error diff --git a/src/test/ui/const-generics/issues/issue-62456.min.stderr b/src/test/ui/const-generics/issues/issue-62456.min.stderr index c73f62a4a07d9..a4b501a7bb109 100644 --- a/src/test/ui/const-generics/issues/issue-62456.min.stderr +++ b/src/test/ui/const-generics/issues/issue-62456.min.stderr @@ -5,6 +5,7 @@ LL | let _ = [0u64; N + 1]; | ^ cannot perform const operation using `N` | = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: aborting due to previous error diff --git a/src/test/ui/const-generics/issues/issue-62579-no-match.min.stderr b/src/test/ui/const-generics/issues/issue-62579-no-match.min.stderr index 6903b20fad63c..5117e20d6266b 100644 --- a/src/test/ui/const-generics/issues/issue-62579-no-match.min.stderr +++ b/src/test/ui/const-generics/issues/issue-62579-no-match.min.stderr @@ -5,7 +5,7 @@ LL | fn foo() -> bool { | ^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = note: more complex types are supported with `#[feature(const_generics)]` + = help: more complex types are supported with `#[feature(const_generics)]` error: aborting due to previous error diff --git a/src/test/ui/const-generics/issues/issue-62878.min.stderr b/src/test/ui/const-generics/issues/issue-62878.min.stderr index 34edd09b51565..9f95e5d88623e 100644 --- a/src/test/ui/const-generics/issues/issue-62878.min.stderr +++ b/src/test/ui/const-generics/issues/issue-62878.min.stderr @@ -11,7 +11,7 @@ LL | fn foo() {} | ^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = note: more complex types are supported with `#[feature(const_generics)]` + = help: more complex types are supported with `#[feature(const_generics)]` error: aborting due to 2 previous errors diff --git a/src/test/ui/const-generics/issues/issue-63322-forbid-dyn.min.stderr b/src/test/ui/const-generics/issues/issue-63322-forbid-dyn.min.stderr index e6d9fb7a24683..5dbfdc6d652b6 100644 --- a/src/test/ui/const-generics/issues/issue-63322-forbid-dyn.min.stderr +++ b/src/test/ui/const-generics/issues/issue-63322-forbid-dyn.min.stderr @@ -5,7 +5,7 @@ LL | fn test() { | ^^^^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = note: more complex types are supported with `#[feature(const_generics)]` + = help: more complex types are supported with `#[feature(const_generics)]` error[E0741]: `&'static (dyn A + 'static)` must be annotated with `#[derive(PartialEq, Eq)]` to be used as the type of a const parameter --> $DIR/issue-63322-forbid-dyn.rs:10:18 diff --git a/src/test/ui/const-generics/issues/issue-64494.min.stderr b/src/test/ui/const-generics/issues/issue-64494.min.stderr index 8b02fd108bd5b..681166b1d2b94 100644 --- a/src/test/ui/const-generics/issues/issue-64494.min.stderr +++ b/src/test/ui/const-generics/issues/issue-64494.min.stderr @@ -5,6 +5,7 @@ LL | impl MyTrait for T where Is<{T::VAL == 5}>: True {} | ^^^^^^ cannot perform const operation using `T` | = note: type parameters may not be used in const expressions + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/issue-64494.rs:19:38 @@ -13,6 +14,7 @@ LL | impl MyTrait for T where Is<{T::VAL == 6}>: True {} | ^^^^^^ cannot perform const operation using `T` | = note: type parameters may not be used in const expressions + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error[E0119]: conflicting implementations of trait `MyTrait`: --> $DIR/issue-64494.rs:19:1 diff --git a/src/test/ui/const-generics/issues/issue-66205.min.stderr b/src/test/ui/const-generics/issues/issue-66205.min.stderr index 282f72be6da6e..ecd96ac37e404 100644 --- a/src/test/ui/const-generics/issues/issue-66205.min.stderr +++ b/src/test/ui/const-generics/issues/issue-66205.min.stderr @@ -5,6 +5,7 @@ LL | fact::<{ N - 1 }>(); | ^ cannot perform const operation using `N` | = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: aborting due to previous error diff --git a/src/test/ui/const-generics/issues/issue-68366.min.stderr b/src/test/ui/const-generics/issues/issue-68366.min.stderr index b900a0d096ac2..acaf4a33ee0a8 100644 --- a/src/test/ui/const-generics/issues/issue-68366.min.stderr +++ b/src/test/ui/const-generics/issues/issue-68366.min.stderr @@ -5,6 +5,7 @@ LL | impl Collatz<{Some(N)}> {} | ^ cannot perform const operation using `N` | = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error[E0207]: the const parameter `N` is not constrained by the impl trait, self type, or predicates --> $DIR/issue-68366.rs:12:13 diff --git a/src/test/ui/const-generics/issues/issue-68615-adt.min.stderr b/src/test/ui/const-generics/issues/issue-68615-adt.min.stderr index 81c8f4392c735..59653114a6b61 100644 --- a/src/test/ui/const-generics/issues/issue-68615-adt.min.stderr +++ b/src/test/ui/const-generics/issues/issue-68615-adt.min.stderr @@ -5,7 +5,7 @@ LL | struct Const {} | ^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = note: more complex types are supported with `#[feature(const_generics)]` + = help: more complex types are supported with `#[feature(const_generics)]` error: aborting due to previous error diff --git a/src/test/ui/const-generics/issues/issue-68615-array.min.stderr b/src/test/ui/const-generics/issues/issue-68615-array.min.stderr index 8f55a92fce9af..1ee881b96ec60 100644 --- a/src/test/ui/const-generics/issues/issue-68615-array.min.stderr +++ b/src/test/ui/const-generics/issues/issue-68615-array.min.stderr @@ -5,7 +5,7 @@ LL | struct Foo {} | ^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = note: more complex types are supported with `#[feature(const_generics)]` + = help: more complex types are supported with `#[feature(const_generics)]` error: aborting due to previous error diff --git a/src/test/ui/const-generics/issues/issue-68977.min.stderr b/src/test/ui/const-generics/issues/issue-68977.min.stderr index 7828d85939497..ea91df1e0bf4d 100644 --- a/src/test/ui/const-generics/issues/issue-68977.min.stderr +++ b/src/test/ui/const-generics/issues/issue-68977.min.stderr @@ -5,6 +5,7 @@ LL | PhantomU8<{(INT_BITS + FRAC_BITS + 7) / 8}>; | ^^^^^^^^ cannot perform const operation using `INT_BITS` | = help: const parameters may only be used as standalone arguments, i.e. `INT_BITS` + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/issue-68977.rs:29:28 @@ -13,6 +14,7 @@ LL | PhantomU8<{(INT_BITS + FRAC_BITS + 7) / 8}>; | ^^^^^^^^^ cannot perform const operation using `FRAC_BITS` | = help: const parameters may only be used as standalone arguments, i.e. `FRAC_BITS` + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: aborting due to 2 previous errors diff --git a/src/test/ui/const-generics/issues/issue-71169.min.stderr b/src/test/ui/const-generics/issues/issue-71169.min.stderr index 79d63443351ff..9b0a2946ca6cf 100644 --- a/src/test/ui/const-generics/issues/issue-71169.min.stderr +++ b/src/test/ui/const-generics/issues/issue-71169.min.stderr @@ -11,7 +11,7 @@ LL | fn foo() {} | ^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = note: more complex types are supported with `#[feature(const_generics)]` + = help: more complex types are supported with `#[feature(const_generics)]` error: aborting due to 2 previous errors diff --git a/src/test/ui/const-generics/issues/issue-72787.min.stderr b/src/test/ui/const-generics/issues/issue-72787.min.stderr index d960d9513b752..27bbc28011f2e 100644 --- a/src/test/ui/const-generics/issues/issue-72787.min.stderr +++ b/src/test/ui/const-generics/issues/issue-72787.min.stderr @@ -5,6 +5,7 @@ LL | Condition<{ LHS <= RHS }>: True | ^^^ cannot perform const operation using `LHS` | = help: const parameters may only be used as standalone arguments, i.e. `LHS` + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/issue-72787.rs:11:24 @@ -13,6 +14,7 @@ LL | Condition<{ LHS <= RHS }>: True | ^^^ cannot perform const operation using `RHS` | = help: const parameters may only be used as standalone arguments, i.e. `RHS` + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/issue-72787.rs:26:25 @@ -21,6 +23,7 @@ LL | IsLessOrEqual<{ 8 - I }, { 8 - J }>: True, | ^ cannot perform const operation using `I` | = help: const parameters may only be used as standalone arguments, i.e. `I` + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/issue-72787.rs:26:36 @@ -29,6 +32,7 @@ LL | IsLessOrEqual<{ 8 - I }, { 8 - J }>: True, | ^ cannot perform const operation using `J` | = help: const parameters may only be used as standalone arguments, i.e. `J` + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error[E0283]: type annotations needed --> $DIR/issue-72787.rs:22:26 diff --git a/src/test/ui/const-generics/issues/issue-72819-generic-in-const-eval.min.stderr b/src/test/ui/const-generics/issues/issue-72819-generic-in-const-eval.min.stderr index 9fec3eb946d83..2394b23d7995b 100644 --- a/src/test/ui/const-generics/issues/issue-72819-generic-in-const-eval.min.stderr +++ b/src/test/ui/const-generics/issues/issue-72819-generic-in-const-eval.min.stderr @@ -5,6 +5,7 @@ LL | where Assert::<{N < usize::max_value() / 2}>: IsTrue, | ^ cannot perform const operation using `N` | = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: aborting due to previous error diff --git a/src/test/ui/const-generics/issues/issue-73491.min.stderr b/src/test/ui/const-generics/issues/issue-73491.min.stderr index 5bf3671d38be3..3ff0563acc77d 100644 --- a/src/test/ui/const-generics/issues/issue-73491.min.stderr +++ b/src/test/ui/const-generics/issues/issue-73491.min.stderr @@ -5,7 +5,7 @@ LL | fn hoge() {} | ^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = note: more complex types are supported with `#[feature(const_generics)]` + = help: more complex types are supported with `#[feature(const_generics)]` error: aborting due to previous error diff --git a/src/test/ui/const-generics/issues/issue-74101.min.stderr b/src/test/ui/const-generics/issues/issue-74101.min.stderr index 8062faefbe60b..1351246667e9b 100644 --- a/src/test/ui/const-generics/issues/issue-74101.min.stderr +++ b/src/test/ui/const-generics/issues/issue-74101.min.stderr @@ -5,7 +5,7 @@ LL | fn test() {} | ^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = note: more complex types are supported with `#[feature(const_generics)]` + = help: more complex types are supported with `#[feature(const_generics)]` error: `[u8; _]` is forbidden as the type of a const generic parameter --> $DIR/issue-74101.rs:10:21 @@ -14,7 +14,7 @@ LL | struct Foo; | ^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = note: more complex types are supported with `#[feature(const_generics)]` + = help: more complex types are supported with `#[feature(const_generics)]` error: aborting due to 2 previous errors diff --git a/src/test/ui/const-generics/issues/issue-74255.min.stderr b/src/test/ui/const-generics/issues/issue-74255.min.stderr index 86937d715c973..e3e8502ae6349 100644 --- a/src/test/ui/const-generics/issues/issue-74255.min.stderr +++ b/src/test/ui/const-generics/issues/issue-74255.min.stderr @@ -5,7 +5,7 @@ LL | fn ice_struct_fn() {} | ^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = note: more complex types are supported with `#[feature(const_generics)]` + = help: more complex types are supported with `#[feature(const_generics)]` error: aborting due to previous error diff --git a/src/test/ui/const-generics/issues/issue-74950.min.stderr b/src/test/ui/const-generics/issues/issue-74950.min.stderr index f093e6651bc28..12947a2ab3758 100644 --- a/src/test/ui/const-generics/issues/issue-74950.min.stderr +++ b/src/test/ui/const-generics/issues/issue-74950.min.stderr @@ -5,7 +5,7 @@ LL | struct Outer; | ^^^^^ | = note: the only supported types are integers, `bool` and `char` - = note: more complex types are supported with `#[feature(const_generics)]` + = help: more complex types are supported with `#[feature(const_generics)]` error: `Inner` is forbidden as the type of a const generic parameter --> $DIR/issue-74950.rs:18:23 @@ -14,7 +14,7 @@ LL | struct Outer; | ^^^^^ | = note: the only supported types are integers, `bool` and `char` - = note: more complex types are supported with `#[feature(const_generics)]` + = help: more complex types are supported with `#[feature(const_generics)]` error: `Inner` is forbidden as the type of a const generic parameter --> $DIR/issue-74950.rs:18:23 @@ -23,7 +23,7 @@ LL | struct Outer; | ^^^^^ | = note: the only supported types are integers, `bool` and `char` - = note: more complex types are supported with `#[feature(const_generics)]` + = help: more complex types are supported with `#[feature(const_generics)]` error: `Inner` is forbidden as the type of a const generic parameter --> $DIR/issue-74950.rs:18:23 @@ -32,7 +32,7 @@ LL | struct Outer; | ^^^^^ | = note: the only supported types are integers, `bool` and `char` - = note: more complex types are supported with `#[feature(const_generics)]` + = help: more complex types are supported with `#[feature(const_generics)]` error: `Inner` is forbidden as the type of a const generic parameter --> $DIR/issue-74950.rs:18:23 @@ -41,7 +41,7 @@ LL | struct Outer; | ^^^^^ | = note: the only supported types are integers, `bool` and `char` - = note: more complex types are supported with `#[feature(const_generics)]` + = help: more complex types are supported with `#[feature(const_generics)]` error: aborting due to 5 previous errors diff --git a/src/test/ui/const-generics/issues/issue-75047.min.stderr b/src/test/ui/const-generics/issues/issue-75047.min.stderr index edc54b082dbcb..b87bb18a5a683 100644 --- a/src/test/ui/const-generics/issues/issue-75047.min.stderr +++ b/src/test/ui/const-generics/issues/issue-75047.min.stderr @@ -5,7 +5,7 @@ LL | struct Foo::value()]>; | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = note: more complex types are supported with `#[feature(const_generics)]` + = help: more complex types are supported with `#[feature(const_generics)]` error: aborting due to previous error diff --git a/src/test/ui/const-generics/issues/issue-76701-ty-param-in-const.min.stderr b/src/test/ui/const-generics/issues/issue-76701-ty-param-in-const.min.stderr index c10db84ea6ecc..551b8e43e1d4c 100644 --- a/src/test/ui/const-generics/issues/issue-76701-ty-param-in-const.min.stderr +++ b/src/test/ui/const-generics/issues/issue-76701-ty-param-in-const.min.stderr @@ -5,6 +5,7 @@ LL | fn ty_param() -> [u8; std::mem::size_of::()] { | ^ cannot perform const operation using `T` | = note: type parameters may not be used in const expressions + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/issue-76701-ty-param-in-const.rs:12:42 @@ -13,6 +14,7 @@ LL | fn const_param() -> [u8; N + 1] { | ^ cannot perform const operation using `N` | = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: aborting due to 2 previous errors diff --git a/src/test/ui/const-generics/macro_rules-braces.min.stderr b/src/test/ui/const-generics/macro_rules-braces.min.stderr index c6425edc10f15..c400e2c814dd7 100644 --- a/src/test/ui/const-generics/macro_rules-braces.min.stderr +++ b/src/test/ui/const-generics/macro_rules-braces.min.stderr @@ -27,6 +27,7 @@ LL | let _: foo!({{ N }}); | ^ cannot perform const operation using `N` | = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/macro_rules-braces.rs:41:19 @@ -35,6 +36,7 @@ LL | let _: bar!({ N }); | ^ cannot perform const operation using `N` | = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/macro_rules-braces.rs:46:20 @@ -43,6 +45,7 @@ LL | let _: baz!({{ N }}); | ^ cannot perform const operation using `N` | = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/macro_rules-braces.rs:51:19 @@ -51,6 +54,7 @@ LL | let _: biz!({ N }); | ^ cannot perform const operation using `N` | = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: aborting due to 6 previous errors diff --git a/src/test/ui/const-generics/min_const_generics/complex-expression.stderr b/src/test/ui/const-generics/min_const_generics/complex-expression.stderr index a8de987e1675e..2ea66279d4608 100644 --- a/src/test/ui/const-generics/min_const_generics/complex-expression.stderr +++ b/src/test/ui/const-generics/min_const_generics/complex-expression.stderr @@ -5,6 +5,7 @@ LL | struct Break0([u8; { N + 1 }]); | ^ cannot perform const operation using `N` | = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/complex-expression.rs:14:40 @@ -13,6 +14,7 @@ LL | struct Break1([u8; { { N } }]); | ^ cannot perform const operation using `N` | = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/complex-expression.rs:18:17 @@ -21,6 +23,7 @@ LL | let _: [u8; N + 1]; | ^ cannot perform const operation using `N` | = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/complex-expression.rs:23:17 @@ -29,6 +32,7 @@ LL | let _ = [0; N + 1]; | ^ cannot perform const operation using `N` | = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/complex-expression.rs:27:45 @@ -37,6 +41,7 @@ LL | struct BreakTy0(T, [u8; { size_of::<*mut T>() }]); | ^ cannot perform const operation using `T` | = note: type parameters may not be used in const expressions + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/complex-expression.rs:30:47 @@ -45,6 +50,7 @@ LL | struct BreakTy1(T, [u8; { { size_of::<*mut T>() } }]); | ^ cannot perform const operation using `T` | = note: type parameters may not be used in const expressions + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/complex-expression.rs:34:32 @@ -53,6 +59,7 @@ LL | let _: [u8; size_of::<*mut T>() + 1]; | ^ cannot perform const operation using `T` | = note: type parameters may not be used in const expressions + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions warning: cannot use constants which depend on generic parameters in types --> $DIR/complex-expression.rs:39:17 diff --git a/src/test/ui/const-generics/min_const_generics/complex-types.stderr b/src/test/ui/const-generics/min_const_generics/complex-types.stderr index 52ed3c1c6ee8c..5d473f1f8769f 100644 --- a/src/test/ui/const-generics/min_const_generics/complex-types.stderr +++ b/src/test/ui/const-generics/min_const_generics/complex-types.stderr @@ -5,7 +5,7 @@ LL | struct Foo; | ^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = note: more complex types are supported with `#[feature(const_generics)]` + = help: more complex types are supported with `#[feature(const_generics)]` error: `()` is forbidden as the type of a const generic parameter --> $DIR/complex-types.rs:7:21 @@ -14,7 +14,7 @@ LL | struct Bar; | ^^ | = note: the only supported types are integers, `bool` and `char` - = note: more complex types are supported with `#[feature(const_generics)]` + = help: more complex types are supported with `#[feature(const_generics)]` error: `No` is forbidden as the type of a const generic parameter --> $DIR/complex-types.rs:12:21 @@ -23,7 +23,7 @@ LL | struct Fez; | ^^ | = note: the only supported types are integers, `bool` and `char` - = note: more complex types are supported with `#[feature(const_generics)]` + = help: more complex types are supported with `#[feature(const_generics)]` error: `&'static u8` is forbidden as the type of a const generic parameter --> $DIR/complex-types.rs:15:21 @@ -32,7 +32,7 @@ LL | struct Faz; | ^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = note: more complex types are supported with `#[feature(const_generics)]` + = help: more complex types are supported with `#[feature(const_generics)]` error: `!` is forbidden as the type of a const generic parameter --> $DIR/complex-types.rs:18:21 @@ -41,7 +41,7 @@ LL | struct Fiz; | ^ | = note: the only supported types are integers, `bool` and `char` - = note: more complex types are supported with `#[feature(const_generics)]` + = help: more complex types are supported with `#[feature(const_generics)]` error: `()` is forbidden as the type of a const generic parameter --> $DIR/complex-types.rs:21:19 @@ -50,7 +50,7 @@ LL | enum Goo { A, B } | ^^ | = note: the only supported types are integers, `bool` and `char` - = note: more complex types are supported with `#[feature(const_generics)]` + = help: more complex types are supported with `#[feature(const_generics)]` error: `()` is forbidden as the type of a const generic parameter --> $DIR/complex-types.rs:24:20 @@ -59,7 +59,7 @@ LL | union Boo { a: () } | ^^ | = note: the only supported types are integers, `bool` and `char` - = note: more complex types are supported with `#[feature(const_generics)]` + = help: more complex types are supported with `#[feature(const_generics)]` error: aborting due to 7 previous errors diff --git a/src/test/ui/const-generics/min_const_generics/self-ty-in-const-1.stderr b/src/test/ui/const-generics/min_const_generics/self-ty-in-const-1.stderr index 64da5e07df2f4..40c73f0b95136 100644 --- a/src/test/ui/const-generics/min_const_generics/self-ty-in-const-1.stderr +++ b/src/test/ui/const-generics/min_const_generics/self-ty-in-const-1.stderr @@ -5,6 +5,7 @@ LL | fn t1() -> [u8; std::mem::size_of::()]; | ^^^^ cannot perform const operation using `Self` | = note: type parameters may not be used in const expressions + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic `Self` types are currently not permitted in anonymous constants --> $DIR/self-ty-in-const-1.rs:14:41 diff --git a/src/test/ui/const-generics/min_const_generics/static-reference-array-const-param.stderr b/src/test/ui/const-generics/min_const_generics/static-reference-array-const-param.stderr index cc32d8a67fed0..6c39f6b4c1dc3 100644 --- a/src/test/ui/const-generics/min_const_generics/static-reference-array-const-param.stderr +++ b/src/test/ui/const-generics/min_const_generics/static-reference-array-const-param.stderr @@ -5,7 +5,7 @@ LL | fn a() {} | ^^^^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = note: more complex types are supported with `#[feature(const_generics)]` + = help: more complex types are supported with `#[feature(const_generics)]` error: aborting due to previous error diff --git a/src/test/ui/const-generics/min_const_generics/transmute-const-param-static-reference.stderr b/src/test/ui/const-generics/min_const_generics/transmute-const-param-static-reference.stderr index 063120ad074a0..6b90329b72cee 100644 --- a/src/test/ui/const-generics/min_const_generics/transmute-const-param-static-reference.stderr +++ b/src/test/ui/const-generics/min_const_generics/transmute-const-param-static-reference.stderr @@ -5,7 +5,7 @@ LL | struct Const; | ^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = note: more complex types are supported with `#[feature(const_generics)]` + = help: more complex types are supported with `#[feature(const_generics)]` error: aborting due to previous error diff --git a/src/test/ui/const-generics/nested-type.min.stderr b/src/test/ui/const-generics/nested-type.min.stderr index 4f76ec6e02b22..369e387508e9f 100644 --- a/src/test/ui/const-generics/nested-type.min.stderr +++ b/src/test/ui/const-generics/nested-type.min.stderr @@ -12,7 +12,7 @@ LL | | }]>; | |__^ | = note: the only supported types are integers, `bool` and `char` - = note: more complex types are supported with `#[feature(const_generics)]` + = help: more complex types are supported with `#[feature(const_generics)]` error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants --> $DIR/nested-type.rs:16:5 diff --git a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr index 39aa8087cec50..9e0837a0a620c 100644 --- a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr +++ b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr @@ -13,6 +13,7 @@ LL | struct Foo()]>(T, U); | ^ cannot perform const operation using `T` | = note: type parameters may not be used in const expressions + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: constant values inside of type parameter defaults must not depend on generic parameters --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:12:21 diff --git a/src/test/ui/const-generics/slice-const-param-mismatch.min.stderr b/src/test/ui/const-generics/slice-const-param-mismatch.min.stderr index 1f711bef4aa63..46997fed770ac 100644 --- a/src/test/ui/const-generics/slice-const-param-mismatch.min.stderr +++ b/src/test/ui/const-generics/slice-const-param-mismatch.min.stderr @@ -5,7 +5,7 @@ LL | struct ConstString; | ^^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = note: more complex types are supported with `#[feature(const_generics)]` + = help: more complex types are supported with `#[feature(const_generics)]` error: `&'static [u8]` is forbidden as the type of a const generic parameter --> $DIR/slice-const-param-mismatch.rs:10:28 @@ -14,7 +14,7 @@ LL | struct ConstBytes; | ^^^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = note: more complex types are supported with `#[feature(const_generics)]` + = help: more complex types are supported with `#[feature(const_generics)]` error: aborting due to 2 previous errors diff --git a/src/test/ui/const-generics/slice-const-param.min.stderr b/src/test/ui/const-generics/slice-const-param.min.stderr index 2a49619e6614a..7a9f65233e793 100644 --- a/src/test/ui/const-generics/slice-const-param.min.stderr +++ b/src/test/ui/const-generics/slice-const-param.min.stderr @@ -5,7 +5,7 @@ LL | pub fn function_with_str() -> &'static str { | ^^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = note: more complex types are supported with `#[feature(const_generics)]` + = help: more complex types are supported with `#[feature(const_generics)]` error: `&'static [u8]` is forbidden as the type of a const generic parameter --> $DIR/slice-const-param.rs:13:41 @@ -14,7 +14,7 @@ LL | pub fn function_with_bytes() -> &'static [u8] { | ^^^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = note: more complex types are supported with `#[feature(const_generics)]` + = help: more complex types are supported with `#[feature(const_generics)]` error: aborting due to 2 previous errors diff --git a/src/test/ui/const-generics/std/const-generics-range.min.stderr b/src/test/ui/const-generics/std/const-generics-range.min.stderr index 97be6ee64457d..9274ccd2b921a 100644 --- a/src/test/ui/const-generics/std/const-generics-range.min.stderr +++ b/src/test/ui/const-generics/std/const-generics-range.min.stderr @@ -5,7 +5,7 @@ LL | struct _Range>; | ^^^^^^^^^^^^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = note: more complex types are supported with `#[feature(const_generics)]` + = help: more complex types are supported with `#[feature(const_generics)]` error: `RangeFrom` is forbidden as the type of a const generic parameter --> $DIR/const-generics-range.rs:13:28 @@ -14,7 +14,7 @@ LL | struct _RangeFrom>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = note: more complex types are supported with `#[feature(const_generics)]` + = help: more complex types are supported with `#[feature(const_generics)]` error: `RangeFull` is forbidden as the type of a const generic parameter --> $DIR/const-generics-range.rs:18:28 @@ -23,7 +23,7 @@ LL | struct _RangeFull; | ^^^^^^^^^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = note: more complex types are supported with `#[feature(const_generics)]` + = help: more complex types are supported with `#[feature(const_generics)]` error: `RangeInclusive` is forbidden as the type of a const generic parameter --> $DIR/const-generics-range.rs:24:33 @@ -32,7 +32,7 @@ LL | struct _RangeInclusive>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = note: more complex types are supported with `#[feature(const_generics)]` + = help: more complex types are supported with `#[feature(const_generics)]` error: `RangeTo` is forbidden as the type of a const generic parameter --> $DIR/const-generics-range.rs:29:26 @@ -41,7 +41,7 @@ LL | struct _RangeTo>; | ^^^^^^^^^^^^^^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = note: more complex types are supported with `#[feature(const_generics)]` + = help: more complex types are supported with `#[feature(const_generics)]` error: `RangeToInclusive` is forbidden as the type of a const generic parameter --> $DIR/const-generics-range.rs:34:35 @@ -50,7 +50,7 @@ LL | struct _RangeToInclusive>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = note: more complex types are supported with `#[feature(const_generics)]` + = help: more complex types are supported with `#[feature(const_generics)]` error: aborting due to 6 previous errors diff --git a/src/test/ui/const-generics/type-dependent/issue-71348.min.stderr b/src/test/ui/const-generics/type-dependent/issue-71348.min.stderr index 8656239605dfd..8f240f0d930a4 100644 --- a/src/test/ui/const-generics/type-dependent/issue-71348.min.stderr +++ b/src/test/ui/const-generics/type-dependent/issue-71348.min.stderr @@ -5,7 +5,7 @@ LL | trait Get<'a, const N: &'static str> { | ^^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = note: more complex types are supported with `#[feature(const_generics)]` + = help: more complex types are supported with `#[feature(const_generics)]` error: `&'static str` is forbidden as the type of a const generic parameter --> $DIR/issue-71348.rs:19:25 @@ -14,7 +14,7 @@ LL | fn ask<'a, const N: &'static str>(&'a self) -> &'a >::Ta | ^^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = note: more complex types are supported with `#[feature(const_generics)]` + = help: more complex types are supported with `#[feature(const_generics)]` error: aborting due to 2 previous errors diff --git a/src/test/ui/const-generics/wf-misc.min.stderr b/src/test/ui/const-generics/wf-misc.min.stderr index 935f12dd2c304..99142cb6ce7a5 100644 --- a/src/test/ui/const-generics/wf-misc.min.stderr +++ b/src/test/ui/const-generics/wf-misc.min.stderr @@ -5,6 +5,7 @@ LL | let _: [u8; N + 1]; | ^ cannot perform const operation using `N` | = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/wf-misc.rs:17:21 @@ -13,6 +14,7 @@ LL | let _: Const::<{N + 1}>; | ^ cannot perform const operation using `N` | = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions error: aborting due to 2 previous errors