Merge from rustc
This commit is contained in:
commit
1894b49ebb
107 changed files with 1337 additions and 625 deletions
|
|
@ -12,66 +12,93 @@ use crate::AbiFromStrErr;
|
|||
#[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()
|
||||
|
|
|
|||
|
|
@ -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)));
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -1529,7 +1529,7 @@ impl DiagCtxtInner {
|
|||
// 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());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -192,10 +192,10 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
|
|||
let _: R = tcx.ensure_ok().crate_inherent_impls_overlap_check(());
|
||||
});
|
||||
|
||||
// Make sure we evaluate all static and (non-associated) const items, even if unused.
|
||||
// If any of these fail to evaluate, we do not want this crate to pass compilation.
|
||||
tcx.par_hir_body_owners(|item_def_id| {
|
||||
let def_kind = tcx.def_kind(item_def_id);
|
||||
// Make sure we evaluate all static and (non-associated) const items, even if unused.
|
||||
// If any of these fail to evaluate, we do not want this crate to pass compilation.
|
||||
match def_kind {
|
||||
DefKind::Static { .. } => {
|
||||
tcx.ensure_ok().eval_static_initializer(item_def_id);
|
||||
|
|
@ -215,6 +215,11 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
|
|||
if !matches!(def_kind, DefKind::AnonConst) {
|
||||
tcx.ensure_ok().typeck(item_def_id);
|
||||
}
|
||||
// Ensure we generate the new `DefId` before finishing `check_crate`.
|
||||
// Afterwards we freeze the list of `DefId`s.
|
||||
if tcx.needs_coroutine_by_move_body_def_id(item_def_id.to_def_id()) {
|
||||
tcx.ensure_done().coroutine_by_move_body_def_id(item_def_id);
|
||||
}
|
||||
});
|
||||
|
||||
if tcx.features().rustc_attrs() {
|
||||
|
|
|
|||
|
|
@ -380,20 +380,21 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
|||
err.span_label(self.span, "invalid cast");
|
||||
if self.expr_ty.is_numeric() {
|
||||
if self.expr_ty == fcx.tcx.types.u32 {
|
||||
match fcx.tcx.sess.source_map().span_to_snippet(self.expr.span) {
|
||||
Ok(snippet) => err.span_suggestion(
|
||||
self.span,
|
||||
"try `char::from_u32` instead",
|
||||
format!("char::from_u32({snippet})"),
|
||||
Applicability::MachineApplicable,
|
||||
),
|
||||
|
||||
Err(_) => err.span_help(self.span, "try `char::from_u32` instead"),
|
||||
};
|
||||
err.multipart_suggestion(
|
||||
"consider using `char::from_u32` instead",
|
||||
vec![
|
||||
(self.expr_span.shrink_to_lo(), "char::from_u32(".to_string()),
|
||||
(self.expr_span.shrink_to_hi().to(self.cast_span), ")".to_string()),
|
||||
],
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
} else if self.expr_ty == fcx.tcx.types.i8 {
|
||||
err.span_help(self.span, "try casting from `u8` instead");
|
||||
err.span_help(self.span, "consider casting from `u8` instead");
|
||||
} else {
|
||||
err.span_help(self.span, "try `char::from_u32` instead (via a `u32`)");
|
||||
err.span_help(
|
||||
self.span,
|
||||
"consider using `char::from_u32` instead (via a `u32`)",
|
||||
);
|
||||
};
|
||||
}
|
||||
err.emit();
|
||||
|
|
@ -494,11 +495,8 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
|||
self.cast_ty.kind(),
|
||||
ty::FnDef(..) | ty::FnPtr(..) | ty::Closure(..)
|
||||
) {
|
||||
let mut label = true;
|
||||
// Check `impl From<self.expr_ty> for self.cast_ty {}` for accurate suggestion:
|
||||
if let Ok(snippet) = fcx.tcx.sess.source_map().span_to_snippet(self.expr_span)
|
||||
&& let Some(from_trait) = fcx.tcx.get_diagnostic_item(sym::From)
|
||||
{
|
||||
if let Some(from_trait) = fcx.tcx.get_diagnostic_item(sym::From) {
|
||||
let ty = fcx.resolve_vars_if_possible(self.cast_ty);
|
||||
let expr_ty = fcx.resolve_vars_if_possible(self.expr_ty);
|
||||
if fcx
|
||||
|
|
@ -506,26 +504,22 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
|||
.type_implements_trait(from_trait, [ty, expr_ty], fcx.param_env)
|
||||
.must_apply_modulo_regions()
|
||||
{
|
||||
label = false;
|
||||
if let ty::Adt(def, args) = self.cast_ty.kind() {
|
||||
err.span_suggestion_verbose(
|
||||
self.span,
|
||||
"consider using the `From` trait instead",
|
||||
format!(
|
||||
"{}::from({})",
|
||||
fcx.tcx.value_path_str_with_args(def.did(), args),
|
||||
snippet
|
||||
),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
let to_ty = if let ty::Adt(def, args) = self.cast_ty.kind() {
|
||||
fcx.tcx.value_path_str_with_args(def.did(), args)
|
||||
} else {
|
||||
err.span_suggestion(
|
||||
self.span,
|
||||
"consider using the `From` trait instead",
|
||||
format!("{}::from({})", self.cast_ty, snippet),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
self.cast_ty.to_string()
|
||||
};
|
||||
err.multipart_suggestion(
|
||||
"consider using the `From` trait instead",
|
||||
vec![
|
||||
(self.expr_span.shrink_to_lo(), format!("{to_ty}::from(")),
|
||||
(
|
||||
self.expr_span.shrink_to_hi().to(self.cast_span),
|
||||
")".to_string(),
|
||||
),
|
||||
],
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -548,11 +542,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
|||
)
|
||||
};
|
||||
|
||||
if label {
|
||||
err.span_label(self.span, msg);
|
||||
} else {
|
||||
err.note(msg);
|
||||
}
|
||||
err.span_label(self.span, msg);
|
||||
|
||||
if let Some(note) = note {
|
||||
err.note(note);
|
||||
|
|
@ -654,38 +644,22 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
|||
match self.expr_ty.kind() {
|
||||
ty::Ref(_, _, mt) => {
|
||||
let mtstr = mt.prefix_str();
|
||||
match fcx.tcx.sess.source_map().span_to_snippet(self.cast_span) {
|
||||
Ok(s) => {
|
||||
err.span_suggestion(
|
||||
self.cast_span,
|
||||
"try casting to a reference instead",
|
||||
format!("&{mtstr}{s}"),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
Err(_) => {
|
||||
let msg = format!("did you mean `&{mtstr}{tstr}`?");
|
||||
err.span_help(self.cast_span, msg);
|
||||
}
|
||||
}
|
||||
err.span_suggestion_verbose(
|
||||
self.cast_span.shrink_to_lo(),
|
||||
"consider casting to a reference instead",
|
||||
format!("&{mtstr}"),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
ty::Adt(def, ..) if def.is_box() => {
|
||||
match fcx.tcx.sess.source_map().span_to_snippet(self.cast_span) {
|
||||
Ok(s) => {
|
||||
err.span_suggestion(
|
||||
self.cast_span,
|
||||
"you can cast to a `Box` instead",
|
||||
format!("Box<{s}>"),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
Err(_) => {
|
||||
err.span_help(
|
||||
self.cast_span,
|
||||
format!("you might have meant `Box<{tstr}>`"),
|
||||
);
|
||||
}
|
||||
}
|
||||
err.multipart_suggestion(
|
||||
"you can cast to a `Box` instead",
|
||||
vec![
|
||||
(self.cast_span.shrink_to_lo(), "Box<".to_string()),
|
||||
(self.cast_span.shrink_to_hi(), ">".to_string()),
|
||||
],
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
_ => {
|
||||
err.span_help(self.expr_span, "consider using a box or reference as appropriate");
|
||||
|
|
|
|||
|
|
@ -823,6 +823,13 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
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
|
||||
|
|
|
|||
|
|
@ -976,13 +976,6 @@ fn run_required_analyses(tcx: TyCtxt<'_>) {
|
|||
});
|
||||
|
||||
rustc_hir_analysis::check_crate(tcx);
|
||||
sess.time("MIR_coroutine_by_move_body", || {
|
||||
tcx.par_hir_body_owners(|def_id| {
|
||||
if tcx.needs_coroutine_by_move_body_def_id(def_id.to_def_id()) {
|
||||
tcx.ensure_done().coroutine_by_move_body_def_id(def_id);
|
||||
}
|
||||
});
|
||||
});
|
||||
// Freeze definitions as we don't add new ones at this point.
|
||||
// We need to wait until now since we synthesize a by-move body
|
||||
// for all coroutine-closures.
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ declare_lint! {
|
|||
///
|
||||
/// ### 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 @@ declare_lint! {
|
|||
/// }
|
||||
/// ```
|
||||
pub DANGEROUS_IMPLICIT_AUTOREFS,
|
||||
Warn,
|
||||
Deny,
|
||||
"implicit reference to a dereference of a raw pointer",
|
||||
report_in_external_macro
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@
|
|||
#![feature(negative_impls)]
|
||||
#![feature(never_type)]
|
||||
#![feature(ptr_alignment_type)]
|
||||
#![feature(round_char_boundary)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(rustdoc_internals)]
|
||||
#![feature(trusted_len)]
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
use std::borrow::Cow;
|
||||
use std::fmt;
|
||||
use std::hash::Hash;
|
||||
|
||||
|
|
@ -468,6 +469,29 @@ impl<'tcx> CodegenUnit<'tcx> {
|
|||
hash.as_u128().to_base_fixed_len(CASE_INSENSITIVE)
|
||||
}
|
||||
|
||||
pub fn shorten_name(human_readable_name: &str) -> Cow<'_, str> {
|
||||
// Set a limit a somewhat below the common platform limits for file names.
|
||||
const MAX_CGU_NAME_LENGTH: usize = 200;
|
||||
const TRUNCATED_NAME_PREFIX: &str = "-trunc-";
|
||||
if human_readable_name.len() > MAX_CGU_NAME_LENGTH {
|
||||
let mangled_name = Self::mangle_name(human_readable_name);
|
||||
// Determine a safe byte offset to truncate the name to
|
||||
let truncate_to = human_readable_name.floor_char_boundary(
|
||||
MAX_CGU_NAME_LENGTH - TRUNCATED_NAME_PREFIX.len() - mangled_name.len(),
|
||||
);
|
||||
format!(
|
||||
"{}{}{}",
|
||||
&human_readable_name[..truncate_to],
|
||||
TRUNCATED_NAME_PREFIX,
|
||||
mangled_name
|
||||
)
|
||||
.into()
|
||||
} else {
|
||||
// If the name is short enough, we can just return it as is.
|
||||
human_readable_name.into()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn compute_size_estimate(&mut self) {
|
||||
// The size of a codegen unit as the sum of the sizes of the items
|
||||
// within it.
|
||||
|
|
@ -604,7 +628,7 @@ impl<'tcx> CodegenUnitNameBuilder<'tcx> {
|
|||
let cgu_name = self.build_cgu_name_no_mangle(cnum, components, special_suffix);
|
||||
|
||||
if self.tcx.sess.opts.unstable_opts.human_readable_cgu_names {
|
||||
cgu_name
|
||||
Symbol::intern(&CodegenUnit::shorten_name(cgu_name.as_str()))
|
||||
} else {
|
||||
Symbol::intern(&CodegenUnit::mangle_name(cgu_name.as_str()))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -461,15 +461,15 @@ fn merge_codegen_units<'tcx>(
|
|||
|
||||
for cgu in codegen_units.iter_mut() {
|
||||
if let Some(new_cgu_name) = new_cgu_names.get(&cgu.name()) {
|
||||
if cx.tcx.sess.opts.unstable_opts.human_readable_cgu_names {
|
||||
cgu.set_name(Symbol::intern(new_cgu_name));
|
||||
let new_cgu_name = if cx.tcx.sess.opts.unstable_opts.human_readable_cgu_names {
|
||||
Symbol::intern(&CodegenUnit::shorten_name(new_cgu_name))
|
||||
} else {
|
||||
// If we don't require CGU names to be human-readable,
|
||||
// we use a fixed length hash of the composite CGU name
|
||||
// instead.
|
||||
let new_cgu_name = CodegenUnit::mangle_name(new_cgu_name);
|
||||
cgu.set_name(Symbol::intern(&new_cgu_name));
|
||||
}
|
||||
Symbol::intern(&CodegenUnit::mangle_name(new_cgu_name))
|
||||
};
|
||||
cgu.set_name(new_cgu_name);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1266,13 +1266,17 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
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 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
}
|
||||
|
||||
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(
|
||||
|
|
|
|||
|
|
@ -124,7 +124,13 @@ pub(crate) fn base(
|
|||
// to v4, so we do the same.
|
||||
// https://github.com/llvm/llvm-project/blob/378778a0d10c2f8d5df8ceff81f95b6002984a4b/clang/lib/Driver/ToolChains/Darwin.cpp#L1203
|
||||
default_dwarf_version: 4,
|
||||
frame_pointer: FramePointer::Always,
|
||||
frame_pointer: match arch {
|
||||
// clang ignores `-fomit-frame-pointer` for Armv7, it only accepts `-momit-leaf-frame-pointer`
|
||||
Armv7k | Armv7s => FramePointer::Always,
|
||||
// clang supports omitting frame pointers for the rest, but... don't?
|
||||
Arm64 | Arm64e | Arm64_32 => FramePointer::NonLeaf,
|
||||
I386 | I686 | X86_64 | X86_64h => FramePointer::Always,
|
||||
},
|
||||
has_rpath: true,
|
||||
dll_suffix: ".dylib".into(),
|
||||
archive_format: "darwin".into(),
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use crate::spec::base::apple::{Arch, TargetAbi, base};
|
||||
use crate::spec::{FramePointer, SanitizerSet, Target, TargetMetadata, TargetOptions};
|
||||
use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions};
|
||||
|
||||
pub(crate) fn target() -> Target {
|
||||
let (opts, llvm_target, arch) = base("macos", Arch::Arm64, TargetAbi::Normal);
|
||||
|
|
@ -17,7 +17,6 @@ pub(crate) fn target() -> Target {
|
|||
arch,
|
||||
options: TargetOptions {
|
||||
mcount: "\u{1}mcount".into(),
|
||||
frame_pointer: FramePointer::NonLeaf,
|
||||
cpu: "apple-m1".into(),
|
||||
max_atomic_width: Some(128),
|
||||
// FIXME: The leak sanitizer currently fails the tests, see #88132.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use crate::spec::base::apple::{Arch, TargetAbi, base};
|
||||
use crate::spec::{FramePointer, SanitizerSet, Target, TargetMetadata, TargetOptions};
|
||||
use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions};
|
||||
|
||||
pub(crate) fn target() -> Target {
|
||||
let (opts, llvm_target, arch) = base("ios", Arch::Arm64, TargetAbi::Normal);
|
||||
|
|
@ -18,7 +18,6 @@ pub(crate) fn target() -> Target {
|
|||
options: TargetOptions {
|
||||
features: "+neon,+fp-armv8,+apple-a7".into(),
|
||||
max_atomic_width: Some(128),
|
||||
frame_pointer: FramePointer::NonLeaf,
|
||||
supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::THREAD,
|
||||
..opts
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use crate::spec::base::apple::{Arch, TargetAbi, base};
|
||||
use crate::spec::{FramePointer, SanitizerSet, Target, TargetMetadata, TargetOptions};
|
||||
use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions};
|
||||
|
||||
pub(crate) fn target() -> Target {
|
||||
let (opts, llvm_target, arch) = base("ios", Arch::Arm64, TargetAbi::MacCatalyst);
|
||||
|
|
@ -18,7 +18,6 @@ pub(crate) fn target() -> Target {
|
|||
options: TargetOptions {
|
||||
features: "+neon,+fp-armv8,+apple-a12".into(),
|
||||
max_atomic_width: Some(128),
|
||||
frame_pointer: FramePointer::NonLeaf,
|
||||
supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::LEAK | SanitizerSet::THREAD,
|
||||
..opts
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use crate::spec::base::apple::{Arch, TargetAbi, base};
|
||||
use crate::spec::{FramePointer, SanitizerSet, Target, TargetMetadata, TargetOptions};
|
||||
use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions};
|
||||
|
||||
pub(crate) fn target() -> Target {
|
||||
let (opts, llvm_target, arch) = base("ios", Arch::Arm64, TargetAbi::Simulator);
|
||||
|
|
@ -18,7 +18,6 @@ pub(crate) fn target() -> Target {
|
|||
options: TargetOptions {
|
||||
features: "+neon,+fp-armv8,+apple-a7".into(),
|
||||
max_atomic_width: Some(128),
|
||||
frame_pointer: FramePointer::NonLeaf,
|
||||
supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::THREAD,
|
||||
..opts
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use crate::spec::base::apple::{Arch, TargetAbi, base};
|
||||
use crate::spec::{FramePointer, Target, TargetMetadata, TargetOptions};
|
||||
use crate::spec::{Target, TargetMetadata, TargetOptions};
|
||||
|
||||
pub(crate) fn target() -> Target {
|
||||
let (opts, llvm_target, arch) = base("tvos", Arch::Arm64, TargetAbi::Normal);
|
||||
|
|
@ -18,7 +18,6 @@ pub(crate) fn target() -> Target {
|
|||
options: TargetOptions {
|
||||
features: "+neon,+fp-armv8,+apple-a7".into(),
|
||||
max_atomic_width: Some(128),
|
||||
frame_pointer: FramePointer::NonLeaf,
|
||||
..opts
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use crate::spec::base::apple::{Arch, TargetAbi, base};
|
||||
use crate::spec::{FramePointer, Target, TargetMetadata, TargetOptions};
|
||||
use crate::spec::{Target, TargetMetadata, TargetOptions};
|
||||
|
||||
pub(crate) fn target() -> Target {
|
||||
let (opts, llvm_target, arch) = base("tvos", Arch::Arm64, TargetAbi::Simulator);
|
||||
|
|
@ -18,7 +18,6 @@ pub(crate) fn target() -> Target {
|
|||
options: TargetOptions {
|
||||
features: "+neon,+fp-armv8,+apple-a7".into(),
|
||||
max_atomic_width: Some(128),
|
||||
frame_pointer: FramePointer::NonLeaf,
|
||||
..opts
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use crate::spec::base::apple::{Arch, TargetAbi, base};
|
||||
use crate::spec::{FramePointer, SanitizerSet, Target, TargetMetadata, TargetOptions};
|
||||
use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions};
|
||||
|
||||
pub(crate) fn target() -> Target {
|
||||
let (opts, llvm_target, arch) = base("visionos", Arch::Arm64, TargetAbi::Normal);
|
||||
|
|
@ -18,7 +18,6 @@ pub(crate) fn target() -> Target {
|
|||
options: TargetOptions {
|
||||
features: "+neon,+fp-armv8,+apple-a16".into(),
|
||||
max_atomic_width: Some(128),
|
||||
frame_pointer: FramePointer::NonLeaf,
|
||||
supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::THREAD,
|
||||
..opts
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use crate::spec::base::apple::{Arch, TargetAbi, base};
|
||||
use crate::spec::{FramePointer, SanitizerSet, Target, TargetMetadata, TargetOptions};
|
||||
use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions};
|
||||
|
||||
pub(crate) fn target() -> Target {
|
||||
let (opts, llvm_target, arch) = base("visionos", Arch::Arm64, TargetAbi::Simulator);
|
||||
|
|
@ -18,7 +18,6 @@ pub(crate) fn target() -> Target {
|
|||
options: TargetOptions {
|
||||
features: "+neon,+fp-armv8,+apple-a16".into(),
|
||||
max_atomic_width: Some(128),
|
||||
frame_pointer: FramePointer::NonLeaf,
|
||||
supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::THREAD,
|
||||
..opts
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use crate::spec::base::apple::{Arch, TargetAbi, base};
|
||||
use crate::spec::{FramePointer, Target, TargetMetadata, TargetOptions};
|
||||
use crate::spec::{Target, TargetMetadata, TargetOptions};
|
||||
|
||||
pub(crate) fn target() -> Target {
|
||||
let (opts, llvm_target, arch) = base("watchos", Arch::Arm64, TargetAbi::Simulator);
|
||||
|
|
@ -18,7 +18,6 @@ pub(crate) fn target() -> Target {
|
|||
options: TargetOptions {
|
||||
features: "+neon,+fp-armv8,+apple-a7".into(),
|
||||
max_atomic_width: Some(128),
|
||||
frame_pointer: FramePointer::NonLeaf,
|
||||
..opts
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use crate::spec::base::apple::{Arch, TargetAbi, base};
|
||||
use crate::spec::{FramePointer, SanitizerSet, Target, TargetMetadata, TargetOptions};
|
||||
use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions};
|
||||
|
||||
pub(crate) fn target() -> Target {
|
||||
let (opts, llvm_target, arch) = base("macos", Arch::Arm64e, TargetAbi::Normal);
|
||||
|
|
@ -17,7 +17,6 @@ pub(crate) fn target() -> Target {
|
|||
arch,
|
||||
options: TargetOptions {
|
||||
mcount: "\u{1}mcount".into(),
|
||||
frame_pointer: FramePointer::NonLeaf,
|
||||
cpu: "apple-m1".into(),
|
||||
max_atomic_width: Some(128),
|
||||
// FIXME: The leak sanitizer currently fails the tests, see #88132.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use crate::spec::base::apple::{Arch, TargetAbi, base};
|
||||
use crate::spec::{FramePointer, SanitizerSet, Target, TargetMetadata, TargetOptions};
|
||||
use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions};
|
||||
|
||||
pub(crate) fn target() -> Target {
|
||||
let (opts, llvm_target, arch) = base("ios", Arch::Arm64e, TargetAbi::Normal);
|
||||
|
|
@ -18,7 +18,6 @@ pub(crate) fn target() -> Target {
|
|||
options: TargetOptions {
|
||||
features: "+neon,+fp-armv8,+apple-a12,+v8.3a,+pauth".into(),
|
||||
max_atomic_width: Some(128),
|
||||
frame_pointer: FramePointer::NonLeaf,
|
||||
supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::THREAD,
|
||||
..opts
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use crate::spec::base::apple::{Arch, TargetAbi, base};
|
||||
use crate::spec::{FramePointer, Target, TargetMetadata, TargetOptions};
|
||||
use crate::spec::{Target, TargetMetadata, TargetOptions};
|
||||
|
||||
pub(crate) fn target() -> Target {
|
||||
let (opts, llvm_target, arch) = base("tvos", Arch::Arm64e, TargetAbi::Normal);
|
||||
|
|
@ -18,7 +18,6 @@ pub(crate) fn target() -> Target {
|
|||
options: TargetOptions {
|
||||
features: "+neon,+fp-armv8,+apple-a12,+v8.3a,+pauth".into(),
|
||||
max_atomic_width: Some(128),
|
||||
frame_pointer: FramePointer::NonLeaf,
|
||||
..opts
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use crate::spec::base::apple::{Arch, TargetAbi, base};
|
||||
use crate::spec::{FramePointer, Target, TargetMetadata, TargetOptions};
|
||||
use crate::spec::{Target, TargetMetadata, TargetOptions};
|
||||
|
||||
pub(crate) fn target() -> Target {
|
||||
let (opts, llvm_target, arch) = base("macos", Arch::I686, TargetAbi::Normal);
|
||||
|
|
@ -16,11 +16,6 @@ pub(crate) fn target() -> Target {
|
|||
i128:128-f64:32:64-f80:128-n8:16:32-S128"
|
||||
.into(),
|
||||
arch,
|
||||
options: TargetOptions {
|
||||
mcount: "\u{1}mcount".into(),
|
||||
max_atomic_width: Some(64),
|
||||
frame_pointer: FramePointer::Always,
|
||||
..opts
|
||||
},
|
||||
options: TargetOptions { mcount: "\u{1}mcount".into(), max_atomic_width: Some(64), ..opts },
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use crate::spec::base::apple::{Arch, TargetAbi, base};
|
||||
use crate::spec::{FramePointer, SanitizerSet, Target, TargetMetadata, TargetOptions};
|
||||
use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions};
|
||||
|
||||
pub(crate) fn target() -> Target {
|
||||
let (opts, llvm_target, arch) = base("macos", Arch::X86_64, TargetAbi::Normal);
|
||||
|
|
@ -18,7 +18,6 @@ pub(crate) fn target() -> Target {
|
|||
options: TargetOptions {
|
||||
mcount: "\u{1}mcount".into(),
|
||||
max_atomic_width: Some(128), // penryn+ supports cmpxchg16b
|
||||
frame_pointer: FramePointer::Always,
|
||||
supported_sanitizers: SanitizerSet::ADDRESS
|
||||
| SanitizerSet::CFI
|
||||
| SanitizerSet::LEAK
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
use crate::spec::base::apple::{Arch, TargetAbi, base};
|
||||
use crate::spec::{FramePointer, SanitizerSet, Target, TargetMetadata, TargetOptions};
|
||||
use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions};
|
||||
|
||||
pub(crate) fn target() -> Target {
|
||||
let (mut opts, llvm_target, arch) = base("macos", Arch::X86_64h, TargetAbi::Normal);
|
||||
opts.max_atomic_width = Some(128);
|
||||
opts.frame_pointer = FramePointer::Always;
|
||||
opts.supported_sanitizers =
|
||||
SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::LEAK | SanitizerSet::THREAD;
|
||||
|
||||
|
|
|
|||
|
|
@ -1411,7 +1411,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
err.span_suggestion(
|
||||
err.span_suggestion_verbose(
|
||||
obligation.cause.span.shrink_to_lo(),
|
||||
format!(
|
||||
"consider borrowing the value, since `&{self_ty}` can be coerced into `{target_ty}`"
|
||||
|
|
@ -1574,7 +1574,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
.span_extend_while_whitespace(expr_span)
|
||||
.shrink_to_hi()
|
||||
.to(await_expr.span.shrink_to_hi());
|
||||
err.span_suggestion(
|
||||
err.span_suggestion_verbose(
|
||||
removal_span,
|
||||
"remove the `.await`",
|
||||
"",
|
||||
|
|
@ -2126,7 +2126,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
));
|
||||
|
||||
if !assoc_item.is_impl_trait_in_trait() {
|
||||
err.span_suggestion(
|
||||
err.span_suggestion_verbose(
|
||||
span,
|
||||
"use the fully qualified path to an implementation",
|
||||
format!(
|
||||
|
|
@ -2924,12 +2924,14 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
);
|
||||
let sm = tcx.sess.source_map();
|
||||
if matches!(is_constable, IsConstable::Fn | IsConstable::Ctor)
|
||||
&& let Ok(snip) = sm.span_to_snippet(elt_span)
|
||||
&& let Ok(_) = sm.span_to_snippet(elt_span)
|
||||
{
|
||||
err.span_suggestion(
|
||||
elt_span,
|
||||
err.multipart_suggestion(
|
||||
"create an inline `const` block",
|
||||
format!("const {{ {snip} }}"),
|
||||
vec![
|
||||
(elt_span.shrink_to_lo(), "const { ".to_string()),
|
||||
(elt_span.shrink_to_hi(), " }".to_string()),
|
||||
],
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
} else {
|
||||
|
|
@ -3127,13 +3129,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
err.help("change the field's type to have a statically known size");
|
||||
err.span_suggestion(
|
||||
err.span_suggestion_verbose(
|
||||
span.shrink_to_lo(),
|
||||
"borrowed types always have a statically known size",
|
||||
"&",
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
err.multipart_suggestion(
|
||||
err.multipart_suggestion_verbose(
|
||||
"the `Box` type always has a statically known size and allocates its contents \
|
||||
in the heap",
|
||||
vec![
|
||||
|
|
|
|||
|
|
@ -133,45 +133,25 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
|
|||
/// 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 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
|
|||
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 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
|
|||
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
|
||||
|
|
|
|||
|
|
@ -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 tracing::instrument;
|
|||
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 @@ where
|
|||
|
||||
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 @@ where
|
|||
|
||||
// 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 @@ where
|
|||
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 @@ where
|
|||
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 @@ where
|
|||
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 @@ where
|
|||
result,
|
||||
))
|
||||
} else {
|
||||
ensure_sufficient_stack(|| self.normalize_unevaluated_const(uv))
|
||||
Ok(ensure_sufficient_stack(|| self.normalize_alias_term(ct.into()))?.expect_const())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ use rustc_infer::traits::{
|
|||
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,
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,10 +39,7 @@ impl<'tcx> At<'_, '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
|
||||
|
|
|
|||
|
|
@ -9,8 +9,6 @@
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(iter_macro, coroutines)]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # {
|
||||
///
|
||||
/// let it = std::iter::iter!{|| {
|
||||
/// yield 1;
|
||||
|
|
@ -19,7 +17,6 @@
|
|||
/// } }();
|
||||
/// let v: Vec<_> = it.collect();
|
||||
/// assert_eq!(v, [1, 2, 3]);
|
||||
/// # }
|
||||
/// ```
|
||||
#[unstable(feature = "iter_macro", issue = "none", reason = "generators are unstable")]
|
||||
#[allow_internal_unstable(coroutines, iter_from_coroutine)]
|
||||
|
|
|
|||
|
|
@ -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].
|
||||
//!
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ impl [u8] {
|
|||
/// 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 {
|
||||
|
|
|
|||
|
|
@ -2671,7 +2671,7 @@ impl str {
|
|||
/// 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 {
|
||||
|
|
|
|||
|
|
@ -568,7 +568,7 @@ impl OsString {
|
|||
/// However, keep in mind that trimming the capacity may result in a reallocation and copy.
|
||||
///
|
||||
/// [`into_boxed_os_str`]: Self::into_boxed_os_str
|
||||
#[unstable(feature = "os_string_pathbuf_leak", issue = "125965")]
|
||||
#[stable(feature = "os_string_pathbuf_leak", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[inline]
|
||||
pub fn leak<'a>(self) -> &'a mut OsStr {
|
||||
OsStr::from_inner_mut(self.inner.leak())
|
||||
|
|
|
|||
|
|
@ -1252,7 +1252,7 @@ impl PathBuf {
|
|||
/// However, keep in mind that trimming the capacity may result in a reallocation and copy.
|
||||
///
|
||||
/// [`into_boxed_path`]: Self::into_boxed_path
|
||||
#[unstable(feature = "os_string_pathbuf_leak", issue = "125965")]
|
||||
#[stable(feature = "os_string_pathbuf_leak", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[inline]
|
||||
pub fn leak<'a>(self) -> &'a mut Path {
|
||||
Path::from_inner_mut(self.inner.leak())
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
path_add_extension,
|
||||
path_file_prefix,
|
||||
maybe_uninit_slice,
|
||||
os_string_pathbuf_leak,
|
||||
normalize_lexically
|
||||
)]
|
||||
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit b6e2249e388f520627544812649b77b0944e1a2e
|
||||
Subproject commit 5c1c436524c0bbc8db83577f42f8bea9006a7b75
|
||||
|
|
@ -1313,10 +1313,8 @@ impl Builder<'_> {
|
|||
//
|
||||
// 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
|
||||
|
|
|
|||
|
|
@ -28,8 +28,6 @@ use build_helper::git::{GitConfig, PathFreshness, check_path_modifications, outp
|
|||
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;
|
||||
|
|
|
|||
|
|
@ -39,8 +39,6 @@ pub use toml::BUILDER_CONFIG_FILENAME;
|
|||
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;
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ ENV SCRIPT \
|
|||
python3 ../x.py check && \
|
||||
python3 ../x.py clippy ci && \
|
||||
python3 ../x.py test --stage 1 core alloc std test proc_macro && \
|
||||
python3 ../x.py doc --stage 0 bootstrap && \
|
||||
# Build both public and internal documentation.
|
||||
RUSTDOCFLAGS=\"--document-private-items --document-hidden-items\" python3 ../x.py doc --stage 0 compiler && \
|
||||
RUSTDOCFLAGS=\"--document-private-items --document-hidden-items\" python3 ../x.py doc --stage 1 library && \
|
||||
|
|
|
|||
|
|
@ -15,7 +15,8 @@ fi
|
|||
branch=$(git branch --show-current || echo)
|
||||
|
||||
if [ -n "$branch" ]; then
|
||||
branch="${branch}-"
|
||||
# Strip automation/bors/ prefix if present
|
||||
branch="${branch#automation/bors/}-"
|
||||
fi
|
||||
|
||||
if [ "${GITHUB_EVENT_NAME:=none}" = "pull_request" ]; then
|
||||
|
|
|
|||
|
|
@ -143,15 +143,6 @@ But if you include this:
|
|||
|
||||
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 @@ To get around this limitation, we just add `#[doc(alias = "lib_name_do_something
|
|||
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`
|
||||
```
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ mod runner;
|
|||
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 @@ use std::{panic, str};
|
|||
|
||||
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 @@ impl ScrapedDocTest {
|
|||
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 @@ impl ScrapedDocTest {
|
|||
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 @@ impl CreateRunnableDocTests {
|
|||
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 @@ impl CreateRunnableDocTests {
|
|||
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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -35,13 +35,16 @@ impl ExtractedDocTests {
|
|||
) {
|
||||
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,
|
||||
|
|
|
|||
|
|
@ -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 @@ impl<'a> BuildDocTestBuilder<'a> {
|
|||
test_id: None,
|
||||
lang_str: None,
|
||||
span: DUMMY_SP,
|
||||
global_crate_attrs: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -96,6 +98,12 @@ impl<'a> BuildDocTestBuilder<'a> {
|
|||
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 @@ impl<'a> BuildDocTestBuilder<'a> {
|
|||
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 @@ impl<'a> BuildDocTestBuilder<'a> {
|
|||
// 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 @@ impl<'a> BuildDocTestBuilder<'a> {
|
|||
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 @@ impl DocTestBuilder {
|
|||
Self {
|
||||
supports_color: false,
|
||||
has_main_fn: false,
|
||||
global_crate_attrs,
|
||||
crate_attrs,
|
||||
maybe_crate_attrs,
|
||||
crates,
|
||||
|
|
@ -224,7 +238,8 @@ impl DocTestBuilder {
|
|||
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 @@ impl DocTestBuilder {
|
|||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ impl DocTestVisitor for MdCollector {
|
|||
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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ use crate::html::markdown::{Ignore, LangString};
|
|||
/// 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 @@ impl DocTestRunner {
|
|||
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 @@ impl DocTestRunner {
|
|||
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 @@ impl DocTestRunner {
|
|||
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"));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ use std::cell::Cell;
|
|||
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::hir::nested_filter;
|
|||
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 @@ impl DocTestVisitor for RustCollector {
|
|||
config,
|
||||
test,
|
||||
span,
|
||||
self.global_crate_attrs.clone(),
|
||||
));
|
||||
}
|
||||
|
||||
|
|
@ -94,6 +97,7 @@ impl<'tcx> HirCollector<'tcx> {
|
|||
cur_path: vec![],
|
||||
position: DUMMY_SP,
|
||||
tests: vec![],
|
||||
global_crate_attrs: Vec::new(),
|
||||
};
|
||||
Self { codes, tcx, collector }
|
||||
}
|
||||
|
|
@ -123,6 +127,26 @@ impl HirCollector<'_> {
|
|||
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 @@ impl HirCollector<'_> {
|
|||
|
||||
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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 @@ use asdf::qwop;
|
|||
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 @@ use asdf::qwop;
|
|||
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 @@ use std::*;
|
|||
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 @@ use asdf::qwop;
|
|||
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 @@ use asdf::qwop;
|
|||
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 @@ assert_eq!(2+2, 4);
|
|||
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 @@ use asdf::qwop;
|
|||
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 @@ use asdf::qwop;
|
|||
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 @@ assert_eq!(2+2, 4);";
|
|||
//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 @@ 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));
|
||||
}
|
||||
|
||||
|
|
@ -284,7 +294,7 @@ assert_eq!(asdf::foo, 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));
|
||||
}
|
||||
|
||||
|
|
@ -302,7 +312,7 @@ test_wrapper! {
|
|||
}"
|
||||
.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 @@ io::stdin().read_line(&mut input)?;
|
|||
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));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -300,7 +300,6 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'_, 'a, I> {
|
|||
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);
|
||||
|
|
|
|||
|
|
@ -40,7 +40,9 @@ static HOSTS: &[&str] = &[
|
|||
"powerpc64le-unknown-linux-musl",
|
||||
"riscv64gc-unknown-linux-gnu",
|
||||
"s390x-unknown-linux-gnu",
|
||||
"sparcv9-sun-solaris",
|
||||
"x86_64-apple-darwin",
|
||||
"x86_64-pc-solaris",
|
||||
"x86_64-pc-windows-gnu",
|
||||
"x86_64-pc-windows-msvc",
|
||||
"x86_64-unknown-freebsd",
|
||||
|
|
|
|||
|
|
@ -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::*;
|
||||
|
|
|
|||
|
|
@ -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")]
|
||||
|
|
|
|||
|
|
@ -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::*;
|
||||
|
|
|
|||
|
|
@ -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::*;
|
||||
|
|
|
|||
|
|
@ -4451,20 +4451,6 @@ The tracking issue for this feature is: [#133214]
|
|||
|
||||
[#133214]: https://github.com/rust-lang/rust/issues/133214
|
||||
|
||||
------------------------
|
||||
"##,
|
||||
default_severity: Severity::Allow,
|
||||
warn_since: None,
|
||||
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,
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
116
tests/rustdoc-ui/doctest/dead-code-items.rs
Normal file
116
tests/rustdoc-ui/doctest/dead-code-items.rs
Normal file
|
|
@ -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();
|
||||
}
|
||||
146
tests/rustdoc-ui/doctest/dead-code-items.stdout
Normal file
146
tests/rustdoc-ui/doctest/dead-code-items.stdout
Normal file
|
|
@ -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
|
||||
|
||||
27
tests/rustdoc-ui/doctest/dead-code-module-2.rs
Normal file
27
tests/rustdoc-ui/doctest/dead-code-module-2.rs
Normal file
|
|
@ -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() {}
|
||||
35
tests/rustdoc-ui/doctest/dead-code-module-2.stdout
Normal file
35
tests/rustdoc-ui/doctest/dead-code-module-2.stdout
Normal file
|
|
@ -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
|
||||
|
||||
18
tests/rustdoc-ui/doctest/dead-code-module.rs
Normal file
18
tests/rustdoc-ui/doctest/dead-code-module.rs
Normal file
|
|
@ -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() {}
|
||||
}
|
||||
29
tests/rustdoc-ui/doctest/dead-code-module.stdout
Normal file
29
tests/rustdoc-ui/doctest/dead-code-module.stdout
Normal file
|
|
@ -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
|
||||
|
||||
11
tests/rustdoc-ui/doctest/doc-test-attr-pass-module.rs
Normal file
11
tests/rustdoc-ui/doctest/doc-test-attr-pass-module.rs
Normal file
|
|
@ -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() {}
|
||||
}
|
||||
|
|
@ -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")]
|
||||
|
|
|
|||
|
|
@ -2,14 +2,16 @@ error[E0277]: `[usize; usize::MAX]` is not a future
|
|||
--> $DIR/debug-ice-attempted-to-add-with-overflow.rs:8:37
|
||||
|
|
||||
LL | [0usize; 0xffff_ffff_ffff_ffff].await;
|
||||
| -^^^^^
|
||||
| ||
|
||||
| |`[usize; usize::MAX]` is not a future
|
||||
| help: remove the `.await`
|
||||
| ^^^^^ `[usize; usize::MAX]` is not a future
|
||||
|
|
||||
= help: the trait `Future` is not implemented for `[usize; usize::MAX]`
|
||||
= note: [usize; usize::MAX] must be a future or must implement `IntoFuture` to be awaited
|
||||
= note: required for `[usize; usize::MAX]` to implement `IntoFuture`
|
||||
help: remove the `.await`
|
||||
|
|
||||
LL - [0usize; 0xffff_ffff_ffff_ffff].await;
|
||||
LL + [0usize; 0xffff_ffff_ffff_ffff];
|
||||
|
|
||||
|
||||
error[E0752]: `main` function is not allowed to be `async`
|
||||
--> $DIR/debug-ice-attempted-to-add-with-overflow.rs:6:1
|
||||
|
|
|
|||
|
|
@ -10,14 +10,16 @@ error[E0277]: `Option<_>` is not a future
|
|||
--> $DIR/drop-track-bad-field-in-fru.rs:6:46
|
||||
|
|
||||
LL | None { value: (), ..Default::default() }.await;
|
||||
| -^^^^^
|
||||
| ||
|
||||
| |`Option<_>` is not a future
|
||||
| help: remove the `.await`
|
||||
| ^^^^^ `Option<_>` is not a future
|
||||
|
|
||||
= help: the trait `Future` is not implemented for `Option<_>`
|
||||
= note: Option<_> must be a future or must implement `IntoFuture` to be awaited
|
||||
= note: required for `Option<_>` to implement `IntoFuture`
|
||||
help: remove the `.await`
|
||||
|
|
||||
LL - None { value: (), ..Default::default() }.await;
|
||||
LL + None { value: (), ..Default::default() };
|
||||
|
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -2,14 +2,15 @@ error[E0277]: `()` is not a future
|
|||
--> $DIR/issue-101715.rs:11:10
|
||||
|
|
||||
LL | .await
|
||||
| -^^^^^
|
||||
| ||
|
||||
| |`()` is not a future
|
||||
| help: remove the `.await`
|
||||
| ^^^^^ `()` is not a future
|
||||
|
|
||||
= help: the trait `Future` is not implemented for `()`
|
||||
= note: () must be a future or must implement `IntoFuture` to be awaited
|
||||
= note: required for `()` to implement `IntoFuture`
|
||||
help: remove the `.await`
|
||||
|
|
||||
LL - .await
|
||||
|
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
|
|||
|
|
@ -23,14 +23,16 @@ error[E0277]: `()` is not a future
|
|||
--> $DIR/unnecessary-await.rs:28:10
|
||||
|
|
||||
LL | e!().await;
|
||||
| -^^^^^
|
||||
| ||
|
||||
| |`()` is not a future
|
||||
| help: remove the `.await`
|
||||
| ^^^^^ `()` is not a future
|
||||
|
|
||||
= help: the trait `Future` is not implemented for `()`
|
||||
= note: () must be a future or must implement `IntoFuture` to be awaited
|
||||
= note: required for `()` to implement `IntoFuture`
|
||||
help: remove the `.await`
|
||||
|
|
||||
LL - e!().await;
|
||||
LL + e!();
|
||||
|
|
||||
|
||||
error[E0277]: `()` is not a future
|
||||
--> $DIR/unnecessary-await.rs:22:15
|
||||
|
|
@ -53,14 +55,16 @@ error[E0277]: `()` is not a future
|
|||
--> $DIR/unnecessary-await.rs:36:20
|
||||
|
|
||||
LL | for x in [] {}.await
|
||||
| -^^^^^
|
||||
| ||
|
||||
| |`()` is not a future
|
||||
| help: remove the `.await`
|
||||
| ^^^^^ `()` is not a future
|
||||
|
|
||||
= help: the trait `Future` is not implemented for `()`
|
||||
= note: () must be a future or must implement `IntoFuture` to be awaited
|
||||
= note: required for `()` to implement `IntoFuture`
|
||||
help: remove the `.await`
|
||||
|
|
||||
LL - for x in [] {}.await
|
||||
LL + for x in [] {}
|
||||
|
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -2,17 +2,23 @@ error[E0620]: cast to unsized type: `&[u8]` as `[char]`
|
|||
--> $DIR/cast-to-slice.rs:2:5
|
||||
|
|
||||
LL | "example".as_bytes() as [char];
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^------
|
||||
| |
|
||||
| help: try casting to a reference instead: `&[char]`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: consider casting to a reference instead
|
||||
|
|
||||
LL | "example".as_bytes() as &[char];
|
||||
| +
|
||||
|
||||
error[E0620]: cast to unsized type: `&[u8]` as `[char]`
|
||||
--> $DIR/cast-to-slice.rs:6:5
|
||||
|
|
||||
LL | arr as [char];
|
||||
| ^^^^^^^------
|
||||
| |
|
||||
| help: try casting to a reference instead: `&[char]`
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
help: consider casting to a reference instead
|
||||
|
|
||||
LL | arr as &[char];
|
||||
| +
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -2,17 +2,23 @@ error[E0620]: cast to unsized type: `&{integer}` as `dyn Send`
|
|||
--> $DIR/cast-to-unsized-trait-object-suggestion.rs:2:5
|
||||
|
|
||||
LL | &1 as dyn Send;
|
||||
| ^^^^^^--------
|
||||
| |
|
||||
| help: try casting to a reference instead: `&dyn Send`
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
help: consider casting to a reference instead
|
||||
|
|
||||
LL | &1 as &dyn Send;
|
||||
| +
|
||||
|
||||
error[E0620]: cast to unsized type: `Box<{integer}>` as `dyn Send`
|
||||
--> $DIR/cast-to-unsized-trait-object-suggestion.rs:3:5
|
||||
|
|
||||
LL | Box::new(1) as dyn Send;
|
||||
| ^^^^^^^^^^^^^^^--------
|
||||
| |
|
||||
| help: you can cast to a `Box` instead: `Box<dyn Send>`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: you can cast to a `Box` instead
|
||||
|
|
||||
LL | Box::new(1) as Box<dyn Send>;
|
||||
| ++++ +
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -10,9 +10,8 @@ error[E0605]: non-primitive cast: `u32` as `Option<_>`
|
|||
--> $DIR/issue-73886.rs:4:13
|
||||
|
|
||||
LL | let _ = 7u32 as Option<_>;
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
|
||||
|
|
||||
= note: an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
|
||||
help: consider using the `From` trait instead
|
||||
|
|
||||
LL - let _ = 7u32 as Option<_>;
|
||||
|
|
|
|||
|
|
@ -2,9 +2,8 @@ error[E0605]: non-primitive cast: `u32` as `Option<_>`
|
|||
--> $DIR/non-primitive-cast-135412.rs:6:13
|
||||
|
|
||||
LL | let _ = 7u32 as Option<_>;
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
|
||||
|
|
||||
= note: an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
|
||||
help: consider using the `From` trait instead
|
||||
|
|
||||
LL - let _ = 7u32 as Option<_>;
|
||||
|
|
@ -15,9 +14,8 @@ error[E0605]: non-primitive cast: `&'static str` as `Arc<str>`
|
|||
--> $DIR/non-primitive-cast-135412.rs:8:13
|
||||
|
|
||||
LL | let _ = "String" as Arc<str>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
|
||||
|
|
||||
= note: an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
|
||||
help: consider using the `From` trait instead
|
||||
|
|
||||
LL - let _ = "String" as Arc<str>;
|
||||
|
|
|
|||
|
|
@ -13,9 +13,8 @@ LL | struct Bar;
|
|||
|
|
||||
help: create an inline `const` block
|
||||
|
|
||||
LL - let _: [Option<Bar>; 2] = [no_copy(); 2];
|
||||
LL + let _: [Option<Bar>; 2] = [const { no_copy() }; 2];
|
||||
|
|
||||
LL | let _: [Option<Bar>; 2] = [const { no_copy() }; 2];
|
||||
| +++++++ +
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
|
|||
|
|
@ -2,10 +2,7 @@ error[E0277]: the trait bound `String: Copy` is not satisfied
|
|||
--> $DIR/trait-error.rs:5:6
|
||||
|
|
||||
LL | [Foo(String::new()); 4];
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| the trait `Copy` is not implemented for `String`
|
||||
| help: create an inline `const` block: `const { Foo(String::new()) }`
|
||||
| ^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
|
||||
|
|
||||
note: required for `Foo<String>` to implement `Copy`
|
||||
--> $DIR/trait-error.rs:1:10
|
||||
|
|
@ -13,6 +10,10 @@ note: required for `Foo<String>` to implement `Copy`
|
|||
LL | #[derive(Copy, Clone)]
|
||||
| ^^^^ unsatisfied trait bound introduced in this `derive` macro
|
||||
= note: the `Copy` trait is required because this value will be copied for each element of the array
|
||||
help: create an inline `const` block
|
||||
|
|
||||
LL | [const { Foo(String::new()) }; 4];
|
||||
| +++++++ +
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ error[E0604]: only `u8` can be cast as `char`, not `i8`
|
|||
LL | : [u32; 5i8 as char as usize]
|
||||
| ^^^^^^^^^^^ invalid cast
|
||||
|
|
||||
help: try casting from `u8` instead
|
||||
help: consider casting from `u8` instead
|
||||
--> $DIR/const-eval-overflow-4b.rs:24:13
|
||||
|
|
||||
LL | : [u32; 5i8 as char as usize]
|
||||
|
|
|
|||
|
|
@ -2,36 +2,39 @@ error[E0277]: the trait bound `String: Copy` is not satisfied
|
|||
--> $DIR/const-fn-in-vec.rs:1:47
|
||||
|
|
||||
LL | static _MAYBE_STRINGS: [Option<String>; 5] = [None; 5];
|
||||
| ^^^^
|
||||
| |
|
||||
| the trait `Copy` is not implemented for `String`
|
||||
| help: create an inline `const` block: `const { None }`
|
||||
| ^^^^ the trait `Copy` is not implemented for `String`
|
||||
|
|
||||
= note: required for `Option<String>` to implement `Copy`
|
||||
= note: the `Copy` trait is required because this value will be copied for each element of the array
|
||||
help: create an inline `const` block
|
||||
|
|
||||
LL | static _MAYBE_STRINGS: [Option<String>; 5] = [const { None }; 5];
|
||||
| +++++++ +
|
||||
|
||||
error[E0277]: the trait bound `String: Copy` is not satisfied
|
||||
--> $DIR/const-fn-in-vec.rs:7:34
|
||||
|
|
||||
LL | let _strings: [String; 5] = [String::new(); 5];
|
||||
| ^^^^^^^^^^^^^
|
||||
| |
|
||||
| the trait `Copy` is not implemented for `String`
|
||||
| help: create an inline `const` block: `const { String::new() }`
|
||||
| ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
|
||||
|
|
||||
= note: the `Copy` trait is required because this value will be copied for each element of the array
|
||||
help: create an inline `const` block
|
||||
|
|
||||
LL | let _strings: [String; 5] = [const { String::new() }; 5];
|
||||
| +++++++ +
|
||||
|
||||
error[E0277]: the trait bound `String: Copy` is not satisfied
|
||||
--> $DIR/const-fn-in-vec.rs:12:48
|
||||
|
|
||||
LL | let _maybe_strings: [Option<String>; 5] = [None; 5];
|
||||
| ^^^^
|
||||
| |
|
||||
| the trait `Copy` is not implemented for `String`
|
||||
| help: create an inline `const` block: `const { None }`
|
||||
| ^^^^ the trait `Copy` is not implemented for `String`
|
||||
|
|
||||
= note: required for `Option<String>` to implement `Copy`
|
||||
= note: the `Copy` trait is required because this value will be copied for each element of the array
|
||||
help: create an inline `const` block
|
||||
|
|
||||
LL | let _maybe_strings: [Option<String>; 5] = [const { None }; 5];
|
||||
| +++++++ +
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -2,15 +2,18 @@ error[E0277]: `[(); _]` is not a future
|
|||
--> $DIR/unresolved-ct-var.rs:6:45
|
||||
|
|
||||
LL | let s = std::array::from_fn(|_| ()).await;
|
||||
| ----------------------------^^^^^
|
||||
| | ||
|
||||
| | |`[(); _]` is not a future
|
||||
| | help: remove the `.await`
|
||||
| --------------------------- ^^^^^ `[(); _]` is not a future
|
||||
| |
|
||||
| this call returns `[(); _]`
|
||||
|
|
||||
= help: the trait `Future` is not implemented for `[(); _]`
|
||||
= note: [(); _] must be a future or must implement `IntoFuture` to be awaited
|
||||
= note: required for `[(); _]` to implement `IntoFuture`
|
||||
help: remove the `.await`
|
||||
|
|
||||
LL - let s = std::array::from_fn(|_| ()).await;
|
||||
LL + let s = std::array::from_fn(|_| ());
|
||||
|
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
|
|||
|
|
@ -2,10 +2,13 @@ error[E0604]: only `u8` can be cast as `char`, not `u32`
|
|||
--> $DIR/E0604.rs:2:5
|
||||
|
|
||||
LL | 1u32 as char;
|
||||
| ^^^^^^^^^^^^
|
||||
| |
|
||||
| invalid cast
|
||||
| help: try `char::from_u32` instead: `char::from_u32(1u32)`
|
||||
| ^^^^^^^^^^^^ invalid cast
|
||||
|
|
||||
help: consider using `char::from_u32` instead
|
||||
|
|
||||
LL - 1u32 as char;
|
||||
LL + char::from_u32(1u32);
|
||||
|
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
|
|||
|
|
@ -2,9 +2,12 @@ error[E0620]: cast to unsized type: `&[usize; 2]` as `[usize]`
|
|||
--> $DIR/E0620.rs:2:16
|
||||
|
|
||||
LL | let _foo = &[1_usize, 2] as [usize];
|
||||
| ^^^^^^^^^^^^^^^^^-------
|
||||
| |
|
||||
| help: try casting to a reference instead: `&[usize]`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: consider casting to a reference instead
|
||||
|
|
||||
LL | let _foo = &[1_usize, 2] as &[usize];
|
||||
| +
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
|
|||
|
|
@ -58,10 +58,13 @@ error[E0604]: only `u8` can be cast as `char`, not `u32`
|
|||
--> $DIR/error-festival.rs:27:5
|
||||
|
|
||||
LL | 0u32 as char;
|
||||
| ^^^^^^^^^^^^
|
||||
| |
|
||||
| invalid cast
|
||||
| help: try `char::from_u32` instead: `char::from_u32(0u32)`
|
||||
| ^^^^^^^^^^^^ invalid cast
|
||||
|
|
||||
help: consider using `char::from_u32` instead
|
||||
|
|
||||
LL - 0u32 as char;
|
||||
LL + char::from_u32(0u32);
|
||||
|
|
||||
|
||||
error[E0605]: non-primitive cast: `u8` as `Vec<u8>`
|
||||
--> $DIR/error-festival.rs:31:5
|
||||
|
|
|
|||
|
|
@ -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() {}
|
||||
|
|
|
|||
|
|
@ -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 @@ LL | fn f(u8) {}
|
|||
= 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)]`
|
||||
|
||||
|
|
|
|||
|
|
@ -11,9 +11,13 @@ error[E0605]: non-primitive cast: `Foo<'a>` as `T`
|
|||
--> $DIR/issue-16048.rs:24:16
|
||||
|
|
||||
LL | return *self as T;
|
||||
| ^^^^^^^^^^ help: consider using the `From` trait instead: `T::from(*self)`
|
||||
| ^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
|
||||
|
|
||||
help: consider using the `From` trait instead
|
||||
|
|
||||
LL - return *self as T;
|
||||
LL + return T::from(*self);
|
||||
|
|
||||
= note: an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -2,17 +2,23 @@ error[E0620]: cast to unsized type: `&[usize; 2]` as `[usize]`
|
|||
--> $DIR/issue-17441.rs:2:16
|
||||
|
|
||||
LL | let _foo = &[1_usize, 2] as [usize];
|
||||
| ^^^^^^^^^^^^^^^^^-------
|
||||
| |
|
||||
| help: try casting to a reference instead: `&[usize]`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: consider casting to a reference instead
|
||||
|
|
||||
LL | let _foo = &[1_usize, 2] as &[usize];
|
||||
| +
|
||||
|
||||
error[E0620]: cast to unsized type: `Box<usize>` as `dyn Debug`
|
||||
--> $DIR/issue-17441.rs:5:16
|
||||
|
|
||||
LL | let _bar = Box::new(1_usize) as dyn std::fmt::Debug;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^-------------------
|
||||
| |
|
||||
| help: you can cast to a `Box` instead: `Box<dyn std::fmt::Debug>`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: you can cast to a `Box` instead
|
||||
|
|
||||
LL | let _bar = Box::new(1_usize) as Box<dyn std::fmt::Debug>;
|
||||
| ++++ +
|
||||
|
||||
error[E0620]: cast to unsized type: `usize` as `dyn Debug`
|
||||
--> $DIR/issue-17441.rs:8:16
|
||||
|
|
|
|||
9
tests/ui/lint/force-warn/ice-free.rs
Normal file
9
tests/ui/lint/force-warn/ice-free.rs
Normal file
|
|
@ -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() {}
|
||||
32
tests/ui/lint/force-warn/ice-free.stderr
Normal file
32
tests/ui/lint/force-warn/ice-free.stderr
Normal file
|
|
@ -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;
|
||||
| +++
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
//@ check-pass
|
||||
//@ check-fail
|
||||
//@ run-rustfix
|
||||
|
||||
#![allow(dead_code)] // For the rustfix-ed code.
|
||||
|
|
@ -8,7 +8,7 @@ use std::ops::Deref;
|
|||
|
||||
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 _ = (&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() {}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
//@ check-pass
|
||||
//@ check-fail
|
||||
//@ run-rustfix
|
||||
|
||||
#![allow(dead_code)] // For the rustfix-ed code.
|
||||
|
|
@ -8,7 +8,7 @@ use std::ops::Deref;
|
|||
|
||||
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() {}
|
||||
|
|
|
|||
|
|
@ -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 @@ note: autoref is being applied to this expression, resulting in: `&[u8]`
|
|||
|
|
||||
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 @@ help: try using a raw pointer method instead; or if this reference is intentiona
|
|||
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 @@ help: try using a raw pointer method instead; or if this reference is intentiona
|
|||
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 @@ help: try using a raw pointer method instead; or if this reference is intentiona
|
|||
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 @@ help: try using a raw pointer method instead; or if this reference is intentiona
|
|||
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 @@ help: try using a raw pointer method instead; or if this reference is intentiona
|
|||
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 @@ help: try using a raw pointer method instead; or if this reference is intentiona
|
|||
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 @@ help: try using a raw pointer method instead; or if this reference is intentiona
|
|||
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 @@ help: try using a raw pointer method instead; or if this reference is intentiona
|
|||
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 @@ help: try using a raw pointer method instead; or if this reference is intentiona
|
|||
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 @@ LL | let _p: *const i32 = &raw const **w;
|
|||
|
|
||||
= 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 @@ help: try using a raw pointer method instead; or if this reference is intentiona
|
|||
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 @@ LL | unsafe { (*ptr).field.len() }
|
|||
|
|
||||
= 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 @@ help: try using a raw pointer method instead; or if this reference is intentiona
|
|||
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 @@ LL | let _ = (*ptr).get(0);
|
|||
|
|
||||
= 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 @@ help: try using a raw pointer method instead; or if this reference is intentiona
|
|||
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 @@ LL | let _ = (*ptr).get_unchecked(0);
|
|||
|
|
||||
= 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 @@ help: try using a raw pointer method instead; or if this reference is intentiona
|
|||
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 @@ LL | let _ = (*ptr).get_mut(0);
|
|||
|
|
||||
= 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 @@ help: try using a raw pointer method instead; or if this reference is intentiona
|
|||
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 @@ LL | let _ = (*ptr).get_unchecked_mut(0);
|
|||
|
|
||||
= 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 @@ help: try using a raw pointer method instead; or if this reference is intentiona
|
|||
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 @@ LL | let _ = (*ptr).len();
|
|||
|
|
||||
= 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 @@ help: try using a raw pointer method instead; or if this reference is intentiona
|
|||
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 @@ LL | let _ = (*ptr).is_empty();
|
|||
|
|
||||
= 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 @@ help: try using a raw pointer method instead; or if this reference is intentiona
|
|||
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 @@ LL | let _ = (*slice)[..].len();
|
|||
|
|
||||
= 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 @@ help: try using a raw pointer method instead; or if this reference is intentiona
|
|||
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 @@ LL | let _ = (*slice)[..].len();
|
|||
|
|
||||
= 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 @@ help: try using a raw pointer method instead; or if this reference is intentiona
|
|||
LL | let _ = (&(*slice))[..].len();
|
||||
| ++ +
|
||||
|
||||
warning: 20 warnings emitted
|
||||
error: aborting due to 20 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -12,7 +12,28 @@ LL | #![deny(unused_doc_comments)]
|
|||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
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 @@ LL | /// bar
|
|||
= 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 | | /// that is unused
|
|||
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 @@ LL | | }
|
|||
= 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 @@ LL | 1 => {},
|
|||
= 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 @@ LL | unsafe {}
|
|||
= 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 @@ LL | 3;
|
|||
= 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 @@ LL | 3;
|
|||
= 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 @@ LL | let x = /** comment */ 47;
|
|||
= 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 @@ LL | | }
|
|||
|
|
||||
= help: use `//` for a plain comment
|
||||
|
||||
error: aborting due to 10 previous errors
|
||||
error: aborting due to 15 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -104,10 +104,13 @@ error[E0604]: only `u8` can be cast as `char`, not `u32`
|
|||
--> $DIR/cast-rfc0401.rs:41:13
|
||||
|
|
||||
LL | let _ = 0x61u32 as char;
|
||||
| ^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| invalid cast
|
||||
| help: try `char::from_u32` instead: `char::from_u32(0x61u32)`
|
||||
| ^^^^^^^^^^^^^^^ invalid cast
|
||||
|
|
||||
help: consider using `char::from_u32` instead
|
||||
|
|
||||
LL - let _ = 0x61u32 as char;
|
||||
LL + let _ = char::from_u32(0x61u32);
|
||||
|
|
||||
|
||||
error[E0606]: casting `bool` as `f32` is invalid
|
||||
--> $DIR/cast-rfc0401.rs:43:13
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue