mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 23:04:33 +00:00
Auto merge of #89629 - GuillaumeGomez:rollup-s4r8me6, r=GuillaumeGomez
Rollup of 7 pull requests Successful merges: - #89298 (Issue 89193 - Fix ICE when using `usize` and `isize` with SIMD gathers ) - #89461 (Add `deref_into_dyn_supertrait` lint.) - #89477 (Move items related to computing diffs to a separate file) - #89559 (RustWrapper: adapt for LLVM API change) - #89585 (Emit item no type error even if type inference fails) - #89596 (Make cfg imply doc(cfg)) - #89615 (Add InferCtxt::with_opaque_type_inference to get_body_with_borrowck_facts) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
5641481ad7
@ -4454,6 +4454,7 @@ dependencies = [
|
||||
"rustc_hir",
|
||||
"rustc_index",
|
||||
"rustc_infer",
|
||||
"rustc_lint_defs",
|
||||
"rustc_macros",
|
||||
"rustc_middle",
|
||||
"rustc_parse_format",
|
||||
|
@ -279,6 +279,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
||||
|
||||
gate_doc!(
|
||||
cfg => doc_cfg
|
||||
cfg_hide => doc_cfg_hide
|
||||
masked => doc_masked
|
||||
notable_trait => doc_notable_trait
|
||||
keyword => doc_keyword
|
||||
|
@ -31,7 +31,7 @@ pub fn get_body_with_borrowck_facts<'tcx>(
|
||||
def: ty::WithOptConstParam<LocalDefId>,
|
||||
) -> BodyWithBorrowckFacts<'tcx> {
|
||||
let (input_body, promoted) = tcx.mir_promoted(def);
|
||||
tcx.infer_ctxt().enter(|infcx| {
|
||||
tcx.infer_ctxt().with_opaque_type_inference(def.did).enter(|infcx| {
|
||||
let input_body: &Body<'_> = &input_body.borrow();
|
||||
let promoted: &IndexVec<_, _> = &promoted.borrow();
|
||||
*super::do_mir_borrowck(&infcx, input_body, promoted, true).1.unwrap()
|
||||
|
@ -20,7 +20,7 @@ use rustc_middle::ty::{self, Ty};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_span::{sym, symbol::kw, Span, Symbol};
|
||||
use rustc_target::abi::{self, HasDataLayout, Primitive};
|
||||
use rustc_target::spec::PanicStrategy;
|
||||
use rustc_target::spec::{HasTargetSpec, PanicStrategy};
|
||||
|
||||
use std::cmp::Ordering;
|
||||
use std::iter;
|
||||
@ -1190,11 +1190,28 @@ fn generic_simd_intrinsic(
|
||||
// FIXME: use:
|
||||
// https://github.com/llvm-mirror/llvm/blob/master/include/llvm/IR/Function.h#L182
|
||||
// https://github.com/llvm-mirror/llvm/blob/master/include/llvm/IR/Intrinsics.h#L81
|
||||
fn llvm_vector_str(elem_ty: Ty<'_>, vec_len: u64, no_pointers: usize) -> String {
|
||||
fn llvm_vector_str(
|
||||
elem_ty: Ty<'_>,
|
||||
vec_len: u64,
|
||||
no_pointers: usize,
|
||||
bx: &Builder<'a, 'll, 'tcx>,
|
||||
) -> String {
|
||||
let p0s: String = "p0".repeat(no_pointers);
|
||||
match *elem_ty.kind() {
|
||||
ty::Int(v) => format!("v{}{}i{}", vec_len, p0s, v.bit_width().unwrap()),
|
||||
ty::Uint(v) => format!("v{}{}i{}", vec_len, p0s, v.bit_width().unwrap()),
|
||||
ty::Int(v) => format!(
|
||||
"v{}{}i{}",
|
||||
vec_len,
|
||||
p0s,
|
||||
// Normalize to prevent crash if v: IntTy::Isize
|
||||
v.normalize(bx.target_spec().pointer_width).bit_width().unwrap()
|
||||
),
|
||||
ty::Uint(v) => format!(
|
||||
"v{}{}i{}",
|
||||
vec_len,
|
||||
p0s,
|
||||
// Normalize to prevent crash if v: UIntTy::Usize
|
||||
v.normalize(bx.target_spec().pointer_width).bit_width().unwrap()
|
||||
),
|
||||
ty::Float(v) => format!("v{}{}f{}", vec_len, p0s, v.bit_width()),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
@ -1330,11 +1347,11 @@ fn generic_simd_intrinsic(
|
||||
|
||||
// Type of the vector of pointers:
|
||||
let llvm_pointer_vec_ty = llvm_vector_ty(bx, underlying_ty, in_len, pointer_count);
|
||||
let llvm_pointer_vec_str = llvm_vector_str(underlying_ty, in_len, pointer_count);
|
||||
let llvm_pointer_vec_str = llvm_vector_str(underlying_ty, in_len, pointer_count, bx);
|
||||
|
||||
// Type of the vector of elements:
|
||||
let llvm_elem_vec_ty = llvm_vector_ty(bx, underlying_ty, in_len, pointer_count - 1);
|
||||
let llvm_elem_vec_str = llvm_vector_str(underlying_ty, in_len, pointer_count - 1);
|
||||
let llvm_elem_vec_str = llvm_vector_str(underlying_ty, in_len, pointer_count - 1, bx);
|
||||
|
||||
let llvm_intrinsic =
|
||||
format!("llvm.masked.gather.{}.{}", llvm_elem_vec_str, llvm_pointer_vec_str);
|
||||
@ -1458,11 +1475,11 @@ fn generic_simd_intrinsic(
|
||||
|
||||
// Type of the vector of pointers:
|
||||
let llvm_pointer_vec_ty = llvm_vector_ty(bx, underlying_ty, in_len, pointer_count);
|
||||
let llvm_pointer_vec_str = llvm_vector_str(underlying_ty, in_len, pointer_count);
|
||||
let llvm_pointer_vec_str = llvm_vector_str(underlying_ty, in_len, pointer_count, bx);
|
||||
|
||||
// Type of the vector of elements:
|
||||
let llvm_elem_vec_ty = llvm_vector_ty(bx, underlying_ty, in_len, pointer_count - 1);
|
||||
let llvm_elem_vec_str = llvm_vector_str(underlying_ty, in_len, pointer_count - 1);
|
||||
let llvm_elem_vec_str = llvm_vector_str(underlying_ty, in_len, pointer_count - 1, bx);
|
||||
|
||||
let llvm_intrinsic =
|
||||
format!("llvm.masked.scatter.{}.{}", llvm_elem_vec_str, llvm_pointer_vec_str);
|
||||
|
@ -675,6 +675,9 @@ declare_features! (
|
||||
/// Allows `#[track_caller]` on closures and generators.
|
||||
(active, closure_track_caller, "1.57.0", Some(87417), None),
|
||||
|
||||
/// Allows `#[doc(cfg_hide(...))]`.
|
||||
(active, doc_cfg_hide, "1.57.0", Some(43781), None),
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// feature-group-end: actual feature gates
|
||||
// -------------------------------------------------------------------------
|
||||
|
@ -3051,6 +3051,7 @@ declare_lint_pass! {
|
||||
BREAK_WITH_LABEL_AND_LOOP,
|
||||
UNUSED_ATTRIBUTES,
|
||||
NON_EXHAUSTIVE_OMITTED_PATTERNS,
|
||||
DEREF_INTO_DYN_SUPERTRAIT,
|
||||
]
|
||||
}
|
||||
|
||||
@ -3512,3 +3513,48 @@ declare_lint! {
|
||||
Allow,
|
||||
"detect when patterns of types marked `non_exhaustive` are missed",
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
/// The `deref_into_dyn_supertrait` lint is output whenever there is a use of the
|
||||
/// `Deref` implementation with a `dyn SuperTrait` type as `Output`.
|
||||
///
|
||||
/// These implementations will become shadowed when the `trait_upcasting` feature is stablized.
|
||||
/// The `deref` functions will no longer be called implicitly, so there might be behavior change.
|
||||
///
|
||||
/// ### Example
|
||||
///
|
||||
/// ```rust,compile_fail
|
||||
/// #![deny(deref_into_dyn_supertrait)]
|
||||
/// #![allow(dead_code)]
|
||||
///
|
||||
/// use core::ops::Deref;
|
||||
///
|
||||
/// trait A {}
|
||||
/// trait B: A {}
|
||||
/// impl<'a> Deref for dyn 'a + B {
|
||||
/// type Target = dyn A;
|
||||
/// fn deref(&self) -> &Self::Target {
|
||||
/// todo!()
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// fn take_a(_: &dyn A) { }
|
||||
///
|
||||
/// fn take_b(b: &dyn B) {
|
||||
/// take_a(b);
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// {{produces}}
|
||||
///
|
||||
/// ### Explanation
|
||||
///
|
||||
/// The dyn upcasting coercion feature adds new coercion rules, taking priority
|
||||
/// over certain other coercion rules, which will cause some behavior change.
|
||||
pub DEREF_INTO_DYN_SUPERTRAIT,
|
||||
Warn,
|
||||
"`Deref` implementation usage with a supertrait trait object for output might be shadowed in the future",
|
||||
@future_incompatible = FutureIncompatibleInfo {
|
||||
reference: "issue #89460 <https://github.com/rust-lang/rust/issues/89460>",
|
||||
};
|
||||
}
|
||||
|
@ -54,7 +54,11 @@ static LLVM_THREAD_LOCAL char *LastError;
|
||||
//
|
||||
// Notably it exits the process with code 101, unlike LLVM's default of 1.
|
||||
static void FatalErrorHandler(void *UserData,
|
||||
#if LLVM_VERSION_LT(14, 0)
|
||||
const std::string& Reason,
|
||||
#else
|
||||
const char* Reason,
|
||||
#endif
|
||||
bool GenCrashDiag) {
|
||||
// Do the same thing that the default error handler does.
|
||||
std::cerr << "LLVM ERROR: " << Reason << std::endl;
|
||||
|
@ -938,6 +938,7 @@ impl CheckAttrVisitor<'tcx> {
|
||||
// plugins: removed, but rustdoc warns about it itself
|
||||
sym::alias
|
||||
| sym::cfg
|
||||
| sym::cfg_hide
|
||||
| sym::hidden
|
||||
| sym::html_favicon_url
|
||||
| sym::html_logo_url
|
||||
|
@ -399,6 +399,7 @@ symbols! {
|
||||
cfg_attr_multi,
|
||||
cfg_doctest,
|
||||
cfg_eval,
|
||||
cfg_hide,
|
||||
cfg_panic,
|
||||
cfg_sanitize,
|
||||
cfg_target_abi,
|
||||
@ -547,6 +548,7 @@ symbols! {
|
||||
doc,
|
||||
doc_alias,
|
||||
doc_cfg,
|
||||
doc_cfg_hide,
|
||||
doc_keyword,
|
||||
doc_masked,
|
||||
doc_notable_trait,
|
||||
|
@ -17,6 +17,7 @@ rustc_errors = { path = "../rustc_errors" }
|
||||
rustc_hir = { path = "../rustc_hir" }
|
||||
rustc_index = { path = "../rustc_index" }
|
||||
rustc_infer = { path = "../rustc_infer" }
|
||||
rustc_lint_defs = { path = "../rustc_lint_defs" }
|
||||
rustc_macros = { path = "../rustc_macros" }
|
||||
rustc_query_system = { path = "../rustc_query_system" }
|
||||
rustc_session = { path = "../rustc_session" }
|
||||
|
@ -6,12 +6,17 @@
|
||||
//!
|
||||
//! [rustc dev guide]:https://rustc-dev-guide.rust-lang.org/traits/resolution.html#candidate-assembly
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_infer::traits::TraitEngine;
|
||||
use rustc_infer::traits::{Obligation, SelectionError, TraitObligation};
|
||||
use rustc_lint_defs::builtin::DEREF_INTO_DYN_SUPERTRAIT;
|
||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||
use rustc_middle::ty::{self, Ty, TypeFoldable};
|
||||
use rustc_middle::ty::{self, ToPredicate, Ty, TypeFoldable, WithConstness};
|
||||
use rustc_target::spec::abi::Abi;
|
||||
|
||||
use crate::traits;
|
||||
use crate::traits::coherence::Conflict;
|
||||
use crate::traits::query::evaluate_obligation::InferCtxtExt;
|
||||
use crate::traits::{util, SelectionResult};
|
||||
use crate::traits::{Overflow, Unimplemented};
|
||||
|
||||
@ -672,6 +677,55 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
})
|
||||
}
|
||||
|
||||
/// Temporary migration for #89190
|
||||
fn need_migrate_deref_output_trait_object(
|
||||
&mut self,
|
||||
ty: Ty<'tcx>,
|
||||
cause: &traits::ObligationCause<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
) -> Option<(Ty<'tcx>, DefId)> {
|
||||
let tcx = self.tcx();
|
||||
if tcx.features().trait_upcasting {
|
||||
return None;
|
||||
}
|
||||
|
||||
// <ty as Deref>
|
||||
let trait_ref = ty::TraitRef {
|
||||
def_id: tcx.lang_items().deref_trait()?,
|
||||
substs: tcx.mk_substs_trait(ty, &[]),
|
||||
};
|
||||
|
||||
let obligation = traits::Obligation::new(
|
||||
cause.clone(),
|
||||
param_env,
|
||||
ty::Binder::dummy(trait_ref).without_const().to_predicate(tcx),
|
||||
);
|
||||
if !self.infcx.predicate_may_hold(&obligation) {
|
||||
return None;
|
||||
}
|
||||
|
||||
let mut fulfillcx = traits::FulfillmentContext::new_in_snapshot();
|
||||
let normalized_ty = fulfillcx.normalize_projection_type(
|
||||
&self.infcx,
|
||||
param_env,
|
||||
ty::ProjectionTy {
|
||||
item_def_id: tcx.lang_items().deref_target()?,
|
||||
substs: trait_ref.substs,
|
||||
},
|
||||
cause.clone(),
|
||||
);
|
||||
|
||||
let data = if let ty::Dynamic(ref data, ..) = normalized_ty.kind() {
|
||||
data
|
||||
} else {
|
||||
return None;
|
||||
};
|
||||
|
||||
let def_id = data.principal_def_id()?;
|
||||
|
||||
return Some((normalized_ty, def_id));
|
||||
}
|
||||
|
||||
/// Searches for unsizing that might apply to `obligation`.
|
||||
fn assemble_candidates_for_unsizing(
|
||||
&mut self,
|
||||
@ -732,6 +786,30 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
let principal_a = data_a.principal().unwrap();
|
||||
let target_trait_did = principal_def_id_b.unwrap();
|
||||
let source_trait_ref = principal_a.with_self_ty(self.tcx(), source);
|
||||
if let Some((deref_output_ty, deref_output_trait_did)) = self
|
||||
.need_migrate_deref_output_trait_object(
|
||||
source,
|
||||
&obligation.cause,
|
||||
obligation.param_env,
|
||||
)
|
||||
{
|
||||
if deref_output_trait_did == target_trait_did {
|
||||
self.tcx().struct_span_lint_hir(
|
||||
DEREF_INTO_DYN_SUPERTRAIT,
|
||||
obligation.cause.body_id,
|
||||
obligation.cause.span,
|
||||
|lint| {
|
||||
lint.build(&format!(
|
||||
"`{}` implements `Deref` with supertrait `{}` as output",
|
||||
source,
|
||||
deref_output_ty
|
||||
)).emit();
|
||||
},
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (idx, upcast_trait_ref) in
|
||||
util::supertraits(self.tcx(), source_trait_ref).enumerate()
|
||||
{
|
||||
|
@ -752,29 +752,31 @@ fn infer_placeholder_type<'a>(
|
||||
// us to improve in typeck so we do that now.
|
||||
match tcx.sess.diagnostic().steal_diagnostic(span, StashKey::ItemNoType) {
|
||||
Some(mut err) => {
|
||||
// The parser provided a sub-optimal `HasPlaceholders` suggestion for the type.
|
||||
// We are typeck and have the real type, so remove that and suggest the actual type.
|
||||
err.suggestions.clear();
|
||||
if !ty.references_error() {
|
||||
// The parser provided a sub-optimal `HasPlaceholders` suggestion for the type.
|
||||
// We are typeck and have the real type, so remove that and suggest the actual type.
|
||||
err.suggestions.clear();
|
||||
|
||||
// Suggesting unnameable types won't help.
|
||||
let mut mk_nameable = MakeNameable::new(tcx);
|
||||
let ty = mk_nameable.fold_ty(ty);
|
||||
let sugg_ty = if mk_nameable.success { Some(ty) } else { None };
|
||||
if let Some(sugg_ty) = sugg_ty {
|
||||
err.span_suggestion(
|
||||
span,
|
||||
&format!("provide a type for the {item}", item = kind),
|
||||
format!("{}: {}", item_ident, sugg_ty),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
} else {
|
||||
err.span_note(
|
||||
tcx.hir().body(body_id).value.span,
|
||||
&format!("however, the inferred type `{}` cannot be named", ty.to_string()),
|
||||
);
|
||||
// Suggesting unnameable types won't help.
|
||||
let mut mk_nameable = MakeNameable::new(tcx);
|
||||
let ty = mk_nameable.fold_ty(ty);
|
||||
let sugg_ty = if mk_nameable.success { Some(ty) } else { None };
|
||||
if let Some(sugg_ty) = sugg_ty {
|
||||
err.span_suggestion(
|
||||
span,
|
||||
&format!("provide a type for the {item}", item = kind),
|
||||
format!("{}: {}", item_ident, sugg_ty),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
} else {
|
||||
err.span_note(
|
||||
tcx.hir().body(body_id).value.span,
|
||||
&format!("however, the inferred type `{}` cannot be named", ty.to_string()),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
err.emit_unless(ty.references_error());
|
||||
err.emit();
|
||||
}
|
||||
None => {
|
||||
let mut diag = bad_placeholder_type(tcx, vec![span], kind);
|
||||
|
@ -67,6 +67,10 @@
|
||||
issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/",
|
||||
test(no_crate_inject, attr(allow(unused_variables), deny(warnings)))
|
||||
)]
|
||||
#![cfg_attr(
|
||||
not(bootstrap),
|
||||
doc(cfg_hide(not(test), not(any(test, bootstrap)), target_has_atomic = "ptr"))
|
||||
)]
|
||||
#![no_std]
|
||||
#![needs_allocator]
|
||||
#![warn(deprecated_in_future)]
|
||||
@ -146,6 +150,8 @@
|
||||
#![feature(associated_type_bounds)]
|
||||
#![feature(slice_group_by)]
|
||||
#![feature(decl_macro)]
|
||||
#![feature(doc_cfg)]
|
||||
#![cfg_attr(not(bootstrap), feature(doc_cfg_hide))]
|
||||
// Allow testing this library
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -60,6 +60,30 @@
|
||||
test(no_crate_inject, attr(deny(warnings))),
|
||||
test(attr(allow(dead_code, deprecated, unused_variables, unused_mut)))
|
||||
)]
|
||||
#![cfg_attr(
|
||||
not(bootstrap),
|
||||
doc(cfg_hide(
|
||||
not(test),
|
||||
target_pointer_width = "16",
|
||||
target_pointer_width = "32",
|
||||
target_pointer_width = "64",
|
||||
target_has_atomic = "8",
|
||||
target_has_atomic = "16",
|
||||
target_has_atomic = "32",
|
||||
target_has_atomic = "64",
|
||||
target_has_atomic = "ptr",
|
||||
target_has_atomic_equal_alignment = "8",
|
||||
target_has_atomic_equal_alignment = "16",
|
||||
target_has_atomic_equal_alignment = "32",
|
||||
target_has_atomic_equal_alignment = "64",
|
||||
target_has_atomic_equal_alignment = "ptr",
|
||||
target_has_atomic_load_store = "8",
|
||||
target_has_atomic_load_store = "16",
|
||||
target_has_atomic_load_store = "32",
|
||||
target_has_atomic_load_store = "64",
|
||||
target_has_atomic_load_store = "ptr",
|
||||
))
|
||||
)]
|
||||
#![no_core]
|
||||
//
|
||||
// Lints:
|
||||
@ -133,6 +157,7 @@
|
||||
#![feature(doc_notable_trait)]
|
||||
#![feature(doc_primitive)]
|
||||
#![feature(exhaustive_patterns)]
|
||||
#![cfg_attr(not(bootstrap), feature(doc_cfg_hide))]
|
||||
#![feature(extern_types)]
|
||||
#![feature(fundamental)]
|
||||
#![feature(if_let_guard)]
|
||||
|
@ -195,6 +195,7 @@
|
||||
test(no_crate_inject, attr(deny(warnings))),
|
||||
test(attr(allow(dead_code, deprecated, unused_variables, unused_mut)))
|
||||
)]
|
||||
#![cfg_attr(not(bootstrap), doc(cfg_hide(not(test), not(any(test, bootstrap)))))]
|
||||
// Don't link to std. We are std.
|
||||
#![no_std]
|
||||
#![warn(deprecated_in_future)]
|
||||
@ -263,6 +264,7 @@
|
||||
#![feature(custom_test_frameworks)]
|
||||
#![feature(decl_macro)]
|
||||
#![feature(doc_cfg)]
|
||||
#![cfg_attr(not(bootstrap), feature(doc_cfg_hide))]
|
||||
#![feature(doc_keyword)]
|
||||
#![feature(doc_masked)]
|
||||
#![feature(doc_notable_trait)]
|
||||
|
@ -46,6 +46,7 @@ macro_rules! type_alias {
|
||||
}
|
||||
|
||||
type_alias! { "char.md", c_char = u8, NonZero_c_char = NonZeroU8;
|
||||
#[doc(cfg(all()))]
|
||||
#[cfg(any(
|
||||
all(
|
||||
target_os = "linux",
|
||||
@ -88,6 +89,7 @@ type_alias! { "char.md", c_char = u8, NonZero_c_char = NonZeroU8;
|
||||
all(target_os = "fuchsia", target_arch = "aarch64")
|
||||
))]}
|
||||
type_alias! { "char.md", c_char = i8, NonZero_c_char = NonZeroI8;
|
||||
#[doc(cfg(all()))]
|
||||
#[cfg(not(any(
|
||||
all(
|
||||
target_os = "linux",
|
||||
@ -136,12 +138,16 @@ type_alias! { "ushort.md", c_ushort = u16, NonZero_c_ushort = NonZeroU16; }
|
||||
type_alias! { "int.md", c_int = i32, NonZero_c_int = NonZeroI32; }
|
||||
type_alias! { "uint.md", c_uint = u32, NonZero_c_uint = NonZeroU32; }
|
||||
type_alias! { "long.md", c_long = i32, NonZero_c_long = NonZeroI32;
|
||||
#[doc(cfg(all()))]
|
||||
#[cfg(any(target_pointer_width = "32", windows))] }
|
||||
type_alias! { "ulong.md", c_ulong = u32, NonZero_c_ulong = NonZeroU32;
|
||||
#[doc(cfg(all()))]
|
||||
#[cfg(any(target_pointer_width = "32", windows))] }
|
||||
type_alias! { "long.md", c_long = i64, NonZero_c_long = NonZeroI64;
|
||||
#[doc(cfg(all()))]
|
||||
#[cfg(all(target_pointer_width = "64", not(windows)))] }
|
||||
type_alias! { "ulong.md", c_ulong = u64, NonZero_c_ulong = NonZeroU64;
|
||||
#[doc(cfg(all()))]
|
||||
#[cfg(all(target_pointer_width = "64", not(windows)))] }
|
||||
type_alias! { "longlong.md", c_longlong = i64, NonZero_c_longlong = NonZeroI64; }
|
||||
type_alias! { "ulonglong.md", c_ulonglong = u64, NonZero_c_ulonglong = NonZeroU64; }
|
||||
|
@ -7,8 +7,10 @@ use crate::os::raw::c_void;
|
||||
#[stable(feature = "raw_ext", since = "1.1.0")]
|
||||
pub type HANDLE = *mut c_void;
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
#[doc(cfg(all()))]
|
||||
#[stable(feature = "raw_ext", since = "1.1.0")]
|
||||
pub type SOCKET = u32;
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
#[doc(cfg(all()))]
|
||||
#[stable(feature = "raw_ext", since = "1.1.0")]
|
||||
pub type SOCKET = u64;
|
||||
|
@ -318,10 +318,10 @@ fn merge_attrs(
|
||||
} else {
|
||||
Attributes::from_ast(&both, None)
|
||||
},
|
||||
both.cfg(cx.sess()),
|
||||
both.cfg(cx.tcx, &cx.cache.hidden_cfg),
|
||||
)
|
||||
} else {
|
||||
(old_attrs.clean(cx), old_attrs.cfg(cx.sess()))
|
||||
(old_attrs.clean(cx), old_attrs.cfg(cx.tcx, &cx.cache.hidden_cfg))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1973,7 +1973,7 @@ fn clean_extern_crate(
|
||||
def_id: crate_def_id.into(),
|
||||
visibility: krate.vis.clean(cx),
|
||||
kind: box ExternCrateItem { src: orig_name },
|
||||
cfg: attrs.cfg(cx.sess()),
|
||||
cfg: attrs.cfg(cx.tcx, &cx.cache.hidden_cfg),
|
||||
}]
|
||||
}
|
||||
|
||||
|
@ -421,7 +421,7 @@ impl Item {
|
||||
kind,
|
||||
box ast_attrs.clean(cx),
|
||||
cx,
|
||||
ast_attrs.cfg(cx.sess()),
|
||||
ast_attrs.cfg(cx.tcx, &cx.cache.hidden_cfg),
|
||||
)
|
||||
}
|
||||
|
||||
@ -747,7 +747,7 @@ crate trait AttributesExt {
|
||||
|
||||
fn other_attrs(&self) -> Vec<ast::Attribute>;
|
||||
|
||||
fn cfg(&self, sess: &Session) -> Option<Arc<Cfg>>;
|
||||
fn cfg(&self, tcx: TyCtxt<'_>, hidden_cfg: &FxHashSet<Cfg>) -> Option<Arc<Cfg>>;
|
||||
}
|
||||
|
||||
impl AttributesExt for [ast::Attribute] {
|
||||
@ -772,8 +772,41 @@ impl AttributesExt for [ast::Attribute] {
|
||||
self.iter().filter(|attr| attr.doc_str().is_none()).cloned().collect()
|
||||
}
|
||||
|
||||
fn cfg(&self, sess: &Session) -> Option<Arc<Cfg>> {
|
||||
let mut cfg = Cfg::True;
|
||||
fn cfg(&self, tcx: TyCtxt<'_>, hidden_cfg: &FxHashSet<Cfg>) -> Option<Arc<Cfg>> {
|
||||
let sess = tcx.sess;
|
||||
let doc_cfg_active = tcx.features().doc_cfg;
|
||||
|
||||
fn single<T: IntoIterator>(it: T) -> Option<T::Item> {
|
||||
let mut iter = it.into_iter();
|
||||
let item = iter.next()?;
|
||||
if iter.next().is_some() {
|
||||
return None;
|
||||
}
|
||||
Some(item)
|
||||
}
|
||||
|
||||
let mut cfg = if doc_cfg_active {
|
||||
let mut doc_cfg = self
|
||||
.iter()
|
||||
.filter(|attr| attr.has_name(sym::doc))
|
||||
.flat_map(|attr| attr.meta_item_list().unwrap_or_else(Vec::new))
|
||||
.filter(|attr| attr.has_name(sym::cfg))
|
||||
.peekable();
|
||||
if doc_cfg.peek().is_some() {
|
||||
doc_cfg
|
||||
.filter_map(|attr| Cfg::parse(attr.meta_item()?).ok())
|
||||
.fold(Cfg::True, |cfg, new_cfg| cfg & new_cfg)
|
||||
} else {
|
||||
self.iter()
|
||||
.filter(|attr| attr.has_name(sym::cfg))
|
||||
.filter_map(|attr| single(attr.meta_item_list()?))
|
||||
.filter_map(|attr| Cfg::parse(attr.meta_item()?).ok())
|
||||
.filter(|cfg| !hidden_cfg.contains(cfg))
|
||||
.fold(Cfg::True, |cfg, new_cfg| cfg & new_cfg)
|
||||
}
|
||||
} else {
|
||||
Cfg::True
|
||||
};
|
||||
|
||||
for attr in self.iter() {
|
||||
// #[doc]
|
||||
@ -800,6 +833,8 @@ impl AttributesExt for [ast::Attribute] {
|
||||
}
|
||||
}
|
||||
|
||||
// treat #[target_feature(enable = "feat")] attributes as if they were
|
||||
// #[doc(cfg(target_feature = "feat"))] attributes as well
|
||||
for attr in self.lists(sym::target_feature) {
|
||||
if attr.has_name(sym::enable) {
|
||||
if let Some(feat) = attr.value_str() {
|
||||
|
@ -1123,7 +1123,7 @@ impl<'a, 'hir, 'tcx> HirCollector<'a, 'hir, 'tcx> {
|
||||
let ast_attrs = self.tcx.hir().attrs(hir_id);
|
||||
let mut attrs = Attributes::from_ast(ast_attrs, None);
|
||||
|
||||
if let Some(ref cfg) = ast_attrs.cfg(self.sess) {
|
||||
if let Some(ref cfg) = ast_attrs.cfg(self.tcx, &FxHashSet::default()) {
|
||||
if !cfg.matches(&self.sess.parse_sess, Some(&self.sess.features_untracked())) {
|
||||
return;
|
||||
}
|
||||
|
@ -119,6 +119,8 @@ crate struct Cache {
|
||||
///
|
||||
/// Links are indexed by the DefId of the item they document.
|
||||
crate intra_doc_links: FxHashMap<ItemId, Vec<clean::ItemLink>>,
|
||||
/// Cfg that have been hidden via #![doc(cfg_hide(...))]
|
||||
crate hidden_cfg: FxHashSet<clean::cfg::Cfg>,
|
||||
}
|
||||
|
||||
/// This struct is used to wrap the `cache` and `tcx` in order to run `DocFolder`.
|
||||
|
@ -323,7 +323,7 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl
|
||||
let import_item = clean::Item {
|
||||
def_id: import_def_id.into(),
|
||||
attrs: import_attrs,
|
||||
cfg: ast_attrs.cfg(cx.sess()),
|
||||
cfg: ast_attrs.cfg(cx.tcx(), &cx.cache().hidden_cfg),
|
||||
..myitem.clone()
|
||||
};
|
||||
|
||||
|
@ -6,6 +6,7 @@ use rustc_hir as hir;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::Node;
|
||||
use rustc_hir::CRATE_HIR_ID;
|
||||
use rustc_middle::middle::privacy::AccessLevel;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_span;
|
||||
@ -15,7 +16,7 @@ use rustc_span::symbol::{kw, sym, Symbol};
|
||||
|
||||
use std::mem;
|
||||
|
||||
use crate::clean::{self, AttributesExt, NestedAttributesExt};
|
||||
use crate::clean::{self, cfg::Cfg, AttributesExt, NestedAttributesExt};
|
||||
use crate::core;
|
||||
use crate::doctree::*;
|
||||
|
||||
@ -97,6 +98,31 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.cx.cache.hidden_cfg = self
|
||||
.cx
|
||||
.tcx
|
||||
.hir()
|
||||
.attrs(CRATE_HIR_ID)
|
||||
.iter()
|
||||
.filter(|attr| attr.has_name(sym::doc))
|
||||
.flat_map(|attr| attr.meta_item_list().into_iter().flatten())
|
||||
.filter(|attr| attr.has_name(sym::cfg_hide))
|
||||
.flat_map(|attr| {
|
||||
attr.meta_item_list()
|
||||
.unwrap_or(&[])
|
||||
.iter()
|
||||
.filter_map(|attr| {
|
||||
Some(
|
||||
Cfg::parse(attr.meta_item()?)
|
||||
.map_err(|e| self.cx.sess().diagnostic().span_err(e.span, e.msg))
|
||||
.ok()?,
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
})
|
||||
.collect();
|
||||
|
||||
self.cx.cache.exact_paths = self.exact_paths;
|
||||
top_level_module
|
||||
}
|
||||
|
9
src/test/rustdoc-ui/doc-cfg.rs
Normal file
9
src/test/rustdoc-ui/doc-cfg.rs
Normal file
@ -0,0 +1,9 @@
|
||||
#![feature(doc_cfg)]
|
||||
|
||||
#[doc(cfg(), cfg(foo, bar))]
|
||||
//~^ ERROR
|
||||
//~^^ ERROR
|
||||
#[doc(cfg(foo), cfg(bar))] // ok!
|
||||
#[doc(cfg())] //~ ERROR
|
||||
#[doc(cfg(foo, bar))] //~ ERROR
|
||||
pub fn foo() {}
|
26
src/test/rustdoc-ui/doc-cfg.stderr
Normal file
26
src/test/rustdoc-ui/doc-cfg.stderr
Normal file
@ -0,0 +1,26 @@
|
||||
error: `cfg` predicate is not specified
|
||||
--> $DIR/doc-cfg.rs:3:7
|
||||
|
|
||||
LL | #[doc(cfg(), cfg(foo, bar))]
|
||||
| ^^^^^
|
||||
|
||||
error: multiple `cfg` predicates are specified
|
||||
--> $DIR/doc-cfg.rs:3:23
|
||||
|
|
||||
LL | #[doc(cfg(), cfg(foo, bar))]
|
||||
| ^^^
|
||||
|
||||
error: `cfg` predicate is not specified
|
||||
--> $DIR/doc-cfg.rs:7:7
|
||||
|
|
||||
LL | #[doc(cfg())]
|
||||
| ^^^^^
|
||||
|
||||
error: multiple `cfg` predicates are specified
|
||||
--> $DIR/doc-cfg.rs:8:16
|
||||
|
|
||||
LL | #[doc(cfg(foo, bar))]
|
||||
| ^^^
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
7
src/test/rustdoc-ui/feature-gate-doc_cfg_hide.rs
Normal file
7
src/test/rustdoc-ui/feature-gate-doc_cfg_hide.rs
Normal file
@ -0,0 +1,7 @@
|
||||
#![doc(cfg_hide(test))]
|
||||
//~^ ERROR `#[doc(cfg_hide)]` is experimental
|
||||
|
||||
#[cfg(not(test))]
|
||||
pub fn public_fn() {}
|
||||
#[cfg(test)]
|
||||
pub fn internal_use_only() {}
|
14
src/test/rustdoc-ui/feature-gate-doc_cfg_hide.stderr
Normal file
14
src/test/rustdoc-ui/feature-gate-doc_cfg_hide.stderr
Normal file
@ -0,0 +1,14 @@
|
||||
error[E0658]: `#[doc(cfg_hide)]` is experimental
|
||||
--> $DIR/feature-gate-doc_cfg_hide.rs:1:1
|
||||
|
|
||||
LL | #![doc(cfg_hide(test))]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #43781 <https://github.com/rust-lang/rust/issues/43781> for more information
|
||||
= help: add `#![feature(doc_cfg_hide)]` to the crate attributes to enable
|
||||
|
||||
error: Compilation failed, aborting rustdoc
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
32
src/test/rustdoc/doc-cfg-hide.rs
Normal file
32
src/test/rustdoc/doc-cfg-hide.rs
Normal file
@ -0,0 +1,32 @@
|
||||
#![crate_name = "oud"]
|
||||
#![feature(doc_cfg, doc_cfg_hide)]
|
||||
|
||||
#![doc(cfg_hide(feature = "solecism"))]
|
||||
|
||||
// @has 'oud/struct.Solecism.html'
|
||||
// @count - '//*[@class="stab portability"]' 0
|
||||
// compile-flags:--cfg feature="solecism"
|
||||
#[cfg(feature = "solecism")]
|
||||
pub struct Solecism;
|
||||
|
||||
// @has 'oud/struct.Scribacious.html'
|
||||
// @count - '//*[@class="stab portability"]' 1
|
||||
// @matches - '//*[@class="stab portability"]' 'crate feature solecism'
|
||||
#[cfg(feature = "solecism")]
|
||||
#[doc(cfg(feature = "solecism"))]
|
||||
pub struct Scribacious;
|
||||
|
||||
// @has 'oud/struct.Hyperdulia.html'
|
||||
// @count - '//*[@class="stab portability"]' 1
|
||||
// @matches - '//*[@class="stab portability"]' 'crate feature hyperdulia'
|
||||
// compile-flags:--cfg feature="hyperdulia"
|
||||
#[cfg(feature = "solecism")]
|
||||
#[cfg(feature = "hyperdulia")]
|
||||
pub struct Hyperdulia;
|
||||
|
||||
// @has 'oud/struct.Oystercatcher.html'
|
||||
// @count - '//*[@class="stab portability"]' 1
|
||||
// @matches - '//*[@class="stab portability"]' 'crate features solecism and oystercatcher'
|
||||
// compile-flags:--cfg feature="oystercatcher"
|
||||
#[cfg(all(feature = "solecism", feature = "oystercatcher"))]
|
||||
pub struct Oystercatcher;
|
7
src/test/rustdoc/doc-cfg-implicit-gate.rs
Normal file
7
src/test/rustdoc/doc-cfg-implicit-gate.rs
Normal file
@ -0,0 +1,7 @@
|
||||
// compile-flags:--cfg feature="worricow"
|
||||
#![crate_name = "xenogenous"]
|
||||
|
||||
// @has 'xenogenous/struct.Worricow.html'
|
||||
// @count - '//*[@class="stab portability"]' 0
|
||||
#[cfg(feature = "worricow")]
|
||||
pub struct Worricow;
|
31
src/test/rustdoc/doc-cfg-implicit.rs
Normal file
31
src/test/rustdoc/doc-cfg-implicit.rs
Normal file
@ -0,0 +1,31 @@
|
||||
#![crate_name = "funambulism"]
|
||||
#![feature(doc_cfg)]
|
||||
|
||||
// @has 'funambulism/struct.Disorbed.html'
|
||||
// @count - '//*[@class="stab portability"]' 1
|
||||
// @matches - '//*[@class="stab portability"]' 'crate feature disorbed'
|
||||
// compile-flags:--cfg feature="disorbed"
|
||||
#[cfg(feature = "disorbed")]
|
||||
pub struct Disorbed;
|
||||
|
||||
// @has 'funambulism/struct.Aesthesia.html'
|
||||
// @count - '//*[@class="stab portability"]' 1
|
||||
// @matches - '//*[@class="stab portability"]' 'crate feature aesthesia'
|
||||
// compile-flags:--cfg feature="aesthesia"
|
||||
#[doc(cfg(feature = "aesthesia"))]
|
||||
pub struct Aesthesia;
|
||||
|
||||
// @has 'funambulism/struct.Pliothermic.html'
|
||||
// @count - '//*[@class="stab portability"]' 1
|
||||
// @matches - '//*[@class="stab portability"]' 'crate feature pliothermic'
|
||||
// compile-flags:--cfg feature="epopoeist"
|
||||
#[cfg(feature = "epopoeist")]
|
||||
#[doc(cfg(feature = "pliothermic"))]
|
||||
pub struct Pliothermic;
|
||||
|
||||
// @has 'funambulism/struct.Simillimum.html'
|
||||
// @count - '//*[@class="stab portability"]' 0
|
||||
// compile-flags:--cfg feature="simillimum"
|
||||
#[cfg(feature = "simillimum")]
|
||||
#[doc(cfg(all()))]
|
||||
pub struct Simillimum;
|
4
src/test/ui/parser/issue-89574.rs
Normal file
4
src/test/ui/parser/issue-89574.rs
Normal file
@ -0,0 +1,4 @@
|
||||
fn main() {
|
||||
const EMPTY_ARRAY = [];
|
||||
//~^ missing type for `const` item
|
||||
}
|
8
src/test/ui/parser/issue-89574.stderr
Normal file
8
src/test/ui/parser/issue-89574.stderr
Normal file
@ -0,0 +1,8 @@
|
||||
error: missing type for `const` item
|
||||
--> $DIR/issue-89574.rs:2:11
|
||||
|
|
||||
LL | const EMPTY_ARRAY = [];
|
||||
| ^^^^^^^^^^^ help: provide a type for the item: `EMPTY_ARRAY: <type>`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -4,3 +4,4 @@ fn main() {}
|
||||
|
||||
const A: u8; //~ ERROR free constant item without body
|
||||
const B; //~ ERROR free constant item without body
|
||||
//~^ ERROR missing type for `const` item
|
||||
|
@ -14,5 +14,11 @@ LL | const B;
|
||||
| |
|
||||
| help: provide a definition for the constant: `= <expr>;`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: missing type for `const` item
|
||||
--> $DIR/item-free-const-no-body-semantic-fail.rs:6:7
|
||||
|
|
||||
LL | const B;
|
||||
| ^ help: provide a type for the item: `B: <type>`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
@ -4,6 +4,8 @@ fn main() {}
|
||||
|
||||
static A: u8; //~ ERROR free static item without body
|
||||
static B; //~ ERROR free static item without body
|
||||
//~^ ERROR missing type for `static` item
|
||||
|
||||
static mut C: u8; //~ ERROR free static item without body
|
||||
static mut D; //~ ERROR free static item without body
|
||||
//~^ ERROR missing type for `static mut` item
|
||||
|
@ -15,7 +15,7 @@ LL | static B;
|
||||
| help: provide a definition for the static: `= <expr>;`
|
||||
|
||||
error: free static item without body
|
||||
--> $DIR/item-free-static-no-body-semantic-fail.rs:8:1
|
||||
--> $DIR/item-free-static-no-body-semantic-fail.rs:9:1
|
||||
|
|
||||
LL | static mut C: u8;
|
||||
| ^^^^^^^^^^^^^^^^-
|
||||
@ -23,12 +23,24 @@ LL | static mut C: u8;
|
||||
| help: provide a definition for the static: `= <expr>;`
|
||||
|
||||
error: free static item without body
|
||||
--> $DIR/item-free-static-no-body-semantic-fail.rs:9:1
|
||||
--> $DIR/item-free-static-no-body-semantic-fail.rs:10:1
|
||||
|
|
||||
LL | static mut D;
|
||||
| ^^^^^^^^^^^^-
|
||||
| |
|
||||
| help: provide a definition for the static: `= <expr>;`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
error: missing type for `static` item
|
||||
--> $DIR/item-free-static-no-body-semantic-fail.rs:6:8
|
||||
|
|
||||
LL | static B;
|
||||
| ^ help: provide a type for the item: `B: <type>`
|
||||
|
||||
error: missing type for `static mut` item
|
||||
--> $DIR/item-free-static-no-body-semantic-fail.rs:10:12
|
||||
|
|
||||
LL | static mut D;
|
||||
| ^ help: provide a type for the item: `D: <type>`
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
|
51
src/test/ui/simd/issue-89193.rs
Normal file
51
src/test/ui/simd/issue-89193.rs
Normal file
@ -0,0 +1,51 @@
|
||||
// run-pass
|
||||
|
||||
// Test that simd gather instructions on slice of usize don't cause crash
|
||||
// See issue #89183 - https://github.com/rust-lang/rust/issues/89193
|
||||
|
||||
#![feature(repr_simd, platform_intrinsics)]
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
#[repr(simd)]
|
||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
||||
struct x4<T>(pub T, pub T, pub T, pub T);
|
||||
|
||||
extern "platform-intrinsic" {
|
||||
fn simd_gather<T, U, V>(x: T, y: U, z: V) -> T;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let x: [usize; 4] = [10, 11, 12, 13];
|
||||
let default = x4(0_usize, 1, 2, 3);
|
||||
let mask = x4(1_i32, 1, 1, 1);
|
||||
let expected = x4(10_usize, 11, 12, 13);
|
||||
|
||||
unsafe {
|
||||
let pointer = &x[0] as *const usize;
|
||||
let pointers = x4(
|
||||
pointer.offset(0) as *const usize,
|
||||
pointer.offset(1),
|
||||
pointer.offset(2),
|
||||
pointer.offset(3)
|
||||
);
|
||||
let result = simd_gather(default, pointers, mask);
|
||||
assert_eq!(result, expected);
|
||||
}
|
||||
|
||||
// and again for isize
|
||||
let x: [isize; 4] = [10, 11, 12, 13];
|
||||
let default = x4(0_isize, 1, 2, 3);
|
||||
let expected = x4(10_isize, 11, 12, 13);
|
||||
|
||||
unsafe {
|
||||
let pointer = &x[0] as *const isize;
|
||||
let pointers = x4(
|
||||
pointer.offset(0) as *const isize,
|
||||
pointer.offset(1),
|
||||
pointer.offset(2),
|
||||
pointer.offset(3)
|
||||
);
|
||||
let result = simd_gather(default, pointers, mask);
|
||||
assert_eq!(result, expected);
|
||||
}
|
||||
}
|
25
src/test/ui/traits/trait-upcasting/migrate-lint-deny.rs
Normal file
25
src/test/ui/traits/trait-upcasting/migrate-lint-deny.rs
Normal file
@ -0,0 +1,25 @@
|
||||
#![deny(deref_into_dyn_supertrait)]
|
||||
|
||||
extern crate core;
|
||||
|
||||
use core::ops::Deref;
|
||||
|
||||
// issue 89190
|
||||
trait A {}
|
||||
trait B: A {}
|
||||
impl<'a> Deref for dyn 'a + B {
|
||||
type Target = dyn A;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
fn take_a(_: &dyn A) {}
|
||||
|
||||
fn whoops(b: &dyn B) {
|
||||
take_a(b)
|
||||
//~^ ERROR `dyn B` implements `Deref` with supertrait `(dyn A + 'static)` as output
|
||||
//~^^ WARN this was previously accepted by the compiler but is being phased out;
|
||||
}
|
||||
|
||||
fn main() {}
|
16
src/test/ui/traits/trait-upcasting/migrate-lint-deny.stderr
Normal file
16
src/test/ui/traits/trait-upcasting/migrate-lint-deny.stderr
Normal file
@ -0,0 +1,16 @@
|
||||
error: `dyn B` implements `Deref` with supertrait `(dyn A + 'static)` as output
|
||||
--> $DIR/migrate-lint-deny.rs:20:12
|
||||
|
|
||||
LL | take_a(b)
|
||||
| ^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/migrate-lint-deny.rs:1:9
|
||||
|
|
||||
LL | #![deny(deref_into_dyn_supertrait)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= 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 #89460 <https://github.com/rust-lang/rust/issues/89460>
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -1,5 +1,5 @@
|
||||
fn main() {
|
||||
const FOO = "hello" + 1; //~ ERROR cannot add `{integer}` to `&str`
|
||||
//~^ ERROR cannot add `{integer}` to `&str`
|
||||
//~^ missing type for `const` item
|
||||
println!("{}", FOO);
|
||||
}
|
||||
|
@ -6,13 +6,11 @@ LL | const FOO = "hello" + 1;
|
||||
| |
|
||||
| &str
|
||||
|
||||
error[E0369]: cannot add `{integer}` to `&str`
|
||||
--> $DIR/issue-79040.rs:2:25
|
||||
error: missing type for `const` item
|
||||
--> $DIR/issue-79040.rs:2:11
|
||||
|
|
||||
LL | const FOO = "hello" + 1;
|
||||
| ------- ^ - {integer}
|
||||
| |
|
||||
| &str
|
||||
| ^^^ help: provide a type for the item: `FOO: <type>`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
157
src/tools/compiletest/src/compute_diff.rs
Normal file
157
src/tools/compiletest/src/compute_diff.rs
Normal file
@ -0,0 +1,157 @@
|
||||
use std::collections::VecDeque;
|
||||
use std::fs::{File, FileType};
|
||||
use std::path::Path;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum DiffLine {
|
||||
Context(String),
|
||||
Expected(String),
|
||||
Resulting(String),
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct Mismatch {
|
||||
pub line_number: u32,
|
||||
pub lines: Vec<DiffLine>,
|
||||
}
|
||||
|
||||
impl Mismatch {
|
||||
fn new(line_number: u32) -> Mismatch {
|
||||
Mismatch { line_number, lines: Vec::new() }
|
||||
}
|
||||
}
|
||||
|
||||
// Produces a diff between the expected output and actual output.
|
||||
pub fn make_diff(expected: &str, actual: &str, context_size: usize) -> Vec<Mismatch> {
|
||||
let mut line_number = 1;
|
||||
let mut context_queue: VecDeque<&str> = VecDeque::with_capacity(context_size);
|
||||
let mut lines_since_mismatch = context_size + 1;
|
||||
let mut results = Vec::new();
|
||||
let mut mismatch = Mismatch::new(0);
|
||||
|
||||
for result in diff::lines(expected, actual) {
|
||||
match result {
|
||||
diff::Result::Left(str) => {
|
||||
if lines_since_mismatch >= context_size && lines_since_mismatch > 0 {
|
||||
results.push(mismatch);
|
||||
mismatch = Mismatch::new(line_number - context_queue.len() as u32);
|
||||
}
|
||||
|
||||
while let Some(line) = context_queue.pop_front() {
|
||||
mismatch.lines.push(DiffLine::Context(line.to_owned()));
|
||||
}
|
||||
|
||||
mismatch.lines.push(DiffLine::Expected(str.to_owned()));
|
||||
line_number += 1;
|
||||
lines_since_mismatch = 0;
|
||||
}
|
||||
diff::Result::Right(str) => {
|
||||
if lines_since_mismatch >= context_size && lines_since_mismatch > 0 {
|
||||
results.push(mismatch);
|
||||
mismatch = Mismatch::new(line_number - context_queue.len() as u32);
|
||||
}
|
||||
|
||||
while let Some(line) = context_queue.pop_front() {
|
||||
mismatch.lines.push(DiffLine::Context(line.to_owned()));
|
||||
}
|
||||
|
||||
mismatch.lines.push(DiffLine::Resulting(str.to_owned()));
|
||||
lines_since_mismatch = 0;
|
||||
}
|
||||
diff::Result::Both(str, _) => {
|
||||
if context_queue.len() >= context_size {
|
||||
let _ = context_queue.pop_front();
|
||||
}
|
||||
|
||||
if lines_since_mismatch < context_size {
|
||||
mismatch.lines.push(DiffLine::Context(str.to_owned()));
|
||||
} else if context_size > 0 {
|
||||
context_queue.push_back(str);
|
||||
}
|
||||
|
||||
line_number += 1;
|
||||
lines_since_mismatch += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
results.push(mismatch);
|
||||
results.remove(0);
|
||||
|
||||
results
|
||||
}
|
||||
|
||||
pub(crate) fn write_diff(expected: &str, actual: &str, context_size: usize) -> String {
|
||||
use std::fmt::Write;
|
||||
let mut output = String::new();
|
||||
let diff_results = make_diff(expected, actual, context_size);
|
||||
for result in diff_results {
|
||||
let mut line_number = result.line_number;
|
||||
for line in result.lines {
|
||||
match line {
|
||||
DiffLine::Expected(e) => {
|
||||
writeln!(output, "-\t{}", e).unwrap();
|
||||
line_number += 1;
|
||||
}
|
||||
DiffLine::Context(c) => {
|
||||
writeln!(output, "{}\t{}", line_number, c).unwrap();
|
||||
line_number += 1;
|
||||
}
|
||||
DiffLine::Resulting(r) => {
|
||||
writeln!(output, "+\t{}", r).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
writeln!(output).unwrap();
|
||||
}
|
||||
output
|
||||
}
|
||||
|
||||
/// Filters based on filetype and extension whether to diff a file.
|
||||
///
|
||||
/// Returns whether any data was actually written.
|
||||
pub(crate) fn write_filtered_diff<Filter>(
|
||||
diff_filename: &str,
|
||||
out_dir: &Path,
|
||||
compare_dir: &Path,
|
||||
verbose: bool,
|
||||
filter: Filter,
|
||||
) -> bool
|
||||
where
|
||||
Filter: Fn(FileType, Option<&str>) -> bool,
|
||||
{
|
||||
use std::io::{Read, Write};
|
||||
let mut diff_output = File::create(diff_filename).unwrap();
|
||||
let mut wrote_data = false;
|
||||
for entry in walkdir::WalkDir::new(out_dir) {
|
||||
let entry = entry.expect("failed to read file");
|
||||
let extension = entry.path().extension().and_then(|p| p.to_str());
|
||||
if filter(entry.file_type(), extension) {
|
||||
let expected_path = compare_dir.join(entry.path().strip_prefix(&out_dir).unwrap());
|
||||
let expected = if let Ok(s) = std::fs::read(&expected_path) { s } else { continue };
|
||||
let actual_path = entry.path();
|
||||
let actual = std::fs::read(&actual_path).unwrap();
|
||||
let diff = unified_diff::diff(
|
||||
&expected,
|
||||
&expected_path.to_string_lossy(),
|
||||
&actual,
|
||||
&actual_path.to_string_lossy(),
|
||||
3,
|
||||
);
|
||||
wrote_data |= !diff.is_empty();
|
||||
diff_output.write_all(&diff).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
if !wrote_data {
|
||||
println!("note: diff is identical to nightly rustdoc");
|
||||
assert!(diff_output.metadata().unwrap().len() == 0);
|
||||
return false;
|
||||
} else if verbose {
|
||||
eprintln!("printing diff:");
|
||||
let mut buf = Vec::new();
|
||||
diff_output.read_to_end(&mut buf).unwrap();
|
||||
std::io::stderr().lock().write_all(&mut buf).unwrap();
|
||||
}
|
||||
true
|
||||
}
|
@ -28,6 +28,7 @@ use self::header::{make_test_description, EarlyProps};
|
||||
mod tests;
|
||||
|
||||
pub mod common;
|
||||
pub mod compute_diff;
|
||||
pub mod errors;
|
||||
pub mod header;
|
||||
mod json;
|
||||
|
@ -8,6 +8,7 @@ use crate::common::{CompareMode, FailMode, PassMode};
|
||||
use crate::common::{Config, TestPaths};
|
||||
use crate::common::{Pretty, RunPassValgrind};
|
||||
use crate::common::{UI_RUN_STDERR, UI_RUN_STDOUT};
|
||||
use crate::compute_diff::{write_diff, write_filtered_diff};
|
||||
use crate::errors::{self, Error, ErrorKind};
|
||||
use crate::header::TestProps;
|
||||
use crate::json;
|
||||
@ -18,7 +19,7 @@ use regex::{Captures, Regex};
|
||||
use rustfix::{apply_suggestions, get_suggestions_from_json, Filter};
|
||||
|
||||
use std::collections::hash_map::DefaultHasher;
|
||||
use std::collections::{HashMap, HashSet, VecDeque};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::env;
|
||||
use std::ffi::{OsStr, OsString};
|
||||
use std::fs::{self, create_dir_all, File, OpenOptions};
|
||||
@ -100,111 +101,6 @@ pub fn get_lib_name(lib: &str, dylib: bool) -> String {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum DiffLine {
|
||||
Context(String),
|
||||
Expected(String),
|
||||
Resulting(String),
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct Mismatch {
|
||||
pub line_number: u32,
|
||||
pub lines: Vec<DiffLine>,
|
||||
}
|
||||
|
||||
impl Mismatch {
|
||||
fn new(line_number: u32) -> Mismatch {
|
||||
Mismatch { line_number, lines: Vec::new() }
|
||||
}
|
||||
}
|
||||
|
||||
// Produces a diff between the expected output and actual output.
|
||||
pub fn make_diff(expected: &str, actual: &str, context_size: usize) -> Vec<Mismatch> {
|
||||
let mut line_number = 1;
|
||||
let mut context_queue: VecDeque<&str> = VecDeque::with_capacity(context_size);
|
||||
let mut lines_since_mismatch = context_size + 1;
|
||||
let mut results = Vec::new();
|
||||
let mut mismatch = Mismatch::new(0);
|
||||
|
||||
for result in diff::lines(expected, actual) {
|
||||
match result {
|
||||
diff::Result::Left(str) => {
|
||||
if lines_since_mismatch >= context_size && lines_since_mismatch > 0 {
|
||||
results.push(mismatch);
|
||||
mismatch = Mismatch::new(line_number - context_queue.len() as u32);
|
||||
}
|
||||
|
||||
while let Some(line) = context_queue.pop_front() {
|
||||
mismatch.lines.push(DiffLine::Context(line.to_owned()));
|
||||
}
|
||||
|
||||
mismatch.lines.push(DiffLine::Expected(str.to_owned()));
|
||||
line_number += 1;
|
||||
lines_since_mismatch = 0;
|
||||
}
|
||||
diff::Result::Right(str) => {
|
||||
if lines_since_mismatch >= context_size && lines_since_mismatch > 0 {
|
||||
results.push(mismatch);
|
||||
mismatch = Mismatch::new(line_number - context_queue.len() as u32);
|
||||
}
|
||||
|
||||
while let Some(line) = context_queue.pop_front() {
|
||||
mismatch.lines.push(DiffLine::Context(line.to_owned()));
|
||||
}
|
||||
|
||||
mismatch.lines.push(DiffLine::Resulting(str.to_owned()));
|
||||
lines_since_mismatch = 0;
|
||||
}
|
||||
diff::Result::Both(str, _) => {
|
||||
if context_queue.len() >= context_size {
|
||||
let _ = context_queue.pop_front();
|
||||
}
|
||||
|
||||
if lines_since_mismatch < context_size {
|
||||
mismatch.lines.push(DiffLine::Context(str.to_owned()));
|
||||
} else if context_size > 0 {
|
||||
context_queue.push_back(str);
|
||||
}
|
||||
|
||||
line_number += 1;
|
||||
lines_since_mismatch += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
results.push(mismatch);
|
||||
results.remove(0);
|
||||
|
||||
results
|
||||
}
|
||||
|
||||
fn write_diff(expected: &str, actual: &str, context_size: usize) -> String {
|
||||
use std::fmt::Write;
|
||||
let mut output = String::new();
|
||||
let diff_results = make_diff(expected, actual, context_size);
|
||||
for result in diff_results {
|
||||
let mut line_number = result.line_number;
|
||||
for line in result.lines {
|
||||
match line {
|
||||
DiffLine::Expected(e) => {
|
||||
writeln!(output, "-\t{}", e).unwrap();
|
||||
line_number += 1;
|
||||
}
|
||||
DiffLine::Context(c) => {
|
||||
writeln!(output, "{}\t{}", line_number, c).unwrap();
|
||||
line_number += 1;
|
||||
}
|
||||
DiffLine::Resulting(r) => {
|
||||
writeln!(output, "+\t{}", r).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
writeln!(output).unwrap();
|
||||
}
|
||||
output
|
||||
}
|
||||
|
||||
pub fn run(config: Config, testpaths: &TestPaths, revision: Option<&str>) {
|
||||
match &*config.target {
|
||||
"arm-linux-androideabi"
|
||||
@ -2507,43 +2403,17 @@ impl<'test> TestCx<'test> {
|
||||
|
||||
let diff_filename = format!("build/tmp/rustdoc-compare-{}.diff", std::process::id());
|
||||
|
||||
{
|
||||
let mut diff_output = File::create(&diff_filename).unwrap();
|
||||
let mut wrote_data = false;
|
||||
for entry in walkdir::WalkDir::new(out_dir) {
|
||||
let entry = entry.expect("failed to read file");
|
||||
let extension = entry.path().extension().and_then(|p| p.to_str());
|
||||
if entry.file_type().is_file()
|
||||
if !write_filtered_diff(
|
||||
&diff_filename,
|
||||
out_dir,
|
||||
&compare_dir,
|
||||
self.config.verbose,
|
||||
|file_type, extension| {
|
||||
file_type.is_file()
|
||||
&& (extension == Some("html".into()) || extension == Some("js".into()))
|
||||
{
|
||||
let expected_path =
|
||||
compare_dir.join(entry.path().strip_prefix(&out_dir).unwrap());
|
||||
let expected =
|
||||
if let Ok(s) = std::fs::read(&expected_path) { s } else { continue };
|
||||
let actual_path = entry.path();
|
||||
let actual = std::fs::read(&actual_path).unwrap();
|
||||
let diff = unified_diff::diff(
|
||||
&expected,
|
||||
&expected_path.to_string_lossy(),
|
||||
&actual,
|
||||
&actual_path.to_string_lossy(),
|
||||
3,
|
||||
);
|
||||
wrote_data |= !diff.is_empty();
|
||||
diff_output.write_all(&diff).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
if !wrote_data {
|
||||
println!("note: diff is identical to nightly rustdoc");
|
||||
assert!(diff_output.metadata().unwrap().len() == 0);
|
||||
return;
|
||||
} else if self.config.verbose {
|
||||
eprintln!("printing diff:");
|
||||
let mut buf = Vec::new();
|
||||
diff_output.read_to_end(&mut buf).unwrap();
|
||||
std::io::stderr().lock().write_all(&mut buf).unwrap();
|
||||
}
|
||||
},
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
match self.config.color {
|
||||
|
Loading…
Reference in New Issue
Block a user