authorbors <bors@rust-lang.org> 2025-06-07 23:05:07 UTC
committerbors <bors@rust-lang.org> 2025-06-07 23:05:07 UTC
loga5584a8fe16037dc01782064fa41424a6dbe9987
tree45868373b3a39501ee019af887db69e453052a40
parentcdd545be1b4f024d38360aa9f000dcb782fbc81b
parentaa940603f543cfac35045d5be947f84d63e5609e

Auto merge of #142181 - GuillaumeGomez:rollup-pn2p1lu, r=GuillaumeGomez

Rollup of 9 pull requests Successful merges: - rust-lang/rust#140560 (Allow `#![doc(test(attr(..)))]` everywhere) - rust-lang/rust#141447 (Document representation of `Option<unsafe fn()>`) - rust-lang/rust#141661 (Make the `dangerous_implicit_autorefs` lint deny-by-default) - rust-lang/rust#142065 (Stabilize `const_eq_ignore_ascii_case`) - rust-lang/rust#142116 (Fix bootstrap tracing imports) - rust-lang/rust#142126 (Treat normalizing consts like normalizing types in deeply normalize) - rust-lang/rust#142140 (compiler: Sort and doc ExternAbi variants) - rust-lang/rust#142148 (compiler: Treat ForceWarning as a Warning for diagnostic level) - rust-lang/rust#142154 (get rid of spurious cfg(bootstrap)) r? `@ghost` `@rustbot` modify labels: rollup

45 files changed, 988 insertions(+), 344 deletions(-)

compiler/rustc_abi/src/extern_abi.rs+63-36
......@@ -12,66 +12,93 @@ use crate::AbiFromStrErr;
1212#[cfg(test)]
1313mod tests;
1414
15use ExternAbi as Abi;
16
15/// ABI we expect to see within `extern "{abi}"`
1716#[derive(Clone, Copy, Debug)]
1817#[cfg_attr(feature = "nightly", derive(Encodable, Decodable))]
1918pub enum ExternAbi {
20 // Some of the ABIs come first because every time we add a new ABI, we have to re-bless all the
21 // hashing tests. These are used in many places, so giving them stable values reduces test
22 // churn. The specific values are meaningless.
23 Rust,
19 /* universal */
20 /// presumed C ABI for the platform
2421 C {
2522 unwind: bool,
2623 },
27 Cdecl {
24 /// ABI of the "system" interface, e.g. the Win32 API, always "aliasing"
25 System {
2826 unwind: bool,
2927 },
30 Stdcall {
28
29 /// that's us!
30 Rust,
31 /// the mostly-unused `unboxed_closures` ABI, effectively now an impl detail unless someone
32 /// puts in the work to make it viable again... but would we need a special ABI?
33 RustCall,
34 /// For things unlikely to be called, where reducing register pressure in
35 /// `extern "Rust"` callers is worth paying extra cost in the callee.
36 /// Stronger than just `#[cold]` because `fn` pointers might be incompatible.
37 RustCold,
38
39 /// Unstable impl detail that directly uses Rust types to describe the ABI to LLVM.
40 /// Even normally-compatible Rust types can become ABI-incompatible with this ABI!
41 Unadjusted,
42
43 /// UEFI ABI, usually an alias of C, but sometimes an arch-specific alias
44 /// and only valid on platforms that have a UEFI standard
45 EfiApi,
46
47 /* arm */
48 /// Arm Architecture Procedure Call Standard, sometimes `ExternAbi::C` is an alias for this
49 Aapcs {
3150 unwind: bool,
3251 },
33 Fastcall {
52 /// extremely constrained barely-C ABI for TrustZone
53 CCmseNonSecureCall,
54 /// extremely constrained barely-C ABI for TrustZone
55 CCmseNonSecureEntry,
56
57 /* gpu */
58 /// An entry-point function called by the GPU's host
59 // FIXME: should not be callable from Rust on GPU targets, is for host's use only
60 GpuKernel,
61 /// An entry-point function called by the GPU's host
62 // FIXME: why do we have two of these?
63 PtxKernel,
64
65 /* interrupt */
66 AvrInterrupt,
67 AvrNonBlockingInterrupt,
68 Msp430Interrupt,
69 RiscvInterruptM,
70 RiscvInterruptS,
71 X86Interrupt,
72
73 /* x86 */
74 /// `ExternAbi::C` but spelled funny because x86
75 Cdecl {
3476 unwind: bool,
3577 },
36 Vectorcall {
78 /// gnu-stdcall on "unix" and win-stdcall on "windows"
79 Stdcall {
3780 unwind: bool,
3881 },
39 Thiscall {
82 /// gnu-fastcall on "unix" and win-fastcall on "windows"
83 Fastcall {
4084 unwind: bool,
4185 },
42 Aapcs {
86 /// windows C++ ABI
87 Thiscall {
4388 unwind: bool,
4489 },
45 Win64 {
90 /// uses AVX and stuff
91 Vectorcall {
4692 unwind: bool,
4793 },
94
95 /* x86_64 */
4896 SysV64 {
4997 unwind: bool,
5098 },
51 PtxKernel,
52 Msp430Interrupt,
53 X86Interrupt,
54 /// An entry-point function called by the GPU's host
55 // FIXME: should not be callable from Rust on GPU targets, is for host's use only
56 GpuKernel,
57 EfiApi,
58 AvrInterrupt,
59 AvrNonBlockingInterrupt,
60 CCmseNonSecureCall,
61 CCmseNonSecureEntry,
62 System {
99 Win64 {
63100 unwind: bool,
64101 },
65 RustCall,
66 /// *Not* a stable ABI, just directly use the Rust types to describe the ABI for LLVM. Even
67 /// normally ABI-compatible Rust types can become ABI-incompatible with this ABI!
68 Unadjusted,
69 /// For things unlikely to be called, where reducing register pressure in
70 /// `extern "Rust"` callers is worth paying extra cost in the callee.
71 /// Stronger than just `#[cold]` because `fn` pointers might be incompatible.
72 RustCold,
73 RiscvInterruptM,
74 RiscvInterruptS,
75102}
76103
77104macro_rules! abi_impls {
......@@ -224,7 +251,7 @@ pub fn all_names() -> Vec<&'static str> {
224251
225252impl ExternAbi {
226253 /// Default ABI chosen for `extern fn` declarations without an explicit ABI.
227 pub const FALLBACK: Abi = Abi::C { unwind: false };
254 pub const FALLBACK: ExternAbi = ExternAbi::C { unwind: false };
228255
229256 pub fn name(self) -> &'static str {
230257 self.as_str()
compiler/rustc_errors/src/lib.rs+1-1
......@@ -1529,7 +1529,7 @@ impl DiagCtxtInner {
15291529 // Future breakages aren't emitted if they're `Level::Allow` or
15301530 // `Level::Expect`, but they still need to be constructed and
15311531 // stashed below, so they'll trigger the must_produce_diag check.
1532 assert_matches!(diagnostic.level, Error | Warning | Allow | Expect);
1532 assert_matches!(diagnostic.level, Error | ForceWarning | Warning | Allow | Expect);
15331533 self.future_breakage_diagnostics.push(diagnostic.clone());
15341534 }
15351535
compiler/rustc_infer/src/infer/mod.rs+7
......@@ -823,6 +823,13 @@ impl<'tcx> InferCtxt<'tcx> {
823823 ty::Region::new_var(self.tcx, region_var)
824824 }
825825
826 pub fn next_term_var_of_kind(&self, term: ty::Term<'tcx>, span: Span) -> ty::Term<'tcx> {
827 match term.kind() {
828 ty::TermKind::Ty(_) => self.next_ty_var(span).into(),
829 ty::TermKind::Const(_) => self.next_const_var(span).into(),
830 }
831 }
832
826833 /// Return the universe that the region `r` was created in. For
827834 /// most regions (e.g., `'static`, named regions from the user,
828835 /// etc) this is the root universe U0. For inference variables or
compiler/rustc_lint/src/autorefs.rs+2-2
......@@ -16,7 +16,7 @@ declare_lint! {
1616 ///
1717 /// ### Example
1818 ///
19 /// ```rust
19 /// ```rust,compile_fail
2020 /// unsafe fn fun(ptr: *mut [u8]) -> *mut [u8] {
2121 /// unsafe { &raw mut (*ptr)[..16] }
2222 /// // ^^^^^^ this calls `IndexMut::index_mut(&mut ..., ..16)`,
......@@ -51,7 +51,7 @@ declare_lint! {
5151 /// }
5252 /// ```
5353 pub DANGEROUS_IMPLICIT_AUTOREFS,
54 Warn,
54 Deny,
5555 "implicit reference to a dereference of a raw pointer",
5656 report_in_external_macro
5757}
compiler/rustc_passes/src/check_attr.rs+9-7
......@@ -1266,13 +1266,17 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
12661266 true
12671267 }
12681268
1269 /// Checks that `doc(test(...))` attribute contains only valid attributes. Returns `true` if
1270 /// valid.
1271 fn check_test_attr(&self, meta: &MetaItemInner, hir_id: HirId) {
1269 /// Checks that `doc(test(...))` attribute contains only valid attributes and are at the right place.
1270 fn check_test_attr(&self, attr: &Attribute, meta: &MetaItemInner, hir_id: HirId) {
12721271 if let Some(metas) = meta.meta_item_list() {
12731272 for i_meta in metas {
12741273 match (i_meta.name(), i_meta.meta_item()) {
1275 (Some(sym::attr | sym::no_crate_inject), _) => {}
1274 (Some(sym::attr), _) => {
1275 // Allowed everywhere like `#[doc]`
1276 }
1277 (Some(sym::no_crate_inject), _) => {
1278 self.check_attr_crate_level(attr, meta, hir_id);
1279 }
12761280 (_, Some(m)) => {
12771281 self.tcx.emit_node_span_lint(
12781282 INVALID_DOC_ATTRIBUTES,
......@@ -1359,9 +1363,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
13591363 }
13601364
13611365 Some(sym::test) => {
1362 if self.check_attr_crate_level(attr, meta, hir_id) {
1363 self.check_test_attr(meta, hir_id);
1364 }
1366 self.check_test_attr(attr, meta, hir_id);
13651367 }
13661368
13671369 Some(
compiler/rustc_trait_selection/src/solve/inspect/analyse.rs+1-4
......@@ -231,10 +231,7 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
231231 let infcx = self.goal.infcx;
232232 match goal.predicate.kind().no_bound_vars() {
233233 Some(ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term })) => {
234 let unconstrained_term = match term.kind() {
235 ty::TermKind::Ty(_) => infcx.next_ty_var(span).into(),
236 ty::TermKind::Const(_) => infcx.next_const_var(span).into(),
237 };
234 let unconstrained_term = infcx.next_term_var_of_kind(term, span);
238235 let goal =
239236 goal.with(infcx.tcx, ty::NormalizesTo { alias, term: unconstrained_term });
240237 // We have to use a `probe` here as evaluating a `NormalizesTo` can constrain the
compiler/rustc_trait_selection/src/solve/normalize.rs+25-66
......@@ -1,4 +1,3 @@
1use std::assert_matches::assert_matches;
21use std::fmt::Debug;
32
43use rustc_data_structures::stack::ensure_sufficient_stack;
......@@ -16,7 +15,6 @@ use tracing::instrument;
1615use super::{FulfillmentCtxt, NextSolverError};
1716use crate::error_reporting::InferCtxtErrorExt;
1817use crate::error_reporting::traits::OverflowCause;
19use crate::traits::query::evaluate_obligation::InferCtxtExt;
2018use crate::traits::{BoundVarReplacer, PlaceholderReplacer, ScrubbedTraitError};
2119
2220/// Deeply normalize all aliases in `value`. This does not handle inference and expects
......@@ -97,19 +95,18 @@ impl<'tcx, E> NormalizationFolder<'_, 'tcx, E>
9795where
9896 E: FromSolverError<'tcx, NextSolverError<'tcx>>,
9997{
100 fn normalize_alias_ty(&mut self, alias_ty: Ty<'tcx>) -> Result<Ty<'tcx>, Vec<E>> {
101 assert_matches!(alias_ty.kind(), ty::Alias(..));
102
98 fn normalize_alias_term(
99 &mut self,
100 alias_term: ty::Term<'tcx>,
101 ) -> Result<ty::Term<'tcx>, Vec<E>> {
103102 let infcx = self.at.infcx;
104103 let tcx = infcx.tcx;
105104 let recursion_limit = tcx.recursion_limit();
106105 if !recursion_limit.value_within_limit(self.depth) {
107 let ty::Alias(_, data) = *alias_ty.kind() else {
108 unreachable!();
109 };
106 let term = alias_term.to_alias_term().unwrap();
110107
111108 self.at.infcx.err_ctxt().report_overflow_error(
112 OverflowCause::DeeplyNormalize(data.into()),
109 OverflowCause::DeeplyNormalize(term),
113110 self.at.cause.span,
114111 true,
115112 |_| {},
......@@ -118,14 +115,14 @@ where
118115
119116 self.depth += 1;
120117
121 let new_infer_ty = infcx.next_ty_var(self.at.cause.span);
118 let infer_term = infcx.next_term_var_of_kind(alias_term, self.at.cause.span);
122119 let obligation = Obligation::new(
123120 tcx,
124121 self.at.cause.clone(),
125122 self.at.param_env,
126123 ty::PredicateKind::AliasRelate(
127 alias_ty.into(),
128 new_infer_ty.into(),
124 alias_term.into(),
125 infer_term.into(),
129126 ty::AliasRelationDirection::Equate,
130127 ),
131128 );
......@@ -135,50 +132,13 @@ where
135132
136133 // Alias is guaranteed to be fully structurally resolved,
137134 // so we can super fold here.
138 let ty = infcx.resolve_vars_if_possible(new_infer_ty);
139 let result = ty.try_super_fold_with(self)?;
140 self.depth -= 1;
141 Ok(result)
142 }
143
144 fn normalize_unevaluated_const(
145 &mut self,
146 uv: ty::UnevaluatedConst<'tcx>,
147 ) -> Result<ty::Const<'tcx>, Vec<E>> {
148 let infcx = self.at.infcx;
149 let tcx = infcx.tcx;
150 let recursion_limit = tcx.recursion_limit();
151 if !recursion_limit.value_within_limit(self.depth) {
152 self.at.infcx.err_ctxt().report_overflow_error(
153 OverflowCause::DeeplyNormalize(uv.into()),
154 self.at.cause.span,
155 true,
156 |_| {},
157 );
158 }
159
160 self.depth += 1;
161
162 let new_infer_ct = infcx.next_const_var(self.at.cause.span);
163 let obligation = Obligation::new(
164 tcx,
165 self.at.cause.clone(),
166 self.at.param_env,
167 ty::NormalizesTo { alias: uv.into(), term: new_infer_ct.into() },
168 );
169
170 let result = if infcx.predicate_may_hold(&obligation) {
171 self.fulfill_cx.register_predicate_obligation(infcx, obligation);
172 let errors = self.fulfill_cx.select_where_possible(infcx);
173 if !errors.is_empty() {
174 return Err(errors);
175 }
176 let ct = infcx.resolve_vars_if_possible(new_infer_ct);
177 ct.try_fold_with(self)?
178 } else {
179 ty::Const::new_unevaluated(tcx, uv).try_super_fold_with(self)?
135 let term = infcx.resolve_vars_if_possible(infer_term);
136 // super-folding the `term` will directly fold the `Ty` or `Const` so
137 // we have to match on the term and super-fold them manually.
138 let result = match term.kind() {
139 ty::TermKind::Ty(ty) => ty.try_super_fold_with(self)?.into(),
140 ty::TermKind::Const(ct) => ct.try_super_fold_with(self)?.into(),
180141 };
181
182142 self.depth -= 1;
183143 Ok(result)
184144 }
......@@ -238,7 +198,8 @@ where
238198 if ty.has_escaping_bound_vars() {
239199 let (ty, mapped_regions, mapped_types, mapped_consts) =
240200 BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, ty);
241 let result = ensure_sufficient_stack(|| self.normalize_alias_ty(ty))?;
201 let result =
202 ensure_sufficient_stack(|| self.normalize_alias_term(ty.into()))?.expect_type();
242203 Ok(PlaceholderReplacer::replace_placeholders(
243204 infcx,
244205 mapped_regions,
......@@ -248,7 +209,7 @@ where
248209 result,
249210 ))
250211 } else {
251 ensure_sufficient_stack(|| self.normalize_alias_ty(ty))
212 Ok(ensure_sufficient_stack(|| self.normalize_alias_term(ty.into()))?.expect_type())
252213 }
253214 }
254215
......@@ -260,15 +221,13 @@ where
260221 return Ok(ct);
261222 }
262223
263 let uv = match ct.kind() {
264 ty::ConstKind::Unevaluated(ct) => ct,
265 _ => return ct.try_super_fold_with(self),
266 };
224 let ty::ConstKind::Unevaluated(..) = ct.kind() else { return ct.try_super_fold_with(self) };
267225
268 if uv.has_escaping_bound_vars() {
269 let (uv, mapped_regions, mapped_types, mapped_consts) =
270 BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, uv);
271 let result = ensure_sufficient_stack(|| self.normalize_unevaluated_const(uv))?;
226 if ct.has_escaping_bound_vars() {
227 let (ct, mapped_regions, mapped_types, mapped_consts) =
228 BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, ct);
229 let result =
230 ensure_sufficient_stack(|| self.normalize_alias_term(ct.into()))?.expect_const();
272231 Ok(PlaceholderReplacer::replace_placeholders(
273232 infcx,
274233 mapped_regions,
......@@ -278,7 +237,7 @@ where
278237 result,
279238 ))
280239 } else {
281 ensure_sufficient_stack(|| self.normalize_unevaluated_const(uv))
240 Ok(ensure_sufficient_stack(|| self.normalize_alias_term(ct.into()))?.expect_const())
282241 }
283242 }
284243}
compiler/rustc_trait_selection/src/traits/structural_normalize.rs+1-4
......@@ -39,10 +39,7 @@ impl<'tcx> At<'_, 'tcx> {
3939 return Ok(term);
4040 }
4141
42 let new_infer = match term.kind() {
43 ty::TermKind::Ty(_) => self.infcx.next_ty_var(self.cause.span).into(),
44 ty::TermKind::Const(_) => self.infcx.next_const_var(self.cause.span).into(),
45 };
42 let new_infer = self.infcx.next_term_var_of_kind(term, self.cause.span);
4643
4744 // We simply emit an `alias-eq` goal here, since that will take care of
4845 // normalizing the LHS of the projection until it is a rigid projection
library/core/src/iter/sources/generator.rs-3
......@@ -9,8 +9,6 @@
99///
1010/// ```
1111/// #![feature(iter_macro, coroutines)]
12/// # #[cfg(not(bootstrap))]
13/// # {
1412///
1513/// let it = std::iter::iter!{|| {
1614/// yield 1;
......@@ -19,7 +17,6 @@
1917/// } }();
2018/// let v: Vec<_> = it.collect();
2119/// assert_eq!(v, [1, 2, 3]);
22/// # }
2320/// ```
2421#[unstable(feature = "iter_macro", issue = "none", reason = "generators are unstable")]
2522#[allow_internal_unstable(coroutines, iter_from_coroutine)]
library/core/src/option.rs+1-1
......@@ -137,7 +137,7 @@
137137//! | [`ptr::NonNull<U>`] | when `U: Sized` |
138138//! | `#[repr(transparent)]` struct around one of the types in this list. | when it holds for the inner type |
139139//!
140//! [^extern_fn]: this remains true for any argument/return types and any other ABI: `extern "abi" fn` (_e.g._, `extern "system" fn`)
140//! [^extern_fn]: this remains true for `unsafe` variants, any argument/return types, and any other ABI: `[unsafe] extern "abi" fn` (_e.g._, `extern "system" fn`)
141141//!
142142//! Under some conditions the above types `T` are also null pointer optimized when wrapped in a [`Result`][result_repr].
143143//!
library/core/src/slice/ascii.rs+1-1
......@@ -52,7 +52,7 @@ impl [u8] {
5252 /// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`,
5353 /// but without allocating and copying temporaries.
5454 #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
55 #[rustc_const_unstable(feature = "const_eq_ignore_ascii_case", issue = "131719")]
55 #[rustc_const_stable(feature = "const_eq_ignore_ascii_case", since = "CURRENT_RUSTC_VERSION")]
5656 #[must_use]
5757 #[inline]
5858 pub const fn eq_ignore_ascii_case(&self, other: &[u8]) -> bool {
library/core/src/str/mod.rs+1-1
......@@ -2671,7 +2671,7 @@ impl str {
26712671 /// assert!(!"Ferrös".eq_ignore_ascii_case("FERRÖS"));
26722672 /// ```
26732673 #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
2674 #[rustc_const_unstable(feature = "const_eq_ignore_ascii_case", issue = "131719")]
2674 #[rustc_const_stable(feature = "const_eq_ignore_ascii_case", since = "CURRENT_RUSTC_VERSION")]
26752675 #[must_use]
26762676 #[inline]
26772677 pub const fn eq_ignore_ascii_case(&self, other: &str) -> bool {
src/bootstrap/src/core/config/config.rs-2
......@@ -28,8 +28,6 @@ use build_helper::git::{GitConfig, PathFreshness, check_path_modifications, outp
2828use serde::Deserialize;
2929#[cfg(feature = "tracing")]
3030use tracing::{instrument, span};
31#[cfg(feature = "tracing")]
32use tracing::{instrument, span};
3331
3432use crate::core::build_steps::llvm;
3533use crate::core::build_steps::llvm::LLVM_INVALIDATION_PATHS;
src/bootstrap/src/core/config/mod.rs-2
......@@ -39,8 +39,6 @@ pub use toml::BUILDER_CONFIG_FILENAME;
3939pub use toml::change_id::ChangeId;
4040pub use toml::rust::LldMode;
4141pub use toml::target::Target;
42#[cfg(feature = "tracing")]
43use tracing::{instrument, span};
4442
4543use crate::Display;
4644use crate::str::FromStr;
src/doc/rustdoc/src/write-documentation/the-doc-attribute.md+23-9
......@@ -143,15 +143,6 @@ But if you include this:
143143
144144it will not.
145145
146### `test(attr(...))`
147
148This form of the `doc` attribute allows you to add arbitrary attributes to all your doctests. For
149example, if you want your doctests to fail if they have dead code, you could add this:
150
151```rust,no_run
152#![doc(test(attr(deny(dead_code))))]
153```
154
155146## At the item level
156147
157148These forms of the `#[doc]` attribute are used on individual items, to control how
......@@ -283,3 +274,26 @@ To get around this limitation, we just add `#[doc(alias = "lib_name_do_something
283274on the `do_something` method and then it's all good!
284275Users can now look for `lib_name_do_something` in our crate directly and find
285276`Obj::do_something`.
277
278### `test(attr(...))`
279
280This form of the `doc` attribute allows you to add arbitrary attributes to all your doctests. For
281example, if you want your doctests to fail if they have dead code, you could add this:
282
283```rust,no_run
284#![doc(test(attr(deny(dead_code))))]
285
286mod my_mod {
287 #![doc(test(attr(allow(dead_code))))] // but allow `dead_code` for this module
288}
289```
290
291`test(attr(..))` attributes are appended to the parent module's, they do not replace the current
292list of attributes. In the previous example, both attributes would be present:
293
294```rust,no_run
295// For every doctest in `my_mod`
296
297#![deny(dead_code)] // from the crate-root
298#![allow(dead_code)] // from `my_mod`
299```
src/librustdoc/doctest.rs+29-20
......@@ -5,6 +5,7 @@ mod runner;
55mod rust;
66
77use std::fs::File;
8use std::hash::{Hash, Hasher};
89use std::io::{self, Write};
910use std::path::{Path, PathBuf};
1011use std::process::{self, Command, Stdio};
......@@ -14,7 +15,7 @@ use std::{panic, str};
1415
1516pub(crate) use make::{BuildDocTestBuilder, DocTestBuilder};
1617pub(crate) use markdown::test as test_markdown;
17use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet};
18use rustc_data_structures::fx::{FxHashMap, FxHasher, FxIndexMap, FxIndexSet};
1819use rustc_errors::emitter::HumanReadableErrorType;
1920use rustc_errors::{ColorConfig, DiagCtxtHandle};
2021use rustc_hir as hir;
......@@ -45,8 +46,6 @@ pub(crate) struct GlobalTestOptions {
4546 /// Whether inserting extra indent spaces in code block,
4647 /// default is `false`, only `true` for generating code link of Rust playground
4748 pub(crate) insert_indent_space: bool,
48 /// Additional crate-level attributes to add to doctests.
49 pub(crate) attrs: Vec<String>,
5049 /// Path to file containing arguments for the invocation of rustc.
5150 pub(crate) args_file: PathBuf,
5251}
......@@ -283,7 +282,7 @@ pub(crate) fn run_tests(
283282 rustdoc_options: &Arc<RustdocOptions>,
284283 unused_extern_reports: &Arc<Mutex<Vec<UnusedExterns>>>,
285284 mut standalone_tests: Vec<test::TestDescAndFn>,
286 mergeable_tests: FxIndexMap<Edition, Vec<(DocTestBuilder, ScrapedDocTest)>>,
285 mergeable_tests: FxIndexMap<MergeableTestKey, Vec<(DocTestBuilder, ScrapedDocTest)>>,
287286 // We pass this argument so we can drop it manually before using `exit`.
288287 mut temp_dir: Option<TempDir>,
289288) {
......@@ -298,7 +297,7 @@ pub(crate) fn run_tests(
298297 let mut ran_edition_tests = 0;
299298 let target_str = rustdoc_options.target.to_string();
300299
301 for (edition, mut doctests) in mergeable_tests {
300 for (MergeableTestKey { edition, global_crate_attrs_hash }, mut doctests) in mergeable_tests {
302301 if doctests.is_empty() {
303302 continue;
304303 }
......@@ -308,8 +307,8 @@ pub(crate) fn run_tests(
308307
309308 let rustdoc_test_options = IndividualTestOptions::new(
310309 rustdoc_options,
311 &Some(format!("merged_doctest_{edition}")),
312 PathBuf::from(format!("doctest_{edition}.rs")),
310 &Some(format!("merged_doctest_{edition}_{global_crate_attrs_hash}")),
311 PathBuf::from(format!("doctest_{edition}_{global_crate_attrs_hash}.rs")),
313312 );
314313
315314 for (doctest, scraped_test) in &doctests {
......@@ -371,12 +370,9 @@ fn scrape_test_config(
371370 attrs: &[hir::Attribute],
372371 args_file: PathBuf,
373372) -> GlobalTestOptions {
374 use rustc_ast_pretty::pprust;
375
376373 let mut opts = GlobalTestOptions {
377374 crate_name,
378375 no_crate_inject: false,
379 attrs: Vec::new(),
380376 insert_indent_space: false,
381377 args_file,
382378 };
......@@ -393,13 +389,7 @@ fn scrape_test_config(
393389 if attr.has_name(sym::no_crate_inject) {
394390 opts.no_crate_inject = true;
395391 }
396 if attr.has_name(sym::attr)
397 && let Some(l) = attr.meta_item_list()
398 {
399 for item in l {
400 opts.attrs.push(pprust::meta_list_item_to_string(item));
401 }
402 }
392 // NOTE: `test(attr(..))` is handled when discovering the individual tests
403393 }
404394
405395 opts
......@@ -848,6 +838,7 @@ pub(crate) struct ScrapedDocTest {
848838 text: String,
849839 name: String,
850840 span: Span,
841 global_crate_attrs: Vec<String>,
851842}
852843
853844impl ScrapedDocTest {
......@@ -858,6 +849,7 @@ impl ScrapedDocTest {
858849 langstr: LangString,
859850 text: String,
860851 span: Span,
852 global_crate_attrs: Vec<String>,
861853 ) -> Self {
862854 let mut item_path = logical_path.join("::");
863855 item_path.retain(|c| c != ' ');
......@@ -867,7 +859,7 @@ impl ScrapedDocTest {
867859 let name =
868860 format!("{} - {item_path}(line {line})", filename.prefer_remapped_unconditionaly());
869861
870 Self { filename, line, langstr, text, name, span }
862 Self { filename, line, langstr, text, name, span, global_crate_attrs }
871863 }
872864 fn edition(&self, opts: &RustdocOptions) -> Edition {
873865 self.langstr.edition.unwrap_or(opts.edition)
......@@ -896,9 +888,15 @@ pub(crate) trait DocTestVisitor {
896888 fn visit_header(&mut self, _name: &str, _level: u32) {}
897889}
898890
891#[derive(Clone, Debug, Hash, Eq, PartialEq)]
892pub(crate) struct MergeableTestKey {
893 edition: Edition,
894 global_crate_attrs_hash: u64,
895}
896
899897struct CreateRunnableDocTests {
900898 standalone_tests: Vec<test::TestDescAndFn>,
901 mergeable_tests: FxIndexMap<Edition, Vec<(DocTestBuilder, ScrapedDocTest)>>,
899 mergeable_tests: FxIndexMap<MergeableTestKey, Vec<(DocTestBuilder, ScrapedDocTest)>>,
902900
903901 rustdoc_options: Arc<RustdocOptions>,
904902 opts: GlobalTestOptions,
......@@ -949,6 +947,7 @@ impl CreateRunnableDocTests {
949947 let edition = scraped_test.edition(&self.rustdoc_options);
950948 let doctest = BuildDocTestBuilder::new(&scraped_test.text)
951949 .crate_name(&self.opts.crate_name)
950 .global_crate_attrs(scraped_test.global_crate_attrs.clone())
952951 .edition(edition)
953952 .can_merge_doctests(self.can_merge_doctests)
954953 .test_id(test_id)
......@@ -965,7 +964,17 @@ impl CreateRunnableDocTests {
965964 let test_desc = self.generate_test_desc_and_fn(doctest, scraped_test);
966965 self.standalone_tests.push(test_desc);
967966 } else {
968 self.mergeable_tests.entry(edition).or_default().push((doctest, scraped_test));
967 self.mergeable_tests
968 .entry(MergeableTestKey {
969 edition,
970 global_crate_attrs_hash: {
971 let mut hasher = FxHasher::default();
972 scraped_test.global_crate_attrs.hash(&mut hasher);
973 hasher.finish()
974 },
975 })
976 .or_default()
977 .push((doctest, scraped_test));
969978 }
970979 }
971980
src/librustdoc/doctest/extracted.rs+4-1
......@@ -35,13 +35,16 @@ impl ExtractedDocTests {
3535 ) {
3636 let edition = scraped_test.edition(options);
3737
38 let ScrapedDocTest { filename, line, langstr, text, name, .. } = scraped_test;
38 let ScrapedDocTest { filename, line, langstr, text, name, global_crate_attrs, .. } =
39 scraped_test;
3940
4041 let doctest = BuildDocTestBuilder::new(&text)
4142 .crate_name(&opts.crate_name)
43 .global_crate_attrs(global_crate_attrs)
4244 .edition(edition)
4345 .lang_str(&langstr)
4446 .build(None);
47
4548 let (full_test_code, size) = doctest.generate_unique_doctest(
4649 &text,
4750 langstr.test_harness,
src/librustdoc/doctest/make.rs+18-3
......@@ -45,6 +45,7 @@ pub(crate) struct BuildDocTestBuilder<'a> {
4545 test_id: Option<String>,
4646 lang_str: Option<&'a LangString>,
4747 span: Span,
48 global_crate_attrs: Vec<String>,
4849}
4950
5051impl<'a> BuildDocTestBuilder<'a> {
......@@ -57,6 +58,7 @@ impl<'a> BuildDocTestBuilder<'a> {
5758 test_id: None,
5859 lang_str: None,
5960 span: DUMMY_SP,
61 global_crate_attrs: Vec::new(),
6062 }
6163 }
6264
......@@ -96,6 +98,12 @@ impl<'a> BuildDocTestBuilder<'a> {
9698 self
9799 }
98100
101 #[inline]
102 pub(crate) fn global_crate_attrs(mut self, global_crate_attrs: Vec<String>) -> Self {
103 self.global_crate_attrs = global_crate_attrs;
104 self
105 }
106
99107 pub(crate) fn build(self, dcx: Option<DiagCtxtHandle<'_>>) -> DocTestBuilder {
100108 let BuildDocTestBuilder {
101109 source,
......@@ -106,6 +114,7 @@ impl<'a> BuildDocTestBuilder<'a> {
106114 test_id,
107115 lang_str,
108116 span,
117 global_crate_attrs,
109118 } = self;
110119 let can_merge_doctests = can_merge_doctests
111120 && lang_str.is_some_and(|lang_str| {
......@@ -133,6 +142,7 @@ impl<'a> BuildDocTestBuilder<'a> {
133142 // If the AST returned an error, we don't want this doctest to be merged with the
134143 // others.
135144 return DocTestBuilder::invalid(
145 Vec::new(),
136146 String::new(),
137147 String::new(),
138148 String::new(),
......@@ -155,6 +165,7 @@ impl<'a> BuildDocTestBuilder<'a> {
155165 DocTestBuilder {
156166 supports_color,
157167 has_main_fn,
168 global_crate_attrs,
158169 crate_attrs,
159170 maybe_crate_attrs,
160171 crates,
......@@ -173,6 +184,7 @@ pub(crate) struct DocTestBuilder {
173184 pub(crate) supports_color: bool,
174185 pub(crate) already_has_extern_crate: bool,
175186 pub(crate) has_main_fn: bool,
187 pub(crate) global_crate_attrs: Vec<String>,
176188 pub(crate) crate_attrs: String,
177189 /// If this is a merged doctest, it will be put into `everything_else`, otherwise it will
178190 /// put into `crate_attrs`.
......@@ -186,6 +198,7 @@ pub(crate) struct DocTestBuilder {
186198
187199impl DocTestBuilder {
188200 fn invalid(
201 global_crate_attrs: Vec<String>,
189202 crate_attrs: String,
190203 maybe_crate_attrs: String,
191204 crates: String,
......@@ -195,6 +208,7 @@ impl DocTestBuilder {
195208 Self {
196209 supports_color: false,
197210 has_main_fn: false,
211 global_crate_attrs,
198212 crate_attrs,
199213 maybe_crate_attrs,
200214 crates,
......@@ -224,7 +238,8 @@ impl DocTestBuilder {
224238 let mut line_offset = 0;
225239 let mut prog = String::new();
226240 let everything_else = self.everything_else.trim();
227 if opts.attrs.is_empty() {
241
242 if self.global_crate_attrs.is_empty() {
228243 // If there aren't any attributes supplied by #![doc(test(attr(...)))], then allow some
229244 // lints that are commonly triggered in doctests. The crate-level test attributes are
230245 // commonly used to make tests fail in case they trigger warnings, so having this there in
......@@ -233,8 +248,8 @@ impl DocTestBuilder {
233248 line_offset += 1;
234249 }
235250
236 // Next, any attributes that came from the crate root via #![doc(test(attr(...)))].
237 for attr in &opts.attrs {
251 // Next, any attributes that came from #![doc(test(attr(...)))].
252 for attr in &self.global_crate_attrs {
238253 prog.push_str(&format!("#![{attr}]\n"));
239254 line_offset += 1;
240255 }
src/librustdoc/doctest/markdown.rs+1-1
......@@ -31,6 +31,7 @@ impl DocTestVisitor for MdCollector {
3131 config,
3232 test,
3333 DUMMY_SP,
34 Vec::new(),
3435 ));
3536 }
3637
......@@ -96,7 +97,6 @@ pub(crate) fn test(input: &Input, options: Options) -> Result<(), String> {
9697 crate_name,
9798 no_crate_inject: true,
9899 insert_indent_space: false,
99 attrs: vec![],
100100 args_file,
101101 };
102102
src/librustdoc/doctest/runner.rs+8-3
......@@ -12,6 +12,7 @@ use crate::html::markdown::{Ignore, LangString};
1212/// Convenient type to merge compatible doctests into one.
1313pub(crate) struct DocTestRunner {
1414 crate_attrs: FxIndexSet<String>,
15 global_crate_attrs: FxIndexSet<String>,
1516 ids: String,
1617 output: String,
1718 output_merged_tests: String,
......@@ -23,6 +24,7 @@ impl DocTestRunner {
2324 pub(crate) fn new() -> Self {
2425 Self {
2526 crate_attrs: FxIndexSet::default(),
27 global_crate_attrs: FxIndexSet::default(),
2628 ids: String::new(),
2729 output: String::new(),
2830 output_merged_tests: String::new(),
......@@ -46,6 +48,9 @@ impl DocTestRunner {
4648 for line in doctest.crate_attrs.split('\n') {
4749 self.crate_attrs.insert(line.to_string());
4850 }
51 for line in &doctest.global_crate_attrs {
52 self.global_crate_attrs.insert(line.to_string());
53 }
4954 }
5055 self.ids.push_str(&format!(
5156 "tests.push({}::TEST);\n",
......@@ -85,7 +90,7 @@ impl DocTestRunner {
8590 code_prefix.push('\n');
8691 }
8792
88 if opts.attrs.is_empty() {
93 if self.global_crate_attrs.is_empty() {
8994 // If there aren't any attributes supplied by #![doc(test(attr(...)))], then allow some
9095 // lints that are commonly triggered in doctests. The crate-level test attributes are
9196 // commonly used to make tests fail in case they trigger warnings, so having this there in
......@@ -93,8 +98,8 @@ impl DocTestRunner {
9398 code_prefix.push_str("#![allow(unused)]\n");
9499 }
95100
96 // Next, any attributes that came from the crate root via #![doc(test(attr(...)))].
97 for attr in &opts.attrs {
101 // Next, any attributes that came from #![doc(test(attr(...)))].
102 for attr in &self.global_crate_attrs {
98103 code_prefix.push_str(&format!("#![{attr}]\n"));
99104 }
100105
src/librustdoc/doctest/rust.rs+28-1
......@@ -4,6 +4,7 @@ use std::cell::Cell;
44use std::env;
55use std::sync::Arc;
66
7use rustc_ast_pretty::pprust;
78use rustc_data_structures::fx::FxHashSet;
89use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId};
910use rustc_hir::{self as hir, CRATE_HIR_ID, intravisit};
......@@ -11,7 +12,7 @@ use rustc_middle::hir::nested_filter;
1112use rustc_middle::ty::TyCtxt;
1213use rustc_resolve::rustdoc::span_of_fragments;
1314use rustc_span::source_map::SourceMap;
14use rustc_span::{BytePos, DUMMY_SP, FileName, Pos, Span};
15use rustc_span::{BytePos, DUMMY_SP, FileName, Pos, Span, sym};
1516
1617use super::{DocTestVisitor, ScrapedDocTest};
1718use crate::clean::{Attributes, extract_cfg_from_attrs};
......@@ -22,6 +23,7 @@ struct RustCollector {
2223 tests: Vec<ScrapedDocTest>,
2324 cur_path: Vec<String>,
2425 position: Span,
26 global_crate_attrs: Vec<String>,
2527}
2628
2729impl RustCollector {
......@@ -75,6 +77,7 @@ impl DocTestVisitor for RustCollector {
7577 config,
7678 test,
7779 span,
80 self.global_crate_attrs.clone(),
7881 ));
7982 }
8083
......@@ -94,6 +97,7 @@ impl<'tcx> HirCollector<'tcx> {
9497 cur_path: vec![],
9598 position: DUMMY_SP,
9699 tests: vec![],
100 global_crate_attrs: Vec::new(),
97101 };
98102 Self { codes, tcx, collector }
99103 }
......@@ -123,6 +127,26 @@ impl HirCollector<'_> {
123127 return;
124128 }
125129
130 // Try collecting `#[doc(test(attr(...)))]`
131 let old_global_crate_attrs_len = self.collector.global_crate_attrs.len();
132 for doc_test_attrs in ast_attrs
133 .iter()
134 .filter(|a| a.has_name(sym::doc))
135 .flat_map(|a| a.meta_item_list().unwrap_or_default())
136 .filter(|a| a.has_name(sym::test))
137 {
138 let Some(doc_test_attrs) = doc_test_attrs.meta_item_list() else { continue };
139 for attr in doc_test_attrs
140 .iter()
141 .filter(|a| a.has_name(sym::attr))
142 .flat_map(|a| a.meta_item_list().unwrap_or_default())
143 .map(|i| pprust::meta_list_item_to_string(i))
144 {
145 // Add the additional attributes to the global_crate_attrs vector
146 self.collector.global_crate_attrs.push(attr);
147 }
148 }
149
126150 let mut has_name = false;
127151 if let Some(name) = name {
128152 self.collector.cur_path.push(name);
......@@ -157,6 +181,9 @@ impl HirCollector<'_> {
157181
158182 nested(self);
159183
184 // Restore global_crate_attrs to it's previous size/content
185 self.collector.global_crate_attrs.truncate(old_global_crate_attrs_len);
186
160187 if has_name {
161188 self.collector.cur_path.pop();
162189 }
src/librustdoc/doctest/tests.rs+39-29
......@@ -7,9 +7,11 @@ fn make_test(
77 crate_name: Option<&str>,
88 dont_insert_main: bool,
99 opts: &GlobalTestOptions,
10 global_crate_attrs: Vec<&str>,
1011 test_id: Option<&str>,
1112) -> (String, usize) {
12 let mut builder = BuildDocTestBuilder::new(test_code);
13 let mut builder = BuildDocTestBuilder::new(test_code)
14 .global_crate_attrs(global_crate_attrs.into_iter().map(|a| a.to_string()).collect());
1315 if let Some(crate_name) = crate_name {
1416 builder = builder.crate_name(crate_name);
1517 }
......@@ -28,7 +30,6 @@ fn default_global_opts(crate_name: impl Into<String>) -> GlobalTestOptions {
2830 crate_name: crate_name.into(),
2931 no_crate_inject: false,
3032 insert_indent_space: false,
31 attrs: vec![],
3233 args_file: PathBuf::new(),
3334 }
3435}
......@@ -43,7 +44,7 @@ fn main() {
4344assert_eq!(2+2, 4);
4445}"
4546 .to_string();
46 let (output, len) = make_test(input, None, false, &opts, None);
47 let (output, len) = make_test(input, None, false, &opts, Vec::new(), None);
4748 assert_eq!((output, len), (expected, 2));
4849}
4950
......@@ -58,7 +59,7 @@ fn main() {
5859assert_eq!(2+2, 4);
5960}"
6061 .to_string();
61 let (output, len) = make_test(input, Some("asdf"), false, &opts, None);
62 let (output, len) = make_test(input, Some("asdf"), false, &opts, Vec::new(), None);
6263 assert_eq!((output, len), (expected, 2));
6364}
6465
......@@ -77,7 +78,7 @@ use asdf::qwop;
7778assert_eq!(2+2, 4);
7879}"
7980 .to_string();
80 let (output, len) = make_test(input, Some("asdf"), false, &opts, None);
81 let (output, len) = make_test(input, Some("asdf"), false, &opts, Vec::new(), None);
8182 assert_eq!((output, len), (expected, 3));
8283}
8384
......@@ -94,7 +95,7 @@ use asdf::qwop;
9495assert_eq!(2+2, 4);
9596}"
9697 .to_string();
97 let (output, len) = make_test(input, Some("asdf"), false, &opts, None);
98 let (output, len) = make_test(input, Some("asdf"), false, &opts, Vec::new(), None);
9899 assert_eq!((output, len), (expected, 2));
99100}
100101
......@@ -112,7 +113,7 @@ use std::*;
112113assert_eq!(2+2, 4);
113114}"
114115 .to_string();
115 let (output, len) = make_test(input, Some("std"), false, &opts, None);
116 let (output, len) = make_test(input, Some("std"), false, &opts, Vec::new(), None);
116117 assert_eq!((output, len), (expected, 2));
117118}
118119
......@@ -131,7 +132,7 @@ use asdf::qwop;
131132assert_eq!(2+2, 4);
132133}"
133134 .to_string();
134 let (output, len) = make_test(input, Some("asdf"), false, &opts, None);
135 let (output, len) = make_test(input, Some("asdf"), false, &opts, Vec::new(), None);
135136 assert_eq!((output, len), (expected, 2));
136137}
137138
......@@ -148,7 +149,7 @@ use asdf::qwop;
148149assert_eq!(2+2, 4);
149150}"
150151 .to_string();
151 let (output, len) = make_test(input, Some("asdf"), false, &opts, None);
152 let (output, len) = make_test(input, Some("asdf"), false, &opts, Vec::new(), None);
152153 assert_eq!((output, len), (expected, 2));
153154}
154155
......@@ -156,8 +157,7 @@ assert_eq!(2+2, 4);
156157fn make_test_opts_attrs() {
157158 // If you supplied some doctest attributes with `#![doc(test(attr(...)))]`, it will use
158159 // those instead of the stock `#![allow(unused)]`.
159 let mut opts = default_global_opts("asdf");
160 opts.attrs.push("feature(sick_rad)".to_string());
160 let opts = default_global_opts("asdf");
161161 let input = "use asdf::qwop;
162162assert_eq!(2+2, 4);";
163163 let expected = "#![feature(sick_rad)]
......@@ -168,11 +168,10 @@ use asdf::qwop;
168168assert_eq!(2+2, 4);
169169}"
170170 .to_string();
171 let (output, len) = make_test(input, Some("asdf"), false, &opts, None);
171 let (output, len) =
172 make_test(input, Some("asdf"), false, &opts, vec!["feature(sick_rad)"], None);
172173 assert_eq!((output, len), (expected, 3));
173174
174 // Adding more will also bump the returned line offset.
175 opts.attrs.push("feature(hella_dope)".to_string());
176175 let expected = "#![feature(sick_rad)]
177176#![feature(hella_dope)]
178177#[allow(unused_extern_crates)]
......@@ -182,7 +181,18 @@ use asdf::qwop;
182181assert_eq!(2+2, 4);
183182}"
184183 .to_string();
185 let (output, len) = make_test(input, Some("asdf"), false, &opts, None);
184 let (output, len) = make_test(
185 input,
186 Some("asdf"),
187 false,
188 &opts,
189 vec![
190 "feature(sick_rad)",
191 // Adding more will also bump the returned line offset.
192 "feature(hella_dope)",
193 ],
194 None,
195 );
186196 assert_eq!((output, len), (expected, 4));
187197}
188198
......@@ -200,7 +210,7 @@ fn main() {
200210assert_eq!(2+2, 4);
201211}"
202212 .to_string();
203 let (output, len) = make_test(input, None, false, &opts, None);
213 let (output, len) = make_test(input, None, false, &opts, Vec::new(), None);
204214 assert_eq!((output, len), (expected, 2));
205215}
206216
......@@ -216,7 +226,7 @@ fn main() {
216226 assert_eq!(2+2, 4);
217227}"
218228 .to_string();
219 let (output, len) = make_test(input, None, false, &opts, None);
229 let (output, len) = make_test(input, None, false, &opts, Vec::new(), None);
220230 assert_eq!((output, len), (expected, 1));
221231}
222232
......@@ -232,7 +242,7 @@ fn main() {
232242assert_eq!(2+2, 4);
233243}"
234244 .to_string();
235 let (output, len) = make_test(input, None, false, &opts, None);
245 let (output, len) = make_test(input, None, false, &opts, Vec::new(), None);
236246 assert_eq!((output, len), (expected, 2));
237247}
238248
......@@ -246,7 +256,7 @@ assert_eq!(2+2, 4);";
246256//Ceci n'est pas une `fn main`
247257assert_eq!(2+2, 4);"
248258 .to_string();
249 let (output, len) = make_test(input, None, true, &opts, None);
259 let (output, len) = make_test(input, None, true, &opts, Vec::new(), None);
250260 assert_eq!((output, len), (expected, 1));
251261}
252262
......@@ -264,7 +274,7 @@ assert_eq!(2+2, 4);
264274}"
265275 .to_string();
266276
267 let (output, len) = make_test(input, None, false, &opts, None);
277 let (output, len) = make_test(input, None, false, &opts, Vec::new(), None);
268278 assert_eq!((output, len), (expected, 2));
269279}
270280
......@@ -284,7 +294,7 @@ assert_eq!(asdf::foo, 4);
284294}"
285295 .to_string();
286296
287 let (output, len) = make_test(input, Some("asdf"), false, &opts, None);
297 let (output, len) = make_test(input, Some("asdf"), false, &opts, Vec::new(), None);
288298 assert_eq!((output, len), (expected, 3));
289299}
290300
......@@ -302,7 +312,7 @@ test_wrapper! {
302312}"
303313 .to_string();
304314
305 let (output, len) = make_test(input, Some("my_crate"), false, &opts, None);
315 let (output, len) = make_test(input, Some("my_crate"), false, &opts, Vec::new(), None);
306316 assert_eq!((output, len), (expected, 1));
307317}
308318
......@@ -322,7 +332,7 @@ io::stdin().read_line(&mut input)?;
322332Ok::<(), io:Error>(())
323333} _inner().unwrap() }"
324334 .to_string();
325 let (output, len) = make_test(input, None, false, &opts, None);
335 let (output, len) = make_test(input, None, false, &opts, Vec::new(), None);
326336 assert_eq!((output, len), (expected, 2));
327337}
328338
......@@ -336,7 +346,7 @@ fn main() { #[allow(non_snake_case)] fn _doctest_main__some_unique_name() {
336346assert_eq!(2+2, 4);
337347} _doctest_main__some_unique_name() }"
338348 .to_string();
339 let (output, len) = make_test(input, None, false, &opts, Some("_some_unique_name"));
349 let (output, len) = make_test(input, None, false, &opts, Vec::new(), Some("_some_unique_name"));
340350 assert_eq!((output, len), (expected, 2));
341351}
342352
......@@ -355,7 +365,7 @@ fn main() {
355365 eprintln!(\"hello anan\");
356366}"
357367 .to_string();
358 let (output, len) = make_test(input, None, false, &opts, None);
368 let (output, len) = make_test(input, None, false, &opts, Vec::new(), None);
359369 assert_eq!((output, len), (expected, 2));
360370}
361371
......@@ -375,7 +385,7 @@ fn main() {
375385 eprintln!(\"hello anan\");
376386}"
377387 .to_string();
378 let (output, len) = make_test(input, None, false, &opts, None);
388 let (output, len) = make_test(input, None, false, &opts, Vec::new(), None);
379389 assert_eq!((output, len), (expected, 1));
380390}
381391
......@@ -400,7 +410,7 @@ fn main() {
400410
401411}"
402412 .to_string();
403 let (output, len) = make_test(input, None, false, &opts, None);
413 let (output, len) = make_test(input, None, false, &opts, Vec::new(), None);
404414 assert_eq!((output, len), (expected, 2));
405415
406416 // And same, if there is a `main` function provided by the user, we ensure that it's
......@@ -420,7 +430,7 @@ fn main() {}";
420430
421431fn main() {}"
422432 .to_string();
423 let (output, len) = make_test(input, None, false, &opts, None);
433 let (output, len) = make_test(input, None, false, &opts, Vec::new(), None);
424434 assert_eq!((output, len), (expected, 1));
425435}
426436
......@@ -448,6 +458,6 @@ pub mod outer_module {
448458}
449459}"
450460 .to_string();
451 let (output, len) = make_test(input, None, false, &opts, None);
461 let (output, len) = make_test(input, None, false, &opts, Vec::new(), None);
452462 assert_eq!((output, len), (expected, 2));
453463}
src/librustdoc/html/markdown.rs-1
......@@ -300,7 +300,6 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'_, 'a, I> {
300300 crate_name: krate.map(String::from).unwrap_or_default(),
301301 no_crate_inject: false,
302302 insert_indent_space: true,
303 attrs: vec![],
304303 args_file: PathBuf::new(),
305304 };
306305 let mut builder = doctest::BuildDocTestBuilder::new(&test).edition(edition);
src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs-14
......@@ -4451,20 +4451,6 @@ The tracking issue for this feature is: [#133214]
44514451
44524452[#133214]: https://github.com/rust-lang/rust/issues/133214
44534453
4454------------------------
4455"##,
4456 default_severity: Severity::Allow,
4457 warn_since: None,
4458 deny_since: None,
4459 },
4460 Lint {
4461 label: "const_eq_ignore_ascii_case",
4462 description: r##"# `const_eq_ignore_ascii_case`
4463
4464The tracking issue for this feature is: [#131719]
4465
4466[#131719]: https://github.com/rust-lang/rust/issues/131719
4467
44684454------------------------
44694455"##,
44704456 default_severity: Severity::Allow,
tests/crashes/140571.rs deleted-14
......@@ -1,14 +0,0 @@
1//@ known-bug: #140571
2pub trait IsVoid {
3 const IS_VOID: bool;
4}
5impl<T> IsVoid for T {
6 default const IS_VOID: bool = false;
7}
8impl<T> Maybe<T> for () where T: NotVoid + ?Sized {}
9
10pub trait NotVoid {}
11impl<T> NotVoid for T where T: IsVoid<IS_VOID = false> + ?Sized {}
12
13pub trait Maybe<T> {}
14impl<T> Maybe<T> for T {}
tests/run-make/doctests-keep-binaries-2024/rmake.rs+16-1
......@@ -16,7 +16,22 @@ fn setup_test_env<F: FnOnce(&Path, &Path)>(callback: F) {
1616}
1717
1818fn check_generated_binaries() {
19 run("doctests/merged_doctest_2024/rust_out");
19 let mut found_merged_doctest = false;
20 rfs::read_dir_entries("doctests/", |path| {
21 if path
22 .file_name()
23 .and_then(|name| name.to_str())
24 .is_some_and(|name| name.starts_with("merged_doctest_2024"))
25 {
26 found_merged_doctest = true;
27 let rust_out = path.join("rust_out");
28 let rust_out = rust_out.to_string_lossy();
29 run(&*rust_out);
30 }
31 });
32 if !found_merged_doctest {
33 panic!("no directory starting with `merged_doctest_2024` found under `doctests/`");
34 }
2035}
2136
2237fn main() {
tests/rustdoc-ui/doctest/dead-code-items.rs created+116
......@@ -0,0 +1,116 @@
1// Same test as dead-code-module but with 2 doc(test(attr())) at different levels.
2
3//@ edition: 2024
4//@ compile-flags:--test --test-args=--test-threads=1
5//@ normalize-stdout: "tests/rustdoc-ui/doctest" -> "$$DIR"
6//@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME"
7//@ failure-status: 101
8
9#![doc(test(attr(deny(warnings))))]
10
11#[doc(test(attr(allow(dead_code))))]
12/// Example
13///
14/// ```rust,no_run
15/// trait OnlyWarning { fn no_deny_warnings(); }
16/// ```
17static S: u32 = 5;
18
19#[doc(test(attr(allow(dead_code))))]
20/// Example
21///
22/// ```rust,no_run
23/// let unused_error = 5;
24///
25/// fn dead_code_but_no_error() {}
26/// ```
27const C: u32 = 5;
28
29#[doc(test(attr(allow(dead_code))))]
30/// Example
31///
32/// ```rust,no_run
33/// trait OnlyWarningAtA { fn no_deny_warnings(); }
34/// ```
35struct A {
36 #[doc(test(attr(deny(dead_code))))]
37 /// Example
38 ///
39 /// ```rust,no_run
40 /// trait DeadCodeInField {}
41 /// ```
42 field: u32
43}
44
45#[doc(test(attr(allow(dead_code))))]
46/// Example
47///
48/// ```rust,no_run
49/// trait OnlyWarningAtU { fn no_deny_warnings(); }
50/// ```
51union U {
52 #[doc(test(attr(deny(dead_code))))]
53 /// Example
54 ///
55 /// ```rust,no_run
56 /// trait DeadCodeInUnionField {}
57 /// ```
58 field: u32,
59 /// Example
60 ///
61 /// ```rust,no_run
62 /// trait NotDeadCodeInUnionField {}
63 /// ```
64 field2: u64,
65}
66
67#[doc(test(attr(deny(dead_code))))]
68/// Example
69///
70/// ```rust,no_run
71/// let not_dead_code_but_unused = 5;
72/// ```
73enum Enum {
74 #[doc(test(attr(allow(dead_code))))]
75 /// Example
76 ///
77 /// ```rust,no_run
78 /// trait NotDeadCodeInVariant {}
79 ///
80 /// fn main() { let unused_in_variant = 5; }
81 /// ```
82 Variant1,
83}
84
85#[doc(test(attr(allow(dead_code))))]
86/// Example
87///
88/// ```rust,no_run
89/// trait OnlyWarningAtImplA { fn no_deny_warnings(); }
90/// ```
91impl A {
92 /// Example
93 ///
94 /// ```rust,no_run
95 /// trait NotDeadCodeInImplMethod {}
96 /// ```
97 fn method() {}
98}
99
100#[doc(test(attr(deny(dead_code))))]
101/// Example
102///
103/// ```rust,no_run
104/// trait StillDeadCodeAtMyTrait { }
105/// ```
106trait MyTrait {
107 #[doc(test(attr(allow(dead_code))))]
108 /// Example
109 ///
110 /// ```rust,no_run
111 /// trait NotDeadCodeAtImplFn {}
112 ///
113 /// fn main() { let unused_in_impl = 5; }
114 /// ```
115 fn my_trait_fn();
116}
tests/rustdoc-ui/doctest/dead-code-items.stdout created+146
......@@ -0,0 +1,146 @@
1
2running 13 tests
3test $DIR/dead-code-items.rs - A (line 32) - compile ... ok
4test $DIR/dead-code-items.rs - A (line 88) - compile ... ok
5test $DIR/dead-code-items.rs - A::field (line 39) - compile ... FAILED
6test $DIR/dead-code-items.rs - A::method (line 94) - compile ... ok
7test $DIR/dead-code-items.rs - C (line 22) - compile ... FAILED
8test $DIR/dead-code-items.rs - Enum (line 70) - compile ... FAILED
9test $DIR/dead-code-items.rs - Enum::Variant1 (line 77) - compile ... FAILED
10test $DIR/dead-code-items.rs - MyTrait (line 103) - compile ... FAILED
11test $DIR/dead-code-items.rs - MyTrait::my_trait_fn (line 110) - compile ... FAILED
12test $DIR/dead-code-items.rs - S (line 14) - compile ... ok
13test $DIR/dead-code-items.rs - U (line 48) - compile ... ok
14test $DIR/dead-code-items.rs - U::field (line 55) - compile ... FAILED
15test $DIR/dead-code-items.rs - U::field2 (line 61) - compile ... ok
16
17failures:
18
19---- $DIR/dead-code-items.rs - A::field (line 39) stdout ----
20error: trait `DeadCodeInField` is never used
21 --> $DIR/dead-code-items.rs:40:7
22 |
23LL | trait DeadCodeInField {}
24 | ^^^^^^^^^^^^^^^
25 |
26note: the lint level is defined here
27 --> $DIR/dead-code-items.rs:38:9
28 |
29LL | #![deny(dead_code)]
30 | ^^^^^^^^^
31
32error: aborting due to 1 previous error
33
34Couldn't compile the test.
35---- $DIR/dead-code-items.rs - C (line 22) stdout ----
36error: unused variable: `unused_error`
37 --> $DIR/dead-code-items.rs:23:5
38 |
39LL | let unused_error = 5;
40 | ^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused_error`
41 |
42note: the lint level is defined here
43 --> $DIR/dead-code-items.rs:20:9
44 |
45LL | #![deny(warnings)]
46 | ^^^^^^^^
47 = note: `#[deny(unused_variables)]` implied by `#[deny(warnings)]`
48
49error: aborting due to 1 previous error
50
51Couldn't compile the test.
52---- $DIR/dead-code-items.rs - Enum (line 70) stdout ----
53error: unused variable: `not_dead_code_but_unused`
54 --> $DIR/dead-code-items.rs:71:5
55 |
56LL | let not_dead_code_but_unused = 5;
57 | ^^^^^^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_not_dead_code_but_unused`
58 |
59note: the lint level is defined here
60 --> $DIR/dead-code-items.rs:68:9
61 |
62LL | #![deny(warnings)]
63 | ^^^^^^^^
64 = note: `#[deny(unused_variables)]` implied by `#[deny(warnings)]`
65
66error: aborting due to 1 previous error
67
68Couldn't compile the test.
69---- $DIR/dead-code-items.rs - Enum::Variant1 (line 77) stdout ----
70error: unused variable: `unused_in_variant`
71 --> $DIR/dead-code-items.rs:80:17
72 |
73LL | fn main() { let unused_in_variant = 5; }
74 | ^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused_in_variant`
75 |
76note: the lint level is defined here
77 --> $DIR/dead-code-items.rs:75:9
78 |
79LL | #![deny(warnings)]
80 | ^^^^^^^^
81 = note: `#[deny(unused_variables)]` implied by `#[deny(warnings)]`
82
83error: aborting due to 1 previous error
84
85Couldn't compile the test.
86---- $DIR/dead-code-items.rs - MyTrait (line 103) stdout ----
87error: trait `StillDeadCodeAtMyTrait` is never used
88 --> $DIR/dead-code-items.rs:104:7
89 |
90LL | trait StillDeadCodeAtMyTrait { }
91 | ^^^^^^^^^^^^^^^^^^^^^^
92 |
93note: the lint level is defined here
94 --> $DIR/dead-code-items.rs:102:9
95 |
96LL | #![deny(dead_code)]
97 | ^^^^^^^^^
98
99error: aborting due to 1 previous error
100
101Couldn't compile the test.
102---- $DIR/dead-code-items.rs - MyTrait::my_trait_fn (line 110) stdout ----
103error: unused variable: `unused_in_impl`
104 --> $DIR/dead-code-items.rs:113:17
105 |
106LL | fn main() { let unused_in_impl = 5; }
107 | ^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused_in_impl`
108 |
109note: the lint level is defined here
110 --> $DIR/dead-code-items.rs:108:9
111 |
112LL | #![deny(warnings)]
113 | ^^^^^^^^
114 = note: `#[deny(unused_variables)]` implied by `#[deny(warnings)]`
115
116error: aborting due to 1 previous error
117
118Couldn't compile the test.
119---- $DIR/dead-code-items.rs - U::field (line 55) stdout ----
120error: trait `DeadCodeInUnionField` is never used
121 --> $DIR/dead-code-items.rs:56:7
122 |
123LL | trait DeadCodeInUnionField {}
124 | ^^^^^^^^^^^^^^^^^^^^
125 |
126note: the lint level is defined here
127 --> $DIR/dead-code-items.rs:54:9
128 |
129LL | #![deny(dead_code)]
130 | ^^^^^^^^^
131
132error: aborting due to 1 previous error
133
134Couldn't compile the test.
135
136failures:
137 $DIR/dead-code-items.rs - A::field (line 39)
138 $DIR/dead-code-items.rs - C (line 22)
139 $DIR/dead-code-items.rs - Enum (line 70)
140 $DIR/dead-code-items.rs - Enum::Variant1 (line 77)
141 $DIR/dead-code-items.rs - MyTrait (line 103)
142 $DIR/dead-code-items.rs - MyTrait::my_trait_fn (line 110)
143 $DIR/dead-code-items.rs - U::field (line 55)
144
145test result: FAILED. 6 passed; 7 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
146
tests/rustdoc-ui/doctest/dead-code-module-2.rs created+27
......@@ -0,0 +1,27 @@
1// Same test as dead-code-module but with 2 doc(test(attr())) at different levels.
2
3//@ edition: 2024
4//@ compile-flags:--test
5//@ normalize-stdout: "tests/rustdoc-ui/doctest" -> "$$DIR"
6//@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME"
7//@ failure-status: 101
8
9#![doc(test(attr(allow(unused_variables))))]
10
11mod my_mod {
12 #![doc(test(attr(deny(warnings))))]
13
14 /// Example
15 ///
16 /// ```rust,no_run
17 /// trait T { fn f(); }
18 /// ```
19 pub fn f() {}
20}
21
22/// Example
23///
24/// ```rust,no_run
25/// trait OnlyWarning { fn no_deny_warnings(); }
26/// ```
27pub fn g() {}
tests/rustdoc-ui/doctest/dead-code-module-2.stdout created+35
......@@ -0,0 +1,35 @@
1
2running 1 test
3test $DIR/dead-code-module-2.rs - g (line 24) - compile ... ok
4
5test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
6
7
8running 1 test
9test $DIR/dead-code-module-2.rs - my_mod::f (line 16) - compile ... FAILED
10
11failures:
12
13---- $DIR/dead-code-module-2.rs - my_mod::f (line 16) stdout ----
14error: trait `T` is never used
15 --> $DIR/dead-code-module-2.rs:17:7
16 |
17LL | trait T { fn f(); }
18 | ^
19 |
20note: the lint level is defined here
21 --> $DIR/dead-code-module-2.rs:15:9
22 |
23LL | #![deny(warnings)]
24 | ^^^^^^^^
25 = note: `#[deny(dead_code)]` implied by `#[deny(warnings)]`
26
27error: aborting due to 1 previous error
28
29Couldn't compile the test.
30
31failures:
32 $DIR/dead-code-module-2.rs - my_mod::f (line 16)
33
34test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
35
tests/rustdoc-ui/doctest/dead-code-module.rs created+18
......@@ -0,0 +1,18 @@
1// Same test as dead-code but inside a module.
2
3//@ edition: 2024
4//@ compile-flags:--test
5//@ normalize-stdout: "tests/rustdoc-ui/doctest" -> "$$DIR"
6//@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME"
7//@ failure-status: 101
8
9mod my_mod {
10 #![doc(test(attr(allow(unused_variables), deny(warnings))))]
11
12 /// Example
13 ///
14 /// ```rust,no_run
15 /// trait T { fn f(); }
16 /// ```
17 pub fn f() {}
18}
tests/rustdoc-ui/doctest/dead-code-module.stdout created+29
......@@ -0,0 +1,29 @@
1
2running 1 test
3test $DIR/dead-code-module.rs - my_mod::f (line 14) - compile ... FAILED
4
5failures:
6
7---- $DIR/dead-code-module.rs - my_mod::f (line 14) stdout ----
8error: trait `T` is never used
9 --> $DIR/dead-code-module.rs:15:7
10 |
11LL | trait T { fn f(); }
12 | ^
13 |
14note: the lint level is defined here
15 --> $DIR/dead-code-module.rs:13:9
16 |
17LL | #![deny(warnings)]
18 | ^^^^^^^^
19 = note: `#[deny(dead_code)]` implied by `#[deny(warnings)]`
20
21error: aborting due to 1 previous error
22
23Couldn't compile the test.
24
25failures:
26 $DIR/dead-code-module.rs - my_mod::f (line 14)
27
28test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
29
tests/rustdoc-ui/doctest/doc-test-attr-pass-module.rs created+11
......@@ -0,0 +1,11 @@
1//@ check-pass
2
3#![crate_type = "lib"]
4#![deny(invalid_doc_attributes)]
5#![doc(test(no_crate_inject))]
6
7mod my_mod {
8 #![doc(test(attr(deny(warnings))))]
9
10 pub fn foo() {}
11}
tests/ui/future-incompatible-lint-group.rs+4-6
......@@ -2,16 +2,14 @@
22// lints for changes that are not tied to an edition
33#![deny(future_incompatible)]
44
5// Error since this is a `future_incompatible` lint
6macro_rules! m { ($i) => {} } //~ ERROR missing fragment specifier
7 //~| WARN this was previously accepted
8
59trait Tr {
610 // Warn only since this is not a `future_incompatible` lint
711 fn f(u8) {} //~ WARN anonymous parameters are deprecated
812 //~| WARN this is accepted in the current edition
913}
1014
11pub mod submodule {
12 // Error since this is a `future_incompatible` lint
13 #![doc(test(some_test))]
14 //~^ ERROR this attribute can only be applied at the crate level
15}
16
1715fn main() {}
tests/ui/future-incompatible-lint-group.stderr+31-9
......@@ -1,5 +1,20 @@
1error: missing fragment specifier
2 --> $DIR/future-incompatible-lint-group.rs:6:19
3 |
4LL | macro_rules! m { ($i) => {} }
5 | ^^
6 |
7 = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
8 = note: for more information, see issue #40107 <https://github.com/rust-lang/rust/issues/40107>
9note: the lint level is defined here
10 --> $DIR/future-incompatible-lint-group.rs:3:9
11 |
12LL | #![deny(future_incompatible)]
13 | ^^^^^^^^^^^^^^^^^^^
14 = note: `#[deny(missing_fragment_specifier)]` implied by `#[deny(future_incompatible)]`
15
116warning: anonymous parameters are deprecated and will be removed in the next edition
2 --> $DIR/future-incompatible-lint-group.rs:7:10
17 --> $DIR/future-incompatible-lint-group.rs:11:10
318 |
419LL | fn f(u8) {}
520 | ^^ help: try naming the parameter or explicitly ignoring it: `_: u8`
......@@ -8,14 +23,21 @@ LL | fn f(u8) {}
823 = note: for more information, see issue #41686 <https://github.com/rust-lang/rust/issues/41686>
924 = note: `#[warn(anonymous_parameters)]` on by default
1025
11error: this attribute can only be applied at the crate level
12 --> $DIR/future-incompatible-lint-group.rs:13:12
26error: aborting due to 1 previous error; 1 warning emitted
27
28Future incompatibility report: Future breakage diagnostic:
29error: missing fragment specifier
30 --> $DIR/future-incompatible-lint-group.rs:6:19
1331 |
14LL | #![doc(test(some_test))]
15 | ^^^^^^^^^^^^^^^
32LL | macro_rules! m { ($i) => {} }
33 | ^^
1634 |
17 = note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information
18 = note: `#[deny(invalid_doc_attributes)]` on by default
19
20error: aborting due to 1 previous error; 1 warning emitted
35 = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
36 = note: for more information, see issue #40107 <https://github.com/rust-lang/rust/issues/40107>
37note: the lint level is defined here
38 --> $DIR/future-incompatible-lint-group.rs:3:9
39 |
40LL | #![deny(future_incompatible)]
41 | ^^^^^^^^^^^^^^^^^^^
42 = note: `#[deny(missing_fragment_specifier)]` implied by `#[deny(future_incompatible)]`
2143
tests/ui/lint/force-warn/ice-free.rs created+9
......@@ -0,0 +1,9 @@
1//@ compile-flags: --force-warn pub_use_of_private_extern_crate
2//@ check-pass
3
4extern crate core;
5pub use core as reexported_core;
6//~^ warning: extern crate `core` is private
7//~| warning: this was previously accepted by the compiler
8
9fn main() {}
tests/ui/lint/force-warn/ice-free.stderr created+32
......@@ -0,0 +1,32 @@
1warning[E0365]: extern crate `core` is private and cannot be re-exported
2 --> $DIR/ice-free.rs:5:9
3 |
4LL | pub use core as reexported_core;
5 | ^^^^^^^^^^^^^^^^^^^^^^^
6 |
7 = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
8 = note: for more information, see issue #127909 <https://github.com/rust-lang/rust/issues/127909>
9 = note: requested on the command line with `--force-warn pub-use-of-private-extern-crate`
10help: consider making the `extern crate` item publicly accessible
11 |
12LL | pub extern crate core;
13 | +++
14
15warning: 1 warning emitted
16
17For more information about this error, try `rustc --explain E0365`.
18Future incompatibility report: Future breakage diagnostic:
19warning[E0365]: extern crate `core` is private and cannot be re-exported
20 --> $DIR/ice-free.rs:5:9
21 |
22LL | pub use core as reexported_core;
23 | ^^^^^^^^^^^^^^^^^^^^^^^
24 |
25 = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
26 = note: for more information, see issue #127909 <https://github.com/rust-lang/rust/issues/127909>
27 = note: requested on the command line with `--force-warn pub-use-of-private-extern-crate`
28help: consider making the `extern crate` item publicly accessible
29 |
30LL | pub extern crate core;
31 | +++
32
tests/ui/lint/implicit_autorefs.fixed+28-25
......@@ -1,4 +1,4 @@
1//@ check-pass
1//@ check-fail
22//@ run-rustfix
33
44#![allow(dead_code)] // For the rustfix-ed code.
......@@ -8,7 +8,7 @@ use std::ops::Deref;
88
99unsafe fn test_const(ptr: *const [u8]) {
1010 let _ = (&(*ptr))[..16];
11 //~^ WARN implicit autoref
11 //~^ ERROR implicit autoref
1212}
1313
1414struct Test {
......@@ -17,36 +17,36 @@ struct Test {
1717
1818unsafe fn test_field(ptr: *const Test) -> *const [u8] {
1919 let l = (&(*ptr).field).len();
20 //~^ WARN implicit autoref
20 //~^ ERROR implicit autoref
2121
2222 &raw const (&(*ptr).field)[..l - 1]
23 //~^ WARN implicit autoref
23 //~^ ERROR implicit autoref
2424}
2525
2626unsafe fn test_builtin_index(a: *mut [String]) {
2727 _ = (&(*a)[0]).len();
28 //~^ WARN implicit autoref
28 //~^ ERROR implicit autoref
2929
3030 _ = (&(&(*a))[..1][0]).len();
31 //~^ WARN implicit autoref
32 //~^^ WARN implicit autoref
31 //~^ ERROR implicit autoref
32 //~^^ ERROR implicit autoref
3333}
3434
3535unsafe fn test_overloaded_deref_const(ptr: *const ManuallyDrop<Test>) {
3636 let _ = (&(*ptr)).field;
37 //~^ WARN implicit autoref
37 //~^ ERROR implicit autoref
3838 let _ = &raw const (&(*ptr)).field;
39 //~^ WARN implicit autoref
39 //~^ ERROR implicit autoref
4040}
4141
4242unsafe fn test_overloaded_deref_mut(ptr: *mut ManuallyDrop<Test>) {
4343 let _ = (&(*ptr)).field;
44 //~^ WARN implicit autoref
44 //~^ ERROR implicit autoref
4545}
4646
4747unsafe fn test_double_overloaded_deref_const(ptr: *const ManuallyDrop<ManuallyDrop<Test>>) {
4848 let _ = (&(*ptr)).field;
49 //~^ WARN implicit autoref
49 //~^ ERROR implicit autoref
5050}
5151
5252unsafe fn test_manually_overloaded_deref() {
......@@ -54,52 +54,55 @@ unsafe fn test_manually_overloaded_deref() {
5454
5555 impl<T> Deref for W<T> {
5656 type Target = T;
57 fn deref(&self) -> &T { &self.0 }
57 fn deref(&self) -> &T {
58 &self.0
59 }
5860 }
5961
6062 let w: W<i32> = W(5);
6163 let w = &raw const w;
6264 let _p: *const i32 = &raw const *(&**w);
63 //~^ WARN implicit autoref
65 //~^ ERROR implicit autoref
6466}
6567
6668struct Test2 {
6769 // Derefs to `[u8]`.
68 field: &'static [u8]
70 field: &'static [u8],
6971}
7072
7173fn test_more_manual_deref(ptr: *const Test2) -> usize {
7274 unsafe { (&(*ptr).field).len() }
73 //~^ WARN implicit autoref
75 //~^ ERROR implicit autoref
7476}
7577
7678unsafe fn test_no_attr(ptr: *mut ManuallyDrop<u8>) {
77 ptr.write(ManuallyDrop::new(1)); // Should not warn, as `ManuallyDrop::write` is not
78 // annotated with `#[rustc_no_implicit_auto_ref]`
79 // Should not warn, as `ManuallyDrop::write` is not
80 // annotated with `#[rustc_no_implicit_auto_ref]`
81 ptr.write(ManuallyDrop::new(1));
7982}
8083
8184unsafe fn test_vec_get(ptr: *mut Vec<u8>) {
8285 let _ = (&(*ptr)).get(0);
83 //~^ WARN implicit autoref
86 //~^ ERROR implicit autoref
8487 let _ = (&(*ptr)).get_unchecked(0);
85 //~^ WARN implicit autoref
88 //~^ ERROR implicit autoref
8689 let _ = (&mut (*ptr)).get_mut(0);
87 //~^ WARN implicit autoref
90 //~^ ERROR implicit autoref
8891 let _ = (&mut (*ptr)).get_unchecked_mut(0);
89 //~^ WARN implicit autoref
92 //~^ ERROR implicit autoref
9093}
9194
9295unsafe fn test_string(ptr: *mut String) {
9396 let _ = (&(*ptr)).len();
94 //~^ WARN implicit autoref
97 //~^ ERROR implicit autoref
9598 let _ = (&(*ptr)).is_empty();
96 //~^ WARN implicit autoref
99 //~^ ERROR implicit autoref
97100}
98101
99102unsafe fn slice_ptr_len_because_of_msrv<T>(slice: *const [T]) {
100103 let _ = (&(&(*slice))[..]).len();
101 //~^ WARN implicit autoref
102 //~^^ WARN implicit autoref
104 //~^ ERROR implicit autoref
105 //~^^ ERROR implicit autoref
103106}
104107
105108fn main() {}
tests/ui/lint/implicit_autorefs.rs+28-25
......@@ -1,4 +1,4 @@
1//@ check-pass
1//@ check-fail
22//@ run-rustfix
33
44#![allow(dead_code)] // For the rustfix-ed code.
......@@ -8,7 +8,7 @@ use std::ops::Deref;
88
99unsafe fn test_const(ptr: *const [u8]) {
1010 let _ = (*ptr)[..16];
11 //~^ WARN implicit autoref
11 //~^ ERROR implicit autoref
1212}
1313
1414struct Test {
......@@ -17,36 +17,36 @@ struct Test {
1717
1818unsafe fn test_field(ptr: *const Test) -> *const [u8] {
1919 let l = (*ptr).field.len();
20 //~^ WARN implicit autoref
20 //~^ ERROR implicit autoref
2121
2222 &raw const (*ptr).field[..l - 1]
23 //~^ WARN implicit autoref
23 //~^ ERROR implicit autoref
2424}
2525
2626unsafe fn test_builtin_index(a: *mut [String]) {
2727 _ = (*a)[0].len();
28 //~^ WARN implicit autoref
28 //~^ ERROR implicit autoref
2929
3030 _ = (*a)[..1][0].len();
31 //~^ WARN implicit autoref
32 //~^^ WARN implicit autoref
31 //~^ ERROR implicit autoref
32 //~^^ ERROR implicit autoref
3333}
3434
3535unsafe fn test_overloaded_deref_const(ptr: *const ManuallyDrop<Test>) {
3636 let _ = (*ptr).field;
37 //~^ WARN implicit autoref
37 //~^ ERROR implicit autoref
3838 let _ = &raw const (*ptr).field;
39 //~^ WARN implicit autoref
39 //~^ ERROR implicit autoref
4040}
4141
4242unsafe fn test_overloaded_deref_mut(ptr: *mut ManuallyDrop<Test>) {
4343 let _ = (*ptr).field;
44 //~^ WARN implicit autoref
44 //~^ ERROR implicit autoref
4545}
4646
4747unsafe fn test_double_overloaded_deref_const(ptr: *const ManuallyDrop<ManuallyDrop<Test>>) {
4848 let _ = (*ptr).field;
49 //~^ WARN implicit autoref
49 //~^ ERROR implicit autoref
5050}
5151
5252unsafe fn test_manually_overloaded_deref() {
......@@ -54,52 +54,55 @@ unsafe fn test_manually_overloaded_deref() {
5454
5555 impl<T> Deref for W<T> {
5656 type Target = T;
57 fn deref(&self) -> &T { &self.0 }
57 fn deref(&self) -> &T {
58 &self.0
59 }
5860 }
5961
6062 let w: W<i32> = W(5);
6163 let w = &raw const w;
6264 let _p: *const i32 = &raw const **w;
63 //~^ WARN implicit autoref
65 //~^ ERROR implicit autoref
6466}
6567
6668struct Test2 {
6769 // Derefs to `[u8]`.
68 field: &'static [u8]
70 field: &'static [u8],
6971}
7072
7173fn test_more_manual_deref(ptr: *const Test2) -> usize {
7274 unsafe { (*ptr).field.len() }
73 //~^ WARN implicit autoref
75 //~^ ERROR implicit autoref
7476}
7577
7678unsafe fn test_no_attr(ptr: *mut ManuallyDrop<u8>) {
77 ptr.write(ManuallyDrop::new(1)); // Should not warn, as `ManuallyDrop::write` is not
78 // annotated with `#[rustc_no_implicit_auto_ref]`
79 // Should not warn, as `ManuallyDrop::write` is not
80 // annotated with `#[rustc_no_implicit_auto_ref]`
81 ptr.write(ManuallyDrop::new(1));
7982}
8083
8184unsafe fn test_vec_get(ptr: *mut Vec<u8>) {
8285 let _ = (*ptr).get(0);
83 //~^ WARN implicit autoref
86 //~^ ERROR implicit autoref
8487 let _ = (*ptr).get_unchecked(0);
85 //~^ WARN implicit autoref
88 //~^ ERROR implicit autoref
8689 let _ = (*ptr).get_mut(0);
87 //~^ WARN implicit autoref
90 //~^ ERROR implicit autoref
8891 let _ = (*ptr).get_unchecked_mut(0);
89 //~^ WARN implicit autoref
92 //~^ ERROR implicit autoref
9093}
9194
9295unsafe fn test_string(ptr: *mut String) {
9396 let _ = (*ptr).len();
94 //~^ WARN implicit autoref
97 //~^ ERROR implicit autoref
9598 let _ = (*ptr).is_empty();
96 //~^ WARN implicit autoref
99 //~^ ERROR implicit autoref
97100}
98101
99102unsafe fn slice_ptr_len_because_of_msrv<T>(slice: *const [T]) {
100103 let _ = (*slice)[..].len();
101 //~^ WARN implicit autoref
102 //~^^ WARN implicit autoref
104 //~^ ERROR implicit autoref
105 //~^^ ERROR implicit autoref
103106}
104107
105108fn main() {}
tests/ui/lint/implicit_autorefs.stderr+42-42
......@@ -1,4 +1,4 @@
1warning: implicit autoref creates a reference to the dereference of a raw pointer
1error: implicit autoref creates a reference to the dereference of a raw pointer
22 --> $DIR/implicit_autorefs.rs:10:13
33 |
44LL | let _ = (*ptr)[..16];
......@@ -12,13 +12,13 @@ note: autoref is being applied to this expression, resulting in: `&[u8]`
1212 |
1313LL | let _ = (*ptr)[..16];
1414 | ^^^^^^
15 = note: `#[warn(dangerous_implicit_autorefs)]` on by default
15 = note: `#[deny(dangerous_implicit_autorefs)]` on by default
1616help: try using a raw pointer method instead; or if this reference is intentional, make it explicit
1717 |
1818LL | let _ = (&(*ptr))[..16];
1919 | ++ +
2020
21warning: implicit autoref creates a reference to the dereference of a raw pointer
21error: implicit autoref creates a reference to the dereference of a raw pointer
2222 --> $DIR/implicit_autorefs.rs:19:13
2323 |
2424LL | let l = (*ptr).field.len();
......@@ -39,7 +39,7 @@ help: try using a raw pointer method instead; or if this reference is intentiona
3939LL | let l = (&(*ptr).field).len();
4040 | ++ +
4141
42warning: implicit autoref creates a reference to the dereference of a raw pointer
42error: implicit autoref creates a reference to the dereference of a raw pointer
4343 --> $DIR/implicit_autorefs.rs:22:16
4444 |
4545LL | &raw const (*ptr).field[..l - 1]
......@@ -58,7 +58,7 @@ help: try using a raw pointer method instead; or if this reference is intentiona
5858LL | &raw const (&(*ptr).field)[..l - 1]
5959 | ++ +
6060
61warning: implicit autoref creates a reference to the dereference of a raw pointer
61error: implicit autoref creates a reference to the dereference of a raw pointer
6262 --> $DIR/implicit_autorefs.rs:27:9
6363 |
6464LL | _ = (*a)[0].len();
......@@ -79,7 +79,7 @@ help: try using a raw pointer method instead; or if this reference is intentiona
7979LL | _ = (&(*a)[0]).len();
8080 | ++ +
8181
82warning: implicit autoref creates a reference to the dereference of a raw pointer
82error: implicit autoref creates a reference to the dereference of a raw pointer
8383 --> $DIR/implicit_autorefs.rs:30:9
8484 |
8585LL | _ = (*a)[..1][0].len();
......@@ -100,7 +100,7 @@ help: try using a raw pointer method instead; or if this reference is intentiona
100100LL | _ = (&(*a)[..1][0]).len();
101101 | ++ +
102102
103warning: implicit autoref creates a reference to the dereference of a raw pointer
103error: implicit autoref creates a reference to the dereference of a raw pointer
104104 --> $DIR/implicit_autorefs.rs:30:9
105105 |
106106LL | _ = (*a)[..1][0].len();
......@@ -119,7 +119,7 @@ help: try using a raw pointer method instead; or if this reference is intentiona
119119LL | _ = (&(*a))[..1][0].len();
120120 | ++ +
121121
122warning: implicit autoref creates a reference to the dereference of a raw pointer
122error: implicit autoref creates a reference to the dereference of a raw pointer
123123 --> $DIR/implicit_autorefs.rs:36:13
124124 |
125125LL | let _ = (*ptr).field;
......@@ -134,7 +134,7 @@ help: try using a raw pointer method instead; or if this reference is intentiona
134134LL | let _ = (&(*ptr)).field;
135135 | ++ +
136136
137warning: implicit autoref creates a reference to the dereference of a raw pointer
137error: implicit autoref creates a reference to the dereference of a raw pointer
138138 --> $DIR/implicit_autorefs.rs:38:24
139139 |
140140LL | let _ = &raw const (*ptr).field;
......@@ -149,7 +149,7 @@ help: try using a raw pointer method instead; or if this reference is intentiona
149149LL | let _ = &raw const (&(*ptr)).field;
150150 | ++ +
151151
152warning: implicit autoref creates a reference to the dereference of a raw pointer
152error: implicit autoref creates a reference to the dereference of a raw pointer
153153 --> $DIR/implicit_autorefs.rs:43:13
154154 |
155155LL | let _ = (*ptr).field;
......@@ -164,7 +164,7 @@ help: try using a raw pointer method instead; or if this reference is intentiona
164164LL | let _ = (&(*ptr)).field;
165165 | ++ +
166166
167warning: implicit autoref creates a reference to the dereference of a raw pointer
167error: implicit autoref creates a reference to the dereference of a raw pointer
168168 --> $DIR/implicit_autorefs.rs:48:13
169169 |
170170LL | let _ = (*ptr).field;
......@@ -179,8 +179,8 @@ help: try using a raw pointer method instead; or if this reference is intentiona
179179LL | let _ = (&(*ptr)).field;
180180 | ++ +
181181
182warning: implicit autoref creates a reference to the dereference of a raw pointer
183 --> $DIR/implicit_autorefs.rs:62:26
182error: implicit autoref creates a reference to the dereference of a raw pointer
183 --> $DIR/implicit_autorefs.rs:64:26
184184 |
185185LL | let _p: *const i32 = &raw const **w;
186186 | ^^^^^^^^^^^^^-
......@@ -189,7 +189,7 @@ LL | let _p: *const i32 = &raw const **w;
189189 |
190190 = note: creating a reference requires the pointer target to be valid and imposes aliasing requirements
191191note: autoref is being applied to this expression, resulting in: `&W<i32>`
192 --> $DIR/implicit_autorefs.rs:62:38
192 --> $DIR/implicit_autorefs.rs:64:38
193193 |
194194LL | let _p: *const i32 = &raw const **w;
195195 | ^^
......@@ -198,8 +198,8 @@ help: try using a raw pointer method instead; or if this reference is intentiona
198198LL | let _p: *const i32 = &raw const *(&**w);
199199 | +++ +
200200
201warning: implicit autoref creates a reference to the dereference of a raw pointer
202 --> $DIR/implicit_autorefs.rs:72:14
201error: implicit autoref creates a reference to the dereference of a raw pointer
202 --> $DIR/implicit_autorefs.rs:74:14
203203 |
204204LL | unsafe { (*ptr).field.len() }
205205 | ^^---^^^^^^^^^^^^^
......@@ -208,7 +208,7 @@ LL | unsafe { (*ptr).field.len() }
208208 |
209209 = note: creating a reference requires the pointer target to be valid and imposes aliasing requirements
210210note: autoref is being applied to this expression, resulting in: `&[u8]`
211 --> $DIR/implicit_autorefs.rs:72:14
211 --> $DIR/implicit_autorefs.rs:74:14
212212 |
213213LL | unsafe { (*ptr).field.len() }
214214 | ^^^^^^^^^^^^
......@@ -219,8 +219,8 @@ help: try using a raw pointer method instead; or if this reference is intentiona
219219LL | unsafe { (&(*ptr).field).len() }
220220 | ++ +
221221
222warning: implicit autoref creates a reference to the dereference of a raw pointer
223 --> $DIR/implicit_autorefs.rs:82:13
222error: implicit autoref creates a reference to the dereference of a raw pointer
223 --> $DIR/implicit_autorefs.rs:85:13
224224 |
225225LL | let _ = (*ptr).get(0);
226226 | ^^---^^^^^^^^
......@@ -229,7 +229,7 @@ LL | let _ = (*ptr).get(0);
229229 |
230230 = note: creating a reference requires the pointer target to be valid and imposes aliasing requirements
231231note: autoref is being applied to this expression, resulting in: `&[u8]`
232 --> $DIR/implicit_autorefs.rs:82:13
232 --> $DIR/implicit_autorefs.rs:85:13
233233 |
234234LL | let _ = (*ptr).get(0);
235235 | ^^^^^^
......@@ -240,8 +240,8 @@ help: try using a raw pointer method instead; or if this reference is intentiona
240240LL | let _ = (&(*ptr)).get(0);
241241 | ++ +
242242
243warning: implicit autoref creates a reference to the dereference of a raw pointer
244 --> $DIR/implicit_autorefs.rs:84:13
243error: implicit autoref creates a reference to the dereference of a raw pointer
244 --> $DIR/implicit_autorefs.rs:87:13
245245 |
246246LL | let _ = (*ptr).get_unchecked(0);
247247 | ^^---^^^^^^^^^^^^^^^^^^
......@@ -250,7 +250,7 @@ LL | let _ = (*ptr).get_unchecked(0);
250250 |
251251 = note: creating a reference requires the pointer target to be valid and imposes aliasing requirements
252252note: autoref is being applied to this expression, resulting in: `&[u8]`
253 --> $DIR/implicit_autorefs.rs:84:13
253 --> $DIR/implicit_autorefs.rs:87:13
254254 |
255255LL | let _ = (*ptr).get_unchecked(0);
256256 | ^^^^^^
......@@ -261,8 +261,8 @@ help: try using a raw pointer method instead; or if this reference is intentiona
261261LL | let _ = (&(*ptr)).get_unchecked(0);
262262 | ++ +
263263
264warning: implicit autoref creates a reference to the dereference of a raw pointer
265 --> $DIR/implicit_autorefs.rs:86:13
264error: implicit autoref creates a reference to the dereference of a raw pointer
265 --> $DIR/implicit_autorefs.rs:89:13
266266 |
267267LL | let _ = (*ptr).get_mut(0);
268268 | ^^---^^^^^^^^^^^^
......@@ -271,7 +271,7 @@ LL | let _ = (*ptr).get_mut(0);
271271 |
272272 = note: creating a reference requires the pointer target to be valid and imposes aliasing requirements
273273note: autoref is being applied to this expression, resulting in: `&mut [u8]`
274 --> $DIR/implicit_autorefs.rs:86:13
274 --> $DIR/implicit_autorefs.rs:89:13
275275 |
276276LL | let _ = (*ptr).get_mut(0);
277277 | ^^^^^^
......@@ -282,8 +282,8 @@ help: try using a raw pointer method instead; or if this reference is intentiona
282282LL | let _ = (&mut (*ptr)).get_mut(0);
283283 | +++++ +
284284
285warning: implicit autoref creates a reference to the dereference of a raw pointer
286 --> $DIR/implicit_autorefs.rs:88:13
285error: implicit autoref creates a reference to the dereference of a raw pointer
286 --> $DIR/implicit_autorefs.rs:91:13
287287 |
288288LL | let _ = (*ptr).get_unchecked_mut(0);
289289 | ^^---^^^^^^^^^^^^^^^^^^^^^^
......@@ -292,7 +292,7 @@ LL | let _ = (*ptr).get_unchecked_mut(0);
292292 |
293293 = note: creating a reference requires the pointer target to be valid and imposes aliasing requirements
294294note: autoref is being applied to this expression, resulting in: `&mut [u8]`
295 --> $DIR/implicit_autorefs.rs:88:13
295 --> $DIR/implicit_autorefs.rs:91:13
296296 |
297297LL | let _ = (*ptr).get_unchecked_mut(0);
298298 | ^^^^^^
......@@ -303,8 +303,8 @@ help: try using a raw pointer method instead; or if this reference is intentiona
303303LL | let _ = (&mut (*ptr)).get_unchecked_mut(0);
304304 | +++++ +
305305
306warning: implicit autoref creates a reference to the dereference of a raw pointer
307 --> $DIR/implicit_autorefs.rs:93:13
306error: implicit autoref creates a reference to the dereference of a raw pointer
307 --> $DIR/implicit_autorefs.rs:96:13
308308 |
309309LL | let _ = (*ptr).len();
310310 | ^^---^^^^^^^
......@@ -313,7 +313,7 @@ LL | let _ = (*ptr).len();
313313 |
314314 = note: creating a reference requires the pointer target to be valid and imposes aliasing requirements
315315note: autoref is being applied to this expression, resulting in: `&String`
316 --> $DIR/implicit_autorefs.rs:93:13
316 --> $DIR/implicit_autorefs.rs:96:13
317317 |
318318LL | let _ = (*ptr).len();
319319 | ^^^^^^
......@@ -324,8 +324,8 @@ help: try using a raw pointer method instead; or if this reference is intentiona
324324LL | let _ = (&(*ptr)).len();
325325 | ++ +
326326
327warning: implicit autoref creates a reference to the dereference of a raw pointer
328 --> $DIR/implicit_autorefs.rs:95:13
327error: implicit autoref creates a reference to the dereference of a raw pointer
328 --> $DIR/implicit_autorefs.rs:98:13
329329 |
330330LL | let _ = (*ptr).is_empty();
331331 | ^^---^^^^^^^^^^^^
......@@ -334,7 +334,7 @@ LL | let _ = (*ptr).is_empty();
334334 |
335335 = note: creating a reference requires the pointer target to be valid and imposes aliasing requirements
336336note: autoref is being applied to this expression, resulting in: `&String`
337 --> $DIR/implicit_autorefs.rs:95:13
337 --> $DIR/implicit_autorefs.rs:98:13
338338 |
339339LL | let _ = (*ptr).is_empty();
340340 | ^^^^^^
......@@ -345,8 +345,8 @@ help: try using a raw pointer method instead; or if this reference is intentiona
345345LL | let _ = (&(*ptr)).is_empty();
346346 | ++ +
347347
348warning: implicit autoref creates a reference to the dereference of a raw pointer
349 --> $DIR/implicit_autorefs.rs:100:13
348error: implicit autoref creates a reference to the dereference of a raw pointer
349 --> $DIR/implicit_autorefs.rs:103:13
350350 |
351351LL | let _ = (*slice)[..].len();
352352 | ^^-----^^^^^^^^^^^
......@@ -355,7 +355,7 @@ LL | let _ = (*slice)[..].len();
355355 |
356356 = note: creating a reference requires the pointer target to be valid and imposes aliasing requirements
357357note: autoref is being applied to this expression, resulting in: `&[T]`
358 --> $DIR/implicit_autorefs.rs:100:13
358 --> $DIR/implicit_autorefs.rs:103:13
359359 |
360360LL | let _ = (*slice)[..].len();
361361 | ^^^^^^^^^^^^
......@@ -366,8 +366,8 @@ help: try using a raw pointer method instead; or if this reference is intentiona
366366LL | let _ = (&(*slice)[..]).len();
367367 | ++ +
368368
369warning: implicit autoref creates a reference to the dereference of a raw pointer
370 --> $DIR/implicit_autorefs.rs:100:13
369error: implicit autoref creates a reference to the dereference of a raw pointer
370 --> $DIR/implicit_autorefs.rs:103:13
371371 |
372372LL | let _ = (*slice)[..].len();
373373 | ^^-----^^^^^
......@@ -376,7 +376,7 @@ LL | let _ = (*slice)[..].len();
376376 |
377377 = note: creating a reference requires the pointer target to be valid and imposes aliasing requirements
378378note: autoref is being applied to this expression, resulting in: `&[T]`
379 --> $DIR/implicit_autorefs.rs:100:13
379 --> $DIR/implicit_autorefs.rs:103:13
380380 |
381381LL | let _ = (*slice)[..].len();
382382 | ^^^^^^^^
......@@ -385,5 +385,5 @@ help: try using a raw pointer method instead; or if this reference is intentiona
385385LL | let _ = (&(*slice))[..].len();
386386 | ++ +
387387
388warning: 20 warnings emitted
388error: aborting due to 20 previous errors
389389
tests/ui/lint/unused/useless-comment.rs+7
......@@ -9,8 +9,13 @@ macro_rules! mac {
99/// foo //~ ERROR unused doc comment
1010mac!();
1111
12/// a //~ ERROR unused doc comment
13#[doc(test(attr(allow(dead_code))))] //~ ERROR unused doc comment
14unsafe extern "C" { }
15
1216fn foo() {
1317 /// a //~ ERROR unused doc comment
18 #[doc(test(attr(allow(dead_code))))] //~ ERROR unused doc comment
1419 let x = 12;
1520
1621 /// multi-line //~ ERROR unused doc comment
......@@ -19,6 +24,7 @@ fn foo() {
1924 match x {
2025 /// c //~ ERROR unused doc comment
2126 1 => {},
27 #[doc(test(attr(allow(dead_code))))] //~ ERROR unused doc comment
2228 _ => {}
2329 }
2430
......@@ -32,6 +38,7 @@ fn foo() {
3238 /// bar //~ ERROR unused doc comment
3339 mac!();
3440
41 #[doc(test(attr(allow(dead_code))))] //~ ERROR unused doc comment
3542 let x = /** comment */ 47; //~ ERROR unused doc comment
3643
3744 /// dox //~ ERROR unused doc comment
tests/ui/lint/unused/useless-comment.stderr+63-10
......@@ -12,7 +12,28 @@ LL | #![deny(unused_doc_comments)]
1212 | ^^^^^^^^^^^^^^^^^^^
1313
1414error: unused doc comment
15 --> $DIR/useless-comment.rs:32:5
15 --> $DIR/useless-comment.rs:12:1
16 |
17LL | /// a
18 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
19LL | #[doc(test(attr(allow(dead_code))))]
20LL | unsafe extern "C" { }
21 | --------------------- rustdoc does not generate documentation for extern blocks
22 |
23 = help: use `//` for a plain comment
24
25error: unused doc comment
26 --> $DIR/useless-comment.rs:13:1
27 |
28LL | #[doc(test(attr(allow(dead_code))))]
29 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
30LL | unsafe extern "C" { }
31 | --------------------- rustdoc does not generate documentation for extern blocks
32 |
33 = help: use `//` for a plain comment
34
35error: unused doc comment
36 --> $DIR/useless-comment.rs:38:5
1637 |
1738LL | /// bar
1839 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ rustdoc does not generate documentation for macro invocations
......@@ -20,17 +41,28 @@ LL | /// bar
2041 = help: to document an item produced by a macro, the macro must produce the documentation as part of its expansion
2142
2243error: unused doc comment
23 --> $DIR/useless-comment.rs:13:5
44 --> $DIR/useless-comment.rs:17:5
2445 |
2546LL | /// a
2647 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
48LL | #[doc(test(attr(allow(dead_code))))]
2749LL | let x = 12;
2850 | ----------- rustdoc does not generate documentation for statements
2951 |
3052 = help: use `//` for a plain comment
3153
3254error: unused doc comment
33 --> $DIR/useless-comment.rs:16:5
55 --> $DIR/useless-comment.rs:18:5
56 |
57LL | #[doc(test(attr(allow(dead_code))))]
58 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
59LL | let x = 12;
60 | ----------- rustdoc does not generate documentation for statements
61 |
62 = help: use `//` for a plain comment
63
64error: unused doc comment
65 --> $DIR/useless-comment.rs:21:5
3466 |
3567LL | / /// multi-line
3668LL | | /// doc comment
......@@ -39,6 +71,7 @@ LL | | /// that is unused
3971LL | / match x {
4072LL | | /// c
4173LL | | 1 => {},
74LL | | #[doc(test(attr(allow(dead_code))))]
4275LL | | _ => {}
4376LL | | }
4477 | |_____- rustdoc does not generate documentation for expressions
......@@ -46,7 +79,7 @@ LL | | }
4679 = help: use `//` for a plain comment
4780
4881error: unused doc comment
49 --> $DIR/useless-comment.rs:20:9
82 --> $DIR/useless-comment.rs:25:9
5083 |
5184LL | /// c
5285 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
......@@ -56,7 +89,17 @@ LL | 1 => {},
5689 = help: use `//` for a plain comment
5790
5891error: unused doc comment
59 --> $DIR/useless-comment.rs:25:5
92 --> $DIR/useless-comment.rs:27:9
93 |
94LL | #[doc(test(attr(allow(dead_code))))]
95 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
96LL | _ => {}
97 | ------- rustdoc does not generate documentation for match arms
98 |
99 = help: use `//` for a plain comment
100
101error: unused doc comment
102 --> $DIR/useless-comment.rs:31:5
60103 |
61104LL | /// foo
62105 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
......@@ -66,7 +109,7 @@ LL | unsafe {}
66109 = help: use `//` for a plain comment
67110
68111error: unused doc comment
69 --> $DIR/useless-comment.rs:28:5
112 --> $DIR/useless-comment.rs:34:5
70113 |
71114LL | #[doc = "foo"]
72115 | ^^^^^^^^^^^^^^
......@@ -77,7 +120,7 @@ LL | 3;
77120 = help: use `//` for a plain comment
78121
79122error: unused doc comment
80 --> $DIR/useless-comment.rs:29:5
123 --> $DIR/useless-comment.rs:35:5
81124 |
82125LL | #[doc = "bar"]
83126 | ^^^^^^^^^^^^^^
......@@ -87,7 +130,17 @@ LL | 3;
87130 = help: use `//` for a plain comment
88131
89132error: unused doc comment
90 --> $DIR/useless-comment.rs:35:13
133 --> $DIR/useless-comment.rs:41:5
134 |
135LL | #[doc(test(attr(allow(dead_code))))]
136 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
137LL | let x = /** comment */ 47;
138 | -------------------------- rustdoc does not generate documentation for statements
139 |
140 = help: use `//` for a plain comment
141
142error: unused doc comment
143 --> $DIR/useless-comment.rs:42:13
91144 |
92145LL | let x = /** comment */ 47;
93146 | ^^^^^^^^^^^^^^ -- rustdoc does not generate documentation for expressions
......@@ -95,7 +148,7 @@ LL | let x = /** comment */ 47;
95148 = help: use `/* */` for a plain comment
96149
97150error: unused doc comment
98 --> $DIR/useless-comment.rs:37:5
151 --> $DIR/useless-comment.rs:44:5
99152 |
100153LL | /// dox
101154 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
......@@ -106,5 +159,5 @@ LL | | }
106159 |
107160 = help: use `//` for a plain comment
108161
109error: aborting due to 10 previous errors
162error: aborting due to 15 previous errors
110163
tests/ui/rustdoc/doc-test-attr-pass.rs+42
......@@ -6,4 +6,46 @@
66#![doc(test(attr(deny(warnings))))]
77#![doc(test())]
88
9mod test {
10 #![doc(test(attr(allow(warnings))))]
11}
12
13#[doc(test(attr(allow(dead_code))))]
14static S: u32 = 5;
15
16#[doc(test(attr(allow(dead_code))))]
17const C: u32 = 5;
18
19#[doc(test(attr(deny(dead_code))))]
20struct A {
21 #[doc(test(attr(allow(dead_code))))]
22 field: u32
23}
24
25#[doc(test(attr(deny(dead_code))))]
26union U {
27 #[doc(test(attr(allow(dead_code))))]
28 field: u32,
29 field2: u64,
30}
31
32#[doc(test(attr(deny(dead_code))))]
33enum Enum {
34 #[doc(test(attr(allow(dead_code))))]
35 Variant1,
36}
37
38#[doc(test(attr(deny(dead_code))))]
39impl A {
40 #[doc(test(attr(deny(dead_code))))]
41 fn method() {}
42}
43
44#[doc(test(attr(deny(dead_code))))]
45trait MyTrait {
46 #[doc(test(attr(deny(dead_code))))]
47 fn my_trait_fn();
48}
49
50#[doc(test(attr(deny(dead_code))))]
951pub fn foo() {}
tests/ui/specialization/overlap-due-to-unsatisfied-const-bound.rs created+21
......@@ -0,0 +1,21 @@
1// Regression test for #140571. The compiler used to ICE
2
3#![feature(associated_const_equality, specialization)]
4//~^ WARN the feature `specialization` is incomplete
5
6pub trait IsVoid {
7 const IS_VOID: bool;
8}
9impl<T> IsVoid for T {
10 default const IS_VOID: bool = false;
11}
12
13pub trait NotVoid {}
14impl<T> NotVoid for T where T: IsVoid<IS_VOID = false> + ?Sized {}
15
16pub trait Maybe<T> {}
17impl<T> Maybe<T> for T {}
18impl<T> Maybe<T> for () where T: NotVoid + ?Sized {}
19//~^ ERROR conflicting implementations of trait `Maybe<()>` for type `()`
20
21fn main() {}
tests/ui/specialization/overlap-due-to-unsatisfied-const-bound.stderr created+21
......@@ -0,0 +1,21 @@
1warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
2 --> $DIR/overlap-due-to-unsatisfied-const-bound.rs:3:39
3 |
4LL | #![feature(associated_const_equality, specialization)]
5 | ^^^^^^^^^^^^^^
6 |
7 = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
8 = help: consider using `min_specialization` instead, which is more stable and complete
9 = note: `#[warn(incomplete_features)]` on by default
10
11error[E0119]: conflicting implementations of trait `Maybe<()>` for type `()`
12 --> $DIR/overlap-due-to-unsatisfied-const-bound.rs:18:1
13 |
14LL | impl<T> Maybe<T> for T {}
15 | ---------------------- first implementation here
16LL | impl<T> Maybe<T> for () where T: NotVoid + ?Sized {}
17 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()`
18
19error: aborting due to 1 previous error; 1 warning emitted
20
21For more information about this error, try `rustc --explain E0119`.