Auto merge of #94103 - matthiaskrgr:rollup-cd70ofn, r=matthiaskrgr
Rollup of 9 pull requests Successful merges: - #93337 (Update tracking issue numbers for inline assembly sub-features) - #93758 (Improve comments about type folding/visiting.) - #93780 (Generate list instead of div items in sidebar) - #93976 (Add MAIN_SEPARATOR_STR) - #94011 (Even more let_else adoptions) - #94041 (Add a `try_collect()` helper method to `Iterator`) - #94043 (Fix ICE when using Box<T, A> with pointer sized A) - #94082 (Remove CFG_PLATFORM) - #94085 (Clippy: Don't lint `needless_borrow` in method receiver positions) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
73a7423e77
@ -142,11 +142,9 @@ fn report_error(
|
||||
let tcx = mbcx.infcx.tcx;
|
||||
let base_universe = self.base_universe();
|
||||
|
||||
let adjusted_universe = if let Some(adjusted) =
|
||||
let Some(adjusted_universe) =
|
||||
placeholder.universe.as_u32().checked_sub(base_universe.as_u32())
|
||||
{
|
||||
adjusted
|
||||
} else {
|
||||
else {
|
||||
mbcx.buffer_error(self.fallback_error(tcx, cause.span));
|
||||
return;
|
||||
};
|
||||
|
@ -867,15 +867,14 @@ pub(super) fn move_spans(
|
||||
kind: TerminatorKind::Call { fn_span, from_hir_call, .. }, ..
|
||||
}) = &self.body[location.block].terminator
|
||||
{
|
||||
let (method_did, method_substs) = if let Some(info) =
|
||||
let Some((method_did, method_substs)) =
|
||||
rustc_const_eval::util::find_self_call(
|
||||
self.infcx.tcx,
|
||||
&self.body,
|
||||
target_temp,
|
||||
location.block,
|
||||
) {
|
||||
info
|
||||
} else {
|
||||
)
|
||||
else {
|
||||
return normal_ret;
|
||||
};
|
||||
|
||||
|
@ -639,11 +639,9 @@ fn is_error_in_trait(&self, local: Local) -> (bool, Option<Span>) {
|
||||
let hir_map = self.infcx.tcx.hir();
|
||||
let my_def = self.body.source.def_id();
|
||||
let my_hir = hir_map.local_def_id_to_hir_id(my_def.as_local().unwrap());
|
||||
let td = if let Some(a) =
|
||||
let Some(td) =
|
||||
self.infcx.tcx.impl_of_method(my_def).and_then(|x| self.infcx.tcx.trait_id_of_impl(x))
|
||||
{
|
||||
a
|
||||
} else {
|
||||
else {
|
||||
return (false, None);
|
||||
};
|
||||
(
|
||||
|
@ -6,9 +6,7 @@
|
||||
|
||||
/// Emits errors for literal expressions that are invalid inside and outside of an array.
|
||||
fn invalid_type_err(cx: &mut base::ExtCtxt<'_>, expr: &P<rustc_ast::Expr>, is_nested: bool) {
|
||||
let lit = if let ast::ExprKind::Lit(lit) = &expr.kind {
|
||||
lit
|
||||
} else {
|
||||
let ast::ExprKind::Lit(lit) = &expr.kind else {
|
||||
unreachable!();
|
||||
};
|
||||
match lit.kind {
|
||||
|
@ -9,6 +9,7 @@
|
||||
#![feature(decl_macro)]
|
||||
#![feature(is_sorted)]
|
||||
#![feature(nll)]
|
||||
#![feature(let_else)]
|
||||
#![feature(proc_macro_internals)]
|
||||
#![feature(proc_macro_quote)]
|
||||
#![recursion_limit = "256"]
|
||||
|
@ -330,7 +330,9 @@ fn scalar_pair_element_llvm_type<'a>(
|
||||
ty::Ref(..) | ty::RawPtr(_) => {
|
||||
return self.field(cx, index).llvm_type(cx);
|
||||
}
|
||||
ty::Adt(def, _) if def.is_box() => {
|
||||
// only wide pointer boxes are handled as pointers
|
||||
// thin pointer boxes with scalar allocators are handled by the general logic below
|
||||
ty::Adt(def, substs) if def.is_box() && cx.layout_of(substs.type_at(1)).is_zst() => {
|
||||
let ptr_ty = cx.tcx.mk_mut_ptr(self.ty.boxed_ty());
|
||||
return cx.layout_of(ptr_ty).scalar_pair_element_llvm_type(cx, index, immediate);
|
||||
}
|
||||
|
@ -216,17 +216,18 @@ pub fn each_linked_rlib(
|
||||
}
|
||||
let name = &info.crate_name[&cnum];
|
||||
let used_crate_source = &info.used_crate_source[&cnum];
|
||||
let path = if let Some((path, _)) = &used_crate_source.rlib {
|
||||
path
|
||||
} else if used_crate_source.rmeta.is_some() {
|
||||
return Err(format!(
|
||||
"could not find rlib for: `{}`, found rmeta (metadata) file",
|
||||
name
|
||||
));
|
||||
if let Some((path, _)) = &used_crate_source.rlib {
|
||||
f(cnum, &path);
|
||||
} else {
|
||||
return Err(format!("could not find rlib for: `{}`", name));
|
||||
};
|
||||
f(cnum, &path);
|
||||
if used_crate_source.rmeta.is_some() {
|
||||
return Err(format!(
|
||||
"could not find rlib for: `{}`, found rmeta (metadata) file",
|
||||
name
|
||||
));
|
||||
} else {
|
||||
return Err(format!("could not find rlib for: `{}`", name));
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
@ -200,9 +200,7 @@ fn create_object_file(sess: &Session) -> Option<write::Object<'static>> {
|
||||
// `SHF_EXCLUDE` flag we can set on sections in an object file to get
|
||||
// automatically removed from the final output.
|
||||
pub fn create_rmeta_file(sess: &Session, metadata: &[u8]) -> Vec<u8> {
|
||||
let mut file = if let Some(file) = create_object_file(sess) {
|
||||
file
|
||||
} else {
|
||||
let Some(mut file) = create_object_file(sess) else {
|
||||
// This is used to handle all "other" targets. This includes targets
|
||||
// in two categories:
|
||||
//
|
||||
@ -262,9 +260,7 @@ pub fn create_compressed_metadata_file(
|
||||
) -> Vec<u8> {
|
||||
let mut compressed = rustc_metadata::METADATA_HEADER.to_vec();
|
||||
FrameEncoder::new(&mut compressed).write_all(metadata.raw_data()).unwrap();
|
||||
let mut file = if let Some(file) = create_object_file(sess) {
|
||||
file
|
||||
} else {
|
||||
let Some(mut file) = create_object_file(sess) else {
|
||||
return compressed.to_vec();
|
||||
};
|
||||
let section = file.add_section(
|
||||
|
@ -285,13 +285,13 @@ pub fn set(&self, features: &mut Features, span: Span) {
|
||||
/// Allows trait methods with arbitrary self types.
|
||||
(active, arbitrary_self_types, "1.23.0", Some(44874), None),
|
||||
/// Allows using `const` operands in inline assembly.
|
||||
(active, asm_const, "1.58.0", Some(72016), None),
|
||||
(active, asm_const, "1.58.0", Some(93332), None),
|
||||
/// Enables experimental inline assembly support for additional architectures.
|
||||
(active, asm_experimental_arch, "1.58.0", Some(72016), None),
|
||||
(active, asm_experimental_arch, "1.58.0", Some(93335), None),
|
||||
/// Allows using `sym` operands in inline assembly.
|
||||
(active, asm_sym, "1.58.0", Some(72016), None),
|
||||
(active, asm_sym, "1.58.0", Some(93333), None),
|
||||
/// Allows the `may_unwind` option in inline assembly.
|
||||
(active, asm_unwind, "1.58.0", Some(72016), None),
|
||||
(active, asm_unwind, "1.58.0", Some(93334), None),
|
||||
/// Allows users to enforce equality of associated constants `TraitImpl<AssocConst=3>`.
|
||||
(active, associated_const_equality, "1.58.0", Some(92827), None),
|
||||
/// Allows the user of associated type bounds.
|
||||
|
@ -852,11 +852,7 @@ pub fn insert_range(&mut self, elems: impl RangeBounds<T>) {
|
||||
Bound::Excluded(end) => end.index(),
|
||||
Bound::Unbounded => self.domain_size() - 1,
|
||||
};
|
||||
let len = if let Some(l) = end.checked_sub(start) {
|
||||
l
|
||||
} else {
|
||||
return;
|
||||
};
|
||||
let Some(len) = end.checked_sub(start) else { return };
|
||||
match self {
|
||||
HybridBitSet::Sparse(sparse) if sparse.len() + len < SPARSE_MAX => {
|
||||
// The set is sparse and has space for `elems`.
|
||||
|
@ -553,8 +553,7 @@ pub fn emit_inference_failure_err(
|
||||
let ty_msg = match (local_visitor.found_node_ty, local_visitor.found_exact_method_call) {
|
||||
(_, Some(_)) => String::new(),
|
||||
(Some(ty), _) if ty.is_closure() => {
|
||||
let substs =
|
||||
if let ty::Closure(_, substs) = *ty.kind() { substs } else { unreachable!() };
|
||||
let ty::Closure(_, substs) = *ty.kind() else { unreachable!() };
|
||||
let fn_sig = substs.as_closure().sig();
|
||||
let args = closure_args(&fn_sig);
|
||||
let ret = fn_sig.output().skip_binder().to_string();
|
||||
@ -597,8 +596,7 @@ pub fn emit_inference_failure_err(
|
||||
let param_type = arg_data.kind.descr();
|
||||
let suffix = match local_visitor.found_node_ty {
|
||||
Some(ty) if ty.is_closure() => {
|
||||
let substs =
|
||||
if let ty::Closure(_, substs) = *ty.kind() { substs } else { unreachable!() };
|
||||
let ty::Closure(_, substs) = *ty.kind() else { unreachable!() };
|
||||
let fn_sig = substs.as_closure().sig();
|
||||
let ret = fn_sig.output().skip_binder().to_string();
|
||||
|
||||
|
@ -982,7 +982,7 @@ fn encode_def_ids(&mut self) {
|
||||
for local_id in hir.iter_local_def_id() {
|
||||
let def_id = local_id.to_def_id();
|
||||
let def_kind = tcx.opt_def_kind(local_id);
|
||||
let def_kind = if let Some(def_kind) = def_kind { def_kind } else { continue };
|
||||
let Some(def_kind) = def_kind else { continue };
|
||||
record!(self.tables.def_kind[def_id] <- match def_kind {
|
||||
// Replace Ctor by the enclosing object to avoid leaking details in children crates.
|
||||
DefKind::Ctor(CtorOf::Struct, _) => DefKind::Struct,
|
||||
|
@ -61,7 +61,7 @@ fn read_deps<OP>(op: OP)
|
||||
OP: for<'a> FnOnce(TaskDepsRef<'a>),
|
||||
{
|
||||
ty::tls::with_context_opt(|icx| {
|
||||
let icx = if let Some(icx) = icx { icx } else { return };
|
||||
let Some(icx) = icx else { return };
|
||||
op(icx.task_deps)
|
||||
})
|
||||
}
|
||||
|
@ -1,38 +1,56 @@
|
||||
//! Generalized type folding mechanism. The setup is a bit convoluted
|
||||
//! but allows for convenient usage. Let T be an instance of some
|
||||
//! "foldable type" (one which implements `TypeFoldable`) and F be an
|
||||
//! instance of a "folder" (a type which implements `TypeFolder`). Then
|
||||
//! the setup is intended to be:
|
||||
//! A generalized traversal mechanism for complex data structures that contain
|
||||
//! type information.
|
||||
//!
|
||||
//! T.fold_with(F) --calls--> F.fold_T(T) --calls--> T.super_fold_with(F)
|
||||
//! There are two types of traversal.
|
||||
//! - Folding. This is a modifying traversal. It consumes the data structure,
|
||||
//! producing a (possibly) modified version of it. Both fallible and
|
||||
//! infallible versions are available. The name is potentially
|
||||
//! confusing, because this traversal is more like `Iterator::map` than
|
||||
//! `Iterator::fold`.
|
||||
//! - Visiting. This is a read-only traversal of the data structure.
|
||||
//!
|
||||
//! This way, when you define a new folder F, you can override
|
||||
//! `fold_T()` to customize the behavior, and invoke `T.super_fold_with()`
|
||||
//! to get the original behavior. Meanwhile, to actually fold
|
||||
//! something, you can just write `T.fold_with(F)`, which is
|
||||
//! convenient. (Note that `fold_with` will also transparently handle
|
||||
//! things like a `Vec<T>` where T is foldable and so on.)
|
||||
//! These traversals have limited flexibility. Only a small number of "types of
|
||||
//! interest" within the complex data structures can receive custom
|
||||
//! modification (when folding) or custom visitation (when visiting). These are
|
||||
//! the ones containing the most important type-related information, such as
|
||||
//! `Ty`, `Predicate`, `Region`, and `Const`.
|
||||
//!
|
||||
//! In this ideal setup, the only function that actually *does*
|
||||
//! anything is `T.super_fold_with()`, which traverses the type `T`.
|
||||
//! Moreover, `T.super_fold_with()` should only ever call `T.fold_with()`.
|
||||
//! There are two traits involved in each traversal type.
|
||||
//! - The first trait is `TypeFoldable`, which is implemented once for many
|
||||
//! types. This includes both (a) types of interest, and (b) all other
|
||||
//! relevant types, including generic containers like `Vec` and `Option`. It
|
||||
//! defines a "skeleton" of how they should be traversed, for both folding
|
||||
//! and visiting.
|
||||
//! - The second trait is `TypeFolder`/`FallibleTypeFolder` (for
|
||||
//! infallible/fallible folding traversals) or `TypeVisitor` (for visiting
|
||||
//! traversals). One of these is implemented for each folder/visitor. This
|
||||
//! defines how types of interest are handled.
|
||||
//!
|
||||
//! In some cases, we follow a degenerate pattern where we do not have
|
||||
//! a `fold_T` method. Instead, `T.fold_with` traverses the structure directly.
|
||||
//! This is suboptimal because the behavior cannot be overridden, but it's
|
||||
//! much less work to implement. If you ever *do* need an override that
|
||||
//! doesn't exist, it's not hard to convert the degenerate pattern into the
|
||||
//! proper thing.
|
||||
//! This means each traversal is a mixture of (a) generic traversal operations,
|
||||
//! and (b) custom fold/visit operations that are specific to the
|
||||
//! folder/visitor.
|
||||
//! - The `TypeFoldable` impls handle most of the traversal, and call into
|
||||
//! `TypeFolder`/`FallibleTypeFolder`/`TypeVisitor` when they encounter a
|
||||
//! type of interest.
|
||||
//! - A `TypeFolder`/`FallibleTypeFolder`/`TypeVisitor` may also call back into
|
||||
//! a `TypeFoldable` impl, because (a) the types of interest are recursive
|
||||
//! and can contain other types of interest, and (b) each folder/visitor
|
||||
//! might provide custom handling only for some types of interest, or only
|
||||
//! for some variants of each type of interest, and then use default
|
||||
//! traversal for the remaining cases.
|
||||
//!
|
||||
//! A `TypeFoldable` T can also be visited by a `TypeVisitor` V using similar setup:
|
||||
//!
|
||||
//! T.visit_with(V) --calls--> V.visit_T(T) --calls--> T.super_visit_with(V).
|
||||
//!
|
||||
//! These methods return true to indicate that the visitor has found what it is
|
||||
//! looking for, and does not need to visit anything else.
|
||||
//! For example, if you have `struct S(Ty, U)` where `S: TypeFoldable` and `U:
|
||||
//! TypeFoldable`, and an instance `S(ty, u)`, it would be visited like so:
|
||||
//! ```
|
||||
//! s.visit_with(visitor) calls
|
||||
//! - s.super_visit_with(visitor) calls
|
||||
//! - ty.visit_with(visitor) calls
|
||||
//! - visitor.visit_ty(ty) may call
|
||||
//! - ty.super_visit_with(visitor)
|
||||
//! - u.visit_with(visitor)
|
||||
//! ```
|
||||
use crate::mir;
|
||||
use crate::ty::{self, flags::FlagComputation, Binder, Ty, TyCtxt, TypeFlags};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::DefId;
|
||||
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
@ -41,42 +59,67 @@
|
||||
use std::fmt;
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
/// This trait is implemented for every type that can be folded.
|
||||
/// Basically, every type that has a corresponding method in `TypeFolder`.
|
||||
/// This trait is implemented for every type that can be folded/visited,
|
||||
/// providing the skeleton of the traversal.
|
||||
///
|
||||
/// To implement this conveniently, use the derive macro located in `rustc_macros`.
|
||||
/// To implement this conveniently, use the derive macro located in
|
||||
/// `rustc_macros`.
|
||||
pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
|
||||
/// Consumers may find this more convenient to use with infallible folders than
|
||||
/// [`try_super_fold_with`][`TypeFoldable::try_super_fold_with`], to which the
|
||||
/// provided default definition delegates. Implementors **should not** override
|
||||
/// this provided default definition, to ensure that the two methods are coherent
|
||||
/// (provide a definition of `try_super_fold_with` instead).
|
||||
fn super_fold_with<F: TypeFolder<'tcx, Error = !>>(self, folder: &mut F) -> Self {
|
||||
self.try_super_fold_with(folder).into_ok()
|
||||
/// The main entry point for folding. To fold a value `t` with a folder `f`
|
||||
/// call: `t.try_fold_with(f)`.
|
||||
///
|
||||
/// For types of interest (such as `Ty`), this default is overridden with a
|
||||
/// method that calls a folder method specifically for that type (such as
|
||||
/// `F::try_fold_ty`). This is where control transfers from `TypeFoldable`
|
||||
/// to `TypeFolder`.
|
||||
///
|
||||
/// For other types, this default is used.
|
||||
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
|
||||
self.try_super_fold_with(folder)
|
||||
}
|
||||
/// Consumers may find this more convenient to use with infallible folders than
|
||||
/// [`try_fold_with`][`TypeFoldable::try_fold_with`], to which the provided
|
||||
/// default definition delegates. Implementors **should not** override this
|
||||
/// provided default definition, to ensure that the two methods are coherent
|
||||
/// (provide a definition of `try_fold_with` instead).
|
||||
|
||||
/// A convenient alternative to `try_fold_with` for use with infallible
|
||||
/// folders. Do not override this method, to ensure coherence with
|
||||
/// `try_fold_with`.
|
||||
fn fold_with<F: TypeFolder<'tcx, Error = !>>(self, folder: &mut F) -> Self {
|
||||
self.try_fold_with(folder).into_ok()
|
||||
}
|
||||
|
||||
/// Traverses the type in question, typically by calling `try_fold_with` on
|
||||
/// each field/element. This is true even for types of interest such as
|
||||
/// `Ty`. This should only be called within `TypeFolder` methods, when
|
||||
/// non-custom traversals are desired for types of interest.
|
||||
fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
|
||||
self,
|
||||
folder: &mut F,
|
||||
) -> Result<Self, F::Error>;
|
||||
|
||||
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
|
||||
self.try_super_fold_with(folder)
|
||||
/// A convenient alternative to `try_super_fold_with` for use with
|
||||
/// infallible folders. Do not override this method, to ensure coherence
|
||||
/// with `try_super_fold_with`.
|
||||
fn super_fold_with<F: TypeFolder<'tcx, Error = !>>(self, folder: &mut F) -> Self {
|
||||
self.try_super_fold_with(folder).into_ok()
|
||||
}
|
||||
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy>;
|
||||
/// The entry point for visiting. To visit a value `t` with a visitor `v`
|
||||
/// call: `t.visit_with(v)`.
|
||||
///
|
||||
/// For types of interest (such as `Ty`), this default is overridden with a
|
||||
/// method that calls a visitor method specifically for that type (such as
|
||||
/// `V::visit_ty`). This is where control transfers from `TypeFoldable` to
|
||||
/// `TypeVisitor`.
|
||||
///
|
||||
/// For other types, this default is used.
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
self.super_visit_with(visitor)
|
||||
}
|
||||
|
||||
/// Traverses the type in question, typically by calling `visit_with` on
|
||||
/// each field/element. This is true even for types of interest such as
|
||||
/// `Ty`. This should only be called within `TypeVisitor` methods, when
|
||||
/// non-custom traversals are desired for types of interest.
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy>;
|
||||
|
||||
/// Returns `true` if `self` has any late-bound regions that are either
|
||||
/// bound by `binder` or bound by some binder outside of `binder`.
|
||||
/// If `binder` is `ty::INNERMOST`, this indicates whether
|
||||
@ -168,24 +211,13 @@ fn still_further_specializable(&self) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for hir::Constness {
|
||||
fn try_super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> {
|
||||
Ok(self)
|
||||
}
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
ControlFlow::CONTINUE
|
||||
}
|
||||
}
|
||||
|
||||
/// The `TypeFolder` trait defines the actual *folding*. There is a
|
||||
/// method defined for every foldable type. Each of these has a
|
||||
/// default implementation that does an "identity" fold. Within each
|
||||
/// identity fold, it should invoke `foo.fold_with(self)` to fold each
|
||||
/// sub-item.
|
||||
/// This trait is implemented for every folding traversal. There is a fold
|
||||
/// method defined for every type of interest. Each such method has a default
|
||||
/// that does an "identity" fold.
|
||||
///
|
||||
/// If this folder is fallible (and therefore its [`Error`][`TypeFolder::Error`]
|
||||
/// associated type is something other than the default, never),
|
||||
/// [`FallibleTypeFolder`] should be implemented manually; otherwise,
|
||||
/// associated type is something other than the default `!`) then
|
||||
/// [`FallibleTypeFolder`] should be implemented manually. Otherwise,
|
||||
/// a blanket implementation of [`FallibleTypeFolder`] will defer to
|
||||
/// the infallible methods of this trait to ensure that the two APIs
|
||||
/// are coherent.
|
||||
@ -238,11 +270,9 @@ fn fold_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'t
|
||||
}
|
||||
}
|
||||
|
||||
/// The `FallibleTypeFolder` trait defines the actual *folding*. There is a
|
||||
/// method defined for every foldable type. Each of these has a
|
||||
/// default implementation that does an "identity" fold. Within each
|
||||
/// identity fold, it should invoke `foo.try_fold_with(self)` to fold each
|
||||
/// sub-item.
|
||||
/// This trait is implemented for every folding traversal. There is a fold
|
||||
/// method defined for every type of interest. Each such method has a default
|
||||
/// that does an "identity" fold.
|
||||
///
|
||||
/// A blanket implementation of this trait (that defers to the relevant
|
||||
/// method of [`TypeFolder`]) is provided for all infallible folders in
|
||||
@ -282,8 +312,8 @@ fn try_fold_mir_const(
|
||||
}
|
||||
}
|
||||
|
||||
// Blanket implementation of fallible trait for infallible folders
|
||||
// delegates to infallible methods to prevent incoherence
|
||||
// This blanket implementation of the fallible trait for infallible folders
|
||||
// delegates to infallible methods to ensure coherence.
|
||||
impl<'tcx, F> FallibleTypeFolder<'tcx> for F
|
||||
where
|
||||
F: TypeFolder<'tcx, Error = !>,
|
||||
@ -322,6 +352,9 @@ fn try_fold_mir_const(
|
||||
}
|
||||
}
|
||||
|
||||
/// This trait is implemented for every visiting traversal. There is a visit
|
||||
/// method defined for every type of interest. Each such method has a default
|
||||
/// that recurses into the type's fields in a non-custom fashion.
|
||||
pub trait TypeVisitor<'tcx>: Sized {
|
||||
type BreakTy = !;
|
||||
|
||||
|
@ -8,6 +8,7 @@
|
||||
use crate::ty::print::{with_no_trimmed_paths, FmtPrinter, Printer};
|
||||
use crate::ty::{self, InferConst, Lift, Term, Ty, TyCtxt};
|
||||
use rustc_data_structures::functor::IdFunctor;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::Namespace;
|
||||
use rustc_hir::def_id::CRATE_DEF_INDEX;
|
||||
use rustc_index::vec::{Idx, IndexVec};
|
||||
@ -663,14 +664,6 @@ fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// TypeFoldable implementations.
|
||||
//
|
||||
// Ideally, each type should invoke `folder.fold_foo(self)` and
|
||||
// nothing else. In some cases, though, we haven't gotten around to
|
||||
// adding methods on the `folder` yet, and thus the folding is
|
||||
// hard-coded here. This is less-flexible, because folders cannot
|
||||
// override the behavior, but there are a lot of random types and one
|
||||
// can easily refactor the folding into the TypeFolder trait as
|
||||
// needed.
|
||||
|
||||
/// AdtDefs are basically the same as a DefId.
|
||||
impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::AdtDef {
|
||||
@ -1270,3 +1263,13 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow
|
||||
self.substs.visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for hir::Constness {
|
||||
fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> {
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
ControlFlow::CONTINUE
|
||||
}
|
||||
}
|
||||
|
@ -1241,9 +1241,7 @@ fn phase_change(&self) -> Option<MirPhase> {
|
||||
}
|
||||
|
||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||
let yield_ty = if let Some(yield_ty) = body.yield_ty() {
|
||||
yield_ty
|
||||
} else {
|
||||
let Some(yield_ty) = body.yield_ty() else {
|
||||
// This only applies to generators
|
||||
return;
|
||||
};
|
||||
|
@ -212,12 +212,7 @@ fn normalize_array_len_call<'tcx>(
|
||||
let Some(local) = place.as_local() else { return };
|
||||
match operand {
|
||||
Operand::Copy(place) | Operand::Move(place) => {
|
||||
let operand_local =
|
||||
if let Some(local) = place.local_or_deref_local() {
|
||||
local
|
||||
} else {
|
||||
return;
|
||||
};
|
||||
let Some(operand_local) = place.local_or_deref_local() else { return; };
|
||||
if !interesting_locals.contains(operand_local) {
|
||||
return;
|
||||
}
|
||||
|
@ -947,9 +947,7 @@ fn visit_instance_use<'tcx>(
|
||||
/// Returns `true` if we should codegen an instance in the local crate, or returns `false` if we
|
||||
/// can just link to the upstream crate and therefore don't need a mono item.
|
||||
fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: &Instance<'tcx>) -> bool {
|
||||
let def_id = if let Some(def_id) = instance.def.def_id_if_not_guaranteed_local_codegen() {
|
||||
def_id
|
||||
} else {
|
||||
let Some(def_id) = instance.def.def_id_if_not_guaranteed_local_codegen() else {
|
||||
return true;
|
||||
};
|
||||
|
||||
|
@ -8,13 +8,11 @@
|
||||
/// During the same compile all closures dump the information in the same file
|
||||
/// "closure_profile_XXXXX.csv", which is created in the directory where the compiler is invoked.
|
||||
crate fn dump_closure_profile<'tcx>(tcx: TyCtxt<'tcx>, closure_instance: Instance<'tcx>) {
|
||||
let mut file = if let Ok(file) = OpenOptions::new()
|
||||
let Ok(mut file) = OpenOptions::new()
|
||||
.create(true)
|
||||
.append(true)
|
||||
.open(&format!("closure_profile_{}.csv", std::process::id()))
|
||||
{
|
||||
file
|
||||
} else {
|
||||
else {
|
||||
eprintln!("Cound't open file for writing closure profile");
|
||||
return;
|
||||
};
|
||||
|
@ -158,9 +158,7 @@ fn cook_lexer_token(&self, token: rustc_lexer::TokenKind, start: BytePos) -> Opt
|
||||
Some(match token {
|
||||
rustc_lexer::TokenKind::LineComment { doc_style } => {
|
||||
// Skip non-doc comments
|
||||
let doc_style = if let Some(doc_style) = doc_style {
|
||||
doc_style
|
||||
} else {
|
||||
let Some(doc_style) = doc_style else {
|
||||
self.lint_unicode_text_flow(start);
|
||||
return None;
|
||||
};
|
||||
@ -185,9 +183,7 @@ fn cook_lexer_token(&self, token: rustc_lexer::TokenKind, start: BytePos) -> Opt
|
||||
}
|
||||
|
||||
// Skip non-doc comments
|
||||
let doc_style = if let Some(doc_style) = doc_style {
|
||||
doc_style
|
||||
} else {
|
||||
let Some(doc_style) = doc_style else {
|
||||
self.lint_unicode_text_flow(start);
|
||||
return None;
|
||||
};
|
||||
|
@ -4,6 +4,7 @@
|
||||
#![feature(crate_visibility_modifier)]
|
||||
#![feature(if_let_guard)]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(let_else)]
|
||||
#![recursion_limit = "256"]
|
||||
|
||||
#[macro_use]
|
||||
|
@ -704,7 +704,7 @@ fn restrict_assoc_type_in_where_clause(
|
||||
) = &bounded_ty.kind
|
||||
{
|
||||
// use this to verify that ident is a type param.
|
||||
let partial_res = if let Ok(Some(partial_res)) = self.resolve_qpath_anywhere(
|
||||
let Ok(Some(partial_res)) = self.resolve_qpath_anywhere(
|
||||
bounded_ty.id,
|
||||
None,
|
||||
&Segment::from_path(path),
|
||||
@ -712,9 +712,7 @@ fn restrict_assoc_type_in_where_clause(
|
||||
span,
|
||||
true,
|
||||
CrateLint::No,
|
||||
) {
|
||||
partial_res
|
||||
} else {
|
||||
) else {
|
||||
return false;
|
||||
};
|
||||
if !(matches!(
|
||||
@ -731,7 +729,7 @@ fn restrict_assoc_type_in_where_clause(
|
||||
|
||||
if let ast::TyKind::Path(None, type_param_path) = &ty.peel_refs().kind {
|
||||
// Confirm that the `SelfTy` is a type parameter.
|
||||
let partial_res = if let Ok(Some(partial_res)) = self.resolve_qpath_anywhere(
|
||||
let Ok(Some(partial_res)) = self.resolve_qpath_anywhere(
|
||||
bounded_ty.id,
|
||||
None,
|
||||
&Segment::from_path(type_param_path),
|
||||
@ -739,9 +737,7 @@ fn restrict_assoc_type_in_where_clause(
|
||||
span,
|
||||
true,
|
||||
CrateLint::No,
|
||||
) {
|
||||
partial_res
|
||||
} else {
|
||||
) else {
|
||||
return false;
|
||||
};
|
||||
if !(matches!(
|
||||
|
@ -1099,9 +1099,7 @@ fn suggest_impl_trait(
|
||||
_ => return false,
|
||||
};
|
||||
|
||||
let ret_ty = if let hir::FnRetTy::Return(ret_ty) = sig.decl.output {
|
||||
ret_ty
|
||||
} else {
|
||||
let hir::FnRetTy::Return(ret_ty) = sig.decl.output else {
|
||||
return false;
|
||||
};
|
||||
|
||||
@ -1168,7 +1166,7 @@ fn suggest_impl_trait(
|
||||
};
|
||||
|
||||
let sm = self.tcx.sess.source_map();
|
||||
let snippet = if let (true, hir::TyKind::TraitObject(..), Ok(snippet), true) = (
|
||||
let (true, hir::TyKind::TraitObject(..), Ok(snippet), true) = (
|
||||
// Verify that we're dealing with a return `dyn Trait`
|
||||
ret_ty.span.overlaps(span),
|
||||
&ret_ty.kind,
|
||||
@ -1176,9 +1174,7 @@ fn suggest_impl_trait(
|
||||
// If any of the return types does not conform to the trait, then we can't
|
||||
// suggest `impl Trait` nor trait objects: it is a type mismatch error.
|
||||
all_returns_conform_to_trait,
|
||||
) {
|
||||
snippet
|
||||
} else {
|
||||
) else {
|
||||
return false;
|
||||
};
|
||||
err.code(error_code!(E0746));
|
||||
|
@ -1318,10 +1318,7 @@ fn check_expr_struct(
|
||||
base_expr: &'tcx Option<&'tcx hir::Expr<'tcx>>,
|
||||
) -> Ty<'tcx> {
|
||||
// Find the relevant variant
|
||||
let (variant, adt_ty) = if let Some(variant_ty) = self.check_struct_path(qpath, expr.hir_id)
|
||||
{
|
||||
variant_ty
|
||||
} else {
|
||||
let Some((variant, adt_ty)) = self.check_struct_path(qpath, expr.hir_id) else {
|
||||
self.check_struct_fields_on_error(fields, base_expr);
|
||||
return self.tcx.ty_error();
|
||||
};
|
||||
|
@ -1,6 +1,7 @@
|
||||
use crate::cmp::{self, Ordering};
|
||||
use crate::ops::{ChangeOutputType, ControlFlow, FromResidual, Residual, Try};
|
||||
|
||||
use super::super::try_process;
|
||||
use super::super::TrustedRandomAccessNoCoerce;
|
||||
use super::super::{Chain, Cloned, Copied, Cycle, Enumerate, Filter, FilterMap, Fuse};
|
||||
use super::super::{FlatMap, Flatten};
|
||||
@ -1777,6 +1778,87 @@ fn collect<B: FromIterator<Self::Item>>(self) -> B
|
||||
FromIterator::from_iter(self)
|
||||
}
|
||||
|
||||
/// Fallibly transforms an iterator into a collection, short circuiting if
|
||||
/// a failure is encountered.
|
||||
///
|
||||
/// `try_collect()` is a variation of [`collect()`][`collect`] that allows fallible
|
||||
/// conversions during collection. Its main use case is simplifying conversions from
|
||||
/// iterators yielding [`Option<T>`][`Option`] into `Option<Collection<T>>`, or similarly for other [`Try`]
|
||||
/// types (e.g. [`Result`]).
|
||||
///
|
||||
/// Importantly, `try_collect()` doesn't require that the outer [`Try`] type also implements [`FromIterator`];
|
||||
/// only the inner type produced on `Try::Output` must implement it. Concretely,
|
||||
/// this means that collecting into `ControlFlow<_, Vec<i32>>` is valid because `Vec<i32>` implements
|
||||
/// [`FromIterator`], even though [`ControlFlow`] doesn't.
|
||||
///
|
||||
/// Also, if a failure is encountered during `try_collect()`, the iterator is still valid and
|
||||
/// may continue to be used, in which case it will continue iterating starting after the element that
|
||||
/// triggered the failure. See the last example below for an example of how this works.
|
||||
///
|
||||
/// # Examples
|
||||
/// Successfully collecting an iterator of `Option<i32>` into `Option<Vec<i32>>`:
|
||||
/// ```
|
||||
/// #![feature(iterator_try_collect)]
|
||||
///
|
||||
/// let u = vec![Some(1), Some(2), Some(3)];
|
||||
/// let v = u.into_iter().try_collect::<Vec<i32>>();
|
||||
/// assert_eq!(v, Some(vec![1, 2, 3]));
|
||||
/// ```
|
||||
///
|
||||
/// Failing to collect in the same way:
|
||||
/// ```
|
||||
/// #![feature(iterator_try_collect)]
|
||||
///
|
||||
/// let u = vec![Some(1), Some(2), None, Some(3)];
|
||||
/// let v = u.into_iter().try_collect::<Vec<i32>>();
|
||||
/// assert_eq!(v, None);
|
||||
/// ```
|
||||
///
|
||||
/// A similar example, but with `Result`:
|
||||
/// ```
|
||||
/// #![feature(iterator_try_collect)]
|
||||
///
|
||||
/// let u: Vec<Result<i32, ()>> = vec![Ok(1), Ok(2), Ok(3)];
|
||||
/// let v = u.into_iter().try_collect::<Vec<i32>>();
|
||||
/// assert_eq!(v, Ok(vec![1, 2, 3]));
|
||||
///
|
||||
/// let u = vec![Ok(1), Ok(2), Err(()), Ok(3)];
|
||||
/// let v = u.into_iter().try_collect::<Vec<i32>>();
|
||||
/// assert_eq!(v, Err(()));
|
||||
/// ```
|
||||
///
|
||||
/// Finally, even [`ControlFlow`] works, despite the fact that it
|
||||
/// doesn't implement [`FromIterator`]. Note also that the iterator can
|
||||
/// continue to be used, even if a failure is encountered:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(iterator_try_collect)]
|
||||
///
|
||||
/// use core::ops::ControlFlow::{Break, Continue};
|
||||
///
|
||||
/// let u = [Continue(1), Continue(2), Break(3), Continue(4), Continue(5)];
|
||||
/// let mut it = u.into_iter();
|
||||
///
|
||||
/// let v = it.try_collect::<Vec<_>>();
|
||||
/// assert_eq!(v, Break(3));
|
||||
///
|
||||
/// let v = it.try_collect::<Vec<_>>();
|
||||
/// assert_eq!(v, Continue(vec![4, 5]));
|
||||
/// ```
|
||||
///
|
||||
/// [`collect`]: Iterator::collect
|
||||
#[inline]
|
||||
#[unstable(feature = "iterator_try_collect", issue = "94047")]
|
||||
fn try_collect<B>(&mut self) -> ChangeOutputType<Self::Item, B>
|
||||
where
|
||||
Self: Sized,
|
||||
<Self as Iterator>::Item: Try,
|
||||
<<Self as Iterator>::Item as Try>::Residual: Residual<B>,
|
||||
B: FromIterator<<Self::Item as Try>::Output>,
|
||||
{
|
||||
try_process(self, |i| i.collect())
|
||||
}
|
||||
|
||||
/// Consumes an iterator, creating two collections from it.
|
||||
///
|
||||
/// The predicate passed to `partition()` can return `true`, or `false`.
|
||||
|
@ -497,6 +497,52 @@ fn test_collect() {
|
||||
assert!(a == b);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_try_collect() {
|
||||
use core::ops::ControlFlow::{Break, Continue};
|
||||
|
||||
let u = vec![Some(1), Some(2), Some(3)];
|
||||
let v = u.into_iter().try_collect::<Vec<i32>>();
|
||||
assert_eq!(v, Some(vec![1, 2, 3]));
|
||||
|
||||
let u = vec![Some(1), Some(2), None, Some(3)];
|
||||
let mut it = u.into_iter();
|
||||
let v = it.try_collect::<Vec<i32>>();
|
||||
assert_eq!(v, None);
|
||||
let v = it.try_collect::<Vec<i32>>();
|
||||
assert_eq!(v, Some(vec![3]));
|
||||
|
||||
let u: Vec<Result<i32, ()>> = vec![Ok(1), Ok(2), Ok(3)];
|
||||
let v = u.into_iter().try_collect::<Vec<i32>>();
|
||||
assert_eq!(v, Ok(vec![1, 2, 3]));
|
||||
|
||||
let u = vec![Ok(1), Ok(2), Err(()), Ok(3)];
|
||||
let v = u.into_iter().try_collect::<Vec<i32>>();
|
||||
assert_eq!(v, Err(()));
|
||||
|
||||
let numbers = vec![1, 2, 3, 4, 5];
|
||||
let all_positive = numbers
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(|n| if n > 0 { Some(n) } else { None })
|
||||
.try_collect::<Vec<i32>>();
|
||||
assert_eq!(all_positive, Some(numbers));
|
||||
|
||||
let numbers = vec![-2, -1, 0, 1, 2];
|
||||
let all_positive =
|
||||
numbers.into_iter().map(|n| if n > 0 { Some(n) } else { None }).try_collect::<Vec<i32>>();
|
||||
assert_eq!(all_positive, None);
|
||||
|
||||
let u = [Continue(1), Continue(2), Break(3), Continue(4), Continue(5)];
|
||||
let mut it = u.into_iter();
|
||||
|
||||
let v = it.try_collect::<Vec<_>>();
|
||||
assert_eq!(v, Break(3));
|
||||
|
||||
let v = it.try_collect::<Vec<_>>();
|
||||
assert_eq!(v, Continue(vec![4, 5]));
|
||||
}
|
||||
|
||||
// just tests by whether or not this compiles
|
||||
fn _empty_impl_all_auto_traits<T>() {
|
||||
use std::panic::{RefUnwindSafe, UnwindSafe};
|
||||
|
@ -67,6 +67,7 @@
|
||||
#![feature(iter_intersperse)]
|
||||
#![feature(iter_is_partitioned)]
|
||||
#![feature(iter_order_by)]
|
||||
#![feature(iterator_try_collect)]
|
||||
#![feature(iterator_try_reduce)]
|
||||
#![feature(const_mut_refs)]
|
||||
#![feature(const_pin)]
|
||||
|
@ -268,6 +268,12 @@ pub fn is_separator(c: char) -> bool {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const MAIN_SEPARATOR: char = crate::sys::path::MAIN_SEP;
|
||||
|
||||
/// The primary separator of path components for the current platform.
|
||||
///
|
||||
/// For example, `/` on Unix and `\` on Windows.
|
||||
#[unstable(feature = "main_separator_str", issue = "94071")]
|
||||
pub const MAIN_SEPARATOR_STR: &str = crate::sys::path::MAIN_SEP_STR;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Misc helpers
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1877,12 +1877,6 @@ fn add_env(builder: &Builder<'_>, cmd: &mut Command, target: TargetSelection) {
|
||||
} else {
|
||||
cmd.env("CFG_MINGW", "0").env("CFG_ABI", "MSVC");
|
||||
}
|
||||
|
||||
if target.contains("x86_64") {
|
||||
cmd.env("CFG_PLATFORM", "x64");
|
||||
} else {
|
||||
cmd.env("CFG_PLATFORM", "x86");
|
||||
}
|
||||
}
|
||||
|
||||
/// Maybe add LLVM object files to the given destination lib-dir. Allows either static or dynamic linking.
|
||||
|
@ -1,8 +1,8 @@
|
||||
# `asm_const`
|
||||
|
||||
The tracking issue for this feature is: [#72016]
|
||||
The tracking issue for this feature is: [#93332]
|
||||
|
||||
[#72016]: https://github.com/rust-lang/rust/issues/72016
|
||||
[#93332]: https://github.com/rust-lang/rust/issues/93332
|
||||
|
||||
------------------------
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
# `asm_experimental_arch`
|
||||
|
||||
The tracking issue for this feature is: [#72016]
|
||||
The tracking issue for this feature is: [#93335]
|
||||
|
||||
[#72016]: https://github.com/rust-lang/rust/issues/72016
|
||||
[#93335]: https://github.com/rust-lang/rust/issues/93335
|
||||
|
||||
------------------------
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
# `asm_sym`
|
||||
|
||||
The tracking issue for this feature is: [#72016]
|
||||
The tracking issue for this feature is: [#93333]
|
||||
|
||||
[#72016]: https://github.com/rust-lang/rust/issues/72016
|
||||
[#93333]: https://github.com/rust-lang/rust/issues/93333
|
||||
|
||||
------------------------
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
# `asm_unwind`
|
||||
|
||||
The tracking issue for this feature is: [#72016]
|
||||
The tracking issue for this feature is: [#93334]
|
||||
|
||||
[#72016]: https://github.com/rust-lang/rust/issues/72016
|
||||
[#93334]: https://github.com/rust-lang/rust/issues/93334
|
||||
|
||||
------------------------
|
||||
|
||||
|
@ -51,9 +51,7 @@
|
||||
// Look for equality predicates on associated types that can be merged into
|
||||
// general bound predicates
|
||||
equalities.retain(|&(ref lhs, ref rhs)| {
|
||||
let (self_, trait_did, name) = if let Some(p) = lhs.projection() {
|
||||
p
|
||||
} else {
|
||||
let Some((self_, trait_did, name)) = lhs.projection() else {
|
||||
return true;
|
||||
};
|
||||
let generic = match self_ {
|
||||
|
@ -236,9 +236,7 @@ fn next(&mut self) -> Option<Self::Item> {
|
||||
let should_panic;
|
||||
let ignore;
|
||||
let edition;
|
||||
let kind = if let Some(Event::Start(Tag::CodeBlock(kind))) = event {
|
||||
kind
|
||||
} else {
|
||||
let Some(Event::Start(Tag::CodeBlock(kind))) = event else {
|
||||
return event;
|
||||
};
|
||||
|
||||
|
@ -1963,16 +1963,12 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
|
||||
// We want links' order to be reproducible so we don't use unstable sort.
|
||||
assoc_consts.sort();
|
||||
|
||||
out.push_str(
|
||||
"<h3 class=\"sidebar-title\">\
|
||||
<a href=\"#implementations\">Associated Constants</a>\
|
||||
</h3>\
|
||||
<div class=\"sidebar-links\">",
|
||||
print_sidebar_block(
|
||||
out,
|
||||
"implementations",
|
||||
"Associated Constants",
|
||||
assoc_consts.iter(),
|
||||
);
|
||||
for line in assoc_consts {
|
||||
write!(out, "{}", line);
|
||||
}
|
||||
out.push_str("</div>");
|
||||
}
|
||||
let mut methods = v
|
||||
.iter()
|
||||
@ -1983,14 +1979,7 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
|
||||
// We want links' order to be reproducible so we don't use unstable sort.
|
||||
methods.sort();
|
||||
|
||||
out.push_str(
|
||||
"<h3 class=\"sidebar-title\"><a href=\"#implementations\">Methods</a></h3>\
|
||||
<div class=\"sidebar-links\">",
|
||||
);
|
||||
for line in methods {
|
||||
write!(out, "{}", line);
|
||||
}
|
||||
out.push_str("</div>");
|
||||
print_sidebar_block(out, "implementations", "Methods", methods.iter());
|
||||
}
|
||||
}
|
||||
|
||||
@ -2029,14 +2018,6 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
|
||||
ret
|
||||
};
|
||||
|
||||
let write_sidebar_links = |out: &mut Buffer, links: Vec<String>| {
|
||||
out.push_str("<div class=\"sidebar-links\">");
|
||||
for link in links {
|
||||
out.push_str(&link);
|
||||
}
|
||||
out.push_str("</div>");
|
||||
};
|
||||
|
||||
let (synthetic, concrete): (Vec<&Impl>, Vec<&Impl>) =
|
||||
v.iter().partition::<Vec<_>, _>(|i| i.inner_impl().kind.is_auto());
|
||||
let (blanket_impl, concrete): (Vec<&Impl>, Vec<&Impl>) =
|
||||
@ -2047,27 +2028,30 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
|
||||
let blanket_format = format_impls(blanket_impl);
|
||||
|
||||
if !concrete_format.is_empty() {
|
||||
out.push_str(
|
||||
"<h3 class=\"sidebar-title\"><a href=\"#trait-implementations\">\
|
||||
Trait Implementations</a></h3>",
|
||||
print_sidebar_block(
|
||||
out,
|
||||
"trait-implementations",
|
||||
"Trait Implementations",
|
||||
concrete_format.iter(),
|
||||
);
|
||||
write_sidebar_links(out, concrete_format);
|
||||
}
|
||||
|
||||
if !synthetic_format.is_empty() {
|
||||
out.push_str(
|
||||
"<h3 class=\"sidebar-title\"><a href=\"#synthetic-implementations\">\
|
||||
Auto Trait Implementations</a></h3>",
|
||||
print_sidebar_block(
|
||||
out,
|
||||
"synthetic-implementations",
|
||||
"Auto Trait Implementations",
|
||||
synthetic_format.iter(),
|
||||
);
|
||||
write_sidebar_links(out, synthetic_format);
|
||||
}
|
||||
|
||||
if !blanket_format.is_empty() {
|
||||
out.push_str(
|
||||
"<h3 class=\"sidebar-title\"><a href=\"#blanket-implementations\">\
|
||||
Blanket Implementations</a></h3>",
|
||||
print_sidebar_block(
|
||||
out,
|
||||
"blanket-implementations",
|
||||
"Blanket Implementations",
|
||||
blanket_format.iter(),
|
||||
);
|
||||
write_sidebar_links(out, blanket_format);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2127,20 +2111,14 @@ fn sidebar_deref_methods(
|
||||
} else {
|
||||
"deref-methods"
|
||||
};
|
||||
write!(
|
||||
out,
|
||||
"<h3 class=\"sidebar-title\"><a href=\"#{}\">Methods from {}<Target={}></a></h3>",
|
||||
id,
|
||||
let title = format!(
|
||||
"Methods from {}<Target={}>",
|
||||
Escape(&format!("{:#}", impl_.inner_impl().trait_.as_ref().unwrap().print(cx))),
|
||||
Escape(&format!("{:#}", real_target.print(cx))),
|
||||
);
|
||||
// We want links' order to be reproducible so we don't use unstable sort.
|
||||
ret.sort();
|
||||
out.push_str("<div class=\"sidebar-links\">");
|
||||
for link in ret {
|
||||
write!(out, "{}", link);
|
||||
}
|
||||
out.push_str("</div>");
|
||||
print_sidebar_block(out, id, &title, ret.iter());
|
||||
}
|
||||
}
|
||||
|
||||
@ -2166,27 +2144,19 @@ fn sidebar_struct(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, s: &clea
|
||||
let fields = get_struct_fields_name(&s.fields);
|
||||
|
||||
if !fields.is_empty() {
|
||||
if let CtorKind::Fictive = s.struct_type {
|
||||
sidebar.push_str(
|
||||
"<h3 class=\"sidebar-title\"><a href=\"#fields\">Fields</a></h3>\
|
||||
<div class=\"sidebar-links\">",
|
||||
);
|
||||
|
||||
for field in fields {
|
||||
sidebar.push_str(&field);
|
||||
match s.struct_type {
|
||||
CtorKind::Fictive => {
|
||||
print_sidebar_block(&mut sidebar, "fields", "Fields", fields.iter());
|
||||
}
|
||||
|
||||
sidebar.push_str("</div>");
|
||||
} else if let CtorKind::Fn = s.struct_type {
|
||||
sidebar
|
||||
.push_str("<h3 class=\"sidebar-title\"><a href=\"#fields\">Tuple Fields</a></h3>");
|
||||
CtorKind::Fn => print_sidebar_title(&mut sidebar, "fields", "Tuple Fields"),
|
||||
CtorKind::Const => {}
|
||||
}
|
||||
}
|
||||
|
||||
sidebar_assoc_items(cx, &mut sidebar, it);
|
||||
|
||||
if !sidebar.is_empty() {
|
||||
write!(buf, "<div class=\"block items\">{}</div>", sidebar.into_inner());
|
||||
write!(buf, "<section>{}</section>", sidebar.into_inner());
|
||||
}
|
||||
}
|
||||
|
||||
@ -2214,18 +2184,50 @@ fn extract_for_impl_name(item: &clean::Item, cx: &Context<'_>) -> Option<(String
|
||||
}
|
||||
}
|
||||
|
||||
/// Don't call this function directly!!! Use `print_sidebar_title` or `print_sidebar_block` instead!
|
||||
fn print_sidebar_title_inner(buf: &mut Buffer, id: &str, title: &str) {
|
||||
write!(
|
||||
buf,
|
||||
"<h3 class=\"sidebar-title\">\
|
||||
<a href=\"#{}\">{}</a>\
|
||||
</h3>",
|
||||
id, title
|
||||
);
|
||||
}
|
||||
|
||||
fn print_sidebar_title(buf: &mut Buffer, id: &str, title: &str) {
|
||||
buf.push_str("<div class=\"block\">");
|
||||
print_sidebar_title_inner(buf, id, title);
|
||||
buf.push_str("</div>");
|
||||
}
|
||||
|
||||
fn print_sidebar_block(
|
||||
buf: &mut Buffer,
|
||||
id: &str,
|
||||
title: &str,
|
||||
items: impl Iterator<Item = impl fmt::Display>,
|
||||
) {
|
||||
buf.push_str("<div class=\"block\">");
|
||||
print_sidebar_title_inner(buf, id, title);
|
||||
buf.push_str("<ul>");
|
||||
for item in items {
|
||||
write!(buf, "<li>{}</li>", item);
|
||||
}
|
||||
buf.push_str("</ul></div>");
|
||||
}
|
||||
|
||||
fn sidebar_trait(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, t: &clean::Trait) {
|
||||
buf.write_str("<div class=\"block items\">");
|
||||
buf.write_str("<section>");
|
||||
|
||||
fn print_sidebar_section(
|
||||
out: &mut Buffer,
|
||||
items: &[clean::Item],
|
||||
before: &str,
|
||||
id: &str,
|
||||
title: &str,
|
||||
filter: impl Fn(&clean::Item) -> bool,
|
||||
write: impl Fn(&mut Buffer, &str),
|
||||
after: &str,
|
||||
mapper: impl Fn(&str) -> String,
|
||||
) {
|
||||
let mut items = items
|
||||
let mut items: Vec<&str> = items
|
||||
.iter()
|
||||
.filter_map(|m| match m.name {
|
||||
Some(ref name) if filter(m) => Some(name.as_str()),
|
||||
@ -2235,52 +2237,44 @@ fn print_sidebar_section(
|
||||
|
||||
if !items.is_empty() {
|
||||
items.sort_unstable();
|
||||
out.push_str(before);
|
||||
for item in items.into_iter() {
|
||||
write(out, &item);
|
||||
}
|
||||
out.push_str(after);
|
||||
print_sidebar_block(out, id, title, items.into_iter().map(mapper));
|
||||
}
|
||||
}
|
||||
|
||||
print_sidebar_section(
|
||||
buf,
|
||||
&t.items,
|
||||
"<h3 class=\"sidebar-title\"><a href=\"#associated-types\">\
|
||||
Associated Types</a></h3><div class=\"sidebar-links\">",
|
||||
"associated-types",
|
||||
"Associated Types",
|
||||
|m| m.is_associated_type(),
|
||||
|out, sym| write!(out, "<a href=\"#associatedtype.{0}\">{0}</a>", sym),
|
||||
"</div>",
|
||||
|sym| format!("<a href=\"#associatedtype.{0}\">{0}</a>", sym),
|
||||
);
|
||||
|
||||
print_sidebar_section(
|
||||
buf,
|
||||
&t.items,
|
||||
"<h3 class=\"sidebar-title\"><a href=\"#associated-const\">\
|
||||
Associated Constants</a></h3><div class=\"sidebar-links\">",
|
||||
"associated-const",
|
||||
"Associated Constants",
|
||||
|m| m.is_associated_const(),
|
||||
|out, sym| write!(out, "<a href=\"#associatedconstant.{0}\">{0}</a>", sym),
|
||||
"</div>",
|
||||
|sym| format!("<a href=\"#associatedconstant.{0}\">{0}</a>", sym),
|
||||
);
|
||||
|
||||
print_sidebar_section(
|
||||
buf,
|
||||
&t.items,
|
||||
"<h3 class=\"sidebar-title\"><a href=\"#required-methods\">\
|
||||
Required Methods</a></h3><div class=\"sidebar-links\">",
|
||||
"required-methods",
|
||||
"Required Methods",
|
||||
|m| m.is_ty_method(),
|
||||
|out, sym| write!(out, "<a href=\"#tymethod.{0}\">{0}</a>", sym),
|
||||
"</div>",
|
||||
|sym| format!("<a href=\"#tymethod.{0}\">{0}</a>", sym),
|
||||
);
|
||||
|
||||
print_sidebar_section(
|
||||
buf,
|
||||
&t.items,
|
||||
"<h3 class=\"sidebar-title\"><a href=\"#provided-methods\">\
|
||||
Provided Methods</a></h3><div class=\"sidebar-links\">",
|
||||
"provided-methods",
|
||||
"Provided Methods",
|
||||
|m| m.is_method(),
|
||||
|out, sym| write!(out, "<a href=\"#method.{0}\">{0}</a>", sym),
|
||||
"</div>",
|
||||
|sym| format!("<a href=\"#method.{0}\">{0}</a>", sym),
|
||||
);
|
||||
|
||||
let cache = cx.cache();
|
||||
@ -2295,29 +2289,23 @@ fn print_sidebar_section(
|
||||
|
||||
if !res.is_empty() {
|
||||
res.sort();
|
||||
buf.push_str(
|
||||
"<h3 class=\"sidebar-title\"><a href=\"#foreign-impls\">\
|
||||
Implementations on Foreign Types</a></h3>\
|
||||
<div class=\"sidebar-links\">",
|
||||
print_sidebar_block(
|
||||
buf,
|
||||
"foreign-impls",
|
||||
"Implementations on Foreign Types",
|
||||
res.iter().map(|(name, id)| format!("<a href=\"#{}\">{}</a>", id, Escape(&name))),
|
||||
);
|
||||
for (name, id) in res.into_iter() {
|
||||
write!(buf, "<a href=\"#{}\">{}</a>", id, Escape(&name));
|
||||
}
|
||||
buf.push_str("</div>");
|
||||
}
|
||||
}
|
||||
|
||||
sidebar_assoc_items(cx, buf, it);
|
||||
|
||||
buf.push_str("<h3 class=\"sidebar-title\"><a href=\"#implementors\">Implementors</a></h3>");
|
||||
print_sidebar_title(buf, "implementors", "Implementors");
|
||||
if t.is_auto {
|
||||
buf.push_str(
|
||||
"<h3 class=\"sidebar-title\"><a \
|
||||
href=\"#synthetic-implementors\">Auto Implementors</a></h3>",
|
||||
);
|
||||
print_sidebar_title(buf, "synthetic-implementors", "Auto Implementors");
|
||||
}
|
||||
|
||||
buf.push_str("</div>")
|
||||
buf.push_str("</section>")
|
||||
}
|
||||
|
||||
fn sidebar_primitive(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item) {
|
||||
@ -2325,7 +2313,7 @@ fn sidebar_primitive(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item) {
|
||||
sidebar_assoc_items(cx, &mut sidebar, it);
|
||||
|
||||
if !sidebar.is_empty() {
|
||||
write!(buf, "<div class=\"block items\">{}</div>", sidebar.into_inner());
|
||||
write!(buf, "<section>{}</section>", sidebar.into_inner());
|
||||
}
|
||||
}
|
||||
|
||||
@ -2334,7 +2322,7 @@ fn sidebar_typedef(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item) {
|
||||
sidebar_assoc_items(cx, &mut sidebar, it);
|
||||
|
||||
if !sidebar.is_empty() {
|
||||
write!(buf, "<div class=\"block items\">{}</div>", sidebar.into_inner());
|
||||
write!(buf, "<section>{}</section>", sidebar.into_inner());
|
||||
}
|
||||
}
|
||||
|
||||
@ -2355,22 +2343,13 @@ fn sidebar_union(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, u: &clean
|
||||
let fields = get_struct_fields_name(&u.fields);
|
||||
|
||||
if !fields.is_empty() {
|
||||
sidebar.push_str(
|
||||
"<h3 class=\"sidebar-title\"><a href=\"#fields\">Fields</a></h3>\
|
||||
<div class=\"sidebar-links\">",
|
||||
);
|
||||
|
||||
for field in fields {
|
||||
sidebar.push_str(&field);
|
||||
}
|
||||
|
||||
sidebar.push_str("</div>");
|
||||
print_sidebar_block(&mut sidebar, "fields", "Fields", fields.iter());
|
||||
}
|
||||
|
||||
sidebar_assoc_items(cx, &mut sidebar, it);
|
||||
|
||||
if !sidebar.is_empty() {
|
||||
write!(buf, "<div class=\"block items\">{}</div>", sidebar.into_inner());
|
||||
write!(buf, "<section>{}</section>", sidebar.into_inner());
|
||||
}
|
||||
}
|
||||
|
||||
@ -2388,17 +2367,13 @@ fn sidebar_enum(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, e: &clean:
|
||||
.collect::<Vec<_>>();
|
||||
if !variants.is_empty() {
|
||||
variants.sort_unstable();
|
||||
sidebar.push_str(&format!(
|
||||
"<h3 class=\"sidebar-title\"><a href=\"#variants\">Variants</a></h3>\
|
||||
<div class=\"sidebar-links\">{}</div>",
|
||||
variants.join(""),
|
||||
));
|
||||
print_sidebar_block(&mut sidebar, "variants", "Variants", variants.iter());
|
||||
}
|
||||
|
||||
sidebar_assoc_items(cx, &mut sidebar, it);
|
||||
|
||||
if !sidebar.is_empty() {
|
||||
write!(buf, "<div class=\"block items\">{}</div>", sidebar.into_inner());
|
||||
write!(buf, "<section>{}</section>", sidebar.into_inner());
|
||||
}
|
||||
}
|
||||
|
||||
@ -2569,7 +2544,15 @@ fn sidebar_module(buf: &mut Buffer, items: &[clean::Item]) {
|
||||
}
|
||||
|
||||
if !sidebar.is_empty() {
|
||||
write!(buf, "<div class=\"block items\"><ul>{}</ul></div>", sidebar);
|
||||
write!(
|
||||
buf,
|
||||
"<section>\
|
||||
<div class=\"block\">\
|
||||
<ul>{}</ul>\
|
||||
</div>\
|
||||
</section>",
|
||||
sidebar
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2578,7 +2561,7 @@ fn sidebar_foreign_type(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item) {
|
||||
sidebar_assoc_items(cx, &mut sidebar, it);
|
||||
|
||||
if !sidebar.is_empty() {
|
||||
write!(buf, "<div class=\"block items\">{}</div>", sidebar.into_inner());
|
||||
write!(buf, "<section>{}</section>", sidebar.into_inner());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1752,9 +1752,7 @@ fn write_size_of_layout(w: &mut Buffer, layout: &Layout, tag_size: u64) {
|
||||
<ul>",
|
||||
);
|
||||
|
||||
let adt = if let Adt(adt, _) = ty_layout.ty.kind() {
|
||||
adt
|
||||
} else {
|
||||
let Adt(adt, _) = ty_layout.ty.kind() else {
|
||||
span_bug!(tcx.def_span(ty_def_id), "not an adt")
|
||||
};
|
||||
|
||||
|
@ -484,10 +484,6 @@ h2.location a {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.sidebar-links a {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.sidebar h2 {
|
||||
border-bottom: none;
|
||||
font-weight: 500;
|
||||
@ -504,11 +500,14 @@ h2.location a {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.sidebar-links,
|
||||
.block {
|
||||
.sidebar-elems .block {
|
||||
margin-bottom: 2em;
|
||||
}
|
||||
|
||||
.sidebar-elems .block li a {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.mobile-topbar {
|
||||
display: none;
|
||||
}
|
||||
|
@ -1226,9 +1226,7 @@ fn resolve_link(
|
||||
let base_node =
|
||||
if item.is_mod() && inner_docs { self.mod_ids.last().copied() } else { parent_node };
|
||||
|
||||
let mut module_id = if let Some(id) = base_node {
|
||||
id
|
||||
} else {
|
||||
let Some(mut module_id) = base_node else {
|
||||
// This is a bug.
|
||||
debug!("attempting to resolve item without parent module: {}", path_str);
|
||||
resolution_failure(
|
||||
@ -1977,9 +1975,7 @@ fn split(path: &str) -> Option<(&str, &str)> {
|
||||
// If so, report it and say the first which failed; if not, say the first path segment didn't resolve.
|
||||
let mut name = path_str;
|
||||
'outer: loop {
|
||||
let (start, end) = if let Some(x) = split(name) {
|
||||
x
|
||||
} else {
|
||||
let Some((start, end)) = split(name) else {
|
||||
// avoid bug that marked [Quux::Z] as missing Z, not Quux
|
||||
if partial_res.is_none() {
|
||||
*unresolved = name.into();
|
||||
|
@ -152,9 +152,7 @@ fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
|
||||
}
|
||||
hir::ExprKind::MethodCall(_, _, span) => {
|
||||
let types = tcx.typeck(ex.hir_id.owner);
|
||||
let def_id = if let Some(def_id) = types.type_dependent_def_id(ex.hir_id) {
|
||||
def_id
|
||||
} else {
|
||||
let Some(def_id) = types.type_dependent_def_id(ex.hir_id) else {
|
||||
trace!("type_dependent_def_id({}) = None", ex.hir_id);
|
||||
return;
|
||||
};
|
||||
|
@ -188,9 +188,7 @@ fn maybe_inline_local(
|
||||
debug!("maybe_inline_local res: {:?}", res);
|
||||
|
||||
let tcx = self.cx.tcx;
|
||||
let res_did = if let Some(did) = res.opt_def_id() {
|
||||
did
|
||||
} else {
|
||||
let Some(res_did) = res.opt_def_id() else {
|
||||
return false;
|
||||
};
|
||||
|
||||
|
@ -5,7 +5,7 @@ assert-attribute: ("#blanket-implementations-list > details:nth-child(2)", {"ope
|
||||
// We first check that the impl block is open by default.
|
||||
assert-attribute: ("#implementations + details", {"open": ""})
|
||||
// To ensure that we will click on the currently hidden method.
|
||||
assert-text: (".sidebar-links > a", "must_use")
|
||||
click: ".sidebar-links > a"
|
||||
assert-text: (".sidebar-elems section .block li > a", "must_use")
|
||||
click: ".sidebar-elems section .block li > a"
|
||||
// We check that the impl block was opened as expected so that we can see the method.
|
||||
assert-attribute: ("#implementations + details", {"open": ""})
|
||||
|
@ -33,7 +33,7 @@ assert-property: (".mobile-topbar", {"clientHeight": "45"})
|
||||
// Check that clicking an element from the sidebar scrolls to the right place
|
||||
// so the target is not obscured by the topbar.
|
||||
click: ".sidebar-menu-toggle"
|
||||
click: ".sidebar-links a"
|
||||
click: ".sidebar-elems section .block li > a"
|
||||
assert-position: ("#method\.must_use", {"y": 45})
|
||||
|
||||
// Check that the bottom-most item on the sidebar menu can be scrolled fully into view.
|
||||
|
@ -13,15 +13,15 @@ assert-css: ("#all-types", {"color": "rgb(53, 109, 164)"})
|
||||
// We check that we have the crates list and that the "current" on is "test_docs".
|
||||
assert-text: (".sidebar-elems .crate > ul > li > a.current", "test_docs")
|
||||
// And we're also supposed to have the list of items in the current module.
|
||||
assert-text: (".sidebar-elems .items > ul > li:nth-child(1)", "Modules")
|
||||
assert-text: (".sidebar-elems .items > ul > li:nth-child(2)", "Macros")
|
||||
assert-text: (".sidebar-elems .items > ul > li:nth-child(3)", "Structs")
|
||||
assert-text: (".sidebar-elems .items > ul > li:nth-child(4)", "Enums")
|
||||
assert-text: (".sidebar-elems .items > ul > li:nth-child(5)", "Traits")
|
||||
assert-text: (".sidebar-elems .items > ul > li:nth-child(6)", "Functions")
|
||||
assert-text: (".sidebar-elems .items > ul > li:nth-child(7)", "Type Definitions")
|
||||
assert-text: (".sidebar-elems .items > ul > li:nth-child(8)", "Unions")
|
||||
assert-text: (".sidebar-elems .items > ul > li:nth-child(9)", "Keywords")
|
||||
assert-text: (".sidebar-elems section ul > li:nth-child(1)", "Modules")
|
||||
assert-text: (".sidebar-elems section ul > li:nth-child(2)", "Macros")
|
||||
assert-text: (".sidebar-elems section ul > li:nth-child(3)", "Structs")
|
||||
assert-text: (".sidebar-elems section ul > li:nth-child(4)", "Enums")
|
||||
assert-text: (".sidebar-elems section ul > li:nth-child(5)", "Traits")
|
||||
assert-text: (".sidebar-elems section ul > li:nth-child(6)", "Functions")
|
||||
assert-text: (".sidebar-elems section ul > li:nth-child(7)", "Type Definitions")
|
||||
assert-text: (".sidebar-elems section ul > li:nth-child(8)", "Unions")
|
||||
assert-text: (".sidebar-elems section ul > li:nth-child(9)", "Keywords")
|
||||
assert-text: ("#structs + .item-table .item-left > a", "Foo")
|
||||
click: "#structs + .item-table .item-left > a"
|
||||
|
||||
@ -30,7 +30,7 @@ assert-count: (".sidebar .location", 2)
|
||||
// We check that there is no crate listed outside of the top level.
|
||||
assert-false: ".sidebar-elems > .crate"
|
||||
|
||||
click: ".sidebar-links a"
|
||||
click: ".sidebar-elems section .block li > a"
|
||||
assert-property-false: ("html", {"scrollTop": "0"})
|
||||
|
||||
click: ".sidebar h2.location a"
|
||||
@ -47,11 +47,11 @@ assert-text: (".sidebar > .location", "Crate lib2")
|
||||
// We check that we have the crates list and that the "current" on is now "lib2".
|
||||
assert-text: (".sidebar-elems .crate > ul > li > a.current", "lib2")
|
||||
// We now go to the "foobar" function page.
|
||||
assert-text: (".sidebar-elems > .items > ul > li:nth-child(1)", "Modules")
|
||||
assert-text: (".sidebar-elems > .items > ul > li:nth-child(2)", "Structs")
|
||||
assert-text: (".sidebar-elems > .items > ul > li:nth-child(3)", "Traits")
|
||||
assert-text: (".sidebar-elems > .items > ul > li:nth-child(4)", "Functions")
|
||||
assert-text: (".sidebar-elems > .items > ul > li:nth-child(5)", "Type Definitions")
|
||||
assert-text: (".sidebar-elems > section .block ul > li:nth-child(1)", "Modules")
|
||||
assert-text: (".sidebar-elems > section .block ul > li:nth-child(2)", "Structs")
|
||||
assert-text: (".sidebar-elems > section .block ul > li:nth-child(3)", "Traits")
|
||||
assert-text: (".sidebar-elems > section .block ul > li:nth-child(4)", "Functions")
|
||||
assert-text: (".sidebar-elems > section .block ul > li:nth-child(5)", "Type Definitions")
|
||||
assert-text: ("#functions + .item-table .item-left > a", "foobar")
|
||||
click: "#functions + .item-table .item-left > a"
|
||||
|
||||
@ -72,12 +72,12 @@ goto: ./sub_module/sub_sub_module/index.html
|
||||
assert-text: (".sidebar > .location", "Module sub_sub_module")
|
||||
// We check that we don't have the crate list.
|
||||
assert-false: ".sidebar-elems .crate"
|
||||
assert-text: (".sidebar-elems .items > ul > li:nth-child(1)", "Functions")
|
||||
assert-text: (".sidebar-elems > section ul > li:nth-child(1)", "Functions")
|
||||
assert-text: ("#functions + .item-table .item-left > a", "foo")
|
||||
|
||||
// Links to trait implementations in the sidebar should not wrap even if they are long.
|
||||
goto: file://|DOC_PATH|/lib2/struct.HasALongTraitWithParams.html
|
||||
assert-property: (".sidebar-links a", {"offsetHeight": 29})
|
||||
assert-property: (".sidebar-elems section .block li > a", {"offsetHeight": 29})
|
||||
|
||||
// Test that clicking on of the "In <module>" headings in the sidebar links to the
|
||||
// appropriate anchor in index.html.
|
||||
|
@ -1,8 +1,8 @@
|
||||
// Checks that the elements in the sidebar are alphabetically sorted.
|
||||
goto: file://|DOC_PATH|/test_docs/trait.AnotherOne.html
|
||||
assert-text: (".sidebar-links a:nth-of-type(1)", "another")
|
||||
assert-text: (".sidebar-links a:nth-of-type(2)", "func1")
|
||||
assert-text: (".sidebar-links a:nth-of-type(3)", "func2")
|
||||
assert-text: (".sidebar-links a:nth-of-type(4)", "func3")
|
||||
assert-text: (".sidebar-links a:nth-of-type(5)", "hello")
|
||||
assert-text: (".sidebar-links a:nth-of-type(6)", "why_not")
|
||||
assert-text: (".sidebar-elems section .block li:nth-of-type(1) > a", "another")
|
||||
assert-text: (".sidebar-elems section .block li:nth-of-type(2) > a", "func1")
|
||||
assert-text: (".sidebar-elems section .block li:nth-of-type(3) > a", "func2")
|
||||
assert-text: (".sidebar-elems section .block li:nth-of-type(4) > a", "func3")
|
||||
assert-text: (".sidebar-elems section .block li:nth-of-type(5) > a", "hello")
|
||||
assert-text: (".sidebar-elems section .block li:nth-of-type(6) > a", "why_not")
|
||||
|
@ -10,7 +10,7 @@ pub trait Trait {
|
||||
|
||||
// @has 'foo/struct.Bar.html'
|
||||
// @has - '//h3[@class="sidebar-title"]' 'Associated Constants'
|
||||
// @has - '//div[@class="sidebar-elems"]//div[@class="sidebar-links"]/a' 'FOO'
|
||||
// @has - '//div[@class="sidebar-elems"]//a' 'FOO'
|
||||
impl Trait for Bar {
|
||||
const FOO: u32 = 1;
|
||||
|
||||
@ -23,7 +23,7 @@ pub enum Foo {
|
||||
|
||||
// @has 'foo/enum.Foo.html'
|
||||
// @has - '//h3[@class="sidebar-title"]' 'Associated Constants'
|
||||
// @has - '//div[@class="sidebar-elems"]//div[@class="sidebar-links"]/a' 'FOO'
|
||||
// @has - '//div[@class="sidebar-elems"]//a' 'FOO'
|
||||
impl Trait for Foo {
|
||||
const FOO: u32 = 1;
|
||||
|
||||
|
@ -9,7 +9,7 @@ pub fn foo(&mut self) {}
|
||||
}
|
||||
|
||||
// @has foo/struct.Bar.html
|
||||
// @has - '//div[@class="sidebar-links"]/a[@href="#method.foo"]' 'foo'
|
||||
// @has - '//*[@class="sidebar-elems"]//*[@class="block"]//a[@href="#method.foo"]' 'foo'
|
||||
pub struct Bar {
|
||||
foo: Foo,
|
||||
}
|
||||
|
@ -8,9 +8,9 @@
|
||||
// @has '-' '//*[@id="deref-methods-Path"]' 'Methods from Deref<Target = Path>'
|
||||
// @has '-' '//*[@class="impl-items"]//*[@id="method.exists"]' 'pub fn exists(&self)'
|
||||
// @has '-' '//*[@class="sidebar-title"]/a[@href="#deref-methods-PathBuf"]' 'Methods from Deref<Target=PathBuf>'
|
||||
// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.as_path"]' 'as_path'
|
||||
// @has '-' '//*[@class="sidebar-elems"]//*[@class="block"]//a[@href="#method.as_path"]' 'as_path'
|
||||
// @has '-' '//*[@class="sidebar-title"]/a[@href="#deref-methods-Path"]' 'Methods from Deref<Target=Path>'
|
||||
// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.exists"]' 'exists'
|
||||
// @has '-' '//*[@class="sidebar-elems"]//*[@class="block"]//a[@href="#method.exists"]' 'exists'
|
||||
|
||||
#![crate_name = "foo"]
|
||||
|
||||
|
@ -8,9 +8,9 @@
|
||||
// @has '-' '//*[@id="deref-methods-Baz"]' 'Methods from Deref<Target = Baz>'
|
||||
// @has '-' '//*[@class="impl-items"]//*[@id="method.baz"]' 'pub fn baz(&self)'
|
||||
// @has '-' '//*[@class="sidebar-title"]/a[@href="#deref-methods-Bar"]' 'Methods from Deref<Target=Bar>'
|
||||
// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.bar"]' 'bar'
|
||||
// @has '-' '//*[@class="sidebar-elems"]//section//a[@href="#method.bar"]' 'bar'
|
||||
// @has '-' '//*[@class="sidebar-title"]/a[@href="#deref-methods-Baz"]' 'Methods from Deref<Target=Baz>'
|
||||
// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.baz"]' 'baz'
|
||||
// @has '-' '//*[@class="sidebar-elems"]//section//a[@href="#method.baz"]' 'baz'
|
||||
|
||||
#![crate_name = "foo"]
|
||||
|
||||
|
@ -7,10 +7,10 @@
|
||||
// @has '-' '//*[@class="impl-items"]//*[@id="method.foo_c"]' 'pub fn foo_c(&self)'
|
||||
// @has '-' '//*[@class="impl-items"]//*[@id="method.foo_j"]' 'pub fn foo_j(&self)'
|
||||
// @has '-' '//*[@class="sidebar-title"]/a[@href="#deref-methods-FooJ"]' 'Methods from Deref<Target=FooJ>'
|
||||
// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.foo_a"]' 'foo_a'
|
||||
// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.foo_b"]' 'foo_b'
|
||||
// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.foo_c"]' 'foo_c'
|
||||
// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.foo_j"]' 'foo_j'
|
||||
// @has '-' '//*[@class="sidebar-elems"]//section//a[@href="#method.foo_a"]' 'foo_a'
|
||||
// @has '-' '//*[@class="sidebar-elems"]//section//a[@href="#method.foo_b"]' 'foo_b'
|
||||
// @has '-' '//*[@class="sidebar-elems"]//section//a[@href="#method.foo_c"]' 'foo_c'
|
||||
// @has '-' '//*[@class="sidebar-elems"]//section//a[@href="#method.foo_j"]' 'foo_j'
|
||||
|
||||
pub struct FooA;
|
||||
pub type FooB = FooA;
|
||||
|
@ -8,5 +8,5 @@ fn foo() {}
|
||||
pub struct Bar;
|
||||
|
||||
// @has foo/struct.Bar.html
|
||||
// @has - '//*[@class="sidebar-links"]/a[@href="#impl-Foo%3Cunsafe%20extern%20%22C%22%20fn()%3E"]' 'Foo<unsafe extern "C" fn()>'
|
||||
// @has - '//*[@class="sidebar-elems"]//section//a[@href="#impl-Foo%3Cunsafe%20extern%20%22C%22%20fn()%3E"]' 'Foo<unsafe extern "C" fn()>'
|
||||
impl Foo<unsafe extern "C" fn()> for Bar {}
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
// @has foo/struct.Foo.html '//*[@id="impl-ToString"]//h3[@class="code-header in-band"]' 'impl<T> ToString for T'
|
||||
pub struct Foo;
|
||||
// @has foo/struct.Foo.html '//div[@class="sidebar-links"]/a[@href="#impl-ToString"]' 'ToString'
|
||||
// @has foo/struct.Foo.html '//*[@class="sidebar-elems"]//section//a[@href="#impl-ToString"]' 'ToString'
|
||||
|
||||
impl fmt::Display for Foo {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
|
@ -1,8 +1,8 @@
|
||||
#![crate_name = "foo"]
|
||||
|
||||
// @has foo/struct.Foo.html
|
||||
// @has - '//*[@class="sidebar-links"]/a' 'super_long_name'
|
||||
// @has - '//*[@class="sidebar-links"]/a' 'Disp'
|
||||
// @has - '//*[@class="sidebar-elems"]//section//a' 'super_long_name'
|
||||
// @has - '//*[@class="sidebar-elems"]//section//a' 'Disp'
|
||||
pub struct Foo(usize);
|
||||
|
||||
impl Foo {
|
||||
|
@ -5,5 +5,5 @@
|
||||
|
||||
// @has foo/struct.Foo.html
|
||||
// @has - '//*[@class="sidebar-title"]/a[@href="#trait-implementations"]' 'Trait Implementations'
|
||||
// @has - '//*[@class="sidebar-links"]/a' '!Sync'
|
||||
// @has - '//*[@class="sidebar-elems"]//section//a' '!Sync'
|
||||
impl !Sync for Foo {}
|
||||
|
@ -9,13 +9,13 @@ impl B { pub fn foo_b(&self) {} }
|
||||
pub struct C {}
|
||||
impl C { pub fn foo_c(&self) {} }
|
||||
|
||||
// @has recursive_deref_sidebar/struct.A.html '//div[@class="sidebar-links"]' 'foo_b'
|
||||
// @has recursive_deref_sidebar/struct.A.html '//*[@class="sidebar-elems"]//section' 'foo_b'
|
||||
impl Deref for A {
|
||||
type Target = B;
|
||||
fn deref(&self) -> &B { todo!() }
|
||||
}
|
||||
|
||||
// @has recursive_deref_sidebar/struct.A.html '//div[@class="sidebar-links"]' 'foo_c'
|
||||
// @has recursive_deref_sidebar/struct.A.html '//*[@class="sidebar-elems"]//section' 'foo_c'
|
||||
impl Deref for B {
|
||||
type Target = C;
|
||||
fn deref(&self) -> &C { todo!() }
|
||||
|
@ -2,13 +2,13 @@
|
||||
|
||||
// @has foo/trait.Foo.html
|
||||
// @has - '//*[@class="sidebar-title"]/a[@href="#required-methods"]' 'Required Methods'
|
||||
// @has - '//*[@class="sidebar-links"]/a' 'bar'
|
||||
// @has - '//*[@class="sidebar-elems"]//section//a' 'bar'
|
||||
// @has - '//*[@class="sidebar-title"]/a[@href="#provided-methods"]' 'Provided Methods'
|
||||
// @has - '//*[@class="sidebar-links"]/a' 'foo'
|
||||
// @has - '//*[@class="sidebar-elems"]//section//a' 'foo'
|
||||
// @has - '//*[@class="sidebar-title"]/a[@href="#associated-const"]' 'Associated Constants'
|
||||
// @has - '//*[@class="sidebar-links"]/a' 'BAR'
|
||||
// @has - '//*[@class="sidebar-elems"]//section//a' 'BAR'
|
||||
// @has - '//*[@class="sidebar-title"]/a[@href="#associated-types"]' 'Associated Types'
|
||||
// @has - '//*[@class="sidebar-links"]/a' 'Output'
|
||||
// @has - '//*[@class="sidebar-elems"]//section//a' 'Output'
|
||||
pub trait Foo {
|
||||
const BAR: u32 = 0;
|
||||
type Output: ?Sized;
|
||||
@ -19,9 +19,9 @@ fn foo() {}
|
||||
|
||||
// @has foo/struct.Bar.html
|
||||
// @has - '//*[@class="sidebar-title"]/a[@href="#fields"]' 'Fields'
|
||||
// @has - '//*[@class="sidebar-links"]/a[@href="#structfield.f"]' 'f'
|
||||
// @has - '//*[@class="sidebar-links"]/a[@href="#structfield.u"]' 'u'
|
||||
// @!has - '//*[@class="sidebar-links"]/a' 'waza'
|
||||
// @has - '//*[@class="sidebar-elems"]//section//a[@href="#structfield.f"]' 'f'
|
||||
// @has - '//*[@class="sidebar-elems"]//section//a[@href="#structfield.u"]' 'u'
|
||||
// @!has - '//*[@class="sidebar-elems"]//section//a' 'waza'
|
||||
pub struct Bar {
|
||||
pub f: u32,
|
||||
pub u: u32,
|
||||
@ -30,8 +30,8 @@ pub struct Bar {
|
||||
|
||||
// @has foo/enum.En.html
|
||||
// @has - '//*[@class="sidebar-title"]/a[@href="#variants"]' 'Variants'
|
||||
// @has - '//*[@class="sidebar-links"]/a' 'Foo'
|
||||
// @has - '//*[@class="sidebar-links"]/a' 'Bar'
|
||||
// @has - '//*[@class="sidebar-elems"]//section//a' 'Foo'
|
||||
// @has - '//*[@class="sidebar-elems"]//section//a' 'Bar'
|
||||
pub enum En {
|
||||
Foo,
|
||||
Bar,
|
||||
@ -39,9 +39,9 @@ pub enum En {
|
||||
|
||||
// @has foo/union.MyUnion.html
|
||||
// @has - '//*[@class="sidebar-title"]/a[@href="#fields"]' 'Fields'
|
||||
// @has - '//*[@class="sidebar-links"]/a[@href="#structfield.f1"]' 'f1'
|
||||
// @has - '//*[@class="sidebar-links"]/a[@href="#structfield.f2"]' 'f2'
|
||||
// @!has - '//*[@class="sidebar-links"]/a' 'waza'
|
||||
// @has - '//*[@class="sidebar-elems"]//section//a[@href="#structfield.f1"]' 'f1'
|
||||
// @has - '//*[@class="sidebar-elems"]//section//a[@href="#structfield.f2"]' 'f2'
|
||||
// @!has - '//*[@class="sidebar-elems"]//section//a' 'waza'
|
||||
pub union MyUnion {
|
||||
pub f1: u32,
|
||||
pub f2: f32,
|
||||
|
@ -1,6 +1,6 @@
|
||||
#![crate_name = "foo"]
|
||||
|
||||
// @has foo/struct.SomeStruct.html '//*[@class="sidebar-links"]/a[@href="#method.some_fn-1"]' \
|
||||
// @has foo/struct.SomeStruct.html '//*[@class="sidebar-elems"]//section//li/a[@href="#method.some_fn-1"]' \
|
||||
// "some_fn"
|
||||
pub struct SomeStruct<T> { _inner: T }
|
||||
|
||||
|
@ -5,9 +5,9 @@
|
||||
// @has foo/trait.Foo.html
|
||||
// @has - '//*[@class="sidebar-title"]/a[@href="#foreign-impls"]' 'Implementations on Foreign Types'
|
||||
// @has - '//h2[@id="foreign-impls"]' 'Implementations on Foreign Types'
|
||||
// @has - '//*[@class="sidebar-links"]/a[@href="#impl-Foo-for-u32"]' 'u32'
|
||||
// @has - '//*[@class="sidebar-elems"]//section//a[@href="#impl-Foo-for-u32"]' 'u32'
|
||||
// @has - '//*[@id="impl-Foo-for-u32"]//h3[@class="code-header in-band"]' 'impl Foo for u32'
|
||||
// @has - '//*[@class="sidebar-links"]/a[@href="#impl-Foo-for-%26%27a%20str"]' "&'a str"
|
||||
// @has - '//*[@class="sidebar-elems"]//section//a[@href="#impl-Foo-for-%26%27a%20str"]' "&'a str"
|
||||
// @has - '//*[@id="impl-Foo-for-%26%27a%20str"]//h3[@class="code-header in-band"]' "impl<'a> Foo for &'a str"
|
||||
pub trait Foo {}
|
||||
|
||||
|
6
src/test/ui/box/issue-78459-ice.rs
Normal file
6
src/test/ui/box/issue-78459-ice.rs
Normal file
@ -0,0 +1,6 @@
|
||||
// check-pass
|
||||
#![feature(allocator_api)]
|
||||
|
||||
fn main() {
|
||||
Box::new_in((), &std::alloc::Global);
|
||||
}
|
@ -4,7 +4,7 @@ error[E0658]: const operands for inline assembly are unstable
|
||||
LL | asm!("mov eax, {}", const 123);
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: see issue #72016 <https://github.com/rust-lang/rust/issues/72016> for more information
|
||||
= note: see issue #93332 <https://github.com/rust-lang/rust/issues/93332> for more information
|
||||
= help: add `#![feature(asm_const)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -4,7 +4,7 @@ error[E0658]: inline assembly is not stable yet on this architecture
|
||||
LL | asm!("");
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= note: see issue #72016 <https://github.com/rust-lang/rust/issues/72016> for more information
|
||||
= note: see issue #93335 <https://github.com/rust-lang/rust/issues/93335> for more information
|
||||
= help: add `#![feature(asm_experimental_arch)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -4,7 +4,7 @@ error[E0658]: sym operands for inline assembly are unstable
|
||||
LL | asm!("mov eax, {}", sym main);
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= note: see issue #72016 <https://github.com/rust-lang/rust/issues/72016> for more information
|
||||
= note: see issue #93333 <https://github.com/rust-lang/rust/issues/93333> for more information
|
||||
= help: add `#![feature(asm_sym)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -4,7 +4,7 @@ error[E0658]: the `may_unwind` option is unstable
|
||||
LL | asm!("", options(may_unwind));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #72016 <https://github.com/rust-lang/rust/issues/72016> for more information
|
||||
= note: see issue #93334 <https://github.com/rust-lang/rust/issues/93334> for more information
|
||||
= help: add `#![feature(asm_unwind)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -528,7 +528,7 @@ fn is_auto_reborrow_position(parent: Option<Node<'_>>) -> bool {
|
||||
fn is_auto_borrow_position(parent: Option<Node<'_>>, child_id: HirId) -> bool {
|
||||
if let Some(Node::Expr(parent)) = parent {
|
||||
match parent.kind {
|
||||
ExprKind::MethodCall(_, [self_arg, ..], _) => self_arg.hir_id == child_id,
|
||||
// ExprKind::MethodCall(_, [self_arg, ..], _) => self_arg.hir_id == child_id,
|
||||
ExprKind::Field(..) => true,
|
||||
ExprKind::Call(f, _) => f.hir_id == child_id,
|
||||
_ => false,
|
||||
|
@ -64,9 +64,9 @@ fn main() {
|
||||
*x = 5;
|
||||
|
||||
let s = String::new();
|
||||
let _ = s.len();
|
||||
let _ = s.capacity();
|
||||
let _ = s.capacity();
|
||||
// let _ = (&s).len();
|
||||
// let _ = (&s).capacity();
|
||||
// let _ = (&&s).capacity();
|
||||
|
||||
let x = (1, 2);
|
||||
let _ = x.0;
|
||||
|
@ -64,9 +64,9 @@ fn main() {
|
||||
*x = 5;
|
||||
|
||||
let s = String::new();
|
||||
let _ = (&s).len();
|
||||
let _ = (&s).capacity();
|
||||
let _ = (&&s).capacity();
|
||||
// let _ = (&s).len();
|
||||
// let _ = (&s).capacity();
|
||||
// let _ = (&&s).capacity();
|
||||
|
||||
let x = (1, 2);
|
||||
let _ = (&x).0;
|
||||
|
@ -84,24 +84,6 @@ error: this expression creates a reference which is immediately dereferenced by
|
||||
LL | let y: &mut i32 = &mut &mut x;
|
||||
| ^^^^^^^^^^^ help: change this to: `x`
|
||||
|
||||
error: this expression borrows a value the compiler would automatically borrow
|
||||
--> $DIR/needless_borrow.rs:67:13
|
||||
|
|
||||
LL | let _ = (&s).len();
|
||||
| ^^^^ help: change this to: `s`
|
||||
|
||||
error: this expression borrows a value the compiler would automatically borrow
|
||||
--> $DIR/needless_borrow.rs:68:13
|
||||
|
|
||||
LL | let _ = (&s).capacity();
|
||||
| ^^^^ help: change this to: `s`
|
||||
|
||||
error: this expression creates a reference which is immediately dereferenced by the compiler
|
||||
--> $DIR/needless_borrow.rs:69:13
|
||||
|
|
||||
LL | let _ = (&&s).capacity();
|
||||
| ^^^^^ help: change this to: `s`
|
||||
|
||||
error: this expression borrows a value the compiler would automatically borrow
|
||||
--> $DIR/needless_borrow.rs:72:13
|
||||
|
|
||||
@ -114,5 +96,5 @@ error: this expression borrows a value the compiler would automatically borrow
|
||||
LL | let _ = unsafe { (&*x).0 };
|
||||
| ^^^^^ help: change this to: `(*x)`
|
||||
|
||||
error: aborting due to 19 previous errors
|
||||
error: aborting due to 16 previous errors
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user