Auto merge of #151809 - Zalathar:rollup-YOo3wjw, r=Zalathar
Rollup of 12 pull requests Successful merges: - rust-lang/rust#150474 (Tidy: detect ui tests subdirectory changes so `tests/ui/README.md` stays in sync) - rust-lang/rust#150572 (Improve move error diagnostic for `AsyncFn` closures) - rust-lang/rust#151596 (Fix -Zmir-enable-passes to detect unregistered enum names in declare_passes macro) - rust-lang/rust#151802 (Make `QueryDispatcher::Qcx` an associated type) - rust-lang/rust#149110 (Implement `cast_slice` for raw pointer types) - rust-lang/rust#151559 ([rustdoc] Add a marker to tell users that there are hidden (deprecated) items in the search results) - rust-lang/rust#151665 (Fix contrast ratio for `Since` element in rustdoc dark theme) - rust-lang/rust#151785 (Stabilize feature(push_mut)) - rust-lang/rust#151798 (Update `askama` to `0.15.3`) - rust-lang/rust#151800 (Subscribe myself to translation diagnostics) - rust-lang/rust#151804 (Document, sort, and tweak spellcheck entries in `typos.toml`) - rust-lang/rust#151805 (Fix grammar in `env::current_exe()#Security`)
This commit is contained in:
commit
80b898258d
33 changed files with 778 additions and 305 deletions
16
Cargo.lock
16
Cargo.lock
|
|
@ -184,9 +184,9 @@ checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
|
|||
|
||||
[[package]]
|
||||
name = "askama"
|
||||
version = "0.15.2"
|
||||
version = "0.15.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "03341eae1125472b0672fbf35cc9aa7b74cd8e0c3d02f02c28a04678f12aaa7a"
|
||||
checksum = "10a800c6f7c005e5bcb76ff0b9e61c9e54ad379ce4e83a88ed14ff487a73776d"
|
||||
dependencies = [
|
||||
"askama_macros",
|
||||
"itoa",
|
||||
|
|
@ -197,9 +197,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "askama_derive"
|
||||
version = "0.15.2"
|
||||
version = "0.15.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "461bd78f3da90b5e44eee4272cfb1c4832aa3dcdb6c370aedd3eb253d2b9e3ca"
|
||||
checksum = "0cb7657165bac49b5c533850e7cd67c1c60059aefc31088f89aa431c8a90d5d9"
|
||||
dependencies = [
|
||||
"askama_parser",
|
||||
"basic-toml",
|
||||
|
|
@ -214,18 +214,18 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "askama_macros"
|
||||
version = "0.15.2"
|
||||
version = "0.15.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba49fb22ee3074574b8510abd9495d4f0bb9b8f87e8e45ee31e2cee508f7a8e5"
|
||||
checksum = "e55eacd3e54d32483cd10d0a881a0f28a40f3a763704ac9b8693edc39d7321c7"
|
||||
dependencies = [
|
||||
"askama_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "askama_parser"
|
||||
version = "0.15.2"
|
||||
version = "0.15.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7e33eb7484958aaa1f27e9adb556f5d557331cd891bdbb33781bc1f9550b6f6e"
|
||||
checksum = "20c3df8886ab5acdcd76eee93b3e2df1ef734251438b5b942b5fea22c50d2a0f"
|
||||
dependencies = [
|
||||
"rustc-hash 2.1.1",
|
||||
"serde",
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
use rustc_abi::FieldIdx;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_errors::{Applicability, Diag};
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
|
|
@ -7,7 +8,7 @@ use rustc_middle::mir::*;
|
|||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_mir_dataflow::move_paths::{LookupResult, MovePathIndex};
|
||||
use rustc_span::def_id::DefId;
|
||||
use rustc_span::{BytePos, DUMMY_SP, ExpnKind, MacroKind, Span};
|
||||
use rustc_span::{BytePos, ExpnKind, MacroKind, Span};
|
||||
use rustc_trait_selection::error_reporting::traits::FindExprBySpan;
|
||||
use rustc_trait_selection::infer::InferCtxtExt;
|
||||
use tracing::debug;
|
||||
|
|
@ -472,49 +473,30 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
if def_id.as_local() == Some(self.mir_def_id())
|
||||
&& let Some(upvar_field) = upvar_field =>
|
||||
{
|
||||
let closure_kind_ty = closure_args.as_closure().kind_ty();
|
||||
let closure_kind = match closure_kind_ty.to_opt_closure_kind() {
|
||||
Some(kind @ (ty::ClosureKind::Fn | ty::ClosureKind::FnMut)) => kind,
|
||||
Some(ty::ClosureKind::FnOnce) => {
|
||||
bug!("closure kind does not match first argument type")
|
||||
}
|
||||
None => bug!("closure kind not inferred by borrowck"),
|
||||
};
|
||||
let capture_description =
|
||||
format!("captured variable in an `{closure_kind}` closure");
|
||||
|
||||
let upvar = &self.upvars[upvar_field.index()];
|
||||
let upvar_hir_id = upvar.get_root_variable();
|
||||
let upvar_name = upvar.to_string(tcx);
|
||||
let upvar_span = tcx.hir_span(upvar_hir_id);
|
||||
|
||||
let place_name = self.describe_any_place(move_place.as_ref());
|
||||
|
||||
let place_description =
|
||||
if self.is_upvar_field_projection(move_place.as_ref()).is_some() {
|
||||
format!("{place_name}, a {capture_description}")
|
||||
} else {
|
||||
format!("{place_name}, as `{upvar_name}` is a {capture_description}")
|
||||
};
|
||||
|
||||
debug!(
|
||||
"report: closure_kind_ty={:?} closure_kind={:?} place_description={:?}",
|
||||
closure_kind_ty, closure_kind, place_description,
|
||||
);
|
||||
|
||||
let closure_span = tcx.def_span(def_id);
|
||||
|
||||
self.cannot_move_out_of(span, &place_description)
|
||||
.with_span_label(upvar_span, "captured outer variable")
|
||||
.with_span_label(
|
||||
closure_span,
|
||||
format!("captured by this `{closure_kind}` closure"),
|
||||
)
|
||||
.with_span_help(
|
||||
self.get_closure_bound_clause_span(*def_id),
|
||||
"`Fn` and `FnMut` closures require captured values to be able to be \
|
||||
consumed multiple times, but `FnOnce` closures may consume them only once",
|
||||
)
|
||||
self.report_closure_move_error(
|
||||
span,
|
||||
move_place,
|
||||
*def_id,
|
||||
closure_args.as_closure().kind_ty(),
|
||||
upvar_field,
|
||||
ty::Asyncness::No,
|
||||
)
|
||||
}
|
||||
ty::CoroutineClosure(def_id, closure_args)
|
||||
if def_id.as_local() == Some(self.mir_def_id())
|
||||
&& let Some(upvar_field) = upvar_field
|
||||
&& self
|
||||
.get_closure_bound_clause_span(*def_id, ty::Asyncness::Yes)
|
||||
.is_some() =>
|
||||
{
|
||||
self.report_closure_move_error(
|
||||
span,
|
||||
move_place,
|
||||
*def_id,
|
||||
closure_args.as_coroutine_closure().kind_ty(),
|
||||
upvar_field,
|
||||
ty::Asyncness::Yes,
|
||||
)
|
||||
}
|
||||
_ => {
|
||||
let source = self.borrowed_content_source(deref_base);
|
||||
|
|
@ -563,45 +545,134 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
err
|
||||
}
|
||||
|
||||
fn get_closure_bound_clause_span(&self, def_id: DefId) -> Span {
|
||||
fn report_closure_move_error(
|
||||
&self,
|
||||
span: Span,
|
||||
move_place: Place<'tcx>,
|
||||
def_id: DefId,
|
||||
closure_kind_ty: Ty<'tcx>,
|
||||
upvar_field: FieldIdx,
|
||||
asyncness: ty::Asyncness,
|
||||
) -> Diag<'infcx> {
|
||||
let tcx = self.infcx.tcx;
|
||||
|
||||
let closure_kind = match closure_kind_ty.to_opt_closure_kind() {
|
||||
Some(kind @ (ty::ClosureKind::Fn | ty::ClosureKind::FnMut)) => kind,
|
||||
Some(ty::ClosureKind::FnOnce) => {
|
||||
bug!("closure kind does not match first argument type")
|
||||
}
|
||||
None => bug!("closure kind not inferred by borrowck"),
|
||||
};
|
||||
|
||||
let async_prefix = if asyncness.is_async() { "Async" } else { "" };
|
||||
let capture_description =
|
||||
format!("captured variable in an `{async_prefix}{closure_kind}` closure");
|
||||
|
||||
let upvar = &self.upvars[upvar_field.index()];
|
||||
let upvar_hir_id = upvar.get_root_variable();
|
||||
let upvar_name = upvar.to_string(tcx);
|
||||
let upvar_span = tcx.hir_span(upvar_hir_id);
|
||||
|
||||
let place_name = self.describe_any_place(move_place.as_ref());
|
||||
|
||||
let place_description = if self.is_upvar_field_projection(move_place.as_ref()).is_some() {
|
||||
format!("{place_name}, a {capture_description}")
|
||||
} else {
|
||||
format!("{place_name}, as `{upvar_name}` is a {capture_description}")
|
||||
};
|
||||
|
||||
debug!(?closure_kind_ty, ?closure_kind, ?place_description);
|
||||
|
||||
let closure_span = tcx.def_span(def_id);
|
||||
|
||||
let help_msg = format!(
|
||||
"`{async_prefix}Fn` and `{async_prefix}FnMut` closures require captured values to \
|
||||
be able to be consumed multiple times, but `{async_prefix}FnOnce` closures may \
|
||||
consume them only once"
|
||||
);
|
||||
|
||||
let mut err = self
|
||||
.cannot_move_out_of(span, &place_description)
|
||||
.with_span_label(upvar_span, "captured outer variable")
|
||||
.with_span_label(
|
||||
closure_span,
|
||||
format!("captured by this `{async_prefix}{closure_kind}` closure"),
|
||||
);
|
||||
|
||||
if let Some(bound_span) = self.get_closure_bound_clause_span(def_id, asyncness) {
|
||||
err.span_help(bound_span, help_msg);
|
||||
} else if !asyncness.is_async() {
|
||||
// For sync closures, always emit the help message even without a span.
|
||||
// For async closures, we only enter this branch if we found a valid span
|
||||
// (due to the match guard), so no fallback is needed.
|
||||
err.help(help_msg);
|
||||
}
|
||||
|
||||
err
|
||||
}
|
||||
|
||||
fn get_closure_bound_clause_span(
|
||||
&self,
|
||||
def_id: DefId,
|
||||
asyncness: ty::Asyncness,
|
||||
) -> Option<Span> {
|
||||
let tcx = self.infcx.tcx;
|
||||
let typeck_result = tcx.typeck(self.mir_def_id());
|
||||
// Check whether the closure is an argument to a call, if so,
|
||||
// get the instantiated where-bounds of that call.
|
||||
let closure_hir_id = tcx.local_def_id_to_hir_id(def_id.expect_local());
|
||||
let hir::Node::Expr(parent) = tcx.parent_hir_node(closure_hir_id) else { return DUMMY_SP };
|
||||
let hir::Node::Expr(parent) = tcx.parent_hir_node(closure_hir_id) else { return None };
|
||||
|
||||
let predicates = match parent.kind {
|
||||
hir::ExprKind::Call(callee, _) => {
|
||||
let Some(ty) = typeck_result.node_type_opt(callee.hir_id) else { return DUMMY_SP };
|
||||
let ty::FnDef(fn_def_id, args) = ty.kind() else { return DUMMY_SP };
|
||||
let ty = typeck_result.node_type_opt(callee.hir_id)?;
|
||||
let ty::FnDef(fn_def_id, args) = ty.kind() else { return None };
|
||||
tcx.predicates_of(fn_def_id).instantiate(tcx, args)
|
||||
}
|
||||
hir::ExprKind::MethodCall(..) => {
|
||||
let Some((_, method)) = typeck_result.type_dependent_def(parent.hir_id) else {
|
||||
return DUMMY_SP;
|
||||
};
|
||||
let (_, method) = typeck_result.type_dependent_def(parent.hir_id)?;
|
||||
let args = typeck_result.node_args(parent.hir_id);
|
||||
tcx.predicates_of(method).instantiate(tcx, args)
|
||||
}
|
||||
_ => return DUMMY_SP,
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
// Check whether one of the where-bounds requires the closure to impl `Fn[Mut]`.
|
||||
// Check whether one of the where-bounds requires the closure to impl `Fn[Mut]`
|
||||
// or `AsyncFn[Mut]`.
|
||||
for (pred, span) in predicates.predicates.iter().zip(predicates.spans.iter()) {
|
||||
if let Some(clause) = pred.as_trait_clause()
|
||||
&& let ty::Closure(clause_closure_def_id, _) = clause.self_ty().skip_binder().kind()
|
||||
&& *clause_closure_def_id == def_id
|
||||
&& (tcx.lang_items().fn_mut_trait() == Some(clause.def_id())
|
||||
|| tcx.lang_items().fn_trait() == Some(clause.def_id()))
|
||||
{
|
||||
// Found `<TyOfCapturingClosure as FnMut>`
|
||||
// We point at the `Fn()` or `FnMut()` bound that coerced the closure, which
|
||||
// could be changed to `FnOnce()` to avoid the move error.
|
||||
return *span;
|
||||
let dominated_by_fn_trait = self
|
||||
.closure_clause_kind(*pred, def_id, asyncness)
|
||||
.is_some_and(|kind| matches!(kind, ty::ClosureKind::Fn | ty::ClosureKind::FnMut));
|
||||
if dominated_by_fn_trait {
|
||||
// Found `<TyOfCapturingClosure as FnMut>` or
|
||||
// `<TyOfCapturingClosure as AsyncFnMut>`.
|
||||
// We point at the bound that coerced the closure, which could be changed
|
||||
// to `FnOnce()` or `AsyncFnOnce()` to avoid the move error.
|
||||
return Some(*span);
|
||||
}
|
||||
}
|
||||
DUMMY_SP
|
||||
None
|
||||
}
|
||||
|
||||
/// If `pred` is a trait clause binding the closure `def_id` to `Fn`/`FnMut`/`FnOnce`
|
||||
/// (or their async equivalents based on `asyncness`), returns the corresponding
|
||||
/// `ClosureKind`. Otherwise returns `None`.
|
||||
fn closure_clause_kind(
|
||||
&self,
|
||||
pred: ty::Clause<'tcx>,
|
||||
def_id: DefId,
|
||||
asyncness: ty::Asyncness,
|
||||
) -> Option<ty::ClosureKind> {
|
||||
let tcx = self.infcx.tcx;
|
||||
let clause = pred.as_trait_clause()?;
|
||||
let kind = match asyncness {
|
||||
ty::Asyncness::Yes => tcx.async_fn_trait_kind_from_def_id(clause.def_id()),
|
||||
ty::Asyncness::No => tcx.fn_trait_kind_from_def_id(clause.def_id()),
|
||||
}?;
|
||||
match clause.self_ty().skip_binder().kind() {
|
||||
ty::Closure(id, _) | ty::CoroutineClosure(id, _) if *id == def_id => Some(kind),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn add_move_hints(&self, error: GroupedMoveError<'tcx>, err: &mut Diag<'_>, span: Span) {
|
||||
|
|
|
|||
|
|
@ -91,20 +91,32 @@ macro_rules! declare_passes {
|
|||
)+
|
||||
)*
|
||||
|
||||
static PASS_NAMES: LazyLock<FxIndexSet<&str>> = LazyLock::new(|| [
|
||||
static PASS_NAMES: LazyLock<FxIndexSet<&str>> = LazyLock::new(|| {
|
||||
let mut set = FxIndexSet::default();
|
||||
// Fake marker pass
|
||||
"PreCodegen",
|
||||
set.insert("PreCodegen");
|
||||
$(
|
||||
$(
|
||||
stringify!($pass_name),
|
||||
$(
|
||||
$(
|
||||
$mod_name::$pass_name::$ident.name(),
|
||||
)*
|
||||
)?
|
||||
set.extend(pass_names!($mod_name : $pass_name $( { $($ident),* } )? ));
|
||||
)+
|
||||
)*
|
||||
].into_iter().collect());
|
||||
set
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! pass_names {
|
||||
// pass groups: only pass names inside are considered pass_names
|
||||
($mod_name:ident : $pass_group:ident { $($pass_name:ident),* $(,)? }) => {
|
||||
[
|
||||
$(
|
||||
$mod_name::$pass_group::$pass_name.name(),
|
||||
)*
|
||||
]
|
||||
};
|
||||
// lone pass names: stringify the struct or enum name
|
||||
($mod_name:ident : $pass_name:ident) => {
|
||||
[stringify!($pass_name)]
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -67,11 +67,11 @@ impl<'tcx, C: QueryCache, const ANON: bool, const DEPTH_LIMIT: bool, const FEEDA
|
|||
|
||||
// This is `impl QueryDispatcher for SemiDynamicQueryDispatcher`.
|
||||
impl<'tcx, C: QueryCache, const ANON: bool, const DEPTH_LIMIT: bool, const FEEDABLE: bool>
|
||||
QueryDispatcher<QueryCtxt<'tcx>>
|
||||
for SemiDynamicQueryDispatcher<'tcx, C, ANON, DEPTH_LIMIT, FEEDABLE>
|
||||
QueryDispatcher for SemiDynamicQueryDispatcher<'tcx, C, ANON, DEPTH_LIMIT, FEEDABLE>
|
||||
where
|
||||
for<'a> C::Key: HashStable<StableHashingContext<'a>>,
|
||||
{
|
||||
type Qcx = QueryCtxt<'tcx>;
|
||||
type Key = C::Key;
|
||||
type Value = C::Value;
|
||||
type Cache = C;
|
||||
|
|
@ -104,10 +104,7 @@ where
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn query_cache<'a>(self, qcx: QueryCtxt<'tcx>) -> &'a Self::Cache
|
||||
where
|
||||
'tcx: 'a,
|
||||
{
|
||||
fn query_cache<'a>(self, qcx: QueryCtxt<'tcx>) -> &'a Self::Cache {
|
||||
// Safety:
|
||||
// This is just manually doing the subfield referencing through pointer math.
|
||||
unsafe {
|
||||
|
|
@ -215,15 +212,13 @@ where
|
|||
/// on the type `rustc_query_impl::query_impl::$name::QueryType`.
|
||||
trait QueryDispatcherUnerased<'tcx> {
|
||||
type UnerasedValue;
|
||||
type Dispatcher: QueryDispatcher<QueryCtxt<'tcx>>;
|
||||
type Dispatcher: QueryDispatcher<Qcx = QueryCtxt<'tcx>>;
|
||||
|
||||
const NAME: &'static &'static str;
|
||||
|
||||
fn query_dispatcher(tcx: TyCtxt<'tcx>) -> Self::Dispatcher;
|
||||
|
||||
fn restore_val(
|
||||
value: <Self::Dispatcher as QueryDispatcher<QueryCtxt<'tcx>>>::Value,
|
||||
) -> Self::UnerasedValue;
|
||||
fn restore_val(value: <Self::Dispatcher as QueryDispatcher>::Value) -> Self::UnerasedValue;
|
||||
}
|
||||
|
||||
pub fn query_system<'a>(
|
||||
|
|
|
|||
|
|
@ -414,7 +414,7 @@ pub(crate) fn encode_query_results<'a, 'tcx, Q>(
|
|||
}
|
||||
|
||||
pub(crate) fn query_key_hash_verify<'tcx>(
|
||||
query: impl QueryDispatcher<QueryCtxt<'tcx>>,
|
||||
query: impl QueryDispatcher<Qcx = QueryCtxt<'tcx>>,
|
||||
qcx: QueryCtxt<'tcx>,
|
||||
) {
|
||||
let _timer = qcx.tcx.prof.generic_activity_with_arg("query_key_hash_verify_for", query.name());
|
||||
|
|
@ -442,7 +442,7 @@ pub(crate) fn query_key_hash_verify<'tcx>(
|
|||
|
||||
fn try_load_from_on_disk_cache<'tcx, Q>(query: Q, tcx: TyCtxt<'tcx>, dep_node: DepNode)
|
||||
where
|
||||
Q: QueryDispatcher<QueryCtxt<'tcx>>,
|
||||
Q: QueryDispatcher<Qcx = QueryCtxt<'tcx>>,
|
||||
{
|
||||
debug_assert!(tcx.dep_graph.is_green(&dep_node));
|
||||
|
||||
|
|
@ -488,7 +488,7 @@ where
|
|||
|
||||
fn force_from_dep_node<'tcx, Q>(query: Q, tcx: TyCtxt<'tcx>, dep_node: DepNode) -> bool
|
||||
where
|
||||
Q: QueryDispatcher<QueryCtxt<'tcx>>,
|
||||
Q: QueryDispatcher<Qcx = QueryCtxt<'tcx>>,
|
||||
{
|
||||
// We must avoid ever having to call `force_from_dep_node()` for a
|
||||
// `DepNode::codegen_unit`:
|
||||
|
|
@ -523,8 +523,7 @@ pub(crate) fn make_dep_kind_vtable_for_query<'tcx, Q>(
|
|||
where
|
||||
Q: QueryDispatcherUnerased<'tcx>,
|
||||
{
|
||||
let fingerprint_style =
|
||||
<Q::Dispatcher as QueryDispatcher<QueryCtxt<'tcx>>>::Key::fingerprint_style();
|
||||
let fingerprint_style = <Q::Dispatcher as QueryDispatcher>::Key::fingerprint_style();
|
||||
|
||||
if is_anon || !fingerprint_style.reconstructible() {
|
||||
return DepKindVTable {
|
||||
|
|
@ -731,7 +730,7 @@ macro_rules! define_queries {
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn restore_val(value: <Self::Dispatcher as QueryDispatcher<QueryCtxt<'tcx>>>::Value) -> Self::UnerasedValue {
|
||||
fn restore_val(value: <Self::Dispatcher as QueryDispatcher>::Value) -> Self::UnerasedValue {
|
||||
restore::<queries::$name::Value<'tcx>>(value)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,13 +5,18 @@ use rustc_data_structures::fingerprint::Fingerprint;
|
|||
use rustc_span::ErrorGuaranteed;
|
||||
|
||||
use super::QueryStackFrameExtra;
|
||||
use crate::dep_graph::{DepKind, DepNode, DepNodeParams, SerializedDepNodeIndex};
|
||||
use crate::dep_graph::{DepKind, DepNode, DepNodeParams, HasDepContext, SerializedDepNodeIndex};
|
||||
use crate::ich::StableHashingContext;
|
||||
use crate::query::caches::QueryCache;
|
||||
use crate::query::{CycleError, CycleErrorHandling, DepNodeIndex, QueryContext, QueryState};
|
||||
|
||||
pub type HashResult<V> = Option<fn(&mut StableHashingContext<'_>, &V) -> Fingerprint>;
|
||||
|
||||
/// Unambiguous shorthand for `<This::Qcx as HasDepContext>::DepContext`.
|
||||
#[expect(type_alias_bounds)]
|
||||
type DepContextOf<This: QueryDispatcher> =
|
||||
<<This as QueryDispatcher>::Qcx as HasDepContext>::DepContext;
|
||||
|
||||
/// Trait that can be used as a vtable for a single query, providing operations
|
||||
/// and metadata for that query.
|
||||
///
|
||||
|
|
@ -20,12 +25,15 @@ pub type HashResult<V> = Option<fn(&mut StableHashingContext<'_>, &V) -> Fingerp
|
|||
/// Those types are not visible from this `rustc_query_system` crate.
|
||||
///
|
||||
/// "Dispatcher" should be understood as a near-synonym of "vtable".
|
||||
pub trait QueryDispatcher<Qcx: QueryContext>: Copy {
|
||||
pub trait QueryDispatcher: Copy {
|
||||
fn name(self) -> &'static str;
|
||||
|
||||
/// Query context used by this dispatcher, i.e. `rustc_query_impl::QueryCtxt`.
|
||||
type Qcx: QueryContext;
|
||||
|
||||
// `Key` and `Value` are `Copy` instead of `Clone` to ensure copying them stays cheap,
|
||||
// but it isn't necessary.
|
||||
type Key: DepNodeParams<Qcx::DepContext> + Eq + Hash + Copy + Debug;
|
||||
type Key: DepNodeParams<DepContextOf<Self>> + Eq + Hash + Copy + Debug;
|
||||
type Value: Copy;
|
||||
|
||||
type Cache: QueryCache<Key = Self::Key, Value = Self::Value>;
|
||||
|
|
@ -33,36 +41,40 @@ pub trait QueryDispatcher<Qcx: QueryContext>: Copy {
|
|||
fn format_value(self) -> fn(&Self::Value) -> String;
|
||||
|
||||
// Don't use this method to access query results, instead use the methods on TyCtxt
|
||||
fn query_state<'a>(self, tcx: Qcx) -> &'a QueryState<Self::Key, Qcx::QueryInfo>
|
||||
where
|
||||
Qcx: 'a;
|
||||
fn query_state<'a>(
|
||||
self,
|
||||
tcx: Self::Qcx,
|
||||
) -> &'a QueryState<Self::Key, <Self::Qcx as QueryContext>::QueryInfo>;
|
||||
|
||||
// Don't use this method to access query results, instead use the methods on TyCtxt
|
||||
fn query_cache<'a>(self, tcx: Qcx) -> &'a Self::Cache
|
||||
where
|
||||
Qcx: 'a;
|
||||
fn query_cache<'a>(self, tcx: Self::Qcx) -> &'a Self::Cache;
|
||||
|
||||
fn cache_on_disk(self, tcx: Qcx::DepContext, key: &Self::Key) -> bool;
|
||||
fn cache_on_disk(self, tcx: DepContextOf<Self>, key: &Self::Key) -> bool;
|
||||
|
||||
// Don't use this method to compute query results, instead use the methods on TyCtxt
|
||||
fn execute_query(self, tcx: Qcx::DepContext, k: Self::Key) -> Self::Value;
|
||||
fn execute_query(self, tcx: DepContextOf<Self>, k: Self::Key) -> Self::Value;
|
||||
|
||||
fn compute(self, tcx: Qcx, key: Self::Key) -> Self::Value;
|
||||
fn compute(self, tcx: Self::Qcx, key: Self::Key) -> Self::Value;
|
||||
|
||||
fn try_load_from_disk(
|
||||
self,
|
||||
tcx: Qcx,
|
||||
tcx: Self::Qcx,
|
||||
key: &Self::Key,
|
||||
prev_index: SerializedDepNodeIndex,
|
||||
index: DepNodeIndex,
|
||||
) -> Option<Self::Value>;
|
||||
|
||||
fn loadable_from_disk(self, qcx: Qcx, key: &Self::Key, idx: SerializedDepNodeIndex) -> bool;
|
||||
fn loadable_from_disk(
|
||||
self,
|
||||
qcx: Self::Qcx,
|
||||
key: &Self::Key,
|
||||
idx: SerializedDepNodeIndex,
|
||||
) -> bool;
|
||||
|
||||
/// Synthesize an error value to let compilation continue after a cycle.
|
||||
fn value_from_cycle_error(
|
||||
self,
|
||||
tcx: Qcx::DepContext,
|
||||
tcx: DepContextOf<Self>,
|
||||
cycle_error: &CycleError<QueryStackFrameExtra>,
|
||||
guar: ErrorGuaranteed,
|
||||
) -> Self::Value;
|
||||
|
|
@ -77,7 +89,7 @@ pub trait QueryDispatcher<Qcx: QueryContext>: Copy {
|
|||
fn hash_result(self) -> HashResult<Self::Value>;
|
||||
|
||||
// Just here for convenience and checking that the key matches the kind, don't override this.
|
||||
fn construct_dep_node(self, tcx: Qcx::DepContext, key: &Self::Key) -> DepNode {
|
||||
fn construct_dep_node(self, tcx: DepContextOf<Self>, key: &Self::Key) -> DepNode {
|
||||
DepNode::construct(tcx, self.dep_kind(), key)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,9 @@ use rustc_span::{DUMMY_SP, Span};
|
|||
use tracing::instrument;
|
||||
|
||||
use super::{QueryDispatcher, QueryStackFrameExtra};
|
||||
use crate::dep_graph::{DepContext, DepGraphData, DepNode, DepNodeIndex, DepNodeParams};
|
||||
use crate::dep_graph::{
|
||||
DepContext, DepGraphData, DepNode, DepNodeIndex, DepNodeParams, HasDepContext,
|
||||
};
|
||||
use crate::ich::StableHashingContext;
|
||||
use crate::query::caches::QueryCache;
|
||||
use crate::query::job::{QueryInfo, QueryJob, QueryJobId, QueryJobInfo, QueryLatch, report_cycle};
|
||||
|
|
@ -124,24 +126,22 @@ where
|
|||
|
||||
#[cold]
|
||||
#[inline(never)]
|
||||
fn mk_cycle<Q, Qcx>(query: Q, qcx: Qcx, cycle_error: CycleError) -> Q::Value
|
||||
fn mk_cycle<Q>(query: Q, qcx: Q::Qcx, cycle_error: CycleError) -> Q::Value
|
||||
where
|
||||
Q: QueryDispatcher<Qcx>,
|
||||
Qcx: QueryContext,
|
||||
Q: QueryDispatcher,
|
||||
{
|
||||
let error = report_cycle(qcx.dep_context().sess(), &cycle_error);
|
||||
handle_cycle_error(query, qcx, &cycle_error, error)
|
||||
}
|
||||
|
||||
fn handle_cycle_error<Q, Qcx>(
|
||||
fn handle_cycle_error<Q>(
|
||||
query: Q,
|
||||
qcx: Qcx,
|
||||
qcx: Q::Qcx,
|
||||
cycle_error: &CycleError,
|
||||
error: Diag<'_>,
|
||||
) -> Q::Value
|
||||
where
|
||||
Q: QueryDispatcher<Qcx>,
|
||||
Qcx: QueryContext,
|
||||
Q: QueryDispatcher,
|
||||
{
|
||||
match query.cycle_error_handling() {
|
||||
CycleErrorHandling::Error => {
|
||||
|
|
@ -272,15 +272,14 @@ where
|
|||
|
||||
#[cold]
|
||||
#[inline(never)]
|
||||
fn cycle_error<Q, Qcx>(
|
||||
fn cycle_error<Q>(
|
||||
query: Q,
|
||||
qcx: Qcx,
|
||||
qcx: Q::Qcx,
|
||||
try_execute: QueryJobId,
|
||||
span: Span,
|
||||
) -> (Q::Value, Option<DepNodeIndex>)
|
||||
where
|
||||
Q: QueryDispatcher<Qcx>,
|
||||
Qcx: QueryContext,
|
||||
Q: QueryDispatcher,
|
||||
{
|
||||
// Ensure there was no errors collecting all active jobs.
|
||||
// We need the complete map to ensure we find a cycle to break.
|
||||
|
|
@ -291,17 +290,16 @@ where
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn wait_for_query<Q, Qcx>(
|
||||
fn wait_for_query<Q>(
|
||||
query: Q,
|
||||
qcx: Qcx,
|
||||
qcx: Q::Qcx,
|
||||
span: Span,
|
||||
key: Q::Key,
|
||||
latch: QueryLatch<Qcx::QueryInfo>,
|
||||
latch: QueryLatch<<Q::Qcx as QueryContext>::QueryInfo>,
|
||||
current: Option<QueryJobId>,
|
||||
) -> (Q::Value, Option<DepNodeIndex>)
|
||||
where
|
||||
Q: QueryDispatcher<Qcx>,
|
||||
Qcx: QueryContext,
|
||||
Q: QueryDispatcher,
|
||||
{
|
||||
// For parallel queries, we'll block and wait until the query running
|
||||
// in another thread has completed. Record how long we wait in the
|
||||
|
|
@ -341,16 +339,15 @@ where
|
|||
}
|
||||
|
||||
#[inline(never)]
|
||||
fn try_execute_query<Q, Qcx, const INCR: bool>(
|
||||
fn try_execute_query<Q, const INCR: bool>(
|
||||
query: Q,
|
||||
qcx: Qcx,
|
||||
qcx: Q::Qcx,
|
||||
span: Span,
|
||||
key: Q::Key,
|
||||
dep_node: Option<DepNode>,
|
||||
) -> (Q::Value, Option<DepNodeIndex>)
|
||||
where
|
||||
Q: QueryDispatcher<Qcx>,
|
||||
Qcx: QueryContext,
|
||||
Q: QueryDispatcher,
|
||||
{
|
||||
let state = query.query_state(qcx);
|
||||
let key_hash = sharded::make_hash(&key);
|
||||
|
|
@ -382,7 +379,7 @@ where
|
|||
// Drop the lock before we start executing the query
|
||||
drop(state_lock);
|
||||
|
||||
execute_job::<_, _, INCR>(query, qcx, state, key, key_hash, id, dep_node)
|
||||
execute_job::<Q, INCR>(query, qcx, state, key, key_hash, id, dep_node)
|
||||
}
|
||||
Entry::Occupied(mut entry) => {
|
||||
match &mut entry.get_mut().1 {
|
||||
|
|
@ -411,18 +408,17 @@ where
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn execute_job<Q, Qcx, const INCR: bool>(
|
||||
fn execute_job<Q, const INCR: bool>(
|
||||
query: Q,
|
||||
qcx: Qcx,
|
||||
state: &QueryState<Q::Key, Qcx::QueryInfo>,
|
||||
qcx: Q::Qcx,
|
||||
state: &QueryState<Q::Key, <Q::Qcx as QueryContext>::QueryInfo>,
|
||||
key: Q::Key,
|
||||
key_hash: u64,
|
||||
id: QueryJobId,
|
||||
dep_node: Option<DepNode>,
|
||||
) -> (Q::Value, Option<DepNodeIndex>)
|
||||
where
|
||||
Q: QueryDispatcher<Qcx>,
|
||||
Qcx: QueryContext,
|
||||
Q: QueryDispatcher,
|
||||
{
|
||||
// Use `JobOwner` so the query will be poisoned if executing it panics.
|
||||
let job_owner = JobOwner { state, key };
|
||||
|
|
@ -484,15 +480,14 @@ where
|
|||
|
||||
// Fast path for when incr. comp. is off.
|
||||
#[inline(always)]
|
||||
fn execute_job_non_incr<Q, Qcx>(
|
||||
fn execute_job_non_incr<Q>(
|
||||
query: Q,
|
||||
qcx: Qcx,
|
||||
qcx: Q::Qcx,
|
||||
key: Q::Key,
|
||||
job_id: QueryJobId,
|
||||
) -> (Q::Value, DepNodeIndex)
|
||||
where
|
||||
Q: QueryDispatcher<Qcx>,
|
||||
Qcx: QueryContext,
|
||||
Q: QueryDispatcher,
|
||||
{
|
||||
debug_assert!(!qcx.dep_context().dep_graph().is_fully_enabled());
|
||||
|
||||
|
|
@ -521,17 +516,16 @@ where
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn execute_job_incr<Q, Qcx>(
|
||||
fn execute_job_incr<Q>(
|
||||
query: Q,
|
||||
qcx: Qcx,
|
||||
dep_graph_data: &DepGraphData<Qcx::Deps>,
|
||||
qcx: Q::Qcx,
|
||||
dep_graph_data: &DepGraphData<<Q::Qcx as HasDepContext>::Deps>,
|
||||
key: Q::Key,
|
||||
mut dep_node_opt: Option<DepNode>,
|
||||
job_id: QueryJobId,
|
||||
) -> (Q::Value, DepNodeIndex)
|
||||
where
|
||||
Q: QueryDispatcher<Qcx>,
|
||||
Qcx: QueryContext,
|
||||
Q: QueryDispatcher,
|
||||
{
|
||||
if !query.anon() && !query.eval_always() {
|
||||
// `to_dep_node` is expensive for some `DepKind`s.
|
||||
|
|
@ -577,16 +571,15 @@ where
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn try_load_from_disk_and_cache_in_memory<Q, Qcx>(
|
||||
fn try_load_from_disk_and_cache_in_memory<Q>(
|
||||
query: Q,
|
||||
dep_graph_data: &DepGraphData<Qcx::Deps>,
|
||||
qcx: Qcx,
|
||||
dep_graph_data: &DepGraphData<<Q::Qcx as HasDepContext>::Deps>,
|
||||
qcx: Q::Qcx,
|
||||
key: &Q::Key,
|
||||
dep_node: &DepNode,
|
||||
) -> Option<(Q::Value, DepNodeIndex)>
|
||||
where
|
||||
Q: QueryDispatcher<Qcx>,
|
||||
Qcx: QueryContext,
|
||||
Q: QueryDispatcher,
|
||||
{
|
||||
// Note this function can be called concurrently from the same query
|
||||
// We must ensure that this is handled correctly.
|
||||
|
|
@ -764,15 +757,14 @@ fn incremental_verify_ich_failed<Tcx>(
|
|||
///
|
||||
/// Note: The optimization is only available during incr. comp.
|
||||
#[inline(never)]
|
||||
fn ensure_must_run<Q, Qcx>(
|
||||
fn ensure_must_run<Q>(
|
||||
query: Q,
|
||||
qcx: Qcx,
|
||||
qcx: Q::Qcx,
|
||||
key: &Q::Key,
|
||||
check_cache: bool,
|
||||
) -> (bool, Option<DepNode>)
|
||||
where
|
||||
Q: QueryDispatcher<Qcx>,
|
||||
Qcx: QueryContext,
|
||||
Q: QueryDispatcher,
|
||||
{
|
||||
if query.eval_always() {
|
||||
return (true, None);
|
||||
|
|
@ -817,27 +809,25 @@ pub enum QueryMode {
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn get_query_non_incr<Q, Qcx>(query: Q, qcx: Qcx, span: Span, key: Q::Key) -> Q::Value
|
||||
pub fn get_query_non_incr<Q>(query: Q, qcx: Q::Qcx, span: Span, key: Q::Key) -> Q::Value
|
||||
where
|
||||
Q: QueryDispatcher<Qcx>,
|
||||
Qcx: QueryContext,
|
||||
Q: QueryDispatcher,
|
||||
{
|
||||
debug_assert!(!qcx.dep_context().dep_graph().is_fully_enabled());
|
||||
|
||||
ensure_sufficient_stack(|| try_execute_query::<Q, Qcx, false>(query, qcx, span, key, None).0)
|
||||
ensure_sufficient_stack(|| try_execute_query::<Q, false>(query, qcx, span, key, None).0)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn get_query_incr<Q, Qcx>(
|
||||
pub fn get_query_incr<Q>(
|
||||
query: Q,
|
||||
qcx: Qcx,
|
||||
qcx: Q::Qcx,
|
||||
span: Span,
|
||||
key: Q::Key,
|
||||
mode: QueryMode,
|
||||
) -> Option<Q::Value>
|
||||
where
|
||||
Q: QueryDispatcher<Qcx>,
|
||||
Qcx: QueryContext,
|
||||
Q: QueryDispatcher,
|
||||
{
|
||||
debug_assert!(qcx.dep_context().dep_graph().is_fully_enabled());
|
||||
|
||||
|
|
@ -851,19 +841,17 @@ where
|
|||
None
|
||||
};
|
||||
|
||||
let (result, dep_node_index) = ensure_sufficient_stack(|| {
|
||||
try_execute_query::<_, _, true>(query, qcx, span, key, dep_node)
|
||||
});
|
||||
let (result, dep_node_index) =
|
||||
ensure_sufficient_stack(|| try_execute_query::<Q, true>(query, qcx, span, key, dep_node));
|
||||
if let Some(dep_node_index) = dep_node_index {
|
||||
qcx.dep_context().dep_graph().read_index(dep_node_index)
|
||||
}
|
||||
Some(result)
|
||||
}
|
||||
|
||||
pub fn force_query<Q, Qcx>(query: Q, qcx: Qcx, key: Q::Key, dep_node: DepNode)
|
||||
pub fn force_query<Q>(query: Q, qcx: Q::Qcx, key: Q::Key, dep_node: DepNode)
|
||||
where
|
||||
Q: QueryDispatcher<Qcx>,
|
||||
Qcx: QueryContext,
|
||||
Q: QueryDispatcher,
|
||||
{
|
||||
// We may be concurrently trying both execute and force a query.
|
||||
// Ensure that only one of them runs the query.
|
||||
|
|
@ -875,6 +863,6 @@ where
|
|||
debug_assert!(!query.anon());
|
||||
|
||||
ensure_sufficient_stack(|| {
|
||||
try_execute_query::<_, _, true>(query, qcx, DUMMY_SP, key, Some(dep_node))
|
||||
try_execute_query::<Q, true>(query, qcx, DUMMY_SP, key, Some(dep_node))
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Create a name definitinon from the given components, and put it into the local module.
|
||||
/// Create a name definition from the given components, and put it into the local module.
|
||||
fn define_local(
|
||||
&mut self,
|
||||
parent: Module<'ra>,
|
||||
|
|
@ -76,7 +76,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
self.plant_decl_into_local_module(ident, orig_ident.span, ns, decl);
|
||||
}
|
||||
|
||||
/// Create a name definitinon from the given components, and put it into the extern module.
|
||||
/// Create a name definition from the given components, and put it into the extern module.
|
||||
fn define_extern(
|
||||
&self,
|
||||
parent: Module<'ra>,
|
||||
|
|
|
|||
|
|
@ -854,7 +854,6 @@ impl<T, A: Allocator> LinkedList<T, A> {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(push_mut)]
|
||||
/// use std::collections::LinkedList;
|
||||
///
|
||||
/// let mut dl = LinkedList::from([1, 2, 3]);
|
||||
|
|
@ -863,7 +862,7 @@ impl<T, A: Allocator> LinkedList<T, A> {
|
|||
/// *ptr += 4;
|
||||
/// assert_eq!(dl.front().unwrap(), &6);
|
||||
/// ```
|
||||
#[unstable(feature = "push_mut", issue = "135974")]
|
||||
#[stable(feature = "push_mut", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[must_use = "if you don't need a reference to the value, use `LinkedList::push_front` instead"]
|
||||
pub fn push_front_mut(&mut self, elt: T) -> &mut T {
|
||||
let mut node =
|
||||
|
|
@ -926,7 +925,6 @@ impl<T, A: Allocator> LinkedList<T, A> {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(push_mut)]
|
||||
/// use std::collections::LinkedList;
|
||||
///
|
||||
/// let mut dl = LinkedList::from([1, 2, 3]);
|
||||
|
|
@ -935,7 +933,7 @@ impl<T, A: Allocator> LinkedList<T, A> {
|
|||
/// *ptr += 4;
|
||||
/// assert_eq!(dl.back().unwrap(), &6);
|
||||
/// ```
|
||||
#[unstable(feature = "push_mut", issue = "135974")]
|
||||
#[stable(feature = "push_mut", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[must_use = "if you don't need a reference to the value, use `LinkedList::push_back` instead"]
|
||||
pub fn push_back_mut(&mut self, elt: T) -> &mut T {
|
||||
let mut node =
|
||||
|
|
|
|||
|
|
@ -2168,7 +2168,6 @@ impl<T, A: Allocator> VecDeque<T, A> {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(push_mut)]
|
||||
/// use std::collections::VecDeque;
|
||||
///
|
||||
/// let mut d = VecDeque::from([1, 2, 3]);
|
||||
|
|
@ -2176,7 +2175,7 @@ impl<T, A: Allocator> VecDeque<T, A> {
|
|||
/// *x -= 1;
|
||||
/// assert_eq!(d.front(), Some(&7));
|
||||
/// ```
|
||||
#[unstable(feature = "push_mut", issue = "135974")]
|
||||
#[stable(feature = "push_mut", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[must_use = "if you don't need a reference to the value, use `VecDeque::push_front` instead"]
|
||||
pub fn push_front_mut(&mut self, value: T) -> &mut T {
|
||||
if self.is_full() {
|
||||
|
|
@ -2212,7 +2211,6 @@ impl<T, A: Allocator> VecDeque<T, A> {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(push_mut)]
|
||||
/// use std::collections::VecDeque;
|
||||
///
|
||||
/// let mut d = VecDeque::from([1, 2, 3]);
|
||||
|
|
@ -2220,7 +2218,7 @@ impl<T, A: Allocator> VecDeque<T, A> {
|
|||
/// *x += 1;
|
||||
/// assert_eq!(d.back(), Some(&10));
|
||||
/// ```
|
||||
#[unstable(feature = "push_mut", issue = "135974")]
|
||||
#[stable(feature = "push_mut", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[must_use = "if you don't need a reference to the value, use `VecDeque::push_back` instead"]
|
||||
pub fn push_back_mut(&mut self, value: T) -> &mut T {
|
||||
if self.is_full() {
|
||||
|
|
@ -2419,7 +2417,6 @@ impl<T, A: Allocator> VecDeque<T, A> {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(push_mut)]
|
||||
/// use std::collections::VecDeque;
|
||||
///
|
||||
/// let mut vec_deque = VecDeque::from([1, 2, 3]);
|
||||
|
|
@ -2428,7 +2425,7 @@ impl<T, A: Allocator> VecDeque<T, A> {
|
|||
/// *x += 7;
|
||||
/// assert_eq!(vec_deque, &[1, 12, 2, 3]);
|
||||
/// ```
|
||||
#[unstable(feature = "push_mut", issue = "135974")]
|
||||
#[stable(feature = "push_mut", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[must_use = "if you don't need a reference to the value, use `VecDeque::insert` instead"]
|
||||
pub fn insert_mut(&mut self, index: usize, value: T) -> &mut T {
|
||||
assert!(index <= self.len(), "index out of bounds");
|
||||
|
|
|
|||
|
|
@ -1003,9 +1003,6 @@ const impl<T, A: [const] Allocator + [const] Destruct> Vec<T, A> {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(push_mut)]
|
||||
///
|
||||
///
|
||||
/// let mut vec = vec![1, 2];
|
||||
/// let last = vec.push_mut(3);
|
||||
/// assert_eq!(*last, 3);
|
||||
|
|
@ -1023,7 +1020,7 @@ const impl<T, A: [const] Allocator + [const] Destruct> Vec<T, A> {
|
|||
/// vector's elements to a larger allocation. This expensive operation is
|
||||
/// offset by the *capacity* *O*(1) insertions it allows.
|
||||
#[inline]
|
||||
#[unstable(feature = "push_mut", issue = "135974")]
|
||||
#[stable(feature = "push_mut", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[must_use = "if you don't need a reference to the value, use `Vec::push` instead"]
|
||||
pub fn push_mut(&mut self, value: T) -> &mut T {
|
||||
// Inform codegen that the length does not change across grow_one().
|
||||
|
|
@ -2196,7 +2193,6 @@ impl<T, A: Allocator> Vec<T, A> {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(push_mut)]
|
||||
/// let mut vec = vec![1, 3, 5, 9];
|
||||
/// let x = vec.insert_mut(3, 6);
|
||||
/// *x += 1;
|
||||
|
|
@ -2210,7 +2206,7 @@ impl<T, A: Allocator> Vec<T, A> {
|
|||
/// the insertion index is 0.
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
#[inline]
|
||||
#[unstable(feature = "push_mut", issue = "135974")]
|
||||
#[stable(feature = "push_mut", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[track_caller]
|
||||
#[must_use = "if you don't need a reference to the value, use `Vec::insert` instead"]
|
||||
pub fn insert_mut(&mut self, index: usize, element: T) -> &mut T {
|
||||
|
|
@ -2689,7 +2685,6 @@ impl<T, A: Allocator> Vec<T, A> {
|
|||
/// Takes *O*(1) time.
|
||||
#[inline]
|
||||
#[unstable(feature = "vec_push_within_capacity", issue = "100486")]
|
||||
// #[unstable(feature = "push_mut", issue = "135974")]
|
||||
pub fn push_within_capacity(&mut self, value: T) -> Result<&mut T, T> {
|
||||
if self.len == self.buf.capacity() {
|
||||
return Err(value);
|
||||
|
|
|
|||
|
|
@ -1386,6 +1386,43 @@ impl<T> *const T {
|
|||
pub const fn cast_uninit(self) -> *const MaybeUninit<T> {
|
||||
self as _
|
||||
}
|
||||
|
||||
/// Forms a raw slice from a pointer and a length.
|
||||
///
|
||||
/// The `len` argument is the number of **elements**, not the number of bytes.
|
||||
///
|
||||
/// This function is safe, but actually using the return value is unsafe.
|
||||
/// See the documentation of [`slice::from_raw_parts`] for slice safety requirements.
|
||||
///
|
||||
/// [`slice::from_raw_parts`]: crate::slice::from_raw_parts
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// #![feature(ptr_cast_slice)]
|
||||
/// // create a slice pointer when starting out with a pointer to the first element
|
||||
/// let x = [5, 6, 7];
|
||||
/// let raw_pointer = x.as_ptr();
|
||||
/// let slice = raw_pointer.cast_slice(3);
|
||||
/// assert_eq!(unsafe { &*slice }[2], 7);
|
||||
/// ```
|
||||
///
|
||||
/// You must ensure that the pointer is valid and not null before dereferencing
|
||||
/// the raw slice. A slice reference must never have a null pointer, even if it's empty.
|
||||
///
|
||||
/// ```rust,should_panic
|
||||
/// #![feature(ptr_cast_slice)]
|
||||
/// use std::ptr;
|
||||
/// let danger: *const [u8] = ptr::null::<u8>().cast_slice(0);
|
||||
/// unsafe {
|
||||
/// danger.as_ref().expect("references must not be null");
|
||||
/// }
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "ptr_cast_slice", issue = "149103")]
|
||||
pub const fn cast_slice(self, len: usize) -> *const [T] {
|
||||
slice_from_raw_parts(self, len)
|
||||
}
|
||||
}
|
||||
impl<T> *const MaybeUninit<T> {
|
||||
/// Casts from a maybe-uninitialized type to its initialized version.
|
||||
|
|
|
|||
|
|
@ -1655,6 +1655,51 @@ impl<T> *mut T {
|
|||
pub const fn cast_uninit(self) -> *mut MaybeUninit<T> {
|
||||
self as _
|
||||
}
|
||||
|
||||
/// Forms a raw mutable slice from a pointer and a length.
|
||||
///
|
||||
/// The `len` argument is the number of **elements**, not the number of bytes.
|
||||
///
|
||||
/// Performs the same functionality as [`cast_slice`] on a `*const T`, except that a
|
||||
/// raw mutable slice is returned, as opposed to a raw immutable slice.
|
||||
///
|
||||
/// This function is safe, but actually using the return value is unsafe.
|
||||
/// See the documentation of [`slice::from_raw_parts_mut`] for slice safety requirements.
|
||||
///
|
||||
/// [`slice::from_raw_parts_mut`]: crate::slice::from_raw_parts_mut
|
||||
/// [`cast_slice`]: pointer::cast_slice
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// #![feature(ptr_cast_slice)]
|
||||
///
|
||||
/// let x = &mut [5, 6, 7];
|
||||
/// let slice = x.as_mut_ptr().cast_slice(3);
|
||||
///
|
||||
/// unsafe {
|
||||
/// (*slice)[2] = 99; // assign a value at an index in the slice
|
||||
/// };
|
||||
///
|
||||
/// assert_eq!(unsafe { &*slice }[2], 99);
|
||||
/// ```
|
||||
///
|
||||
/// You must ensure that the pointer is valid and not null before dereferencing
|
||||
/// the raw slice. A slice reference must never have a null pointer, even if it's empty.
|
||||
///
|
||||
/// ```rust,should_panic
|
||||
/// #![feature(ptr_cast_slice)]
|
||||
/// use std::ptr;
|
||||
/// let danger: *mut [u8] = ptr::null_mut::<u8>().cast_slice(0);
|
||||
/// unsafe {
|
||||
/// danger.as_mut().expect("references must not be null");
|
||||
/// }
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "ptr_cast_slice", issue = "149103")]
|
||||
pub const fn cast_slice(self, len: usize) -> *mut [T] {
|
||||
slice_from_raw_parts_mut(self, len)
|
||||
}
|
||||
}
|
||||
impl<T> *mut MaybeUninit<T> {
|
||||
/// Casts from a maybe-uninitialized type to its initialized version.
|
||||
|
|
|
|||
|
|
@ -1377,6 +1377,35 @@ impl<T> NonNull<T> {
|
|||
pub const fn cast_uninit(self) -> NonNull<MaybeUninit<T>> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
/// Creates a non-null raw slice from a thin pointer and a length.
|
||||
///
|
||||
/// The `len` argument is the number of **elements**, not the number of bytes.
|
||||
///
|
||||
/// This function is safe, but dereferencing the return value is unsafe.
|
||||
/// See the documentation of [`slice::from_raw_parts`] for slice safety requirements.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// #![feature(ptr_cast_slice)]
|
||||
/// use std::ptr::NonNull;
|
||||
///
|
||||
/// // create a slice pointer when starting out with a pointer to the first element
|
||||
/// let mut x = [5, 6, 7];
|
||||
/// let nonnull_pointer = NonNull::new(x.as_mut_ptr()).unwrap();
|
||||
/// let slice = nonnull_pointer.cast_slice(3);
|
||||
/// assert_eq!(unsafe { slice.as_ref()[2] }, 7);
|
||||
/// ```
|
||||
///
|
||||
/// (Note that this example artificially demonstrates a use of this method,
|
||||
/// but `let slice = NonNull::from(&x[..]);` would be a better way to write code like this.)
|
||||
#[inline]
|
||||
#[must_use]
|
||||
#[unstable(feature = "ptr_cast_slice", issue = "149103")]
|
||||
pub const fn cast_slice(self, len: usize) -> NonNull<[T]> {
|
||||
NonNull::slice_from_raw_parts(self, len)
|
||||
}
|
||||
}
|
||||
impl<T> NonNull<MaybeUninit<T>> {
|
||||
/// Casts from a maybe-uninitialized type to its initialized version.
|
||||
|
|
|
|||
|
|
@ -728,7 +728,7 @@ pub fn temp_dir() -> PathBuf {
|
|||
///
|
||||
/// You expected to safely execute the current executable, but you're
|
||||
/// instead executing something completely different. The code you
|
||||
/// just executed run with your privileges.
|
||||
/// just executed runs with your privileges.
|
||||
///
|
||||
/// This sort of behavior has been known to [lead to privilege escalation] when
|
||||
/// used incorrectly.
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ edition = "2024"
|
|||
|
||||
[dependencies]
|
||||
anyhow = "1"
|
||||
askama = "0.15.2"
|
||||
askama = "0.15.3"
|
||||
clap = { version = "4.5", features = ["derive"] }
|
||||
csv = "1"
|
||||
diff = "0.1"
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ path = "lib.rs"
|
|||
[dependencies]
|
||||
# tidy-alphabetical-start
|
||||
arrayvec = { version = "0.7", default-features = false }
|
||||
askama = { version = "0.15.2", default-features = false, features = ["alloc", "config", "derive"] }
|
||||
askama = { version = "0.15.3", default-features = false, features = ["alloc", "config", "derive"] }
|
||||
base64 = "0.21.7"
|
||||
indexmap = { version = "2", features = ["serde"] }
|
||||
itertools = "0.12"
|
||||
|
|
|
|||
|
|
@ -163,7 +163,7 @@ nav.sub {
|
|||
--headings-border-bottom-color: #d2d2d2;
|
||||
--border-color: #e0e0e0;
|
||||
--button-background-color: #f0f0f0;
|
||||
--right-side-color: grey;
|
||||
--right-side-color: #d0d0d0;
|
||||
--code-attribute-color: #999;
|
||||
--toggles-color: #999;
|
||||
--toggle-filter: invert(100%);
|
||||
|
|
|
|||
|
|
@ -359,7 +359,8 @@ summary.hideme,
|
|||
.rustdoc-breadcrumbs,
|
||||
.search-switcher,
|
||||
/* This selector is for the items listed in the "all items" page. */
|
||||
ul.all-items {
|
||||
ul.all-items,
|
||||
.deprecated-count {
|
||||
font-family: "Fira Sans", Arial, NanumBarunGothic, sans-serif;
|
||||
}
|
||||
|
||||
|
|
@ -2671,6 +2672,18 @@ However, it's not needed with smaller screen width because the doc/code block is
|
|||
display: none;
|
||||
}
|
||||
|
||||
.deprecated-count {
|
||||
display: none;
|
||||
}
|
||||
/*
|
||||
The `:not(:empty)` is a little trick to not have to add conditions in JS to hide/show the marker.
|
||||
It's entirely based on whether it has content and if the setting is enabled.
|
||||
*/
|
||||
.hide-deprecated-items .deprecated-count:not(:empty) {
|
||||
display: block;
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
/*
|
||||
WARNING: RUSTDOC_MOBILE_BREAKPOINT MEDIA QUERY
|
||||
If you update this line, then you also need to update the line with the same warning
|
||||
|
|
@ -3286,7 +3299,7 @@ by default.
|
|||
--headings-border-bottom-color: #d2d2d2;
|
||||
--border-color: #e0e0e0;
|
||||
--button-background-color: #f0f0f0;
|
||||
--right-side-color: grey;
|
||||
--right-side-color: #d0d0d0;
|
||||
--code-attribute-color: #999;
|
||||
--toggles-color: #999;
|
||||
--toggle-filter: invert(100%);
|
||||
|
|
|
|||
|
|
@ -158,6 +158,7 @@ const REGEX_INVALID_TYPE_FILTER = /[^a-z]/ui;
|
|||
|
||||
const MAX_RESULTS = 200;
|
||||
const NO_TYPE_FILTER = -1;
|
||||
const DEPRECATED_COUNT_SELECTOR = "deprecated-count";
|
||||
|
||||
/**
|
||||
* The [edit distance] is a metric for measuring the difference between two strings.
|
||||
|
|
@ -4904,7 +4905,12 @@ async function addTab(results, query, display, finishedCallback, isTypeSearch) {
|
|||
let output = document.createElement("ul");
|
||||
output.className = "search-results " + extraClass;
|
||||
|
||||
const deprecatedCountElem = document.createElement("span");
|
||||
deprecatedCountElem.className = DEPRECATED_COUNT_SELECTOR;
|
||||
output.appendChild(deprecatedCountElem);
|
||||
|
||||
let count = 0;
|
||||
let deprecatedCount = 0;
|
||||
|
||||
/** @type {Promise<string|null>[]} */
|
||||
const descList = [];
|
||||
|
|
@ -4922,6 +4928,10 @@ async function addTab(results, query, display, finishedCallback, isTypeSearch) {
|
|||
link.className = "result-" + type;
|
||||
if (obj.item.deprecated) {
|
||||
link.className += " deprecated";
|
||||
deprecatedCount += 1;
|
||||
const plural = deprecatedCount > 1 ? "s" : "";
|
||||
deprecatedCountElem.innerText =
|
||||
`${deprecatedCount} deprecated item${plural} hidden by setting`;
|
||||
}
|
||||
link.href = obj.href;
|
||||
|
||||
|
|
@ -5411,7 +5421,7 @@ function registerSearchEvents() {
|
|||
const active = document.activeElement;
|
||||
if (active) {
|
||||
const previous = active.previousElementSibling;
|
||||
if (previous) {
|
||||
if (previous && previous.className !== DEPRECATED_COUNT_SELECTOR) {
|
||||
// @ts-expect-error
|
||||
previous.focus();
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ description = "Produces a manifest of all the copyrighted materials in the Rust
|
|||
|
||||
[dependencies]
|
||||
anyhow = "1.0.65"
|
||||
askama = "0.15.2"
|
||||
askama = "0.15.3"
|
||||
cargo_metadata = "0.21"
|
||||
serde = { version = "1.0.147", features = ["derive"] }
|
||||
serde_json = "1.0.85"
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ fn main() {
|
|||
let npm: PathBuf = env::args_os().nth(5).expect("need name/path of npm command").into();
|
||||
|
||||
let root_manifest = root_path.join("Cargo.toml");
|
||||
let typos_toml = root_path.join("typos.toml");
|
||||
let src_path = root_path.join("src");
|
||||
let tests_path = root_path.join("tests");
|
||||
let library_path = root_path.join("library");
|
||||
|
|
@ -143,6 +144,7 @@ fn main() {
|
|||
check!(edition, &library_path);
|
||||
|
||||
check!(alphabetical, &root_manifest);
|
||||
check!(alphabetical, &typos_toml);
|
||||
check!(alphabetical, &src_path);
|
||||
check!(alphabetical, &tests_path);
|
||||
check!(alphabetical, &compiler_path);
|
||||
|
|
|
|||
|
|
@ -73,6 +73,57 @@ pub fn check(root_path: &Path, tidy_ctx: TidyCtx) {
|
|||
));
|
||||
}
|
||||
}
|
||||
|
||||
// The list of subdirectories in ui tests.
|
||||
// Compare previous subdirectory with current subdirectory
|
||||
// to sync with `tests/ui/README.md`.
|
||||
// See <https://github.com/rust-lang/rust/issues/150399>
|
||||
let mut prev_line = String::new();
|
||||
let mut is_sorted = true;
|
||||
let documented_subdirs: BTreeSet<_> = include_str!("../../../../tests/ui/README.md")
|
||||
.lines()
|
||||
.filter_map(|line| {
|
||||
static_regex!(r"^##.*?`(?<dir>[^`]+)`").captures(line).map(|cap| {
|
||||
let dir = &cap["dir"];
|
||||
// FIXME(reddevilmidzy) normalize subdirs title in tests/ui/README.md
|
||||
if dir.ends_with('/') {
|
||||
dir.strip_suffix('/').unwrap().to_string()
|
||||
} else {
|
||||
dir.to_string()
|
||||
}
|
||||
})
|
||||
})
|
||||
.inspect(|line| {
|
||||
if prev_line.as_str() > line.as_str() {
|
||||
is_sorted = false;
|
||||
}
|
||||
|
||||
prev_line = line.clone();
|
||||
})
|
||||
.collect();
|
||||
let filesystem_subdirs = collect_ui_tests_subdirs(&path);
|
||||
let is_modified = !filesystem_subdirs.eq(&documented_subdirs);
|
||||
|
||||
if !is_sorted {
|
||||
check.error("`tests/ui/README.md` is not in order");
|
||||
}
|
||||
if is_modified {
|
||||
for directory in documented_subdirs.symmetric_difference(&filesystem_subdirs) {
|
||||
if documented_subdirs.contains(directory) {
|
||||
check.error(format!(
|
||||
"ui subdirectory `{directory}` is listed in `tests/ui/README.md` but does not exist in the filesystem"
|
||||
));
|
||||
} else {
|
||||
check.error(format!(
|
||||
"ui subdirectory `{directory}` exists in the filesystem but is not documented in `tests/ui/README.md`"
|
||||
));
|
||||
}
|
||||
}
|
||||
check.error(
|
||||
"`tests/ui/README.md` subdirectory listing is out of sync with the filesystem. \
|
||||
Please add or remove subdirectory entries (## headers with backtick-wrapped names) to match the actual directories in `tests/ui/`"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn deny_new_top_level_ui_tests(check: &mut RunningCheck, tests_path: &Path) {
|
||||
|
|
@ -137,6 +188,24 @@ fn recursively_check_ui_tests<'issues>(
|
|||
remaining_issue_names
|
||||
}
|
||||
|
||||
fn collect_ui_tests_subdirs(path: &Path) -> BTreeSet<String> {
|
||||
let ui = path.join("ui");
|
||||
let entries = std::fs::read_dir(ui.as_path()).unwrap();
|
||||
|
||||
entries
|
||||
.filter_map(|entry| entry.ok())
|
||||
.map(|entry| entry.path())
|
||||
.filter(|path| path.is_dir())
|
||||
.map(|dir_path| {
|
||||
let dir_path = dir_path.strip_prefix(path).unwrap();
|
||||
format!(
|
||||
"tests/{}",
|
||||
dir_path.to_string_lossy().replace(std::path::MAIN_SEPARATOR_STR, "/")
|
||||
)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn check_unexpected_extension(check: &mut RunningCheck, file_path: &Path, ext: &str) {
|
||||
const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[
|
||||
"rs", // test source files
|
||||
|
|
|
|||
|
|
@ -221,14 +221,14 @@ call-function: (
|
|||
|
||||
define-function: (
|
||||
"check-since-color",
|
||||
[theme],
|
||||
[theme, color],
|
||||
block {
|
||||
call-function: ("switch-theme", {"theme": |theme|})
|
||||
assert-css: (".since", {"color": "#808080"}, ALL)
|
||||
assert-css: (".since", {"color": |color|}, ALL)
|
||||
},
|
||||
)
|
||||
|
||||
go-to: "file://" + |DOC_PATH| + "/staged_api/struct.Foo.html"
|
||||
call-function: ("check-since-color", {"theme": "ayu"})
|
||||
call-function: ("check-since-color", {"theme": "dark"})
|
||||
call-function: ("check-since-color", {"theme": "light"})
|
||||
call-function: ("check-since-color", {"theme": "ayu", "color": "#808080"})
|
||||
call-function: ("check-since-color", {"theme": "dark", "color": "#d0d0d0"})
|
||||
call-function: ("check-since-color", {"theme": "light", "color": "#808080"})
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ wait-for-css: ("details" + |deprecated_class|, {"display": "block"}, ALL)
|
|||
|
||||
// And now we check with the search results.
|
||||
call-function: ("perform-search", {"query": "deprecated::depr"})
|
||||
// There should at least 7 results.
|
||||
// There should be at least 7 results.
|
||||
store-count: ("#results ul.search-results.active > a", nb_search_results)
|
||||
assert: |nb_search_results| >= 7
|
||||
// There should be at least 5 deprecated items.
|
||||
|
|
@ -77,6 +77,12 @@ store-count: ("#results ul.search-results.active > a" + |deprecated_class|, nb_d
|
|||
assert: |nb_search_results| >= 5
|
||||
// Deprecated items should all be displayed.
|
||||
assert-css: ("#results ul.search-results.active > a" + |deprecated_class|, {"display": "grid"}, ALL)
|
||||
// The "X deprecated items hidden by setting" element should not be displayed.
|
||||
assert-text: (
|
||||
"#results ul.search-results.active .deprecated-count",
|
||||
"5 deprecated items hidden by setting",
|
||||
)
|
||||
assert-css: ("#results ul.search-results.active .deprecated-count", {"display": "none"})
|
||||
// We enable the "hide deprecated items" setting.
|
||||
call-function: ("open-settings-menu", {})
|
||||
click: "#hide-deprecated-items"
|
||||
|
|
@ -86,11 +92,16 @@ wait-for-css: (
|
|||
{"display": "none"},
|
||||
ALL,
|
||||
)
|
||||
// The "X deprecated items hidden by setting" element should be displayed.
|
||||
assert-css: ("#results ul.search-results.active .deprecated-count", {"display": "block"})
|
||||
|
||||
// Finally we check that the future deprecated item doesn't have the deprecated class in the search
|
||||
// and therefore isn't impact by the setting.
|
||||
call-function: ("perform-search", {"query": "deprecated::future_deprecated"})
|
||||
// and therefore isn't impacted by the setting.
|
||||
call-function: ("perform-search", {"query": '"future_deprecated_fn"'})
|
||||
assert-text: (
|
||||
"#results ul.search-results.active > a:not(" + |deprecated_class| + ") .path",
|
||||
" lib2::deprecated::NonDeprecatedStruct::future_deprecated_fn",
|
||||
)
|
||||
// The "X deprecated items hidden by setting" element should now be empty, and therefore not displayed.
|
||||
assert-text: ("#results ul.search-results.active .deprecated-count", "")
|
||||
assert-css: ("#results ul.search-results.active .deprecated-count", {"display": "none"})
|
||||
|
|
|
|||
|
|
@ -10,17 +10,23 @@ These tests deal with *Application Binary Interfaces* (ABI), mostly relating to
|
|||
|
||||
Tests for unsupported ABIs can be made cross-platform by using the `extern "rust-invalid"` ABI, which is considered unsupported on every platform.
|
||||
|
||||
## `tests/ui/alloc-error`
|
||||
|
||||
These tests exercise alloc error handling.
|
||||
|
||||
See <https://doc.rust-lang.org/std/alloc/fn.handle_alloc_error.html>.
|
||||
|
||||
## `tests/ui/allocator`
|
||||
|
||||
These tests exercise `#![feature(allocator_api)]` and the `#[global_allocator]` attribute.
|
||||
|
||||
See [Allocator traits and `std::heap` #32838](https://github.com/rust-lang/rust/issues/32838).
|
||||
|
||||
## `tests/ui/alloc-error`
|
||||
## `tests/ui/annotate-moves`
|
||||
|
||||
These tests exercise alloc error handling.
|
||||
These tests exercise the `annotate-moves` feature.
|
||||
|
||||
See <https://doc.rust-lang.org/std/alloc/fn.handle_alloc_error.html>.
|
||||
See [`annotate-moves` | The Unstable book](https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/annotate-moves.html)
|
||||
|
||||
## `tests/ui/annotate-snippet`
|
||||
|
||||
|
|
@ -34,20 +40,26 @@ These tests exercise the [`annotate-snippets`]-based emitter implementation.
|
|||
|
||||
These tests deal with anonymous parameters (no name, only type), a deprecated feature that becomes a hard error in Edition 2018.
|
||||
|
||||
## `tests/ui/any`
|
||||
|
||||
These tests exercise the `try_as_dyn` feature.
|
||||
|
||||
See [`core::any::try_as_dyn`](https://doc.rust-lang.org/nightly/core/any/fn.try_as_dyn.html)
|
||||
|
||||
## `tests/ui/argfile`: External files providing command line arguments
|
||||
|
||||
These tests exercise rustc reading command line arguments from an externally provided argfile (`@argsfile`).
|
||||
|
||||
See [Implement `@argsfile` to read arguments from command line #63576](https://github.com/rust-lang/rust/issues/63576).
|
||||
|
||||
## `tests/ui/array-slice-vec`: Arrays, slices and vectors
|
||||
|
||||
Exercises various aspects surrounding basic collection types `[]`, `&[]` and `Vec`. E.g. type-checking, out-of-bounds indices, attempted instructions which are allowed in other programming languages, and more.
|
||||
|
||||
## `tests/ui/argument-suggestions`: Argument suggestions
|
||||
|
||||
Calling a function with the wrong number of arguments causes a compilation failure, but the compiler is able to, in some cases, provide suggestions on how to fix the error, such as which arguments to add or delete. These tests exercise the quality of such diagnostics.
|
||||
|
||||
## `tests/ui/array-slice-vec`: Arrays, slices and vectors
|
||||
|
||||
Exercises various aspects surrounding basic collection types `[]`, `&[]` and `Vec`. E.g. type-checking, out-of-bounds indices, attempted instructions which are allowed in other programming languages, and more.
|
||||
|
||||
## `tests/ui/asm`: `asm!` macro
|
||||
|
||||
These tests exercise the `asm!` macro, which is used for adding inline assembly.
|
||||
|
|
@ -172,6 +184,10 @@ See [RFC 3729: Hierarchy of Sized traits](https://github.com/rust-lang/rfcs/pull
|
|||
|
||||
Defining custom auto traits with the `auto` keyword belongs to `tests/ui/auto-traits/` instead.
|
||||
|
||||
## `tests/ui/c-variadic`: C Variadic Function
|
||||
|
||||
Tests for FFI with C varargs (`va_list`).
|
||||
|
||||
## `tests/ui/cast/`: Type Casting
|
||||
|
||||
Tests for type casting using the `as` operator. Includes tests for valid/invalid casts between primitive types, trait objects, and custom types. For example, check that trying to cast `i32` into `bool` results in a helpful error message.
|
||||
|
|
@ -190,16 +206,16 @@ Tests for the `--check-cfg` compiler mechanism for checking cfg configurations,
|
|||
|
||||
See [Checking conditional configurations | The rustc book](https://doc.rust-lang.org/rustc/check-cfg.html).
|
||||
|
||||
## `tests/ui/closure_context/`: Closure type inference in context
|
||||
|
||||
Tests for closure type inference with respect to surrounding scopes, mostly quality of diagnostics.
|
||||
|
||||
## `tests/ui/closure-expected-type/`: Closure type inference
|
||||
|
||||
Tests targeted at how we deduce the types of closure arguments. This process is a result of some heuristics which take into account the *expected type* we have alongside the *actual types* that we get from inputs.
|
||||
|
||||
**FIXME**: Appears to have significant overlap with `tests/ui/closure_context` and `tests/ui/functions-closures/closure-expected-type`. Needs further investigation.
|
||||
|
||||
## `tests/ui/closure_context`: Closure type inference in context
|
||||
|
||||
Tests for closure type inference with respect to surrounding scopes, mostly quality of diagnostics.
|
||||
|
||||
## `tests/ui/closures/`: General Closure Tests
|
||||
|
||||
Any closure-focused tests that does not fit in the other more specific closure subdirectories belong here. E.g. syntax, `move`, lifetimes.
|
||||
|
|
@ -244,6 +260,14 @@ See:
|
|||
|
||||
This directory only contains one highly specific test. Other coinduction tests can be found down the deeply located `tests/ui/traits/next-solver/cycles/coinduction/` subdirectory.
|
||||
|
||||
## `tests/ui/collections`
|
||||
|
||||
These tests exercise the `collections` library.
|
||||
|
||||
See [`std::collections`](https://doc.rust-lang.org/std/collections/index.html)
|
||||
|
||||
**FIXME**: consider merge with `tests/ui/btreemap` and `tests/ui/hashmap`
|
||||
|
||||
## `tests/ui/command/`: `std::process::Command`
|
||||
|
||||
This directory is actually for the standard library [`std::process::Command`](https://doc.rust-lang.org/std/process/struct.Command.html) type, where some tests are too difficult or inconvenient to write as unit tests or integration tests within the standard library itself.
|
||||
|
|
@ -285,10 +309,6 @@ See:
|
|||
- [Tracking Issue for complex generic constants: `feature(generic_const_exprs)` #76560](https://github.com/rust-lang/rust/issues/76560)
|
||||
- [Const generics | Reference](https://doc.rust-lang.org/reference/items/generics.html#const-generics)
|
||||
|
||||
## `tests/ui/const_prop/`: Constant Propagation
|
||||
|
||||
Tests exercising `ConstProp` mir-opt pass (mostly regression tests). See <https://blog.rust-lang.org/inside-rust/2019/12/02/const-prop-on-by-default/>.
|
||||
|
||||
## `tests/ui/const-ptr/`: Constant Pointers
|
||||
|
||||
Tests exercise const raw pointers. E.g. pointer arithmetic, casting and dereferencing, always with a `const`.
|
||||
|
|
@ -299,6 +319,10 @@ See:
|
|||
- [`std::ptr`](https://doc.rust-lang.org/std/ptr/index.html)
|
||||
- [Pointer types | Reference](https://doc.rust-lang.org/reference/types/pointer.html)
|
||||
|
||||
## `tests/ui/const_prop`: Constant Propagation
|
||||
|
||||
Tests exercising `ConstProp` mir-opt pass (mostly regression tests). See <https://blog.rust-lang.org/inside-rust/2019/12/02/const-prop-on-by-default/>.
|
||||
|
||||
## `tests/ui/consts/`: General Constant Evaluation
|
||||
|
||||
Anything to do with constants, which does not fit in the previous two `const` categories, goes here. This does not always imply use of the `const` keyword - other values considered constant, such as defining an enum variant as `enum Foo { Variant = 5 }` also counts.
|
||||
|
|
@ -340,10 +364,6 @@ Tests for `#[bench]`, `#[test_case]` attributes and the `custom_test_frameworks`
|
|||
|
||||
See [Tracking issue for eRFC 2318, Custom test frameworks #50297](https://github.com/rust-lang/rust/issues/50297).
|
||||
|
||||
## `tests/ui/c-variadic/`: C Variadic Function
|
||||
|
||||
Tests for FFI with C varargs (`va_list`).
|
||||
|
||||
## `tests/ui/cycle-trait/`: Trait Cycle Detection
|
||||
|
||||
Tests for detection and handling of cyclic trait dependencies.
|
||||
|
|
@ -380,6 +400,18 @@ These tests use the unstable command line option `query-dep-graph` to examine th
|
|||
|
||||
Tests for `#[deprecated]` attribute and `deprecated_in_future` internal lint.
|
||||
|
||||
## `tests/ui/deref`
|
||||
|
||||
Tests for `Deref` and `DerefMut` traits.
|
||||
|
||||
## `tests/ui/deref-patterns`: `#![feature(deref_patterns)]` and `#![feature(string_deref_patterns)]`
|
||||
|
||||
Tests for `#![feature(deref_patterns)]` and `#![feature(string_deref_patterns)]`. See [Deref patterns | The Unstable book](https://doc.rust-lang.org/nightly/unstable-book/language-features/deref-patterns.html).
|
||||
|
||||
**FIXME**: May have some overlap with `tests/ui/pattern/deref-patterns`.
|
||||
|
||||
See [`std::ops::Deref`](https://doc.rust-lang.org/std/ops/trait.Deref.html) and [`std::ops::DerefMut`](https://doc.rust-lang.org/std/ops/trait.DerefMut.html)
|
||||
|
||||
## `tests/ui/derived-errors/`: Derived Error Messages
|
||||
|
||||
Tests for quality of diagnostics involving suppression of cascading errors in some cases to avoid overwhelming the user.
|
||||
|
|
@ -406,6 +438,10 @@ These tests revolve around command-line flags which change the way error/warning
|
|||
|
||||
**FIXME**: Check redundancy with `annotate-snippet`, which is another emitter.
|
||||
|
||||
## `tests/ui/diagnostic-width`: `--diagnostic-width`
|
||||
|
||||
Everything to do with `--diagnostic-width`.
|
||||
|
||||
## `tests/ui/diagnostic_namespace/`
|
||||
|
||||
Exercises `#[diagnostic::*]` namespaced attributes. See [RFC 3368 Diagnostic attribute namespace](https://github.com/rust-lang/rfcs/blob/master/text/3368-diagnostic-attribute-namespace.md).
|
||||
|
|
@ -414,10 +450,6 @@ Exercises `#[diagnostic::*]` namespaced attributes. See [RFC 3368 Diagnostic att
|
|||
|
||||
This directory contains tests and infrastructure related to the diagnostics system, including support for translatable diagnostics
|
||||
|
||||
## `tests/ui/diagnostic-width/`: `--diagnostic-width`
|
||||
|
||||
Everything to do with `--diagnostic-width`.
|
||||
|
||||
## `tests/ui/did_you_mean/`
|
||||
|
||||
Tests for miscellaneous suggestions.
|
||||
|
|
@ -430,6 +462,10 @@ Exercises diagnostics for when a code block attempts to gain ownership of a non-
|
|||
|
||||
Exercises diagnostics for disallowed struct destructuring.
|
||||
|
||||
## `tests/ui/dist`
|
||||
|
||||
Tests that require distribution artifacts.
|
||||
|
||||
## `tests/ui/dollar-crate/`: `$crate` used with the `use` keyword
|
||||
|
||||
There are a few rules - which are checked in this directory - to follow when using `$crate` - it must be used in the start of a `use` line and is a reserved identifier.
|
||||
|
|
@ -461,10 +497,6 @@ Tests for dynamically-sized types (DSTs). See [Dynamically Sized Types | Referen
|
|||
|
||||
Tests about duplicated symbol names and associated errors, such as using the `#[export_name]` attribute to rename a function with the same name as another function.
|
||||
|
||||
## `tests/ui/dynamically-sized-types/`: Dynamically Sized Types
|
||||
|
||||
**FIXME**: should be coalesced with `tests/ui/dst`.
|
||||
|
||||
## `tests/ui/dyn-compatibility/`: Dyn-compatibility
|
||||
|
||||
Tests for dyn-compatibility of traits.
|
||||
|
|
@ -486,12 +518,20 @@ The `dyn` keyword is used to highlight that calls to methods on the associated T
|
|||
|
||||
See [`dyn` keyword](https://doc.rust-lang.org/std/keyword.dyn.html).
|
||||
|
||||
## `tests/ui/dynamically-sized-types`: Dynamically Sized Types
|
||||
|
||||
**FIXME**: should be coalesced with `tests/ui/dst`.
|
||||
|
||||
## `tests/ui/editions/`: Rust edition-specific peculiarities
|
||||
|
||||
These tests run in specific Rust editions, such as Rust 2015 or Rust 2018, and check errors and functionality related to specific now-deprecated idioms and features.
|
||||
|
||||
**FIXME**: Maybe regroup `rust-2018`, `rust-2021` and `rust-2024` under this umbrella?
|
||||
|
||||
## `tests/ui/eii`: Externally Implementable Items
|
||||
|
||||
Exercises `eii` keyword.
|
||||
|
||||
## `tests/ui/empty/`: Various tests related to the concept of "empty"
|
||||
|
||||
**FIXME**: These tests need better homes, this is not very informative.
|
||||
|
|
@ -571,6 +611,10 @@ See:
|
|||
- [`ffi_const` | The Unstable book](https://doc.rust-lang.org/unstable-book/language-features/ffi-const.html)
|
||||
- [`ffi_pure` | The Unstable book](https://doc.rust-lang.org/beta/unstable-book/language-features/ffi-pure.html)
|
||||
|
||||
## `tests/ui/float`
|
||||
|
||||
See: [Tracking Issue for `f16` and `f128` float types #116909](https://github.com/rust-lang/rust/issues/116909)
|
||||
|
||||
## `tests/ui/fmt/`
|
||||
|
||||
Exercises the `format!` macro.
|
||||
|
|
@ -579,6 +623,16 @@ Exercises the `format!` macro.
|
|||
|
||||
A broad category of tests on functions.
|
||||
|
||||
## `tests/ui/fn_traits`
|
||||
|
||||
Tests for `#![feature(fn_traits)]`. See [`fn_traits` | The Unstable book](https://doc.rust-lang.org/nightly/unstable-book/library-features/fn-traits.html).
|
||||
|
||||
## `tests/ui/for-loop-while`
|
||||
|
||||
Anything to do with loops and `for`, `loop` and `while` keywords to express them.
|
||||
|
||||
**FIXME**: After `ui/for` is merged into this, also carry over its SUMMARY text.
|
||||
|
||||
## `tests/ui/force-inlining/`: `#[rustc_force_inline]`
|
||||
|
||||
Tests for `#[rustc_force_inline]`, which will force a function to always be labelled as inline by the compiler (it will be inserted at the point of its call instead of being used as a normal function call.) If the compiler is unable to inline the function, an error will be reported. See <https://github.com/rust-lang/rust/pull/134082>.
|
||||
|
|
@ -589,12 +643,6 @@ Tests for `extern "C"` and `extern "Rust`.
|
|||
|
||||
**FIXME**: Check for potential overlap/merge with `ui/c-variadic` and/or `ui/extern`.
|
||||
|
||||
## `tests/ui/for-loop-while/`
|
||||
|
||||
Anything to do with loops and `for`, `loop` and `while` keywords to express them.
|
||||
|
||||
**FIXME**: After `ui/for` is merged into this, also carry over its SUMMARY text.
|
||||
|
||||
## `tests/ui/frontmatter/`
|
||||
|
||||
Tests for `#![feature(frontmatter)]`. See [Tracking Issue for `frontmatter` #136889](https://github.com/rust-lang/rust/issues/136889).
|
||||
|
|
@ -603,12 +651,6 @@ Tests for `#![feature(frontmatter)]`. See [Tracking Issue for `frontmatter` #136
|
|||
|
||||
Tests for diagnostics when there may be identically named types that need further qualifications to disambiguate.
|
||||
|
||||
## `tests/ui/functional-struct-update/`
|
||||
|
||||
Functional Struct Update is the name for the idiom by which one can write `..<expr>` at the end of a struct literal expression to fill in all remaining fields of the struct literal by using `<expr>` as the source for them.
|
||||
|
||||
See [RFC 0736 Privacy-respecting Functional Struct Update](https://github.com/rust-lang/rfcs/blob/master/text/0736-privacy-respecting-fru.md).
|
||||
|
||||
## `tests/ui/function-pointer/`
|
||||
|
||||
Tests on function pointers, such as testing their compatibility with higher-ranked trait bounds.
|
||||
|
|
@ -618,6 +660,12 @@ See:
|
|||
- [Function pointer types | Reference](https://doc.rust-lang.org/reference/types/function-pointer.html)
|
||||
- [Higher-ranked trait bounds | Nomicon](https://doc.rust-lang.org/nomicon/hrtb.html)
|
||||
|
||||
## `tests/ui/functional-struct-update/`
|
||||
|
||||
Functional Struct Update is the name for the idiom by which one can write `..<expr>` at the end of a struct literal expression to fill in all remaining fields of the struct literal by using `<expr>` as the source for them.
|
||||
|
||||
See [RFC 0736 Privacy-respecting Functional Struct Update](https://github.com/rust-lang/rfcs/blob/master/text/0736-privacy-respecting-fru.md).
|
||||
|
||||
## `tests/ui/functions-closures/`
|
||||
|
||||
Tests on closures. See [Closure expressions | Reference](https://doc.rust-lang.org/reference/expressions/closure-expr.html).
|
||||
|
|
@ -653,6 +701,10 @@ See:
|
|||
- [Higher-ranked trait bounds | rustc-dev-guide](https://rustc-dev-guide.rust-lang.org/traits/hrtb.html)
|
||||
- [Higher-ranked trait bounds | Nomicon](https://doc.rust-lang.org/nomicon/hrtb.html)
|
||||
|
||||
## `tests/ui/higher-ranked-trait-bounds`
|
||||
|
||||
**FIXME**: move to `tests/ui/higher-ranked/trait-bounds`
|
||||
|
||||
## `tests/ui/hygiene/`
|
||||
|
||||
This seems to have been originally intended for "hygienic macros" - macros which work in all contexts, independent of what surrounds them. However, this category has grown into a mish-mash of many tests that may belong in the other directories.
|
||||
|
|
@ -669,14 +721,14 @@ This test category revolves around trait objects with `Sized` having illegal ope
|
|||
|
||||
Tests on lifetime elision in impl function signatures. See [Lifetime elision | Nomicon](https://doc.rust-lang.org/nomicon/lifetime-elision.html).
|
||||
|
||||
## `tests/ui/implied-bounds/`
|
||||
|
||||
See [Implied bounds | Reference](https://doc.rust-lang.org/reference/trait-bounds.html#implied-bounds).
|
||||
|
||||
## `tests/ui/impl-trait/`
|
||||
|
||||
Tests for trait impls.
|
||||
|
||||
## `tests/ui/implied-bounds/`
|
||||
|
||||
See [Implied bounds | Reference](https://doc.rust-lang.org/reference/trait-bounds.html#implied-bounds).
|
||||
|
||||
## `tests/ui/imports/`
|
||||
|
||||
Tests for module system and imports.
|
||||
|
|
@ -802,6 +854,12 @@ Broad directory on lifetimes, including proper specifiers, lifetimes not living
|
|||
|
||||
These tests exercises numerical limits, such as `[[u8; 1518599999]; 1518600000]`.
|
||||
|
||||
## `tests/ui/link-native-libs/`
|
||||
|
||||
Tests for `#[link(name = "", kind = "")]` and `-l` command line flag.
|
||||
|
||||
See [Tracking Issue for linking modifiers for native libraries #81490](https://github.com/rust-lang/rust/issues/81490).
|
||||
|
||||
## `tests/ui/linkage-attr/`
|
||||
|
||||
Tests for the linkage attribute `#[linkage]` of `#![feature(linkage)]`.
|
||||
|
|
@ -814,12 +872,6 @@ Tests on code which fails during the linking stage, or which contain arguments a
|
|||
|
||||
See [Linkage | Reference](https://doc.rust-lang.org/reference/linkage.html).
|
||||
|
||||
## `tests/ui/link-native-libs/`
|
||||
|
||||
Tests for `#[link(name = "", kind = "")]` and `-l` command line flag.
|
||||
|
||||
See [Tracking Issue for linking modifiers for native libraries #81490](https://github.com/rust-lang/rust/issues/81490).
|
||||
|
||||
## `tests/ui/lint/`
|
||||
|
||||
Tests for the lint infrastructure, lint levels, lint reasons, etc.
|
||||
|
|
@ -835,6 +887,10 @@ Tests exercising analysis for unused variables, unreachable statements, function
|
|||
|
||||
**FIXME**: This seems unrelated to "liveness" as defined in the rustc compiler guide. Is this misleadingly named? https://rustc-dev-guide.rust-lang.org/borrow_check/region_inference/lifetime_parameters.html#liveness-and-universal-regions
|
||||
|
||||
## `tests/ui/loop-match`
|
||||
|
||||
Tests for `loop` with `match` expressions.
|
||||
|
||||
## `tests/ui/loops/`
|
||||
|
||||
Tests on the `loop` construct.
|
||||
|
|
@ -941,6 +997,10 @@ See [RFC 3550 New Range](https://github.com/rust-lang/rfcs/blob/master/text/3550
|
|||
|
||||
Tests for Non-lexical lifetimes. See [RFC 2094 NLL](https://rust-lang.github.io/rfcs/2094-nll.html).
|
||||
|
||||
## `tests/ui/no_std/`
|
||||
|
||||
Tests for where the standard library is disabled through `#![no_std]`.
|
||||
|
||||
## `tests/ui/non_modrs_mods/`
|
||||
|
||||
Despite the size of the directory, this is a single test, spawning a sprawling `mod` dependency tree and checking its successful build.
|
||||
|
|
@ -953,10 +1013,6 @@ A very similar principle as `non_modrs_mods`, but with an added inline `mod` sta
|
|||
|
||||
**FIXME**: Consider merge with `tests/ui/modules/`, keeping the directory structure.
|
||||
|
||||
## `tests/ui/no_std/`
|
||||
|
||||
Tests for where the standard library is disabled through `#![no_std]`.
|
||||
|
||||
## `tests/ui/not-panic/`
|
||||
|
||||
Tests checking various types, such as `&RefCell<i32>`, and whether they are not `UnwindSafe` as expected.
|
||||
|
|
@ -981,6 +1037,15 @@ Contains a single test. Check that we reject the ancient Rust syntax `x <- y` an
|
|||
|
||||
**FIXME**: Definitely should be rehomed, maybe to `tests/ui/deprecation/`.
|
||||
|
||||
## `tests/ui/offload`
|
||||
|
||||
Exercises the offload feature.
|
||||
|
||||
See:
|
||||
|
||||
- [`std::offload` | rustc-dev-guide](https://rustc-dev-guide.rust-lang.org/offload/internals.html)
|
||||
- [Tracking Issue for GPU-offload #131513](https://github.com/rust-lang/rust/issues/131513)
|
||||
|
||||
## `tests/ui/offset-of/`
|
||||
|
||||
Exercises the [`std::mem::offset_of` macro](https://doc.rust-lang.org/beta/std/mem/macro.offset_of.html).
|
||||
|
|
@ -1039,6 +1104,16 @@ Broad category of tests surrounding patterns. See [Patterns | Reference](https:/
|
|||
|
||||
**FIXME**: Some overlap with `tests/ui/match/`.
|
||||
|
||||
## `tests/ui/pin`
|
||||
|
||||
**FIXME**: Consider merging with `tests/ui/pin-macro`.
|
||||
|
||||
## `tests/ui/pin-ergonomics`
|
||||
|
||||
Exercises the `#![feature(pin_ergonomics)]` feature.
|
||||
|
||||
See [Tracking issue for pin ergonomics #130494](https://github.com/rust-lang/rust/issues/130494)
|
||||
|
||||
## `tests/ui/pin-macro/`
|
||||
|
||||
See [`std::pin`](https://doc.rust-lang.org/std/pin/).
|
||||
|
|
@ -1059,6 +1134,10 @@ Exercises the `-Z print-type-sizes` flag.
|
|||
|
||||
Exercises on name privacy. E.g. the meaning of `pub`, `pub(crate)`, etc.
|
||||
|
||||
## `tests/ui/proc-macro/`
|
||||
|
||||
Broad category of tests on proc-macros. See [Procedural Macros | Reference](https://doc.rust-lang.org/reference/procedural-macros.html).
|
||||
|
||||
## `tests/ui/process/`
|
||||
|
||||
Some standard library process tests which are hard to write within standard library crate tests.
|
||||
|
|
@ -1067,10 +1146,6 @@ Some standard library process tests which are hard to write within standard libr
|
|||
|
||||
Some standard library process termination tests which are hard to write within standard library crate tests.
|
||||
|
||||
## `tests/ui/proc-macro/`
|
||||
|
||||
Broad category of tests on proc-macros. See [Procedural Macros | Reference](https://doc.rust-lang.org/reference/procedural-macros.html).
|
||||
|
||||
## `tests/ui/ptr_ops/`: Using operations on a pointer
|
||||
|
||||
Contains only 2 tests, related to a single issue, which was about an error caused by using addition on a pointer to `i8`.
|
||||
|
|
@ -1103,6 +1178,12 @@ Reachability tests, primarily unreachable code and coercions into the never type
|
|||
|
||||
**FIXME**: Check for overlap with `ui/liveness`.
|
||||
|
||||
## `tests/ui/reborrow`
|
||||
|
||||
Exercises the `#![feature(reborrow)]` feature.
|
||||
|
||||
See [Tracking Issue for Reborrow trait lang experiment #145612](https://github.com/rust-lang/rust/issues/145612)
|
||||
|
||||
## `tests/ui/recursion/`
|
||||
|
||||
Broad category of tests exercising recursions (compile test and run time), in functions, macros, `type` definitions, and more.
|
||||
|
|
@ -1115,6 +1196,12 @@ Sets a recursion limit on recursive code.
|
|||
|
||||
**FIXME**: Should be merged with `tests/ui/recursion/`.
|
||||
|
||||
## `tests/ui/reflection/`
|
||||
|
||||
Exercises the `#![feature(type_info)]` feature.
|
||||
|
||||
See [Tracking Issue for type_info #146922](https://github.com/rust-lang/rust/issues/146922)
|
||||
|
||||
## `tests/ui/regions/`
|
||||
|
||||
**FIXME**: Maybe merge with `ui/lifetimes`.
|
||||
|
|
@ -1157,22 +1244,44 @@ Exercises `.rmeta` crate metadata and the `--emit=metadata` cli flag.
|
|||
|
||||
Tests for runtime environment on which Rust programs are executed. E.g. Unix `SIGPIPE`.
|
||||
|
||||
## `tests/ui/rust-{2018,2021,2024}/`
|
||||
## `tests/ui/rust-2018`
|
||||
|
||||
Tests that exercise behaviors and features that are specific to editions.
|
||||
Tests that exercise behaviors and features specific to the Rust 2018 edition.
|
||||
|
||||
## `tests/ui/rust-2021`
|
||||
|
||||
Tests that exercise behaviors and features specific to the Rust 2021 edition.
|
||||
|
||||
## `tests/ui/rust-2024`
|
||||
|
||||
Tests that exercise behaviors and features specific to the Rust 2024 edition.
|
||||
|
||||
## `tests/ui/rustc-env`
|
||||
|
||||
Tests on environmental variables that affect `rustc`.
|
||||
|
||||
## `tests/ui/rustc_public-ir-print`
|
||||
|
||||
Some tests for pretty printing of rustc_public's IR.
|
||||
|
||||
## `tests/ui/rustdoc`
|
||||
|
||||
Hybrid tests that exercises `rustdoc`, and also some joint `rustdoc`/`rustc` interactions.
|
||||
|
||||
## `tests/ui/sanitize-attr`
|
||||
|
||||
Tests for the `#![feature(sanitize)]` attribute.
|
||||
|
||||
See [Sanitize | The Unstable Book](https://doc.rust-lang.org/unstable-book/language-features/sanitize.html).
|
||||
|
||||
## `tests/ui/sanitizer/`
|
||||
|
||||
Exercises sanitizer support. See [Sanitizer | The rustc book](https://doc.rust-lang.org/unstable-book/compiler-flags/sanitizer.html).
|
||||
|
||||
## `tests/ui/scalable-vectors`
|
||||
|
||||
See [Tracking Issue for Scalable Vectors #145052](https://github.com/rust-lang/rust/issues/145052)
|
||||
|
||||
## `tests/ui/self/`: `self` keyword
|
||||
|
||||
Tests with erroneous ways of using `self`, such as using `this.x` syntax as seen in other languages, having it not be the first argument, or using it in a non-associated function (no `impl` or `trait`). It also contains correct uses of `self` which have previously been observed to cause ICEs.
|
||||
|
|
@ -1211,6 +1320,12 @@ This is a test directory for the specific error case where a lifetime never gets
|
|||
|
||||
While many tests here involve the `Sized` trait directly, some instead test, for example the slight variations between returning a zero-sized `Vec` and a `Vec` with one item, where one has no known type and the other does.
|
||||
|
||||
## `tests/ui/sized-hierarchy`
|
||||
|
||||
Tests for `#![feature(sized_hierarchy)]` attribute.
|
||||
|
||||
See [Tracking Issue for Sized Hierarchy #144404](https://github.com/rust-lang/rust/issues/144404)
|
||||
|
||||
## `tests/ui/span/`
|
||||
|
||||
An assorted collection of tests that involves specific diagnostic spans.
|
||||
|
|
@ -1225,9 +1340,9 @@ See [Tracking issue for specialization (RFC 1210) #31844](https://github.com/rus
|
|||
|
||||
Stability attributes used internally by the standard library: `#[stable()]` and `#[unstable()]`.
|
||||
|
||||
## `tests/ui/rustc_public-ir-print/`
|
||||
## `tests/ui/stack-probes`
|
||||
|
||||
Some tests for pretty printing of rustc_public's IR.
|
||||
**FIXME**: Contains a single test, should likely be rehomed to `tests/ui/abi`.
|
||||
|
||||
## `tests/ui/stack-protector/`: `-Z stack-protector` command line flag
|
||||
|
||||
|
|
@ -1359,6 +1474,10 @@ Tests surrounding [`std::mem::transmute`](https://doc.rust-lang.org/std/mem/fn.t
|
|||
|
||||
Exercises compiler development support flag `-Z treat-err-as-bug`.
|
||||
|
||||
## `tests/ui/trimmed-paths/`
|
||||
|
||||
Tests for the `#[doc(hidden)]` items.
|
||||
|
||||
## `tests/ui/trivial-bounds/`
|
||||
|
||||
`#![feature(trivial_bounds)]`. See [RFC 2056 Allow trivial where clause constraints](https://github.com/rust-lang/rfcs/blob/master/text/2056-allow-trivial-where-clause-constraints.md).
|
||||
|
|
@ -1393,17 +1512,13 @@ Tests for `type` aliases in the context of `enum` variants, such as that applied
|
|||
|
||||
`#![feature(type_alias_impl_trait)]`. See [Type Alias Impl Trait | The Unstable book](https://doc.rust-lang.org/nightly/unstable-book/language-features/type-alias-impl-trait.html).
|
||||
|
||||
## `tests/ui/typeck/`
|
||||
|
||||
General collection of type checking related tests.
|
||||
|
||||
## `tests/ui/type-inference/`
|
||||
|
||||
General collection of type inference related tests.
|
||||
|
||||
## `tests/ui/typeof/`
|
||||
## `tests/ui/typeck`
|
||||
|
||||
`typeof` keyword, reserved but unimplemented.
|
||||
General collection of type checking related tests.
|
||||
|
||||
## `tests/ui/ufcs/`
|
||||
|
||||
|
|
@ -1483,7 +1598,11 @@ See:
|
|||
|
||||
**FIXME**: Seems to also contain more generic tests that fit in `tests/ui/unsized/`.
|
||||
|
||||
## `tests/ui/unused-crate-deps/`
|
||||
## `tests/ui/unstable-feature-bound`
|
||||
|
||||
Tests for gating and diagnostics when unstable features are used.
|
||||
|
||||
## `tests/ui/unused-crate-deps`
|
||||
|
||||
Exercises the `unused_crate_dependencies` lint.
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
//@ edition:2021
|
||||
// Test that a by-ref `AsyncFn` closure gets an error when it tries to
|
||||
// consume a value, with a helpful diagnostic pointing to the bound.
|
||||
|
||||
fn call<F>(_: F) where F: AsyncFn() {}
|
||||
|
||||
fn main() {
|
||||
let y = vec![format!("World")];
|
||||
call(async || {
|
||||
//~^ ERROR cannot move out of `y`, a captured variable in an `AsyncFn` closure
|
||||
y.into_iter();
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
error[E0507]: cannot move out of `y`, a captured variable in an `AsyncFn` closure
|
||||
--> $DIR/move-from-async-fn-bound.rs:9:10
|
||||
|
|
||||
LL | let y = vec![format!("World")];
|
||||
| - captured outer variable
|
||||
LL | call(async || {
|
||||
| ^^^^^^^^
|
||||
| |
|
||||
| captured by this `AsyncFn` closure
|
||||
| `y` is moved here
|
||||
LL |
|
||||
LL | y.into_iter();
|
||||
| -
|
||||
| |
|
||||
| variable moved due to use in coroutine
|
||||
| move occurs because `y` has type `Vec<String>`, which does not implement the `Copy` trait
|
||||
|
|
||||
help: `AsyncFn` and `AsyncFnMut` closures require captured values to be able to be consumed multiple times, but `AsyncFnOnce` closures may consume them only once
|
||||
--> $DIR/move-from-async-fn-bound.rs:5:27
|
||||
|
|
||||
LL | fn call<F>(_: F) where F: AsyncFn() {}
|
||||
| ^^^^^^^^^
|
||||
help: consider cloning the value if the performance cost is acceptable
|
||||
|
|
||||
LL | y.clone().into_iter();
|
||||
| ++++++++
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0507`.
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
//@ compile-flags: --crate-type=lib -Zmir-enable-passes=+InstSimplify
|
||||
//@ compile-flags: --crate-type=lib -Zmir-enable-passes=+InstSimplify-before-inline
|
||||
//@ build-pass
|
||||
|
||||
#![feature(core_intrinsics)]
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
warning: MIR pass `SimplifyCfg` is unknown and will be ignored
|
||||
|
||||
warning: MIR pass `SimplifyCfg` is unknown and will be ignored
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
warning: 2 warnings emitted
|
||||
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
//@ revisions: empty unprefixed all_unknown all_known mixed
|
||||
//@ revisions: enum_not_in_pass_names enum_in_pass_names
|
||||
|
||||
//@[empty] compile-flags: -Zmir-enable-passes=
|
||||
|
||||
|
|
@ -13,6 +14,12 @@
|
|||
//@[mixed] check-pass
|
||||
//@[mixed] compile-flags: -Zmir-enable-passes=+ThisPassDoesNotExist,+CheckAlignment
|
||||
|
||||
//@[enum_not_in_pass_names] check-pass
|
||||
//@[enum_not_in_pass_names] compile-flags: -Zmir-enable-passes=+SimplifyCfg
|
||||
|
||||
//@[enum_in_pass_names] check-pass
|
||||
//@[enum_in_pass_names] compile-flags: -Zmir-enable-passes=+AddCallGuards
|
||||
|
||||
fn main() {}
|
||||
|
||||
//[empty]~? ERROR incorrect value `` for unstable option `mir-enable-passes`
|
||||
|
|
@ -23,3 +30,5 @@ fn main() {}
|
|||
//[all_unknown]~? WARN MIR pass `DoesNotExist` is unknown and will be ignored
|
||||
//[all_unknown]~? WARN MIR pass `ThisPass` is unknown and will be ignored
|
||||
//[all_unknown]~? WARN MIR pass `DoesNotExist` is unknown and will be ignored
|
||||
//[enum_not_in_pass_names]~? WARN MIR pass `SimplifyCfg` is unknown and will be ignored
|
||||
//[enum_not_in_pass_names]~? WARN MIR pass `SimplifyCfg` is unknown and will be ignored
|
||||
|
|
|
|||
|
|
@ -1182,11 +1182,11 @@ cc = ["@Muscraft"]
|
|||
|
||||
[mentions."compiler/rustc_errors/src/translation.rs"]
|
||||
message = "`rustc_errors::translation` was changed"
|
||||
cc = ["@davidtwco", "@TaKO8Ki"]
|
||||
cc = ["@davidtwco", "@TaKO8Ki", "@JonathanBrouwer"]
|
||||
|
||||
[mentions."compiler/rustc_macros/src/diagnostics"]
|
||||
message = "`rustc_macros::diagnostics` was changed"
|
||||
cc = ["@davidtwco", "@TaKO8Ki"]
|
||||
cc = ["@davidtwco", "@TaKO8Ki", "@JonathanBrouwer"]
|
||||
|
||||
[mentions."compiler/rustc_public"]
|
||||
message = "This PR changes rustc_public"
|
||||
|
|
|
|||
63
typos.toml
63
typos.toml
|
|
@ -1,3 +1,6 @@
|
|||
# Config for the `typos` crate, used by `./x test tidy --extra-checks=spellcheck`.
|
||||
# See also: https://github.com/crate-ci/typos/blob/v1.28.2/docs/reference.md
|
||||
|
||||
[files]
|
||||
extend-exclude = [
|
||||
# exclude git (sub)modules and generated content
|
||||
|
|
@ -13,57 +16,65 @@ extend-exclude = [
|
|||
]
|
||||
|
||||
[default.extend-words]
|
||||
# Add exclusions here, lines should be like `x = "x"`, where `x` is excluded word.
|
||||
# Allowlist for words that look like typos but are not, or aren't worth fixing
|
||||
# right now. Entries should look like `mipsel = "mipsel"`.
|
||||
#
|
||||
# Also see docs: https://github.com/crate-ci/typos/blob/v1.28.2/docs/reference.md
|
||||
arange = "arange"
|
||||
# tidy-alphabetical-start
|
||||
arange = "arange" # short for A-range
|
||||
childs = "childs"
|
||||
clonable = "clonable"
|
||||
Datas = "Datas"
|
||||
filetimes = "filetimes"
|
||||
filetimes = "filetimes" # short for "file times", not a typo for "lifetimes"
|
||||
leafs = "leafs"
|
||||
makro = "makro"
|
||||
makro = "makro" # deliberate misspelling to avoid `macro` keyword
|
||||
misformed = "misformed"
|
||||
moreso = "moreso"
|
||||
optin = "optin"
|
||||
numer = "numer" # short for numerator, not a typo for "number"
|
||||
optin = "optin" # short for opt-in
|
||||
publically = "publically"
|
||||
rplace = "rplace"
|
||||
smove = "smove"
|
||||
rplace = "rplace" # short for R-place
|
||||
splitted = "splitted"
|
||||
taits = "taits"
|
||||
taits = "taits" # lowercase for TAITs (type alias impl trait)
|
||||
targetting = "targetting"
|
||||
unparseable = "unparseable"
|
||||
unstability = "unstability"
|
||||
unstalled = "unstalled"
|
||||
numer = "numer"
|
||||
unstalled = "unstalled" # short for un-stalled
|
||||
# tidy-alphabetical-end
|
||||
|
||||
# this can be valid word, depends on dictionary edition
|
||||
#matcheable = "matcheable"
|
||||
# Denylist to forbid misspelled words that aren't detected by the built-in
|
||||
# dictionary. Entries should look like `mipsel = ""` or `mipsel = "misspell"`;
|
||||
# the non-empty form can be automatically fixed by `--bless`.
|
||||
#
|
||||
# tidy-alphabetical-start
|
||||
definitinon = "definition"
|
||||
# tidy-alphabetical-end
|
||||
|
||||
[default.extend-identifiers]
|
||||
# An entry goes here if the typo is part of some existing ident
|
||||
# where you want to keep it, but don't want to allow
|
||||
# such typos everywhere.
|
||||
# Allowlist for specific identifiers that should be permitted even though they
|
||||
# appear to contain typos that would be forbidden in other identifiers.
|
||||
#
|
||||
# I.e. you don't want (or can't) fix some constant name, like
|
||||
# `DNS_ERROR_INVAILD_VIRTUALIZATION_INSTANCE_NAME` but actually
|
||||
# want to see `INVAILD` typo fixed in other places.
|
||||
debug_aranges = "debug_aranges"
|
||||
# For example, you might want to allow a specific constant like
|
||||
# `DNS_ERROR_INVAILD_VIRTUALIZATION_INSTANCE_NAME`, but still want to forbid
|
||||
# the typo `INVAILD` in other places.
|
||||
#
|
||||
# tidy-alphabetical-start
|
||||
DNS_ERROR_INVAILD_VIRTUALIZATION_INSTANCE_NAME = "DNS_ERROR_INVAILD_VIRTUALIZATION_INSTANCE_NAME"
|
||||
EnzymeTypeTreeShiftIndiciesEq = "EnzymeTypeTreeShiftIndiciesEq"
|
||||
EnzymeTypeTreeShiftIndiciesEqFn = "EnzymeTypeTreeShiftIndiciesEqFn"
|
||||
shift_indicies_eq = "shift_indicies_eq"
|
||||
ERRNO_ACCES = "ERRNO_ACCES"
|
||||
ERROR_DS_FILTER_USES_CONTRUCTED_ATTRS = "ERROR_DS_FILTER_USES_CONTRUCTED_ATTRS"
|
||||
ERROR_DS_NOT_AUTHORITIVE_FOR_DST_NC = "ERROR_DS_NOT_AUTHORITIVE_FOR_DST_NC"
|
||||
ERROR_FILENAME_EXCED_RANGE = "ERROR_FILENAME_EXCED_RANGE"
|
||||
ERROR_MCA_OCCURED = "ERROR_MCA_OCCURED"
|
||||
ERROR_REQ_NOT_ACCEP = "ERROR_REQ_NOT_ACCEP"
|
||||
Oppen = "Oppen"
|
||||
EnzymeTypeTreeShiftIndiciesEq = "EnzymeTypeTreeShiftIndiciesEq"
|
||||
EnzymeTypeTreeShiftIndiciesEqFn = "EnzymeTypeTreeShiftIndiciesEqFn"
|
||||
Oppen = "Oppen" # Derek C. Oppen, author of "Pretty Printing" (1979)
|
||||
# typos treats this as two different camelcase words (`SETTIN` and `Gs`)
|
||||
# Tracked in: https://github.com/crate-ci/typos/issues/745
|
||||
SETTINGs = "SETTINGs"
|
||||
tolen = "tolen"
|
||||
debug_aranges = "debug_aranges" # debug A-ranges
|
||||
key_smove = "key_smove" # shifted move key, used by terminfo
|
||||
shift_indicies_eq = "shift_indicies_eq"
|
||||
tolen = "tolen" # length of "to" buffer, used by `sendto` in Windows sockets
|
||||
# tidy-alphabetical-end
|
||||
|
||||
[default]
|
||||
extend-ignore-words-re = [
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue