Rollup merge of #142154 - RalfJung:no-more-cfg-bootstrap, r=oli-obk
get rid of spurious cfg(bootstrap)
r? ```@oli-obk```
diff --git a/compiler/rustc_abi/src/extern_abi.rs b/compiler/rustc_abi/src/extern_abi.rs
index c48920e..0bc1c8a 100644
--- a/compiler/rustc_abi/src/extern_abi.rs
+++ b/compiler/rustc_abi/src/extern_abi.rs
@@ -12,66 +12,93 @@
#[cfg(test)]
mod tests;
-use ExternAbi as Abi;
-
+/// ABI we expect to see within `extern "{abi}"`
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "nightly", derive(Encodable, Decodable))]
pub enum ExternAbi {
- // Some of the ABIs come first because every time we add a new ABI, we have to re-bless all the
- // hashing tests. These are used in many places, so giving them stable values reduces test
- // churn. The specific values are meaningless.
- Rust,
+ /* universal */
+ /// presumed C ABI for the platform
C {
unwind: bool,
},
+ /// ABI of the "system" interface, e.g. the Win32 API, always "aliasing"
+ System {
+ unwind: bool,
+ },
+
+ /// that's us!
+ Rust,
+ /// the mostly-unused `unboxed_closures` ABI, effectively now an impl detail unless someone
+ /// puts in the work to make it viable again... but would we need a special ABI?
+ RustCall,
+ /// For things unlikely to be called, where reducing register pressure in
+ /// `extern "Rust"` callers is worth paying extra cost in the callee.
+ /// Stronger than just `#[cold]` because `fn` pointers might be incompatible.
+ RustCold,
+
+ /// Unstable impl detail that directly uses Rust types to describe the ABI to LLVM.
+ /// Even normally-compatible Rust types can become ABI-incompatible with this ABI!
+ Unadjusted,
+
+ /// UEFI ABI, usually an alias of C, but sometimes an arch-specific alias
+ /// and only valid on platforms that have a UEFI standard
+ EfiApi,
+
+ /* arm */
+ /// Arm Architecture Procedure Call Standard, sometimes `ExternAbi::C` is an alias for this
+ Aapcs {
+ unwind: bool,
+ },
+ /// extremely constrained barely-C ABI for TrustZone
+ CCmseNonSecureCall,
+ /// extremely constrained barely-C ABI for TrustZone
+ CCmseNonSecureEntry,
+
+ /* gpu */
+ /// An entry-point function called by the GPU's host
+ // FIXME: should not be callable from Rust on GPU targets, is for host's use only
+ GpuKernel,
+ /// An entry-point function called by the GPU's host
+ // FIXME: why do we have two of these?
+ PtxKernel,
+
+ /* interrupt */
+ AvrInterrupt,
+ AvrNonBlockingInterrupt,
+ Msp430Interrupt,
+ RiscvInterruptM,
+ RiscvInterruptS,
+ X86Interrupt,
+
+ /* x86 */
+ /// `ExternAbi::C` but spelled funny because x86
Cdecl {
unwind: bool,
},
+ /// gnu-stdcall on "unix" and win-stdcall on "windows"
Stdcall {
unwind: bool,
},
+ /// gnu-fastcall on "unix" and win-fastcall on "windows"
Fastcall {
unwind: bool,
},
- Vectorcall {
- unwind: bool,
- },
+ /// windows C++ ABI
Thiscall {
unwind: bool,
},
- Aapcs {
+ /// uses AVX and stuff
+ Vectorcall {
+ unwind: bool,
+ },
+
+ /* x86_64 */
+ SysV64 {
unwind: bool,
},
Win64 {
unwind: bool,
},
- SysV64 {
- unwind: bool,
- },
- PtxKernel,
- Msp430Interrupt,
- X86Interrupt,
- /// An entry-point function called by the GPU's host
- // FIXME: should not be callable from Rust on GPU targets, is for host's use only
- GpuKernel,
- EfiApi,
- AvrInterrupt,
- AvrNonBlockingInterrupt,
- CCmseNonSecureCall,
- CCmseNonSecureEntry,
- System {
- unwind: bool,
- },
- RustCall,
- /// *Not* a stable ABI, just directly use the Rust types to describe the ABI for LLVM. Even
- /// normally ABI-compatible Rust types can become ABI-incompatible with this ABI!
- Unadjusted,
- /// For things unlikely to be called, where reducing register pressure in
- /// `extern "Rust"` callers is worth paying extra cost in the callee.
- /// Stronger than just `#[cold]` because `fn` pointers might be incompatible.
- RustCold,
- RiscvInterruptM,
- RiscvInterruptS,
}
macro_rules! abi_impls {
@@ -224,7 +251,7 @@ pub fn all_names() -> Vec<&'static str> {
impl ExternAbi {
/// Default ABI chosen for `extern fn` declarations without an explicit ABI.
- pub const FALLBACK: Abi = Abi::C { unwind: false };
+ pub const FALLBACK: ExternAbi = ExternAbi::C { unwind: false };
pub fn name(self) -> &'static str {
self.as_str()
diff --git a/compiler/rustc_codegen_cranelift/example/neon.rs b/compiler/rustc_codegen_cranelift/example/neon.rs
index 69ce17d..704f866 100644
--- a/compiler/rustc_codegen_cranelift/example/neon.rs
+++ b/compiler/rustc_codegen_cranelift/example/neon.rs
@@ -233,7 +233,7 @@ unsafe fn test_vaddvq_f32() {
#[cfg(target_arch = "aarch64")]
unsafe fn test_vrndnq_f32() {
- // AArch64 llvm intrinsic: llvm.aarch64.neon.frintn.v4f32
+ // llvm intrinsic: llvm.roundeven.v4f32
let a = f32x4::from([0.1, -1.9, 4.5, 5.5]);
let e = f32x4::from([0., -2., 4., 6.]);
let r: f32x4 = transmute(vrndnq_f32(transmute(a)));
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs
index 99a5518..2dee917 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs
@@ -62,6 +62,14 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>(
});
}
+ _ if intrinsic.starts_with("llvm.roundeven.v") => {
+ intrinsic_args!(fx, args => (v); intrinsic);
+
+ simd_for_each_lane(fx, v, ret, &|fx, _lane_ty, _res_lane_ty, lane| {
+ fx.bcx.ins().nearest(lane)
+ });
+ }
+
_ => {
fx.tcx
.dcx()
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs
index c22f2a7..3cd7ebb 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs
@@ -264,14 +264,6 @@ pub(super) fn codegen_aarch64_llvm_intrinsic_call<'tcx>(
simd_reduce(fx, v, None, ret, &|fx, _ty, a, b| fx.bcx.ins().fadd(a, b));
}
- _ if intrinsic.starts_with("llvm.aarch64.neon.frintn.v") => {
- intrinsic_args!(fx, args => (v); intrinsic);
-
- simd_for_each_lane(fx, v, ret, &|fx, _lane_ty, _res_lane_ty, lane| {
- fx.bcx.ins().nearest(lane)
- });
- }
-
_ if intrinsic.starts_with("llvm.aarch64.neon.smaxv.i") => {
intrinsic_args!(fx, args => (v); intrinsic);
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index bd421a4..6f0090a 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -1529,7 +1529,7 @@ fn emit_diagnostic(
// Future breakages aren't emitted if they're `Level::Allow` or
// `Level::Expect`, but they still need to be constructed and
// stashed below, so they'll trigger the must_produce_diag check.
- assert_matches!(diagnostic.level, Error | Warning | Allow | Expect);
+ assert_matches!(diagnostic.level, Error | ForceWarning | Warning | Allow | Expect);
self.future_breakage_diagnostics.push(diagnostic.clone());
}
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 96e03e3..e9b58eb 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -823,6 +823,13 @@ pub fn next_region_var_in_universe(
ty::Region::new_var(self.tcx, region_var)
}
+ pub fn next_term_var_of_kind(&self, term: ty::Term<'tcx>, span: Span) -> ty::Term<'tcx> {
+ match term.kind() {
+ ty::TermKind::Ty(_) => self.next_ty_var(span).into(),
+ ty::TermKind::Const(_) => self.next_const_var(span).into(),
+ }
+ }
+
/// Return the universe that the region `r` was created in. For
/// most regions (e.g., `'static`, named regions from the user,
/// etc) this is the root universe U0. For inference variables or
diff --git a/compiler/rustc_lint/src/autorefs.rs b/compiler/rustc_lint/src/autorefs.rs
index 5de2cbf..845a1f1 100644
--- a/compiler/rustc_lint/src/autorefs.rs
+++ b/compiler/rustc_lint/src/autorefs.rs
@@ -16,7 +16,7 @@
///
/// ### Example
///
- /// ```rust
+ /// ```rust,compile_fail
/// unsafe fn fun(ptr: *mut [u8]) -> *mut [u8] {
/// unsafe { &raw mut (*ptr)[..16] }
/// // ^^^^^^ this calls `IndexMut::index_mut(&mut ..., ..16)`,
@@ -51,7 +51,7 @@
/// }
/// ```
pub DANGEROUS_IMPLICIT_AUTOREFS,
- Warn,
+ Deny,
"implicit reference to a dereference of a raw pointer",
report_in_external_macro
}
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 5b7d45b..dc29b03 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -1266,13 +1266,17 @@ fn check_attr_crate_level(
true
}
- /// Checks that `doc(test(...))` attribute contains only valid attributes. Returns `true` if
- /// valid.
- fn check_test_attr(&self, meta: &MetaItemInner, hir_id: HirId) {
+ /// Checks that `doc(test(...))` attribute contains only valid attributes and are at the right place.
+ fn check_test_attr(&self, attr: &Attribute, meta: &MetaItemInner, hir_id: HirId) {
if let Some(metas) = meta.meta_item_list() {
for i_meta in metas {
match (i_meta.name(), i_meta.meta_item()) {
- (Some(sym::attr | sym::no_crate_inject), _) => {}
+ (Some(sym::attr), _) => {
+ // Allowed everywhere like `#[doc]`
+ }
+ (Some(sym::no_crate_inject), _) => {
+ self.check_attr_crate_level(attr, meta, hir_id);
+ }
(_, Some(m)) => {
self.tcx.emit_node_span_lint(
INVALID_DOC_ATTRIBUTES,
@@ -1359,9 +1363,7 @@ fn check_doc_attrs(
}
Some(sym::test) => {
- if self.check_attr_crate_level(attr, meta, hir_id) {
- self.check_test_attr(meta, hir_id);
- }
+ self.check_test_attr(attr, meta, hir_id);
}
Some(
diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
index 1193a90..d5d318e 100644
--- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
+++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
@@ -133,45 +133,25 @@ pub fn visit_nested_no_probe<V: ProofTreeVisitor<'tcx>>(&self, visitor: &mut V)
/// Instantiate the nested goals for the candidate without rolling back their
/// inference constraints. This function modifies the state of the `infcx`.
///
- /// See [`Self::instantiate_nested_goals_and_opt_impl_args`] if you need the impl args too.
- pub fn instantiate_nested_goals(&self, span: Span) -> Vec<InspectGoal<'a, 'tcx>> {
- self.instantiate_nested_goals_and_opt_impl_args(span).0
- }
-
- /// Instantiate the nested goals for the candidate without rolling back their
- /// inference constraints, and optionally the args of an impl if this candidate
- /// came from a `CandidateSource::Impl`. This function modifies the state of the
- /// `infcx`.
+ /// See [`Self::instantiate_impl_args`] if you need the impl args too.
#[instrument(
level = "debug",
skip_all,
fields(goal = ?self.goal.goal, steps = ?self.steps)
)]
- pub fn instantiate_nested_goals_and_opt_impl_args(
- &self,
- span: Span,
- ) -> (Vec<InspectGoal<'a, 'tcx>>, Option<ty::GenericArgsRef<'tcx>>) {
+ pub fn instantiate_nested_goals(&self, span: Span) -> Vec<InspectGoal<'a, 'tcx>> {
let infcx = self.goal.infcx;
let param_env = self.goal.goal.param_env;
let mut orig_values = self.goal.orig_values.to_vec();
let mut instantiated_goals = vec![];
- let mut opt_impl_args = None;
for step in &self.steps {
match **step {
inspect::ProbeStep::AddGoal(source, goal) => instantiated_goals.push((
source,
instantiate_canonical_state(infcx, span, param_env, &mut orig_values, goal),
)),
- inspect::ProbeStep::RecordImplArgs { impl_args } => {
- opt_impl_args = Some(instantiate_canonical_state(
- infcx,
- span,
- param_env,
- &mut orig_values,
- impl_args,
- ));
- }
+ inspect::ProbeStep::RecordImplArgs { .. } => {}
inspect::ProbeStep::MakeCanonicalResponse { .. }
| inspect::ProbeStep::NestedProbe(_) => unreachable!(),
}
@@ -187,14 +167,59 @@ pub fn instantiate_nested_goals_and_opt_impl_args(
let _ = term_hack.constrain(infcx, span, param_env);
}
- let opt_impl_args = opt_impl_args.map(|impl_args| eager_resolve_vars(infcx, impl_args));
-
- let goals = instantiated_goals
+ instantiated_goals
.into_iter()
.map(|(source, goal)| self.instantiate_proof_tree_for_nested_goal(source, goal, span))
- .collect();
+ .collect()
+ }
- (goals, opt_impl_args)
+ /// Instantiate the args of an impl if this candidate came from a
+ /// `CandidateSource::Impl`. This function modifies the state of the
+ /// `infcx`.
+ #[instrument(
+ level = "debug",
+ skip_all,
+ fields(goal = ?self.goal.goal, steps = ?self.steps)
+ )]
+ pub fn instantiate_impl_args(&self, span: Span) -> ty::GenericArgsRef<'tcx> {
+ let infcx = self.goal.infcx;
+ let param_env = self.goal.goal.param_env;
+ let mut orig_values = self.goal.orig_values.to_vec();
+
+ for step in &self.steps {
+ match **step {
+ inspect::ProbeStep::RecordImplArgs { impl_args } => {
+ let impl_args = instantiate_canonical_state(
+ infcx,
+ span,
+ param_env,
+ &mut orig_values,
+ impl_args,
+ );
+
+ let () = instantiate_canonical_state(
+ infcx,
+ span,
+ param_env,
+ &mut orig_values,
+ self.final_state,
+ );
+
+ // No reason we couldn't support this, but we don't need to for select.
+ assert!(
+ self.goal.normalizes_to_term_hack.is_none(),
+ "cannot use `instantiate_impl_args` with a `NormalizesTo` goal"
+ );
+
+ return eager_resolve_vars(infcx, impl_args);
+ }
+ inspect::ProbeStep::AddGoal(..) => {}
+ inspect::ProbeStep::MakeCanonicalResponse { .. }
+ | inspect::ProbeStep::NestedProbe(_) => unreachable!(),
+ }
+ }
+
+ bug!("expected impl args probe step for `instantiate_impl_args`");
}
pub fn instantiate_proof_tree_for_nested_goal(
@@ -206,10 +231,7 @@ pub fn instantiate_proof_tree_for_nested_goal(
let infcx = self.goal.infcx;
match goal.predicate.kind().no_bound_vars() {
Some(ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term })) => {
- let unconstrained_term = match term.kind() {
- ty::TermKind::Ty(_) => infcx.next_ty_var(span).into(),
- ty::TermKind::Const(_) => infcx.next_const_var(span).into(),
- };
+ let unconstrained_term = infcx.next_term_var_of_kind(term, span);
let goal =
goal.with(infcx.tcx, ty::NormalizesTo { alias, term: unconstrained_term });
// We have to use a `probe` here as evaluating a `NormalizesTo` can constrain the
diff --git a/compiler/rustc_trait_selection/src/solve/normalize.rs b/compiler/rustc_trait_selection/src/solve/normalize.rs
index d903f94..8f44c26 100644
--- a/compiler/rustc_trait_selection/src/solve/normalize.rs
+++ b/compiler/rustc_trait_selection/src/solve/normalize.rs
@@ -1,4 +1,3 @@
-use std::assert_matches::assert_matches;
use std::fmt::Debug;
use rustc_data_structures::stack::ensure_sufficient_stack;
@@ -16,7 +15,6 @@
use super::{FulfillmentCtxt, NextSolverError};
use crate::error_reporting::InferCtxtErrorExt;
use crate::error_reporting::traits::OverflowCause;
-use crate::traits::query::evaluate_obligation::InferCtxtExt;
use crate::traits::{BoundVarReplacer, PlaceholderReplacer, ScrubbedTraitError};
/// Deeply normalize all aliases in `value`. This does not handle inference and expects
@@ -97,19 +95,18 @@ impl<'tcx, E> NormalizationFolder<'_, 'tcx, E>
where
E: FromSolverError<'tcx, NextSolverError<'tcx>>,
{
- fn normalize_alias_ty(&mut self, alias_ty: Ty<'tcx>) -> Result<Ty<'tcx>, Vec<E>> {
- assert_matches!(alias_ty.kind(), ty::Alias(..));
-
+ fn normalize_alias_term(
+ &mut self,
+ alias_term: ty::Term<'tcx>,
+ ) -> Result<ty::Term<'tcx>, Vec<E>> {
let infcx = self.at.infcx;
let tcx = infcx.tcx;
let recursion_limit = tcx.recursion_limit();
if !recursion_limit.value_within_limit(self.depth) {
- let ty::Alias(_, data) = *alias_ty.kind() else {
- unreachable!();
- };
+ let term = alias_term.to_alias_term().unwrap();
self.at.infcx.err_ctxt().report_overflow_error(
- OverflowCause::DeeplyNormalize(data.into()),
+ OverflowCause::DeeplyNormalize(term),
self.at.cause.span,
true,
|_| {},
@@ -118,14 +115,14 @@ fn normalize_alias_ty(&mut self, alias_ty: Ty<'tcx>) -> Result<Ty<'tcx>, Vec<E>>
self.depth += 1;
- let new_infer_ty = infcx.next_ty_var(self.at.cause.span);
+ let infer_term = infcx.next_term_var_of_kind(alias_term, self.at.cause.span);
let obligation = Obligation::new(
tcx,
self.at.cause.clone(),
self.at.param_env,
ty::PredicateKind::AliasRelate(
- alias_ty.into(),
- new_infer_ty.into(),
+ alias_term.into(),
+ infer_term.into(),
ty::AliasRelationDirection::Equate,
),
);
@@ -135,50 +132,13 @@ fn normalize_alias_ty(&mut self, alias_ty: Ty<'tcx>) -> Result<Ty<'tcx>, Vec<E>>
// Alias is guaranteed to be fully structurally resolved,
// so we can super fold here.
- let ty = infcx.resolve_vars_if_possible(new_infer_ty);
- let result = ty.try_super_fold_with(self)?;
- self.depth -= 1;
- Ok(result)
- }
-
- fn normalize_unevaluated_const(
- &mut self,
- uv: ty::UnevaluatedConst<'tcx>,
- ) -> Result<ty::Const<'tcx>, Vec<E>> {
- let infcx = self.at.infcx;
- let tcx = infcx.tcx;
- let recursion_limit = tcx.recursion_limit();
- if !recursion_limit.value_within_limit(self.depth) {
- self.at.infcx.err_ctxt().report_overflow_error(
- OverflowCause::DeeplyNormalize(uv.into()),
- self.at.cause.span,
- true,
- |_| {},
- );
- }
-
- self.depth += 1;
-
- let new_infer_ct = infcx.next_const_var(self.at.cause.span);
- let obligation = Obligation::new(
- tcx,
- self.at.cause.clone(),
- self.at.param_env,
- ty::NormalizesTo { alias: uv.into(), term: new_infer_ct.into() },
- );
-
- let result = if infcx.predicate_may_hold(&obligation) {
- self.fulfill_cx.register_predicate_obligation(infcx, obligation);
- let errors = self.fulfill_cx.select_where_possible(infcx);
- if !errors.is_empty() {
- return Err(errors);
- }
- let ct = infcx.resolve_vars_if_possible(new_infer_ct);
- ct.try_fold_with(self)?
- } else {
- ty::Const::new_unevaluated(tcx, uv).try_super_fold_with(self)?
+ let term = infcx.resolve_vars_if_possible(infer_term);
+ // super-folding the `term` will directly fold the `Ty` or `Const` so
+ // we have to match on the term and super-fold them manually.
+ let result = match term.kind() {
+ ty::TermKind::Ty(ty) => ty.try_super_fold_with(self)?.into(),
+ ty::TermKind::Const(ct) => ct.try_super_fold_with(self)?.into(),
};
-
self.depth -= 1;
Ok(result)
}
@@ -238,7 +198,8 @@ fn try_fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
if ty.has_escaping_bound_vars() {
let (ty, mapped_regions, mapped_types, mapped_consts) =
BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, ty);
- let result = ensure_sufficient_stack(|| self.normalize_alias_ty(ty))?;
+ let result =
+ ensure_sufficient_stack(|| self.normalize_alias_term(ty.into()))?.expect_type();
Ok(PlaceholderReplacer::replace_placeholders(
infcx,
mapped_regions,
@@ -248,7 +209,7 @@ fn try_fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
result,
))
} else {
- ensure_sufficient_stack(|| self.normalize_alias_ty(ty))
+ Ok(ensure_sufficient_stack(|| self.normalize_alias_term(ty.into()))?.expect_type())
}
}
@@ -260,15 +221,13 @@ fn try_fold_const(&mut self, ct: ty::Const<'tcx>) -> Result<ty::Const<'tcx>, Sel
return Ok(ct);
}
- let uv = match ct.kind() {
- ty::ConstKind::Unevaluated(ct) => ct,
- _ => return ct.try_super_fold_with(self),
- };
+ let ty::ConstKind::Unevaluated(..) = ct.kind() else { return ct.try_super_fold_with(self) };
- if uv.has_escaping_bound_vars() {
- let (uv, mapped_regions, mapped_types, mapped_consts) =
- BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, uv);
- let result = ensure_sufficient_stack(|| self.normalize_unevaluated_const(uv))?;
+ if ct.has_escaping_bound_vars() {
+ let (ct, mapped_regions, mapped_types, mapped_consts) =
+ BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, ct);
+ let result =
+ ensure_sufficient_stack(|| self.normalize_alias_term(ct.into()))?.expect_const();
Ok(PlaceholderReplacer::replace_placeholders(
infcx,
mapped_regions,
@@ -278,7 +237,7 @@ fn try_fold_const(&mut self, ct: ty::Const<'tcx>) -> Result<ty::Const<'tcx>, Sel
result,
))
} else {
- ensure_sufficient_stack(|| self.normalize_unevaluated_const(uv))
+ Ok(ensure_sufficient_stack(|| self.normalize_alias_term(ct.into()))?.expect_const())
}
}
}
diff --git a/compiler/rustc_trait_selection/src/solve/select.rs b/compiler/rustc_trait_selection/src/solve/select.rs
index 21812c8..fb1adc2 100644
--- a/compiler/rustc_trait_selection/src/solve/select.rs
+++ b/compiler/rustc_trait_selection/src/solve/select.rs
@@ -10,6 +10,7 @@
use rustc_macros::extension;
use rustc_middle::{bug, span_bug};
use rustc_span::Span;
+use thin_vec::thin_vec;
use crate::solve::inspect::{self, ProofTreeInferCtxtExt};
@@ -146,18 +147,21 @@ fn to_selection<'tcx>(
return None;
}
- let (nested, impl_args) = cand.instantiate_nested_goals_and_opt_impl_args(span);
- let nested = nested
- .into_iter()
- .map(|nested| {
- Obligation::new(
- nested.infcx().tcx,
- ObligationCause::dummy_with_span(span),
- nested.goal().param_env,
- nested.goal().predicate,
- )
- })
- .collect();
+ let nested = match cand.result().expect("expected positive result") {
+ Certainty::Yes => thin_vec![],
+ Certainty::Maybe(_) => cand
+ .instantiate_nested_goals(span)
+ .into_iter()
+ .map(|nested| {
+ Obligation::new(
+ nested.infcx().tcx,
+ ObligationCause::dummy_with_span(span),
+ nested.goal().param_env,
+ nested.goal().predicate,
+ )
+ })
+ .collect(),
+ };
Some(match cand.kind() {
ProbeKind::TraitCandidate { source, result: _ } => match source {
@@ -166,7 +170,7 @@ fn to_selection<'tcx>(
// For impl candidates, we do the rematch manually to compute the args.
ImplSource::UserDefined(ImplSourceUserDefinedData {
impl_def_id,
- args: impl_args.expect("expected recorded impl args for impl candidate"),
+ args: cand.instantiate_impl_args(span),
nested,
})
}
diff --git a/compiler/rustc_trait_selection/src/traits/structural_normalize.rs b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs
index 3f74134..2e20ede 100644
--- a/compiler/rustc_trait_selection/src/traits/structural_normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs
@@ -39,10 +39,7 @@ fn structurally_normalize_term<E: 'tcx>(
return Ok(term);
}
- let new_infer = match term.kind() {
- ty::TermKind::Ty(_) => self.infcx.next_ty_var(self.cause.span).into(),
- ty::TermKind::Const(_) => self.infcx.next_const_var(self.cause.span).into(),
- };
+ let new_infer = self.infcx.next_term_var_of_kind(term, self.cause.span);
// We simply emit an `alias-eq` goal here, since that will take care of
// normalizing the LHS of the projection until it is a rigid projection
diff --git a/library/core/src/option.rs b/library/core/src/option.rs
index 675556b..c047548 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -137,7 +137,7 @@
//! | [`ptr::NonNull<U>`] | when `U: Sized` |
//! | `#[repr(transparent)]` struct around one of the types in this list. | when it holds for the inner type |
//!
-//! [^extern_fn]: this remains true for any argument/return types and any other ABI: `extern "abi" fn` (_e.g._, `extern "system" fn`)
+//! [^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`)
//!
//! Under some conditions the above types `T` are also null pointer optimized when wrapped in a [`Result`][result_repr].
//!
diff --git a/library/core/src/slice/ascii.rs b/library/core/src/slice/ascii.rs
index 91befdb..d91f8bb 100644
--- a/library/core/src/slice/ascii.rs
+++ b/library/core/src/slice/ascii.rs
@@ -52,7 +52,7 @@ pub const fn as_ascii(&self) -> Option<&[ascii::Char]> {
/// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`,
/// but without allocating and copying temporaries.
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
- #[rustc_const_unstable(feature = "const_eq_ignore_ascii_case", issue = "131719")]
+ #[rustc_const_stable(feature = "const_eq_ignore_ascii_case", since = "CURRENT_RUSTC_VERSION")]
#[must_use]
#[inline]
pub const fn eq_ignore_ascii_case(&self, other: &[u8]) -> bool {
diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs
index 06161cb..4183479 100644
--- a/library/core/src/str/mod.rs
+++ b/library/core/src/str/mod.rs
@@ -2671,7 +2671,7 @@ pub const fn as_ascii(&self) -> Option<&[ascii::Char]> {
/// assert!(!"Ferrös".eq_ignore_ascii_case("FERRÖS"));
/// ```
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
- #[rustc_const_unstable(feature = "const_eq_ignore_ascii_case", issue = "131719")]
+ #[rustc_const_stable(feature = "const_eq_ignore_ascii_case", since = "CURRENT_RUSTC_VERSION")]
#[must_use]
#[inline]
pub const fn eq_ignore_ascii_case(&self, other: &str) -> bool {
diff --git a/library/stdarch b/library/stdarch
index b6e2249..5c1c436 160000
--- a/library/stdarch
+++ b/library/stdarch
@@ -1 +1 @@
-Subproject commit b6e2249e388f520627544812649b77b0944e1a2e
+Subproject commit 5c1c436524c0bbc8db83577f42f8bea9006a7b75
diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs
index 21a119e..9861637 100644
--- a/src/bootstrap/src/core/build_steps/tool.rs
+++ b/src/bootstrap/src/core/build_steps/tool.rs
@@ -1313,10 +1313,8 @@ pub fn tool_cmd(&self, tool: Tool) -> BootstrapCommand {
//
// Notably this munges the dynamic library lookup path to point to the
// right location to run `compiler`.
- let mut lib_paths: Vec<PathBuf> = vec![
- self.build.rustc_snapshot_libdir(),
- self.cargo_out(compiler, Mode::ToolBootstrap, *host).join("deps"),
- ];
+ let mut lib_paths: Vec<PathBuf> =
+ vec![self.cargo_out(compiler, Mode::ToolBootstrap, *host).join("deps")];
// On MSVC a tool may invoke a C compiler (e.g., compiletest in run-make
// mode) and that C compiler may need some extra PATH modification. Do
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index 491f55c..a92d58e 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -28,8 +28,6 @@
use serde::Deserialize;
#[cfg(feature = "tracing")]
use tracing::{instrument, span};
-#[cfg(feature = "tracing")]
-use tracing::{instrument, span};
use crate::core::build_steps::llvm;
use crate::core::build_steps::llvm::LLVM_INVALIDATION_PATHS;
diff --git a/src/bootstrap/src/core/config/mod.rs b/src/bootstrap/src/core/config/mod.rs
index f39e7b0..285d209 100644
--- a/src/bootstrap/src/core/config/mod.rs
+++ b/src/bootstrap/src/core/config/mod.rs
@@ -39,8 +39,6 @@
pub use toml::change_id::ChangeId;
pub use toml::rust::LldMode;
pub use toml::target::Target;
-#[cfg(feature = "tracing")]
-use tracing::{instrument, span};
use crate::Display;
use crate::str::FromStr;
diff --git a/src/doc/rustdoc/src/write-documentation/the-doc-attribute.md b/src/doc/rustdoc/src/write-documentation/the-doc-attribute.md
index 6ec93d1..65e6b41 100644
--- a/src/doc/rustdoc/src/write-documentation/the-doc-attribute.md
+++ b/src/doc/rustdoc/src/write-documentation/the-doc-attribute.md
@@ -143,15 +143,6 @@
it will not.
-### `test(attr(...))`
-
-This form of the `doc` attribute allows you to add arbitrary attributes to all your doctests. For
-example, if you want your doctests to fail if they have dead code, you could add this:
-
-```rust,no_run
-#![doc(test(attr(deny(dead_code))))]
-```
-
## At the item level
These forms of the `#[doc]` attribute are used on individual items, to control how
@@ -283,3 +274,26 @@
on the `do_something` method and then it's all good!
Users can now look for `lib_name_do_something` in our crate directly and find
`Obj::do_something`.
+
+### `test(attr(...))`
+
+This form of the `doc` attribute allows you to add arbitrary attributes to all your doctests. For
+example, if you want your doctests to fail if they have dead code, you could add this:
+
+```rust,no_run
+#![doc(test(attr(deny(dead_code))))]
+
+mod my_mod {
+ #![doc(test(attr(allow(dead_code))))] // but allow `dead_code` for this module
+}
+```
+
+`test(attr(..))` attributes are appended to the parent module's, they do not replace the current
+list of attributes. In the previous example, both attributes would be present:
+
+```rust,no_run
+// For every doctest in `my_mod`
+
+#![deny(dead_code)] // from the crate-root
+#![allow(dead_code)] // from `my_mod`
+```
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index b2fe24d..a81d602 100644
--- a/src/librustdoc/doctest.rs
+++ b/src/librustdoc/doctest.rs
@@ -5,6 +5,7 @@
mod rust;
use std::fs::File;
+use std::hash::{Hash, Hasher};
use std::io::{self, Write};
use std::path::{Path, PathBuf};
use std::process::{self, Command, Stdio};
@@ -14,7 +15,7 @@
pub(crate) use make::{BuildDocTestBuilder, DocTestBuilder};
pub(crate) use markdown::test as test_markdown;
-use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet};
+use rustc_data_structures::fx::{FxHashMap, FxHasher, FxIndexMap, FxIndexSet};
use rustc_errors::emitter::HumanReadableErrorType;
use rustc_errors::{ColorConfig, DiagCtxtHandle};
use rustc_hir as hir;
@@ -45,8 +46,6 @@ pub(crate) struct GlobalTestOptions {
/// Whether inserting extra indent spaces in code block,
/// default is `false`, only `true` for generating code link of Rust playground
pub(crate) insert_indent_space: bool,
- /// Additional crate-level attributes to add to doctests.
- pub(crate) attrs: Vec<String>,
/// Path to file containing arguments for the invocation of rustc.
pub(crate) args_file: PathBuf,
}
@@ -283,7 +282,7 @@ pub(crate) fn run_tests(
rustdoc_options: &Arc<RustdocOptions>,
unused_extern_reports: &Arc<Mutex<Vec<UnusedExterns>>>,
mut standalone_tests: Vec<test::TestDescAndFn>,
- mergeable_tests: FxIndexMap<Edition, Vec<(DocTestBuilder, ScrapedDocTest)>>,
+ mergeable_tests: FxIndexMap<MergeableTestKey, Vec<(DocTestBuilder, ScrapedDocTest)>>,
// We pass this argument so we can drop it manually before using `exit`.
mut temp_dir: Option<TempDir>,
) {
@@ -298,7 +297,7 @@ pub(crate) fn run_tests(
let mut ran_edition_tests = 0;
let target_str = rustdoc_options.target.to_string();
- for (edition, mut doctests) in mergeable_tests {
+ for (MergeableTestKey { edition, global_crate_attrs_hash }, mut doctests) in mergeable_tests {
if doctests.is_empty() {
continue;
}
@@ -308,8 +307,8 @@ pub(crate) fn run_tests(
let rustdoc_test_options = IndividualTestOptions::new(
rustdoc_options,
- &Some(format!("merged_doctest_{edition}")),
- PathBuf::from(format!("doctest_{edition}.rs")),
+ &Some(format!("merged_doctest_{edition}_{global_crate_attrs_hash}")),
+ PathBuf::from(format!("doctest_{edition}_{global_crate_attrs_hash}.rs")),
);
for (doctest, scraped_test) in &doctests {
@@ -371,12 +370,9 @@ fn scrape_test_config(
attrs: &[hir::Attribute],
args_file: PathBuf,
) -> GlobalTestOptions {
- use rustc_ast_pretty::pprust;
-
let mut opts = GlobalTestOptions {
crate_name,
no_crate_inject: false,
- attrs: Vec::new(),
insert_indent_space: false,
args_file,
};
@@ -393,13 +389,7 @@ fn scrape_test_config(
if attr.has_name(sym::no_crate_inject) {
opts.no_crate_inject = true;
}
- if attr.has_name(sym::attr)
- && let Some(l) = attr.meta_item_list()
- {
- for item in l {
- opts.attrs.push(pprust::meta_list_item_to_string(item));
- }
- }
+ // NOTE: `test(attr(..))` is handled when discovering the individual tests
}
opts
@@ -848,6 +838,7 @@ pub(crate) struct ScrapedDocTest {
text: String,
name: String,
span: Span,
+ global_crate_attrs: Vec<String>,
}
impl ScrapedDocTest {
@@ -858,6 +849,7 @@ fn new(
langstr: LangString,
text: String,
span: Span,
+ global_crate_attrs: Vec<String>,
) -> Self {
let mut item_path = logical_path.join("::");
item_path.retain(|c| c != ' ');
@@ -867,7 +859,7 @@ fn new(
let name =
format!("{} - {item_path}(line {line})", filename.prefer_remapped_unconditionaly());
- Self { filename, line, langstr, text, name, span }
+ Self { filename, line, langstr, text, name, span, global_crate_attrs }
}
fn edition(&self, opts: &RustdocOptions) -> Edition {
self.langstr.edition.unwrap_or(opts.edition)
@@ -896,9 +888,15 @@ pub(crate) trait DocTestVisitor {
fn visit_header(&mut self, _name: &str, _level: u32) {}
}
+#[derive(Clone, Debug, Hash, Eq, PartialEq)]
+pub(crate) struct MergeableTestKey {
+ edition: Edition,
+ global_crate_attrs_hash: u64,
+}
+
struct CreateRunnableDocTests {
standalone_tests: Vec<test::TestDescAndFn>,
- mergeable_tests: FxIndexMap<Edition, Vec<(DocTestBuilder, ScrapedDocTest)>>,
+ mergeable_tests: FxIndexMap<MergeableTestKey, Vec<(DocTestBuilder, ScrapedDocTest)>>,
rustdoc_options: Arc<RustdocOptions>,
opts: GlobalTestOptions,
@@ -949,6 +947,7 @@ fn add_test(&mut self, scraped_test: ScrapedDocTest, dcx: Option<DiagCtxtHandle<
let edition = scraped_test.edition(&self.rustdoc_options);
let doctest = BuildDocTestBuilder::new(&scraped_test.text)
.crate_name(&self.opts.crate_name)
+ .global_crate_attrs(scraped_test.global_crate_attrs.clone())
.edition(edition)
.can_merge_doctests(self.can_merge_doctests)
.test_id(test_id)
@@ -965,7 +964,17 @@ fn add_test(&mut self, scraped_test: ScrapedDocTest, dcx: Option<DiagCtxtHandle<
let test_desc = self.generate_test_desc_and_fn(doctest, scraped_test);
self.standalone_tests.push(test_desc);
} else {
- self.mergeable_tests.entry(edition).or_default().push((doctest, scraped_test));
+ self.mergeable_tests
+ .entry(MergeableTestKey {
+ edition,
+ global_crate_attrs_hash: {
+ let mut hasher = FxHasher::default();
+ scraped_test.global_crate_attrs.hash(&mut hasher);
+ hasher.finish()
+ },
+ })
+ .or_default()
+ .push((doctest, scraped_test));
}
}
diff --git a/src/librustdoc/doctest/extracted.rs b/src/librustdoc/doctest/extracted.rs
index 3b17ccc..ebe6bfd 100644
--- a/src/librustdoc/doctest/extracted.rs
+++ b/src/librustdoc/doctest/extracted.rs
@@ -35,13 +35,16 @@ pub(crate) fn add_test(
) {
let edition = scraped_test.edition(options);
- let ScrapedDocTest { filename, line, langstr, text, name, .. } = scraped_test;
+ let ScrapedDocTest { filename, line, langstr, text, name, global_crate_attrs, .. } =
+ scraped_test;
let doctest = BuildDocTestBuilder::new(&text)
.crate_name(&opts.crate_name)
+ .global_crate_attrs(global_crate_attrs)
.edition(edition)
.lang_str(&langstr)
.build(None);
+
let (full_test_code, size) = doctest.generate_unique_doctest(
&text,
langstr.test_harness,
diff --git a/src/librustdoc/doctest/make.rs b/src/librustdoc/doctest/make.rs
index 66647b8..5e57161 100644
--- a/src/librustdoc/doctest/make.rs
+++ b/src/librustdoc/doctest/make.rs
@@ -45,6 +45,7 @@ pub(crate) struct BuildDocTestBuilder<'a> {
test_id: Option<String>,
lang_str: Option<&'a LangString>,
span: Span,
+ global_crate_attrs: Vec<String>,
}
impl<'a> BuildDocTestBuilder<'a> {
@@ -57,6 +58,7 @@ pub(crate) fn new(source: &'a str) -> Self {
test_id: None,
lang_str: None,
span: DUMMY_SP,
+ global_crate_attrs: Vec::new(),
}
}
@@ -96,6 +98,12 @@ pub(crate) fn edition(mut self, edition: Edition) -> Self {
self
}
+ #[inline]
+ pub(crate) fn global_crate_attrs(mut self, global_crate_attrs: Vec<String>) -> Self {
+ self.global_crate_attrs = global_crate_attrs;
+ self
+ }
+
pub(crate) fn build(self, dcx: Option<DiagCtxtHandle<'_>>) -> DocTestBuilder {
let BuildDocTestBuilder {
source,
@@ -106,6 +114,7 @@ pub(crate) fn build(self, dcx: Option<DiagCtxtHandle<'_>>) -> DocTestBuilder {
test_id,
lang_str,
span,
+ global_crate_attrs,
} = self;
let can_merge_doctests = can_merge_doctests
&& lang_str.is_some_and(|lang_str| {
@@ -133,6 +142,7 @@ pub(crate) fn build(self, dcx: Option<DiagCtxtHandle<'_>>) -> DocTestBuilder {
// If the AST returned an error, we don't want this doctest to be merged with the
// others.
return DocTestBuilder::invalid(
+ Vec::new(),
String::new(),
String::new(),
String::new(),
@@ -155,6 +165,7 @@ pub(crate) fn build(self, dcx: Option<DiagCtxtHandle<'_>>) -> DocTestBuilder {
DocTestBuilder {
supports_color,
has_main_fn,
+ global_crate_attrs,
crate_attrs,
maybe_crate_attrs,
crates,
@@ -173,6 +184,7 @@ pub(crate) struct DocTestBuilder {
pub(crate) supports_color: bool,
pub(crate) already_has_extern_crate: bool,
pub(crate) has_main_fn: bool,
+ pub(crate) global_crate_attrs: Vec<String>,
pub(crate) crate_attrs: String,
/// If this is a merged doctest, it will be put into `everything_else`, otherwise it will
/// put into `crate_attrs`.
@@ -186,6 +198,7 @@ pub(crate) struct DocTestBuilder {
impl DocTestBuilder {
fn invalid(
+ global_crate_attrs: Vec<String>,
crate_attrs: String,
maybe_crate_attrs: String,
crates: String,
@@ -195,6 +208,7 @@ fn invalid(
Self {
supports_color: false,
has_main_fn: false,
+ global_crate_attrs,
crate_attrs,
maybe_crate_attrs,
crates,
@@ -224,7 +238,8 @@ pub(crate) fn generate_unique_doctest(
let mut line_offset = 0;
let mut prog = String::new();
let everything_else = self.everything_else.trim();
- if opts.attrs.is_empty() {
+
+ if self.global_crate_attrs.is_empty() {
// If there aren't any attributes supplied by #![doc(test(attr(...)))], then allow some
// lints that are commonly triggered in doctests. The crate-level test attributes are
// commonly used to make tests fail in case they trigger warnings, so having this there in
@@ -233,8 +248,8 @@ pub(crate) fn generate_unique_doctest(
line_offset += 1;
}
- // Next, any attributes that came from the crate root via #![doc(test(attr(...)))].
- for attr in &opts.attrs {
+ // Next, any attributes that came from #![doc(test(attr(...)))].
+ for attr in &self.global_crate_attrs {
prog.push_str(&format!("#![{attr}]\n"));
line_offset += 1;
}
diff --git a/src/librustdoc/doctest/markdown.rs b/src/librustdoc/doctest/markdown.rs
index e358a7e..7f26605 100644
--- a/src/librustdoc/doctest/markdown.rs
+++ b/src/librustdoc/doctest/markdown.rs
@@ -31,6 +31,7 @@ fn visit_test(&mut self, test: String, config: LangString, rel_line: MdRelLine)
config,
test,
DUMMY_SP,
+ Vec::new(),
));
}
@@ -96,7 +97,6 @@ pub(crate) fn test(input: &Input, options: Options) -> Result<(), String> {
crate_name,
no_crate_inject: true,
insert_indent_space: false,
- attrs: vec![],
args_file,
};
diff --git a/src/librustdoc/doctest/runner.rs b/src/librustdoc/doctest/runner.rs
index 39a4f23..f091447 100644
--- a/src/librustdoc/doctest/runner.rs
+++ b/src/librustdoc/doctest/runner.rs
@@ -12,6 +12,7 @@
/// Convenient type to merge compatible doctests into one.
pub(crate) struct DocTestRunner {
crate_attrs: FxIndexSet<String>,
+ global_crate_attrs: FxIndexSet<String>,
ids: String,
output: String,
output_merged_tests: String,
@@ -23,6 +24,7 @@ impl DocTestRunner {
pub(crate) fn new() -> Self {
Self {
crate_attrs: FxIndexSet::default(),
+ global_crate_attrs: FxIndexSet::default(),
ids: String::new(),
output: String::new(),
output_merged_tests: String::new(),
@@ -46,6 +48,9 @@ pub(crate) fn add_test(
for line in doctest.crate_attrs.split('\n') {
self.crate_attrs.insert(line.to_string());
}
+ for line in &doctest.global_crate_attrs {
+ self.global_crate_attrs.insert(line.to_string());
+ }
}
self.ids.push_str(&format!(
"tests.push({}::TEST);\n",
@@ -85,7 +90,7 @@ pub(crate) fn run_merged_tests(
code_prefix.push('\n');
}
- if opts.attrs.is_empty() {
+ if self.global_crate_attrs.is_empty() {
// If there aren't any attributes supplied by #![doc(test(attr(...)))], then allow some
// lints that are commonly triggered in doctests. The crate-level test attributes are
// commonly used to make tests fail in case they trigger warnings, so having this there in
@@ -93,8 +98,8 @@ pub(crate) fn run_merged_tests(
code_prefix.push_str("#![allow(unused)]\n");
}
- // Next, any attributes that came from the crate root via #![doc(test(attr(...)))].
- for attr in &opts.attrs {
+ // Next, any attributes that came from #![doc(test(attr(...)))].
+ for attr in &self.global_crate_attrs {
code_prefix.push_str(&format!("#![{attr}]\n"));
}
diff --git a/src/librustdoc/doctest/rust.rs b/src/librustdoc/doctest/rust.rs
index f9d2aa3..9697510 100644
--- a/src/librustdoc/doctest/rust.rs
+++ b/src/librustdoc/doctest/rust.rs
@@ -4,6 +4,7 @@
use std::env;
use std::sync::Arc;
+use rustc_ast_pretty::pprust;
use rustc_data_structures::fx::FxHashSet;
use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId};
use rustc_hir::{self as hir, CRATE_HIR_ID, intravisit};
@@ -11,7 +12,7 @@
use rustc_middle::ty::TyCtxt;
use rustc_resolve::rustdoc::span_of_fragments;
use rustc_span::source_map::SourceMap;
-use rustc_span::{BytePos, DUMMY_SP, FileName, Pos, Span};
+use rustc_span::{BytePos, DUMMY_SP, FileName, Pos, Span, sym};
use super::{DocTestVisitor, ScrapedDocTest};
use crate::clean::{Attributes, extract_cfg_from_attrs};
@@ -22,6 +23,7 @@ struct RustCollector {
tests: Vec<ScrapedDocTest>,
cur_path: Vec<String>,
position: Span,
+ global_crate_attrs: Vec<String>,
}
impl RustCollector {
@@ -75,6 +77,7 @@ fn visit_test(&mut self, test: String, config: LangString, rel_line: MdRelLine)
config,
test,
span,
+ self.global_crate_attrs.clone(),
));
}
@@ -94,6 +97,7 @@ pub fn new(codes: ErrorCodes, tcx: TyCtxt<'tcx>) -> Self {
cur_path: vec![],
position: DUMMY_SP,
tests: vec![],
+ global_crate_attrs: Vec::new(),
};
Self { codes, tcx, collector }
}
@@ -123,6 +127,26 @@ fn visit_testable<F: FnOnce(&mut Self)>(
return;
}
+ // Try collecting `#[doc(test(attr(...)))]`
+ let old_global_crate_attrs_len = self.collector.global_crate_attrs.len();
+ for doc_test_attrs in ast_attrs
+ .iter()
+ .filter(|a| a.has_name(sym::doc))
+ .flat_map(|a| a.meta_item_list().unwrap_or_default())
+ .filter(|a| a.has_name(sym::test))
+ {
+ let Some(doc_test_attrs) = doc_test_attrs.meta_item_list() else { continue };
+ for attr in doc_test_attrs
+ .iter()
+ .filter(|a| a.has_name(sym::attr))
+ .flat_map(|a| a.meta_item_list().unwrap_or_default())
+ .map(|i| pprust::meta_list_item_to_string(i))
+ {
+ // Add the additional attributes to the global_crate_attrs vector
+ self.collector.global_crate_attrs.push(attr);
+ }
+ }
+
let mut has_name = false;
if let Some(name) = name {
self.collector.cur_path.push(name);
@@ -157,6 +181,9 @@ fn visit_testable<F: FnOnce(&mut Self)>(
nested(self);
+ // Restore global_crate_attrs to it's previous size/content
+ self.collector.global_crate_attrs.truncate(old_global_crate_attrs_len);
+
if has_name {
self.collector.cur_path.pop();
}
diff --git a/src/librustdoc/doctest/tests.rs b/src/librustdoc/doctest/tests.rs
index 08248fd..ce2984c 100644
--- a/src/librustdoc/doctest/tests.rs
+++ b/src/librustdoc/doctest/tests.rs
@@ -7,9 +7,11 @@ fn make_test(
crate_name: Option<&str>,
dont_insert_main: bool,
opts: &GlobalTestOptions,
+ global_crate_attrs: Vec<&str>,
test_id: Option<&str>,
) -> (String, usize) {
- let mut builder = BuildDocTestBuilder::new(test_code);
+ let mut builder = BuildDocTestBuilder::new(test_code)
+ .global_crate_attrs(global_crate_attrs.into_iter().map(|a| a.to_string()).collect());
if let Some(crate_name) = crate_name {
builder = builder.crate_name(crate_name);
}
@@ -28,7 +30,6 @@ fn default_global_opts(crate_name: impl Into<String>) -> GlobalTestOptions {
crate_name: crate_name.into(),
no_crate_inject: false,
insert_indent_space: false,
- attrs: vec![],
args_file: PathBuf::new(),
}
}
@@ -43,7 +44,7 @@ fn main() {
assert_eq!(2+2, 4);
}"
.to_string();
- let (output, len) = make_test(input, None, false, &opts, None);
+ let (output, len) = make_test(input, None, false, &opts, Vec::new(), None);
assert_eq!((output, len), (expected, 2));
}
@@ -58,7 +59,7 @@ fn main() {
assert_eq!(2+2, 4);
}"
.to_string();
- let (output, len) = make_test(input, Some("asdf"), false, &opts, None);
+ let (output, len) = make_test(input, Some("asdf"), false, &opts, Vec::new(), None);
assert_eq!((output, len), (expected, 2));
}
@@ -77,7 +78,7 @@ fn main() {
assert_eq!(2+2, 4);
}"
.to_string();
- let (output, len) = make_test(input, Some("asdf"), false, &opts, None);
+ let (output, len) = make_test(input, Some("asdf"), false, &opts, Vec::new(), None);
assert_eq!((output, len), (expected, 3));
}
@@ -94,7 +95,7 @@ fn main() {
assert_eq!(2+2, 4);
}"
.to_string();
- let (output, len) = make_test(input, Some("asdf"), false, &opts, None);
+ let (output, len) = make_test(input, Some("asdf"), false, &opts, Vec::new(), None);
assert_eq!((output, len), (expected, 2));
}
@@ -112,7 +113,7 @@ fn main() {
assert_eq!(2+2, 4);
}"
.to_string();
- let (output, len) = make_test(input, Some("std"), false, &opts, None);
+ let (output, len) = make_test(input, Some("std"), false, &opts, Vec::new(), None);
assert_eq!((output, len), (expected, 2));
}
@@ -131,7 +132,7 @@ fn main() {
assert_eq!(2+2, 4);
}"
.to_string();
- let (output, len) = make_test(input, Some("asdf"), false, &opts, None);
+ let (output, len) = make_test(input, Some("asdf"), false, &opts, Vec::new(), None);
assert_eq!((output, len), (expected, 2));
}
@@ -148,7 +149,7 @@ fn main() {
assert_eq!(2+2, 4);
}"
.to_string();
- let (output, len) = make_test(input, Some("asdf"), false, &opts, None);
+ let (output, len) = make_test(input, Some("asdf"), false, &opts, Vec::new(), None);
assert_eq!((output, len), (expected, 2));
}
@@ -156,8 +157,7 @@ fn main() {
fn make_test_opts_attrs() {
// If you supplied some doctest attributes with `#![doc(test(attr(...)))]`, it will use
// those instead of the stock `#![allow(unused)]`.
- let mut opts = default_global_opts("asdf");
- opts.attrs.push("feature(sick_rad)".to_string());
+ let opts = default_global_opts("asdf");
let input = "use asdf::qwop;
assert_eq!(2+2, 4);";
let expected = "#![feature(sick_rad)]
@@ -168,11 +168,10 @@ fn main() {
assert_eq!(2+2, 4);
}"
.to_string();
- let (output, len) = make_test(input, Some("asdf"), false, &opts, None);
+ let (output, len) =
+ make_test(input, Some("asdf"), false, &opts, vec!["feature(sick_rad)"], None);
assert_eq!((output, len), (expected, 3));
- // Adding more will also bump the returned line offset.
- opts.attrs.push("feature(hella_dope)".to_string());
let expected = "#![feature(sick_rad)]
#![feature(hella_dope)]
#[allow(unused_extern_crates)]
@@ -182,7 +181,18 @@ fn main() {
assert_eq!(2+2, 4);
}"
.to_string();
- let (output, len) = make_test(input, Some("asdf"), false, &opts, None);
+ let (output, len) = make_test(
+ input,
+ Some("asdf"),
+ false,
+ &opts,
+ vec![
+ "feature(sick_rad)",
+ // Adding more will also bump the returned line offset.
+ "feature(hella_dope)",
+ ],
+ None,
+ );
assert_eq!((output, len), (expected, 4));
}
@@ -200,7 +210,7 @@ fn main() {
assert_eq!(2+2, 4);
}"
.to_string();
- let (output, len) = make_test(input, None, false, &opts, None);
+ let (output, len) = make_test(input, None, false, &opts, Vec::new(), None);
assert_eq!((output, len), (expected, 2));
}
@@ -216,7 +226,7 @@ fn main() {
assert_eq!(2+2, 4);
}"
.to_string();
- let (output, len) = make_test(input, None, false, &opts, None);
+ let (output, len) = make_test(input, None, false, &opts, Vec::new(), None);
assert_eq!((output, len), (expected, 1));
}
@@ -232,7 +242,7 @@ fn main() {
assert_eq!(2+2, 4);
}"
.to_string();
- let (output, len) = make_test(input, None, false, &opts, None);
+ let (output, len) = make_test(input, None, false, &opts, Vec::new(), None);
assert_eq!((output, len), (expected, 2));
}
@@ -246,7 +256,7 @@ fn make_test_dont_insert_main() {
//Ceci n'est pas une `fn main`
assert_eq!(2+2, 4);"
.to_string();
- let (output, len) = make_test(input, None, true, &opts, None);
+ let (output, len) = make_test(input, None, true, &opts, Vec::new(), None);
assert_eq!((output, len), (expected, 1));
}
@@ -264,7 +274,7 @@ fn main() {
}"
.to_string();
- let (output, len) = make_test(input, None, false, &opts, None);
+ let (output, len) = make_test(input, None, false, &opts, Vec::new(), None);
assert_eq!((output, len), (expected, 2));
}
@@ -284,7 +294,7 @@ fn main() {
}"
.to_string();
- let (output, len) = make_test(input, Some("asdf"), false, &opts, None);
+ let (output, len) = make_test(input, Some("asdf"), false, &opts, Vec::new(), None);
assert_eq!((output, len), (expected, 3));
}
@@ -302,7 +312,7 @@ fn main() {}
}"
.to_string();
- let (output, len) = make_test(input, Some("my_crate"), false, &opts, None);
+ let (output, len) = make_test(input, Some("my_crate"), false, &opts, Vec::new(), None);
assert_eq!((output, len), (expected, 1));
}
@@ -322,7 +332,7 @@ fn main() { fn _inner() -> core::result::Result<(), impl core::fmt::Debug> {
Ok::<(), io:Error>(())
} _inner().unwrap() }"
.to_string();
- let (output, len) = make_test(input, None, false, &opts, None);
+ let (output, len) = make_test(input, None, false, &opts, Vec::new(), None);
assert_eq!((output, len), (expected, 2));
}
@@ -336,7 +346,7 @@ fn main() { #[allow(non_snake_case)] fn _doctest_main__some_unique_name() {
assert_eq!(2+2, 4);
} _doctest_main__some_unique_name() }"
.to_string();
- let (output, len) = make_test(input, None, false, &opts, Some("_some_unique_name"));
+ let (output, len) = make_test(input, None, false, &opts, Vec::new(), Some("_some_unique_name"));
assert_eq!((output, len), (expected, 2));
}
@@ -355,7 +365,7 @@ fn main() {
eprintln!(\"hello anan\");
}"
.to_string();
- let (output, len) = make_test(input, None, false, &opts, None);
+ let (output, len) = make_test(input, None, false, &opts, Vec::new(), None);
assert_eq!((output, len), (expected, 2));
}
@@ -375,7 +385,7 @@ fn main() {
eprintln!(\"hello anan\");
}"
.to_string();
- let (output, len) = make_test(input, None, false, &opts, None);
+ let (output, len) = make_test(input, None, false, &opts, Vec::new(), None);
assert_eq!((output, len), (expected, 1));
}
@@ -400,7 +410,7 @@ fn main() {
}"
.to_string();
- let (output, len) = make_test(input, None, false, &opts, None);
+ let (output, len) = make_test(input, None, false, &opts, Vec::new(), None);
assert_eq!((output, len), (expected, 2));
// And same, if there is a `main` function provided by the user, we ensure that it's
@@ -420,7 +430,7 @@ fn main() {
fn main() {}"
.to_string();
- let (output, len) = make_test(input, None, false, &opts, None);
+ let (output, len) = make_test(input, None, false, &opts, Vec::new(), None);
assert_eq!((output, len), (expected, 1));
}
@@ -448,6 +458,6 @@ pub mod outer_module {
}
}"
.to_string();
- let (output, len) = make_test(input, None, false, &opts, None);
+ let (output, len) = make_test(input, None, false, &opts, Vec::new(), None);
assert_eq!((output, len), (expected, 2));
}
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index 68ba124..d370178 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -300,7 +300,6 @@ fn next(&mut self) -> Option<Self::Item> {
crate_name: krate.map(String::from).unwrap_or_default(),
no_crate_inject: false,
insert_indent_space: true,
- attrs: vec![],
args_file: PathBuf::new(),
};
let mut builder = doctest::BuildDocTestBuilder::new(&test).edition(edition);
diff --git a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-aes-vaes.rs b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-aes-vaes.rs
index 48633c0..8936ae8 100644
--- a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-aes-vaes.rs
+++ b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-aes-vaes.rs
@@ -2,8 +2,6 @@
//@only-target: x86_64 i686
//@compile-flags: -C target-feature=+aes,+vaes,+avx512f
-#![feature(stdarch_x86_avx512)]
-
use core::mem::transmute;
#[cfg(target_arch = "x86")]
use std::arch::x86::*;
diff --git a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-avx512.rs b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-avx512.rs
index 0ec2f67..65d7b57 100644
--- a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-avx512.rs
+++ b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-avx512.rs
@@ -2,8 +2,6 @@
//@only-target: x86_64 i686
//@compile-flags: -C target-feature=+avx512f,+avx512vl,+avx512bitalg,+avx512vpopcntdq
-#![feature(stdarch_x86_avx512)]
-
#[cfg(target_arch = "x86")]
use std::arch::x86::*;
#[cfg(target_arch = "x86_64")]
diff --git a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-gfni.rs b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-gfni.rs
index b58d68e..48958ef 100644
--- a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-gfni.rs
+++ b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-gfni.rs
@@ -6,7 +6,6 @@
// be interpreted as integers; signedness does not make sense for them, but
// __mXXXi happens to be defined in terms of signed integers.
#![allow(overflowing_literals)]
-#![feature(stdarch_x86_avx512)]
#[cfg(target_arch = "x86")]
use std::arch::x86::*;
diff --git a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-vpclmulqdq.rs b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-vpclmulqdq.rs
index c7c9eb5..e2a045b 100644
--- a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-vpclmulqdq.rs
+++ b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-vpclmulqdq.rs
@@ -8,7 +8,6 @@
// be interpreted as integers; signedness does not make sense for them, but
// __mXXXi happens to be defined in terms of signed integers.
#![allow(overflowing_literals)]
-#![feature(stdarch_x86_avx512)]
#[cfg(target_arch = "x86")]
use std::arch::x86::*;
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs b/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs
index f9ff392..de8a429 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs
@@ -4458,20 +4458,6 @@ fn foobar() -> u32 { 23 }
deny_since: None,
},
Lint {
- label: "const_eq_ignore_ascii_case",
- description: r##"# `const_eq_ignore_ascii_case`
-
-The tracking issue for this feature is: [#131719]
-
-[#131719]: https://github.com/rust-lang/rust/issues/131719
-
-------------------------
-"##,
- default_severity: Severity::Allow,
- warn_since: None,
- deny_since: None,
- },
- Lint {
label: "const_eval_select",
description: r##"# `const_eval_select`
diff --git a/tests/crashes/140571.rs b/tests/crashes/140571.rs
deleted file mode 100644
index 97fa1d8..0000000
--- a/tests/crashes/140571.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-//@ known-bug: #140571
-pub trait IsVoid {
- const IS_VOID: bool;
-}
-impl<T> IsVoid for T {
- default const IS_VOID: bool = false;
-}
-impl<T> Maybe<T> for () where T: NotVoid + ?Sized {}
-
-pub trait NotVoid {}
-impl<T> NotVoid for T where T: IsVoid<IS_VOID = false> + ?Sized {}
-
-pub trait Maybe<T> {}
-impl<T> Maybe<T> for T {}
diff --git a/tests/run-make/doctests-keep-binaries-2024/rmake.rs b/tests/run-make/doctests-keep-binaries-2024/rmake.rs
index 3e8ffcb..97324e1 100644
--- a/tests/run-make/doctests-keep-binaries-2024/rmake.rs
+++ b/tests/run-make/doctests-keep-binaries-2024/rmake.rs
@@ -16,7 +16,22 @@ fn setup_test_env<F: FnOnce(&Path, &Path)>(callback: F) {
}
fn check_generated_binaries() {
- run("doctests/merged_doctest_2024/rust_out");
+ let mut found_merged_doctest = false;
+ rfs::read_dir_entries("doctests/", |path| {
+ if path
+ .file_name()
+ .and_then(|name| name.to_str())
+ .is_some_and(|name| name.starts_with("merged_doctest_2024"))
+ {
+ found_merged_doctest = true;
+ let rust_out = path.join("rust_out");
+ let rust_out = rust_out.to_string_lossy();
+ run(&*rust_out);
+ }
+ });
+ if !found_merged_doctest {
+ panic!("no directory starting with `merged_doctest_2024` found under `doctests/`");
+ }
}
fn main() {
diff --git a/tests/rustdoc-ui/doctest/dead-code-items.rs b/tests/rustdoc-ui/doctest/dead-code-items.rs
new file mode 100644
index 0000000..015504c
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/dead-code-items.rs
@@ -0,0 +1,116 @@
+// Same test as dead-code-module but with 2 doc(test(attr())) at different levels.
+
+//@ edition: 2024
+//@ compile-flags:--test --test-args=--test-threads=1
+//@ normalize-stdout: "tests/rustdoc-ui/doctest" -> "$$DIR"
+//@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME"
+//@ failure-status: 101
+
+#![doc(test(attr(deny(warnings))))]
+
+#[doc(test(attr(allow(dead_code))))]
+/// Example
+///
+/// ```rust,no_run
+/// trait OnlyWarning { fn no_deny_warnings(); }
+/// ```
+static S: u32 = 5;
+
+#[doc(test(attr(allow(dead_code))))]
+/// Example
+///
+/// ```rust,no_run
+/// let unused_error = 5;
+///
+/// fn dead_code_but_no_error() {}
+/// ```
+const C: u32 = 5;
+
+#[doc(test(attr(allow(dead_code))))]
+/// Example
+///
+/// ```rust,no_run
+/// trait OnlyWarningAtA { fn no_deny_warnings(); }
+/// ```
+struct A {
+ #[doc(test(attr(deny(dead_code))))]
+ /// Example
+ ///
+ /// ```rust,no_run
+ /// trait DeadCodeInField {}
+ /// ```
+ field: u32
+}
+
+#[doc(test(attr(allow(dead_code))))]
+/// Example
+///
+/// ```rust,no_run
+/// trait OnlyWarningAtU { fn no_deny_warnings(); }
+/// ```
+union U {
+ #[doc(test(attr(deny(dead_code))))]
+ /// Example
+ ///
+ /// ```rust,no_run
+ /// trait DeadCodeInUnionField {}
+ /// ```
+ field: u32,
+ /// Example
+ ///
+ /// ```rust,no_run
+ /// trait NotDeadCodeInUnionField {}
+ /// ```
+ field2: u64,
+}
+
+#[doc(test(attr(deny(dead_code))))]
+/// Example
+///
+/// ```rust,no_run
+/// let not_dead_code_but_unused = 5;
+/// ```
+enum Enum {
+ #[doc(test(attr(allow(dead_code))))]
+ /// Example
+ ///
+ /// ```rust,no_run
+ /// trait NotDeadCodeInVariant {}
+ ///
+ /// fn main() { let unused_in_variant = 5; }
+ /// ```
+ Variant1,
+}
+
+#[doc(test(attr(allow(dead_code))))]
+/// Example
+///
+/// ```rust,no_run
+/// trait OnlyWarningAtImplA { fn no_deny_warnings(); }
+/// ```
+impl A {
+ /// Example
+ ///
+ /// ```rust,no_run
+ /// trait NotDeadCodeInImplMethod {}
+ /// ```
+ fn method() {}
+}
+
+#[doc(test(attr(deny(dead_code))))]
+/// Example
+///
+/// ```rust,no_run
+/// trait StillDeadCodeAtMyTrait { }
+/// ```
+trait MyTrait {
+ #[doc(test(attr(allow(dead_code))))]
+ /// Example
+ ///
+ /// ```rust,no_run
+ /// trait NotDeadCodeAtImplFn {}
+ ///
+ /// fn main() { let unused_in_impl = 5; }
+ /// ```
+ fn my_trait_fn();
+}
diff --git a/tests/rustdoc-ui/doctest/dead-code-items.stdout b/tests/rustdoc-ui/doctest/dead-code-items.stdout
new file mode 100644
index 0000000..4b9d8be
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/dead-code-items.stdout
@@ -0,0 +1,146 @@
+
+running 13 tests
+test $DIR/dead-code-items.rs - A (line 32) - compile ... ok
+test $DIR/dead-code-items.rs - A (line 88) - compile ... ok
+test $DIR/dead-code-items.rs - A::field (line 39) - compile ... FAILED
+test $DIR/dead-code-items.rs - A::method (line 94) - compile ... ok
+test $DIR/dead-code-items.rs - C (line 22) - compile ... FAILED
+test $DIR/dead-code-items.rs - Enum (line 70) - compile ... FAILED
+test $DIR/dead-code-items.rs - Enum::Variant1 (line 77) - compile ... FAILED
+test $DIR/dead-code-items.rs - MyTrait (line 103) - compile ... FAILED
+test $DIR/dead-code-items.rs - MyTrait::my_trait_fn (line 110) - compile ... FAILED
+test $DIR/dead-code-items.rs - S (line 14) - compile ... ok
+test $DIR/dead-code-items.rs - U (line 48) - compile ... ok
+test $DIR/dead-code-items.rs - U::field (line 55) - compile ... FAILED
+test $DIR/dead-code-items.rs - U::field2 (line 61) - compile ... ok
+
+failures:
+
+---- $DIR/dead-code-items.rs - A::field (line 39) stdout ----
+error: trait `DeadCodeInField` is never used
+ --> $DIR/dead-code-items.rs:40:7
+ |
+LL | trait DeadCodeInField {}
+ | ^^^^^^^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/dead-code-items.rs:38:9
+ |
+LL | #![deny(dead_code)]
+ | ^^^^^^^^^
+
+error: aborting due to 1 previous error
+
+Couldn't compile the test.
+---- $DIR/dead-code-items.rs - C (line 22) stdout ----
+error: unused variable: `unused_error`
+ --> $DIR/dead-code-items.rs:23:5
+ |
+LL | let unused_error = 5;
+ | ^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused_error`
+ |
+note: the lint level is defined here
+ --> $DIR/dead-code-items.rs:20:9
+ |
+LL | #![deny(warnings)]
+ | ^^^^^^^^
+ = note: `#[deny(unused_variables)]` implied by `#[deny(warnings)]`
+
+error: aborting due to 1 previous error
+
+Couldn't compile the test.
+---- $DIR/dead-code-items.rs - Enum (line 70) stdout ----
+error: unused variable: `not_dead_code_but_unused`
+ --> $DIR/dead-code-items.rs:71:5
+ |
+LL | let not_dead_code_but_unused = 5;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_not_dead_code_but_unused`
+ |
+note: the lint level is defined here
+ --> $DIR/dead-code-items.rs:68:9
+ |
+LL | #![deny(warnings)]
+ | ^^^^^^^^
+ = note: `#[deny(unused_variables)]` implied by `#[deny(warnings)]`
+
+error: aborting due to 1 previous error
+
+Couldn't compile the test.
+---- $DIR/dead-code-items.rs - Enum::Variant1 (line 77) stdout ----
+error: unused variable: `unused_in_variant`
+ --> $DIR/dead-code-items.rs:80:17
+ |
+LL | fn main() { let unused_in_variant = 5; }
+ | ^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused_in_variant`
+ |
+note: the lint level is defined here
+ --> $DIR/dead-code-items.rs:75:9
+ |
+LL | #![deny(warnings)]
+ | ^^^^^^^^
+ = note: `#[deny(unused_variables)]` implied by `#[deny(warnings)]`
+
+error: aborting due to 1 previous error
+
+Couldn't compile the test.
+---- $DIR/dead-code-items.rs - MyTrait (line 103) stdout ----
+error: trait `StillDeadCodeAtMyTrait` is never used
+ --> $DIR/dead-code-items.rs:104:7
+ |
+LL | trait StillDeadCodeAtMyTrait { }
+ | ^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/dead-code-items.rs:102:9
+ |
+LL | #![deny(dead_code)]
+ | ^^^^^^^^^
+
+error: aborting due to 1 previous error
+
+Couldn't compile the test.
+---- $DIR/dead-code-items.rs - MyTrait::my_trait_fn (line 110) stdout ----
+error: unused variable: `unused_in_impl`
+ --> $DIR/dead-code-items.rs:113:17
+ |
+LL | fn main() { let unused_in_impl = 5; }
+ | ^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused_in_impl`
+ |
+note: the lint level is defined here
+ --> $DIR/dead-code-items.rs:108:9
+ |
+LL | #![deny(warnings)]
+ | ^^^^^^^^
+ = note: `#[deny(unused_variables)]` implied by `#[deny(warnings)]`
+
+error: aborting due to 1 previous error
+
+Couldn't compile the test.
+---- $DIR/dead-code-items.rs - U::field (line 55) stdout ----
+error: trait `DeadCodeInUnionField` is never used
+ --> $DIR/dead-code-items.rs:56:7
+ |
+LL | trait DeadCodeInUnionField {}
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/dead-code-items.rs:54:9
+ |
+LL | #![deny(dead_code)]
+ | ^^^^^^^^^
+
+error: aborting due to 1 previous error
+
+Couldn't compile the test.
+
+failures:
+ $DIR/dead-code-items.rs - A::field (line 39)
+ $DIR/dead-code-items.rs - C (line 22)
+ $DIR/dead-code-items.rs - Enum (line 70)
+ $DIR/dead-code-items.rs - Enum::Variant1 (line 77)
+ $DIR/dead-code-items.rs - MyTrait (line 103)
+ $DIR/dead-code-items.rs - MyTrait::my_trait_fn (line 110)
+ $DIR/dead-code-items.rs - U::field (line 55)
+
+test result: FAILED. 6 passed; 7 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/tests/rustdoc-ui/doctest/dead-code-module-2.rs b/tests/rustdoc-ui/doctest/dead-code-module-2.rs
new file mode 100644
index 0000000..de7b11b
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/dead-code-module-2.rs
@@ -0,0 +1,27 @@
+// Same test as dead-code-module but with 2 doc(test(attr())) at different levels.
+
+//@ edition: 2024
+//@ compile-flags:--test
+//@ normalize-stdout: "tests/rustdoc-ui/doctest" -> "$$DIR"
+//@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME"
+//@ failure-status: 101
+
+#![doc(test(attr(allow(unused_variables))))]
+
+mod my_mod {
+ #![doc(test(attr(deny(warnings))))]
+
+ /// Example
+ ///
+ /// ```rust,no_run
+ /// trait T { fn f(); }
+ /// ```
+ pub fn f() {}
+}
+
+/// Example
+///
+/// ```rust,no_run
+/// trait OnlyWarning { fn no_deny_warnings(); }
+/// ```
+pub fn g() {}
diff --git a/tests/rustdoc-ui/doctest/dead-code-module-2.stdout b/tests/rustdoc-ui/doctest/dead-code-module-2.stdout
new file mode 100644
index 0000000..d44068d
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/dead-code-module-2.stdout
@@ -0,0 +1,35 @@
+
+running 1 test
+test $DIR/dead-code-module-2.rs - g (line 24) - compile ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
+
+running 1 test
+test $DIR/dead-code-module-2.rs - my_mod::f (line 16) - compile ... FAILED
+
+failures:
+
+---- $DIR/dead-code-module-2.rs - my_mod::f (line 16) stdout ----
+error: trait `T` is never used
+ --> $DIR/dead-code-module-2.rs:17:7
+ |
+LL | trait T { fn f(); }
+ | ^
+ |
+note: the lint level is defined here
+ --> $DIR/dead-code-module-2.rs:15:9
+ |
+LL | #![deny(warnings)]
+ | ^^^^^^^^
+ = note: `#[deny(dead_code)]` implied by `#[deny(warnings)]`
+
+error: aborting due to 1 previous error
+
+Couldn't compile the test.
+
+failures:
+ $DIR/dead-code-module-2.rs - my_mod::f (line 16)
+
+test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/tests/rustdoc-ui/doctest/dead-code-module.rs b/tests/rustdoc-ui/doctest/dead-code-module.rs
new file mode 100644
index 0000000..f825749
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/dead-code-module.rs
@@ -0,0 +1,18 @@
+// Same test as dead-code but inside a module.
+
+//@ edition: 2024
+//@ compile-flags:--test
+//@ normalize-stdout: "tests/rustdoc-ui/doctest" -> "$$DIR"
+//@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME"
+//@ failure-status: 101
+
+mod my_mod {
+ #![doc(test(attr(allow(unused_variables), deny(warnings))))]
+
+ /// Example
+ ///
+ /// ```rust,no_run
+ /// trait T { fn f(); }
+ /// ```
+ pub fn f() {}
+}
diff --git a/tests/rustdoc-ui/doctest/dead-code-module.stdout b/tests/rustdoc-ui/doctest/dead-code-module.stdout
new file mode 100644
index 0000000..b5ccf22
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/dead-code-module.stdout
@@ -0,0 +1,29 @@
+
+running 1 test
+test $DIR/dead-code-module.rs - my_mod::f (line 14) - compile ... FAILED
+
+failures:
+
+---- $DIR/dead-code-module.rs - my_mod::f (line 14) stdout ----
+error: trait `T` is never used
+ --> $DIR/dead-code-module.rs:15:7
+ |
+LL | trait T { fn f(); }
+ | ^
+ |
+note: the lint level is defined here
+ --> $DIR/dead-code-module.rs:13:9
+ |
+LL | #![deny(warnings)]
+ | ^^^^^^^^
+ = note: `#[deny(dead_code)]` implied by `#[deny(warnings)]`
+
+error: aborting due to 1 previous error
+
+Couldn't compile the test.
+
+failures:
+ $DIR/dead-code-module.rs - my_mod::f (line 14)
+
+test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/tests/rustdoc-ui/doctest/doc-test-attr-pass-module.rs b/tests/rustdoc-ui/doctest/doc-test-attr-pass-module.rs
new file mode 100644
index 0000000..e916ca4
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/doc-test-attr-pass-module.rs
@@ -0,0 +1,11 @@
+//@ check-pass
+
+#![crate_type = "lib"]
+#![deny(invalid_doc_attributes)]
+#![doc(test(no_crate_inject))]
+
+mod my_mod {
+ #![doc(test(attr(deny(warnings))))]
+
+ pub fn foo() {}
+}
diff --git a/tests/ui/asm/x86_64/evex512-implicit-feature.rs b/tests/ui/asm/x86_64/evex512-implicit-feature.rs
index ec5da7c..1f678b2 100644
--- a/tests/ui/asm/x86_64/evex512-implicit-feature.rs
+++ b/tests/ui/asm/x86_64/evex512-implicit-feature.rs
@@ -2,8 +2,6 @@
//@ only-x86_64
//@ compile-flags: --crate-type=lib -C target-cpu=skylake
-#![feature(stdarch_x86_avx512)]
-
use std::arch::x86_64::*;
#[target_feature(enable = "avx512f")]
diff --git a/tests/ui/future-incompatible-lint-group.rs b/tests/ui/future-incompatible-lint-group.rs
index c845383..ed2c47b 100644
--- a/tests/ui/future-incompatible-lint-group.rs
+++ b/tests/ui/future-incompatible-lint-group.rs
@@ -2,16 +2,14 @@
// lints for changes that are not tied to an edition
#![deny(future_incompatible)]
+// Error since this is a `future_incompatible` lint
+macro_rules! m { ($i) => {} } //~ ERROR missing fragment specifier
+ //~| WARN this was previously accepted
+
trait Tr {
// Warn only since this is not a `future_incompatible` lint
fn f(u8) {} //~ WARN anonymous parameters are deprecated
//~| WARN this is accepted in the current edition
}
-pub mod submodule {
- // Error since this is a `future_incompatible` lint
- #![doc(test(some_test))]
- //~^ ERROR this attribute can only be applied at the crate level
-}
-
fn main() {}
diff --git a/tests/ui/future-incompatible-lint-group.stderr b/tests/ui/future-incompatible-lint-group.stderr
index 4e6c434..4c867e0 100644
--- a/tests/ui/future-incompatible-lint-group.stderr
+++ b/tests/ui/future-incompatible-lint-group.stderr
@@ -1,5 +1,20 @@
+error: missing fragment specifier
+ --> $DIR/future-incompatible-lint-group.rs:6:19
+ |
+LL | macro_rules! m { ($i) => {} }
+ | ^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #40107 <https://github.com/rust-lang/rust/issues/40107>
+note: the lint level is defined here
+ --> $DIR/future-incompatible-lint-group.rs:3:9
+ |
+LL | #![deny(future_incompatible)]
+ | ^^^^^^^^^^^^^^^^^^^
+ = note: `#[deny(missing_fragment_specifier)]` implied by `#[deny(future_incompatible)]`
+
warning: anonymous parameters are deprecated and will be removed in the next edition
- --> $DIR/future-incompatible-lint-group.rs:7:10
+ --> $DIR/future-incompatible-lint-group.rs:11:10
|
LL | fn f(u8) {}
| ^^ help: try naming the parameter or explicitly ignoring it: `_: u8`
@@ -8,14 +23,21 @@
= note: for more information, see issue #41686 <https://github.com/rust-lang/rust/issues/41686>
= note: `#[warn(anonymous_parameters)]` on by default
-error: this attribute can only be applied at the crate level
- --> $DIR/future-incompatible-lint-group.rs:13:12
- |
-LL | #![doc(test(some_test))]
- | ^^^^^^^^^^^^^^^
- |
- = note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information
- = note: `#[deny(invalid_doc_attributes)]` on by default
-
error: aborting due to 1 previous error; 1 warning emitted
+Future incompatibility report: Future breakage diagnostic:
+error: missing fragment specifier
+ --> $DIR/future-incompatible-lint-group.rs:6:19
+ |
+LL | macro_rules! m { ($i) => {} }
+ | ^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #40107 <https://github.com/rust-lang/rust/issues/40107>
+note: the lint level is defined here
+ --> $DIR/future-incompatible-lint-group.rs:3:9
+ |
+LL | #![deny(future_incompatible)]
+ | ^^^^^^^^^^^^^^^^^^^
+ = note: `#[deny(missing_fragment_specifier)]` implied by `#[deny(future_incompatible)]`
+
diff --git a/tests/ui/lint/force-warn/ice-free.rs b/tests/ui/lint/force-warn/ice-free.rs
new file mode 100644
index 0000000..99b79f4
--- /dev/null
+++ b/tests/ui/lint/force-warn/ice-free.rs
@@ -0,0 +1,9 @@
+//@ compile-flags: --force-warn pub_use_of_private_extern_crate
+//@ check-pass
+
+extern crate core;
+pub use core as reexported_core;
+//~^ warning: extern crate `core` is private
+//~| warning: this was previously accepted by the compiler
+
+fn main() {}
diff --git a/tests/ui/lint/force-warn/ice-free.stderr b/tests/ui/lint/force-warn/ice-free.stderr
new file mode 100644
index 0000000..b64e3b1
--- /dev/null
+++ b/tests/ui/lint/force-warn/ice-free.stderr
@@ -0,0 +1,32 @@
+warning[E0365]: extern crate `core` is private and cannot be re-exported
+ --> $DIR/ice-free.rs:5:9
+ |
+LL | pub use core as reexported_core;
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #127909 <https://github.com/rust-lang/rust/issues/127909>
+ = note: requested on the command line with `--force-warn pub-use-of-private-extern-crate`
+help: consider making the `extern crate` item publicly accessible
+ |
+LL | pub extern crate core;
+ | +++
+
+warning: 1 warning emitted
+
+For more information about this error, try `rustc --explain E0365`.
+Future incompatibility report: Future breakage diagnostic:
+warning[E0365]: extern crate `core` is private and cannot be re-exported
+ --> $DIR/ice-free.rs:5:9
+ |
+LL | pub use core as reexported_core;
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #127909 <https://github.com/rust-lang/rust/issues/127909>
+ = note: requested on the command line with `--force-warn pub-use-of-private-extern-crate`
+help: consider making the `extern crate` item publicly accessible
+ |
+LL | pub extern crate core;
+ | +++
+
diff --git a/tests/ui/lint/implicit_autorefs.fixed b/tests/ui/lint/implicit_autorefs.fixed
index 454dfe7..7aa21e7 100644
--- a/tests/ui/lint/implicit_autorefs.fixed
+++ b/tests/ui/lint/implicit_autorefs.fixed
@@ -1,4 +1,4 @@
-//@ check-pass
+//@ check-fail
//@ run-rustfix
#![allow(dead_code)] // For the rustfix-ed code.
@@ -8,7 +8,7 @@
unsafe fn test_const(ptr: *const [u8]) {
let _ = (&(*ptr))[..16];
- //~^ WARN implicit autoref
+ //~^ ERROR implicit autoref
}
struct Test {
@@ -17,36 +17,36 @@
unsafe fn test_field(ptr: *const Test) -> *const [u8] {
let l = (&(*ptr).field).len();
- //~^ WARN implicit autoref
+ //~^ ERROR implicit autoref
&raw const (&(*ptr).field)[..l - 1]
- //~^ WARN implicit autoref
+ //~^ ERROR implicit autoref
}
unsafe fn test_builtin_index(a: *mut [String]) {
_ = (&(*a)[0]).len();
- //~^ WARN implicit autoref
+ //~^ ERROR implicit autoref
_ = (&(&(*a))[..1][0]).len();
- //~^ WARN implicit autoref
- //~^^ WARN implicit autoref
+ //~^ ERROR implicit autoref
+ //~^^ ERROR implicit autoref
}
unsafe fn test_overloaded_deref_const(ptr: *const ManuallyDrop<Test>) {
let _ = (&(*ptr)).field;
- //~^ WARN implicit autoref
+ //~^ ERROR implicit autoref
let _ = &raw const (&(*ptr)).field;
- //~^ WARN implicit autoref
+ //~^ ERROR implicit autoref
}
unsafe fn test_overloaded_deref_mut(ptr: *mut ManuallyDrop<Test>) {
let _ = (&(*ptr)).field;
- //~^ WARN implicit autoref
+ //~^ ERROR implicit autoref
}
unsafe fn test_double_overloaded_deref_const(ptr: *const ManuallyDrop<ManuallyDrop<Test>>) {
let _ = (&(*ptr)).field;
- //~^ WARN implicit autoref
+ //~^ ERROR implicit autoref
}
unsafe fn test_manually_overloaded_deref() {
@@ -54,52 +54,55 @@
impl<T> Deref for W<T> {
type Target = T;
- fn deref(&self) -> &T { &self.0 }
+ fn deref(&self) -> &T {
+ &self.0
+ }
}
let w: W<i32> = W(5);
let w = &raw const w;
let _p: *const i32 = &raw const *(&**w);
- //~^ WARN implicit autoref
+ //~^ ERROR implicit autoref
}
struct Test2 {
// Derefs to `[u8]`.
- field: &'static [u8]
+ field: &'static [u8],
}
fn test_more_manual_deref(ptr: *const Test2) -> usize {
unsafe { (&(*ptr).field).len() }
- //~^ WARN implicit autoref
+ //~^ ERROR implicit autoref
}
unsafe fn test_no_attr(ptr: *mut ManuallyDrop<u8>) {
- ptr.write(ManuallyDrop::new(1)); // Should not warn, as `ManuallyDrop::write` is not
- // annotated with `#[rustc_no_implicit_auto_ref]`
+ // Should not warn, as `ManuallyDrop::write` is not
+ // annotated with `#[rustc_no_implicit_auto_ref]`
+ ptr.write(ManuallyDrop::new(1));
}
unsafe fn test_vec_get(ptr: *mut Vec<u8>) {
let _ = (&(*ptr)).get(0);
- //~^ WARN implicit autoref
+ //~^ ERROR implicit autoref
let _ = (&(*ptr)).get_unchecked(0);
- //~^ WARN implicit autoref
+ //~^ ERROR implicit autoref
let _ = (&mut (*ptr)).get_mut(0);
- //~^ WARN implicit autoref
+ //~^ ERROR implicit autoref
let _ = (&mut (*ptr)).get_unchecked_mut(0);
- //~^ WARN implicit autoref
+ //~^ ERROR implicit autoref
}
unsafe fn test_string(ptr: *mut String) {
let _ = (&(*ptr)).len();
- //~^ WARN implicit autoref
+ //~^ ERROR implicit autoref
let _ = (&(*ptr)).is_empty();
- //~^ WARN implicit autoref
+ //~^ ERROR implicit autoref
}
unsafe fn slice_ptr_len_because_of_msrv<T>(slice: *const [T]) {
let _ = (&(&(*slice))[..]).len();
- //~^ WARN implicit autoref
- //~^^ WARN implicit autoref
+ //~^ ERROR implicit autoref
+ //~^^ ERROR implicit autoref
}
fn main() {}
diff --git a/tests/ui/lint/implicit_autorefs.rs b/tests/ui/lint/implicit_autorefs.rs
index 507d653..f33cb08 100644
--- a/tests/ui/lint/implicit_autorefs.rs
+++ b/tests/ui/lint/implicit_autorefs.rs
@@ -1,4 +1,4 @@
-//@ check-pass
+//@ check-fail
//@ run-rustfix
#![allow(dead_code)] // For the rustfix-ed code.
@@ -8,7 +8,7 @@
unsafe fn test_const(ptr: *const [u8]) {
let _ = (*ptr)[..16];
- //~^ WARN implicit autoref
+ //~^ ERROR implicit autoref
}
struct Test {
@@ -17,36 +17,36 @@ struct Test {
unsafe fn test_field(ptr: *const Test) -> *const [u8] {
let l = (*ptr).field.len();
- //~^ WARN implicit autoref
+ //~^ ERROR implicit autoref
&raw const (*ptr).field[..l - 1]
- //~^ WARN implicit autoref
+ //~^ ERROR implicit autoref
}
unsafe fn test_builtin_index(a: *mut [String]) {
_ = (*a)[0].len();
- //~^ WARN implicit autoref
+ //~^ ERROR implicit autoref
_ = (*a)[..1][0].len();
- //~^ WARN implicit autoref
- //~^^ WARN implicit autoref
+ //~^ ERROR implicit autoref
+ //~^^ ERROR implicit autoref
}
unsafe fn test_overloaded_deref_const(ptr: *const ManuallyDrop<Test>) {
let _ = (*ptr).field;
- //~^ WARN implicit autoref
+ //~^ ERROR implicit autoref
let _ = &raw const (*ptr).field;
- //~^ WARN implicit autoref
+ //~^ ERROR implicit autoref
}
unsafe fn test_overloaded_deref_mut(ptr: *mut ManuallyDrop<Test>) {
let _ = (*ptr).field;
- //~^ WARN implicit autoref
+ //~^ ERROR implicit autoref
}
unsafe fn test_double_overloaded_deref_const(ptr: *const ManuallyDrop<ManuallyDrop<Test>>) {
let _ = (*ptr).field;
- //~^ WARN implicit autoref
+ //~^ ERROR implicit autoref
}
unsafe fn test_manually_overloaded_deref() {
@@ -54,52 +54,55 @@ unsafe fn test_manually_overloaded_deref() {
impl<T> Deref for W<T> {
type Target = T;
- fn deref(&self) -> &T { &self.0 }
+ fn deref(&self) -> &T {
+ &self.0
+ }
}
let w: W<i32> = W(5);
let w = &raw const w;
let _p: *const i32 = &raw const **w;
- //~^ WARN implicit autoref
+ //~^ ERROR implicit autoref
}
struct Test2 {
// Derefs to `[u8]`.
- field: &'static [u8]
+ field: &'static [u8],
}
fn test_more_manual_deref(ptr: *const Test2) -> usize {
unsafe { (*ptr).field.len() }
- //~^ WARN implicit autoref
+ //~^ ERROR implicit autoref
}
unsafe fn test_no_attr(ptr: *mut ManuallyDrop<u8>) {
- ptr.write(ManuallyDrop::new(1)); // Should not warn, as `ManuallyDrop::write` is not
- // annotated with `#[rustc_no_implicit_auto_ref]`
+ // Should not warn, as `ManuallyDrop::write` is not
+ // annotated with `#[rustc_no_implicit_auto_ref]`
+ ptr.write(ManuallyDrop::new(1));
}
unsafe fn test_vec_get(ptr: *mut Vec<u8>) {
let _ = (*ptr).get(0);
- //~^ WARN implicit autoref
+ //~^ ERROR implicit autoref
let _ = (*ptr).get_unchecked(0);
- //~^ WARN implicit autoref
+ //~^ ERROR implicit autoref
let _ = (*ptr).get_mut(0);
- //~^ WARN implicit autoref
+ //~^ ERROR implicit autoref
let _ = (*ptr).get_unchecked_mut(0);
- //~^ WARN implicit autoref
+ //~^ ERROR implicit autoref
}
unsafe fn test_string(ptr: *mut String) {
let _ = (*ptr).len();
- //~^ WARN implicit autoref
+ //~^ ERROR implicit autoref
let _ = (*ptr).is_empty();
- //~^ WARN implicit autoref
+ //~^ ERROR implicit autoref
}
unsafe fn slice_ptr_len_because_of_msrv<T>(slice: *const [T]) {
let _ = (*slice)[..].len();
- //~^ WARN implicit autoref
- //~^^ WARN implicit autoref
+ //~^ ERROR implicit autoref
+ //~^^ ERROR implicit autoref
}
fn main() {}
diff --git a/tests/ui/lint/implicit_autorefs.stderr b/tests/ui/lint/implicit_autorefs.stderr
index 80ba8ae..bd914e2 100644
--- a/tests/ui/lint/implicit_autorefs.stderr
+++ b/tests/ui/lint/implicit_autorefs.stderr
@@ -1,4 +1,4 @@
-warning: implicit autoref creates a reference to the dereference of a raw pointer
+error: implicit autoref creates a reference to the dereference of a raw pointer
--> $DIR/implicit_autorefs.rs:10:13
|
LL | let _ = (*ptr)[..16];
@@ -12,13 +12,13 @@
|
LL | let _ = (*ptr)[..16];
| ^^^^^^
- = note: `#[warn(dangerous_implicit_autorefs)]` on by default
+ = note: `#[deny(dangerous_implicit_autorefs)]` on by default
help: try using a raw pointer method instead; or if this reference is intentional, make it explicit
|
LL | let _ = (&(*ptr))[..16];
| ++ +
-warning: implicit autoref creates a reference to the dereference of a raw pointer
+error: implicit autoref creates a reference to the dereference of a raw pointer
--> $DIR/implicit_autorefs.rs:19:13
|
LL | let l = (*ptr).field.len();
@@ -39,7 +39,7 @@
LL | let l = (&(*ptr).field).len();
| ++ +
-warning: implicit autoref creates a reference to the dereference of a raw pointer
+error: implicit autoref creates a reference to the dereference of a raw pointer
--> $DIR/implicit_autorefs.rs:22:16
|
LL | &raw const (*ptr).field[..l - 1]
@@ -58,7 +58,7 @@
LL | &raw const (&(*ptr).field)[..l - 1]
| ++ +
-warning: implicit autoref creates a reference to the dereference of a raw pointer
+error: implicit autoref creates a reference to the dereference of a raw pointer
--> $DIR/implicit_autorefs.rs:27:9
|
LL | _ = (*a)[0].len();
@@ -79,7 +79,7 @@
LL | _ = (&(*a)[0]).len();
| ++ +
-warning: implicit autoref creates a reference to the dereference of a raw pointer
+error: implicit autoref creates a reference to the dereference of a raw pointer
--> $DIR/implicit_autorefs.rs:30:9
|
LL | _ = (*a)[..1][0].len();
@@ -100,7 +100,7 @@
LL | _ = (&(*a)[..1][0]).len();
| ++ +
-warning: implicit autoref creates a reference to the dereference of a raw pointer
+error: implicit autoref creates a reference to the dereference of a raw pointer
--> $DIR/implicit_autorefs.rs:30:9
|
LL | _ = (*a)[..1][0].len();
@@ -119,7 +119,7 @@
LL | _ = (&(*a))[..1][0].len();
| ++ +
-warning: implicit autoref creates a reference to the dereference of a raw pointer
+error: implicit autoref creates a reference to the dereference of a raw pointer
--> $DIR/implicit_autorefs.rs:36:13
|
LL | let _ = (*ptr).field;
@@ -134,7 +134,7 @@
LL | let _ = (&(*ptr)).field;
| ++ +
-warning: implicit autoref creates a reference to the dereference of a raw pointer
+error: implicit autoref creates a reference to the dereference of a raw pointer
--> $DIR/implicit_autorefs.rs:38:24
|
LL | let _ = &raw const (*ptr).field;
@@ -149,7 +149,7 @@
LL | let _ = &raw const (&(*ptr)).field;
| ++ +
-warning: implicit autoref creates a reference to the dereference of a raw pointer
+error: implicit autoref creates a reference to the dereference of a raw pointer
--> $DIR/implicit_autorefs.rs:43:13
|
LL | let _ = (*ptr).field;
@@ -164,7 +164,7 @@
LL | let _ = (&(*ptr)).field;
| ++ +
-warning: implicit autoref creates a reference to the dereference of a raw pointer
+error: implicit autoref creates a reference to the dereference of a raw pointer
--> $DIR/implicit_autorefs.rs:48:13
|
LL | let _ = (*ptr).field;
@@ -179,8 +179,8 @@
LL | let _ = (&(*ptr)).field;
| ++ +
-warning: implicit autoref creates a reference to the dereference of a raw pointer
- --> $DIR/implicit_autorefs.rs:62:26
+error: implicit autoref creates a reference to the dereference of a raw pointer
+ --> $DIR/implicit_autorefs.rs:64:26
|
LL | let _p: *const i32 = &raw const **w;
| ^^^^^^^^^^^^^-
@@ -189,7 +189,7 @@
|
= note: creating a reference requires the pointer target to be valid and imposes aliasing requirements
note: autoref is being applied to this expression, resulting in: `&W<i32>`
- --> $DIR/implicit_autorefs.rs:62:38
+ --> $DIR/implicit_autorefs.rs:64:38
|
LL | let _p: *const i32 = &raw const **w;
| ^^
@@ -198,8 +198,8 @@
LL | let _p: *const i32 = &raw const *(&**w);
| +++ +
-warning: implicit autoref creates a reference to the dereference of a raw pointer
- --> $DIR/implicit_autorefs.rs:72:14
+error: implicit autoref creates a reference to the dereference of a raw pointer
+ --> $DIR/implicit_autorefs.rs:74:14
|
LL | unsafe { (*ptr).field.len() }
| ^^---^^^^^^^^^^^^^
@@ -208,7 +208,7 @@
|
= note: creating a reference requires the pointer target to be valid and imposes aliasing requirements
note: autoref is being applied to this expression, resulting in: `&[u8]`
- --> $DIR/implicit_autorefs.rs:72:14
+ --> $DIR/implicit_autorefs.rs:74:14
|
LL | unsafe { (*ptr).field.len() }
| ^^^^^^^^^^^^
@@ -219,8 +219,8 @@
LL | unsafe { (&(*ptr).field).len() }
| ++ +
-warning: implicit autoref creates a reference to the dereference of a raw pointer
- --> $DIR/implicit_autorefs.rs:82:13
+error: implicit autoref creates a reference to the dereference of a raw pointer
+ --> $DIR/implicit_autorefs.rs:85:13
|
LL | let _ = (*ptr).get(0);
| ^^---^^^^^^^^
@@ -229,7 +229,7 @@
|
= note: creating a reference requires the pointer target to be valid and imposes aliasing requirements
note: autoref is being applied to this expression, resulting in: `&[u8]`
- --> $DIR/implicit_autorefs.rs:82:13
+ --> $DIR/implicit_autorefs.rs:85:13
|
LL | let _ = (*ptr).get(0);
| ^^^^^^
@@ -240,8 +240,8 @@
LL | let _ = (&(*ptr)).get(0);
| ++ +
-warning: implicit autoref creates a reference to the dereference of a raw pointer
- --> $DIR/implicit_autorefs.rs:84:13
+error: implicit autoref creates a reference to the dereference of a raw pointer
+ --> $DIR/implicit_autorefs.rs:87:13
|
LL | let _ = (*ptr).get_unchecked(0);
| ^^---^^^^^^^^^^^^^^^^^^
@@ -250,7 +250,7 @@
|
= note: creating a reference requires the pointer target to be valid and imposes aliasing requirements
note: autoref is being applied to this expression, resulting in: `&[u8]`
- --> $DIR/implicit_autorefs.rs:84:13
+ --> $DIR/implicit_autorefs.rs:87:13
|
LL | let _ = (*ptr).get_unchecked(0);
| ^^^^^^
@@ -261,8 +261,8 @@
LL | let _ = (&(*ptr)).get_unchecked(0);
| ++ +
-warning: implicit autoref creates a reference to the dereference of a raw pointer
- --> $DIR/implicit_autorefs.rs:86:13
+error: implicit autoref creates a reference to the dereference of a raw pointer
+ --> $DIR/implicit_autorefs.rs:89:13
|
LL | let _ = (*ptr).get_mut(0);
| ^^---^^^^^^^^^^^^
@@ -271,7 +271,7 @@
|
= note: creating a reference requires the pointer target to be valid and imposes aliasing requirements
note: autoref is being applied to this expression, resulting in: `&mut [u8]`
- --> $DIR/implicit_autorefs.rs:86:13
+ --> $DIR/implicit_autorefs.rs:89:13
|
LL | let _ = (*ptr).get_mut(0);
| ^^^^^^
@@ -282,8 +282,8 @@
LL | let _ = (&mut (*ptr)).get_mut(0);
| +++++ +
-warning: implicit autoref creates a reference to the dereference of a raw pointer
- --> $DIR/implicit_autorefs.rs:88:13
+error: implicit autoref creates a reference to the dereference of a raw pointer
+ --> $DIR/implicit_autorefs.rs:91:13
|
LL | let _ = (*ptr).get_unchecked_mut(0);
| ^^---^^^^^^^^^^^^^^^^^^^^^^
@@ -292,7 +292,7 @@
|
= note: creating a reference requires the pointer target to be valid and imposes aliasing requirements
note: autoref is being applied to this expression, resulting in: `&mut [u8]`
- --> $DIR/implicit_autorefs.rs:88:13
+ --> $DIR/implicit_autorefs.rs:91:13
|
LL | let _ = (*ptr).get_unchecked_mut(0);
| ^^^^^^
@@ -303,8 +303,8 @@
LL | let _ = (&mut (*ptr)).get_unchecked_mut(0);
| +++++ +
-warning: implicit autoref creates a reference to the dereference of a raw pointer
- --> $DIR/implicit_autorefs.rs:93:13
+error: implicit autoref creates a reference to the dereference of a raw pointer
+ --> $DIR/implicit_autorefs.rs:96:13
|
LL | let _ = (*ptr).len();
| ^^---^^^^^^^
@@ -313,7 +313,7 @@
|
= note: creating a reference requires the pointer target to be valid and imposes aliasing requirements
note: autoref is being applied to this expression, resulting in: `&String`
- --> $DIR/implicit_autorefs.rs:93:13
+ --> $DIR/implicit_autorefs.rs:96:13
|
LL | let _ = (*ptr).len();
| ^^^^^^
@@ -324,8 +324,8 @@
LL | let _ = (&(*ptr)).len();
| ++ +
-warning: implicit autoref creates a reference to the dereference of a raw pointer
- --> $DIR/implicit_autorefs.rs:95:13
+error: implicit autoref creates a reference to the dereference of a raw pointer
+ --> $DIR/implicit_autorefs.rs:98:13
|
LL | let _ = (*ptr).is_empty();
| ^^---^^^^^^^^^^^^
@@ -334,7 +334,7 @@
|
= note: creating a reference requires the pointer target to be valid and imposes aliasing requirements
note: autoref is being applied to this expression, resulting in: `&String`
- --> $DIR/implicit_autorefs.rs:95:13
+ --> $DIR/implicit_autorefs.rs:98:13
|
LL | let _ = (*ptr).is_empty();
| ^^^^^^
@@ -345,8 +345,8 @@
LL | let _ = (&(*ptr)).is_empty();
| ++ +
-warning: implicit autoref creates a reference to the dereference of a raw pointer
- --> $DIR/implicit_autorefs.rs:100:13
+error: implicit autoref creates a reference to the dereference of a raw pointer
+ --> $DIR/implicit_autorefs.rs:103:13
|
LL | let _ = (*slice)[..].len();
| ^^-----^^^^^^^^^^^
@@ -355,7 +355,7 @@
|
= note: creating a reference requires the pointer target to be valid and imposes aliasing requirements
note: autoref is being applied to this expression, resulting in: `&[T]`
- --> $DIR/implicit_autorefs.rs:100:13
+ --> $DIR/implicit_autorefs.rs:103:13
|
LL | let _ = (*slice)[..].len();
| ^^^^^^^^^^^^
@@ -366,8 +366,8 @@
LL | let _ = (&(*slice)[..]).len();
| ++ +
-warning: implicit autoref creates a reference to the dereference of a raw pointer
- --> $DIR/implicit_autorefs.rs:100:13
+error: implicit autoref creates a reference to the dereference of a raw pointer
+ --> $DIR/implicit_autorefs.rs:103:13
|
LL | let _ = (*slice)[..].len();
| ^^-----^^^^^
@@ -376,7 +376,7 @@
|
= note: creating a reference requires the pointer target to be valid and imposes aliasing requirements
note: autoref is being applied to this expression, resulting in: `&[T]`
- --> $DIR/implicit_autorefs.rs:100:13
+ --> $DIR/implicit_autorefs.rs:103:13
|
LL | let _ = (*slice)[..].len();
| ^^^^^^^^
@@ -385,5 +385,5 @@
LL | let _ = (&(*slice))[..].len();
| ++ +
-warning: 20 warnings emitted
+error: aborting due to 20 previous errors
diff --git a/tests/ui/lint/unused/useless-comment.rs b/tests/ui/lint/unused/useless-comment.rs
index 4ec52f2..8986652 100644
--- a/tests/ui/lint/unused/useless-comment.rs
+++ b/tests/ui/lint/unused/useless-comment.rs
@@ -9,8 +9,13 @@ macro_rules! mac {
/// foo //~ ERROR unused doc comment
mac!();
+/// a //~ ERROR unused doc comment
+#[doc(test(attr(allow(dead_code))))] //~ ERROR unused doc comment
+unsafe extern "C" { }
+
fn foo() {
/// a //~ ERROR unused doc comment
+ #[doc(test(attr(allow(dead_code))))] //~ ERROR unused doc comment
let x = 12;
/// multi-line //~ ERROR unused doc comment
@@ -19,6 +24,7 @@ fn foo() {
match x {
/// c //~ ERROR unused doc comment
1 => {},
+ #[doc(test(attr(allow(dead_code))))] //~ ERROR unused doc comment
_ => {}
}
@@ -32,6 +38,7 @@ fn foo() {
/// bar //~ ERROR unused doc comment
mac!();
+ #[doc(test(attr(allow(dead_code))))] //~ ERROR unused doc comment
let x = /** comment */ 47; //~ ERROR unused doc comment
/// dox //~ ERROR unused doc comment
diff --git a/tests/ui/lint/unused/useless-comment.stderr b/tests/ui/lint/unused/useless-comment.stderr
index 8bb5bda..39873b8 100644
--- a/tests/ui/lint/unused/useless-comment.stderr
+++ b/tests/ui/lint/unused/useless-comment.stderr
@@ -12,7 +12,28 @@
| ^^^^^^^^^^^^^^^^^^^
error: unused doc comment
- --> $DIR/useless-comment.rs:32:5
+ --> $DIR/useless-comment.rs:12:1
+ |
+LL | /// a
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[doc(test(attr(allow(dead_code))))]
+LL | unsafe extern "C" { }
+ | --------------------- rustdoc does not generate documentation for extern blocks
+ |
+ = help: use `//` for a plain comment
+
+error: unused doc comment
+ --> $DIR/useless-comment.rs:13:1
+ |
+LL | #[doc(test(attr(allow(dead_code))))]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | unsafe extern "C" { }
+ | --------------------- rustdoc does not generate documentation for extern blocks
+ |
+ = help: use `//` for a plain comment
+
+error: unused doc comment
+ --> $DIR/useless-comment.rs:38:5
|
LL | /// bar
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ rustdoc does not generate documentation for macro invocations
@@ -20,17 +41,28 @@
= help: to document an item produced by a macro, the macro must produce the documentation as part of its expansion
error: unused doc comment
- --> $DIR/useless-comment.rs:13:5
+ --> $DIR/useless-comment.rs:17:5
|
LL | /// a
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[doc(test(attr(allow(dead_code))))]
LL | let x = 12;
| ----------- rustdoc does not generate documentation for statements
|
= help: use `//` for a plain comment
error: unused doc comment
- --> $DIR/useless-comment.rs:16:5
+ --> $DIR/useless-comment.rs:18:5
+ |
+LL | #[doc(test(attr(allow(dead_code))))]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | let x = 12;
+ | ----------- rustdoc does not generate documentation for statements
+ |
+ = help: use `//` for a plain comment
+
+error: unused doc comment
+ --> $DIR/useless-comment.rs:21:5
|
LL | / /// multi-line
LL | | /// doc comment
@@ -39,6 +71,7 @@
LL | / match x {
LL | | /// c
LL | | 1 => {},
+LL | | #[doc(test(attr(allow(dead_code))))]
LL | | _ => {}
LL | | }
| |_____- rustdoc does not generate documentation for expressions
@@ -46,7 +79,7 @@
= help: use `//` for a plain comment
error: unused doc comment
- --> $DIR/useless-comment.rs:20:9
+ --> $DIR/useless-comment.rs:25:9
|
LL | /// c
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -56,7 +89,17 @@
= help: use `//` for a plain comment
error: unused doc comment
- --> $DIR/useless-comment.rs:25:5
+ --> $DIR/useless-comment.rs:27:9
+ |
+LL | #[doc(test(attr(allow(dead_code))))]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | _ => {}
+ | ------- rustdoc does not generate documentation for match arms
+ |
+ = help: use `//` for a plain comment
+
+error: unused doc comment
+ --> $DIR/useless-comment.rs:31:5
|
LL | /// foo
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -66,7 +109,7 @@
= help: use `//` for a plain comment
error: unused doc comment
- --> $DIR/useless-comment.rs:28:5
+ --> $DIR/useless-comment.rs:34:5
|
LL | #[doc = "foo"]
| ^^^^^^^^^^^^^^
@@ -77,7 +120,7 @@
= help: use `//` for a plain comment
error: unused doc comment
- --> $DIR/useless-comment.rs:29:5
+ --> $DIR/useless-comment.rs:35:5
|
LL | #[doc = "bar"]
| ^^^^^^^^^^^^^^
@@ -87,7 +130,17 @@
= help: use `//` for a plain comment
error: unused doc comment
- --> $DIR/useless-comment.rs:35:13
+ --> $DIR/useless-comment.rs:41:5
+ |
+LL | #[doc(test(attr(allow(dead_code))))]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | let x = /** comment */ 47;
+ | -------------------------- rustdoc does not generate documentation for statements
+ |
+ = help: use `//` for a plain comment
+
+error: unused doc comment
+ --> $DIR/useless-comment.rs:42:13
|
LL | let x = /** comment */ 47;
| ^^^^^^^^^^^^^^ -- rustdoc does not generate documentation for expressions
@@ -95,7 +148,7 @@
= help: use `/* */` for a plain comment
error: unused doc comment
- --> $DIR/useless-comment.rs:37:5
+ --> $DIR/useless-comment.rs:44:5
|
LL | /// dox
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -106,5 +159,5 @@
|
= help: use `//` for a plain comment
-error: aborting due to 10 previous errors
+error: aborting due to 15 previous errors
diff --git a/tests/ui/rustdoc/doc-test-attr-pass.rs b/tests/ui/rustdoc/doc-test-attr-pass.rs
index f0120b7..60d1e37 100644
--- a/tests/ui/rustdoc/doc-test-attr-pass.rs
+++ b/tests/ui/rustdoc/doc-test-attr-pass.rs
@@ -6,4 +6,46 @@
#![doc(test(attr(deny(warnings))))]
#![doc(test())]
+mod test {
+ #![doc(test(attr(allow(warnings))))]
+}
+
+#[doc(test(attr(allow(dead_code))))]
+static S: u32 = 5;
+
+#[doc(test(attr(allow(dead_code))))]
+const C: u32 = 5;
+
+#[doc(test(attr(deny(dead_code))))]
+struct A {
+ #[doc(test(attr(allow(dead_code))))]
+ field: u32
+}
+
+#[doc(test(attr(deny(dead_code))))]
+union U {
+ #[doc(test(attr(allow(dead_code))))]
+ field: u32,
+ field2: u64,
+}
+
+#[doc(test(attr(deny(dead_code))))]
+enum Enum {
+ #[doc(test(attr(allow(dead_code))))]
+ Variant1,
+}
+
+#[doc(test(attr(deny(dead_code))))]
+impl A {
+ #[doc(test(attr(deny(dead_code))))]
+ fn method() {}
+}
+
+#[doc(test(attr(deny(dead_code))))]
+trait MyTrait {
+ #[doc(test(attr(deny(dead_code))))]
+ fn my_trait_fn();
+}
+
+#[doc(test(attr(deny(dead_code))))]
pub fn foo() {}
diff --git a/tests/ui/specialization/overlap-due-to-unsatisfied-const-bound.rs b/tests/ui/specialization/overlap-due-to-unsatisfied-const-bound.rs
new file mode 100644
index 0000000..f4cde1d
--- /dev/null
+++ b/tests/ui/specialization/overlap-due-to-unsatisfied-const-bound.rs
@@ -0,0 +1,21 @@
+// Regression test for #140571. The compiler used to ICE
+
+#![feature(associated_const_equality, specialization)]
+//~^ WARN the feature `specialization` is incomplete
+
+pub trait IsVoid {
+ const IS_VOID: bool;
+}
+impl<T> IsVoid for T {
+ default const IS_VOID: bool = false;
+}
+
+pub trait NotVoid {}
+impl<T> NotVoid for T where T: IsVoid<IS_VOID = false> + ?Sized {}
+
+pub trait Maybe<T> {}
+impl<T> Maybe<T> for T {}
+impl<T> Maybe<T> for () where T: NotVoid + ?Sized {}
+//~^ ERROR conflicting implementations of trait `Maybe<()>` for type `()`
+
+fn main() {}
diff --git a/tests/ui/specialization/overlap-due-to-unsatisfied-const-bound.stderr b/tests/ui/specialization/overlap-due-to-unsatisfied-const-bound.stderr
new file mode 100644
index 0000000..a26b30f
--- /dev/null
+++ b/tests/ui/specialization/overlap-due-to-unsatisfied-const-bound.stderr
@@ -0,0 +1,21 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/overlap-due-to-unsatisfied-const-bound.rs:3:39
+ |
+LL | #![feature(associated_const_equality, specialization)]
+ | ^^^^^^^^^^^^^^
+ |
+ = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+ = help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
+
+error[E0119]: conflicting implementations of trait `Maybe<()>` for type `()`
+ --> $DIR/overlap-due-to-unsatisfied-const-bound.rs:18:1
+ |
+LL | impl<T> Maybe<T> for T {}
+ | ---------------------- first implementation here
+LL | impl<T> Maybe<T> for () where T: NotVoid + ?Sized {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()`
+
+error: aborting due to 1 previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0119`.