Auto merge of #79686 - Dylan-DPC:rollup-leama5f, r=Dylan-DPC
Rollup of 11 pull requests Successful merges: - #77686 (Render Markdown in search results) - #79541 (Doc keyword lint pass) - #79602 (Fix SGX CI) - #79611 (Use more std:: instead of core:: in docs for consistency) - #79623 (Pass around Symbols instead of Idents in doctree) - #79627 (Update cargo) - #79631 (disable a ptr equality test on Miri) - #79638 (Use `item_name` instead of pretty printing for resolving `Self` on intra-doc links) - #79646 (rustc_metadata: Remove some dead code) - #79664 (move interpret::MemoryKind::Heap to const eval) - #79678 (Fix some clippy lints) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
e9dd18ca74
49 changed files with 430 additions and 180 deletions
|
@ -235,12 +235,10 @@ impl Annotatable {
|
|||
pub fn derive_allowed(&self) -> bool {
|
||||
match *self {
|
||||
Annotatable::Stmt(ref stmt) => match stmt.kind {
|
||||
ast::StmtKind::Item(ref item) => match item.kind {
|
||||
ast::ItemKind::Struct(..)
|
||||
| ast::ItemKind::Enum(..)
|
||||
| ast::ItemKind::Union(..) => true,
|
||||
_ => false,
|
||||
},
|
||||
ast::StmtKind::Item(ref item) => matches!(
|
||||
item.kind,
|
||||
ast::ItemKind::Struct(..) | ast::ItemKind::Enum(..) | ast::ItemKind::Union(..)
|
||||
),
|
||||
_ => false,
|
||||
},
|
||||
Annotatable::Item(ref item) => match item.kind {
|
||||
|
|
|
@ -1134,7 +1134,9 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
|
|||
if let Some(attr) = self.take_first_attr_no_derive(&mut expr) {
|
||||
// Collect the invoc regardless of whether or not attributes are permitted here
|
||||
// expansion will eat the attribute so it won't error later.
|
||||
attr.0.as_ref().map(|attr| self.cfg.maybe_emit_expr_attr_err(attr));
|
||||
if let Some(attr) = attr.0.as_ref() {
|
||||
self.cfg.maybe_emit_expr_attr_err(attr)
|
||||
}
|
||||
|
||||
// AstFragmentKind::Expr requires the macro to emit an expression.
|
||||
return self
|
||||
|
@ -1231,7 +1233,9 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
|
|||
self.cfg.configure_expr_kind(&mut expr.kind);
|
||||
|
||||
if let Some(attr) = self.take_first_attr_no_derive(&mut expr) {
|
||||
attr.0.as_ref().map(|attr| self.cfg.maybe_emit_expr_attr_err(attr));
|
||||
if let Some(attr) = attr.0.as_ref() {
|
||||
self.cfg.maybe_emit_expr_attr_err(attr)
|
||||
}
|
||||
|
||||
return self
|
||||
.collect_attr(attr, Annotatable::Expr(P(expr)), AstFragmentKind::OptExpr)
|
||||
|
|
|
@ -2401,7 +2401,7 @@ impl StructField<'_> {
|
|||
// Still necessary in couple of places
|
||||
pub fn is_positional(&self) -> bool {
|
||||
let first = self.ident.as_str().as_bytes()[0];
|
||||
first >= b'0' && first <= b'9'
|
||||
(b'0'..=b'9').contains(&first)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -267,8 +267,8 @@ pub fn is_whitespace(c: char) -> bool {
|
|||
pub fn is_id_start(c: char) -> bool {
|
||||
// This is XID_Start OR '_' (which formally is not a XID_Start).
|
||||
// We also add fast-path for ascii idents
|
||||
('a' <= c && c <= 'z')
|
||||
|| ('A' <= c && c <= 'Z')
|
||||
('a'..='z').contains(&c)
|
||||
|| ('A'..='Z').contains(&c)
|
||||
|| c == '_'
|
||||
|| (c > '\x7f' && unicode_xid::UnicodeXID::is_xid_start(c))
|
||||
}
|
||||
|
@ -279,9 +279,9 @@ pub fn is_id_start(c: char) -> bool {
|
|||
pub fn is_id_continue(c: char) -> bool {
|
||||
// This is exactly XID_Continue.
|
||||
// We also add fast-path for ascii idents
|
||||
('a' <= c && c <= 'z')
|
||||
|| ('A' <= c && c <= 'Z')
|
||||
|| ('0' <= c && c <= '9')
|
||||
('a'..='z').contains(&c)
|
||||
|| ('A'..='Z').contains(&c)
|
||||
|| ('0'..='9').contains(&c)
|
||||
|| c == '_'
|
||||
|| (c > '\x7f' && unicode_xid::UnicodeXID::is_xid_continue(c))
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ use rustc_hir::{GenericArg, HirId, MutTy, Mutability, Path, PathSegment, QPath,
|
|||
use rustc_middle::ty;
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint, impl_lint_pass};
|
||||
use rustc_span::hygiene::{ExpnKind, MacroKind};
|
||||
use rustc_span::symbol::{sym, Ident, Symbol};
|
||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||
|
||||
declare_tool_lint! {
|
||||
pub rustc::DEFAULT_HASH_TYPES,
|
||||
|
@ -267,3 +267,47 @@ impl EarlyLintPass for LintPassImpl {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
declare_tool_lint! {
|
||||
pub rustc::EXISTING_DOC_KEYWORD,
|
||||
Allow,
|
||||
"Check that documented keywords in std and core actually exist",
|
||||
report_in_external_macro: true
|
||||
}
|
||||
|
||||
declare_lint_pass!(ExistingDocKeyword => [EXISTING_DOC_KEYWORD]);
|
||||
|
||||
fn is_doc_keyword(s: Symbol) -> bool {
|
||||
s <= kw::Union
|
||||
}
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for ExistingDocKeyword {
|
||||
fn check_item(&mut self, cx: &LateContext<'_>, item: &rustc_hir::Item<'_>) {
|
||||
for attr in item.attrs {
|
||||
if !attr.has_name(sym::doc) {
|
||||
continue;
|
||||
}
|
||||
if let Some(list) = attr.meta_item_list() {
|
||||
for nested in list {
|
||||
if nested.has_name(sym::keyword) {
|
||||
let v = nested
|
||||
.value_str()
|
||||
.expect("#[doc(keyword = \"...\")] expected a value!");
|
||||
if is_doc_keyword(v) {
|
||||
return;
|
||||
}
|
||||
cx.struct_span_lint(EXISTING_DOC_KEYWORD, attr.span, |lint| {
|
||||
lint.build(&format!(
|
||||
"Found non-existing keyword `{}` used in \
|
||||
`#[doc(keyword = \"...\")]`",
|
||||
v,
|
||||
))
|
||||
.help("only existing keywords are allowed in core/std")
|
||||
.emit();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -463,6 +463,8 @@ fn register_internals(store: &mut LintStore) {
|
|||
store.register_early_pass(|| box DefaultHashTypes::new());
|
||||
store.register_lints(&LintPassImpl::get_lints());
|
||||
store.register_early_pass(|| box LintPassImpl);
|
||||
store.register_lints(&ExistingDocKeyword::get_lints());
|
||||
store.register_late_pass(|| box ExistingDocKeyword);
|
||||
store.register_lints(&TyTyKind::get_lints());
|
||||
store.register_late_pass(|| box TyTyKind);
|
||||
store.register_group(
|
||||
|
@ -475,6 +477,7 @@ fn register_internals(store: &mut LintStore) {
|
|||
LintId::of(LINT_PASS_IMPL_WITHOUT_MACRO),
|
||||
LintId::of(TY_PASS_BY_REFERENCE),
|
||||
LintId::of(USAGE_OF_QUALIFIED_TY),
|
||||
LintId::of(EXISTING_DOC_KEYWORD),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1592,23 +1592,6 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
|
|||
self.def_path_hash_unlocked(index, &mut def_path_hashes)
|
||||
}
|
||||
|
||||
fn all_def_path_hashes_and_def_ids(&self) -> Vec<(DefPathHash, DefId)> {
|
||||
let mut def_path_hashes = self.def_path_hash_cache.lock();
|
||||
let mut def_index_to_data = |index| {
|
||||
(self.def_path_hash_unlocked(index, &mut def_path_hashes), self.local_def_id(index))
|
||||
};
|
||||
if let Some(data) = &self.root.proc_macro_data {
|
||||
std::iter::once(CRATE_DEF_INDEX)
|
||||
.chain(data.macros.decode(self))
|
||||
.map(def_index_to_data)
|
||||
.collect()
|
||||
} else {
|
||||
(0..self.num_def_ids())
|
||||
.map(|index| def_index_to_data(DefIndex::from_usize(index)))
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the `DepNodeIndex` corresponding this crate. The result of this
|
||||
/// method is cached in the `dep_node_index` field.
|
||||
fn get_crate_dep_node_index(&self, tcx: TyCtxt<'tcx>) -> DepNodeIndex {
|
||||
|
|
|
@ -456,6 +456,10 @@ impl CStore {
|
|||
pub fn module_expansion_untracked(&self, def_id: DefId, sess: &Session) -> ExpnId {
|
||||
self.get_crate_data(def_id.krate).module_expansion(def_id.index, sess)
|
||||
}
|
||||
|
||||
pub fn num_def_ids(&self, cnum: CrateNum) -> usize {
|
||||
self.get_crate_data(cnum).num_def_ids()
|
||||
}
|
||||
}
|
||||
|
||||
impl CrateStore for CStore {
|
||||
|
@ -498,14 +502,6 @@ impl CrateStore for CStore {
|
|||
self.get_crate_data(def.krate).def_path_hash(def.index)
|
||||
}
|
||||
|
||||
fn all_def_path_hashes_and_def_ids(&self, cnum: CrateNum) -> Vec<(DefPathHash, DefId)> {
|
||||
self.get_crate_data(cnum).all_def_path_hashes_and_def_ids()
|
||||
}
|
||||
|
||||
fn num_def_ids(&self, cnum: CrateNum) -> usize {
|
||||
self.get_crate_data(cnum).num_def_ids()
|
||||
}
|
||||
|
||||
// See `CrateMetadataRef::def_path_hash_to_def_id` for more details
|
||||
fn def_path_hash_to_def_id(
|
||||
&self,
|
||||
|
|
|
@ -189,8 +189,6 @@ pub trait CrateStore {
|
|||
fn def_kind(&self, def: DefId) -> DefKind;
|
||||
fn def_path(&self, def: DefId) -> DefPath;
|
||||
fn def_path_hash(&self, def: DefId) -> DefPathHash;
|
||||
fn all_def_path_hashes_and_def_ids(&self, cnum: CrateNum) -> Vec<(DefPathHash, DefId)>;
|
||||
fn num_def_ids(&self, cnum: CrateNum) -> usize;
|
||||
fn def_path_hash_to_def_id(
|
||||
&self,
|
||||
cnum: CrateNum,
|
||||
|
|
|
@ -7,6 +7,7 @@ use std::collections::hash_map::Entry;
|
|||
use std::hash::Hash;
|
||||
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use std::fmt;
|
||||
|
||||
use rustc_ast::Mutability;
|
||||
use rustc_hir::def_id::DefId;
|
||||
|
@ -179,6 +180,28 @@ impl<K: Hash + Eq, V> interpret::AllocMap<K, V> for FxHashMap<K, V> {
|
|||
crate type CompileTimeEvalContext<'mir, 'tcx> =
|
||||
InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>>;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
||||
pub enum MemoryKind {
|
||||
Heap,
|
||||
}
|
||||
|
||||
impl fmt::Display for MemoryKind {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
MemoryKind::Heap => write!(f, "heap allocation"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl interpret::MayLeak for MemoryKind {
|
||||
#[inline(always)]
|
||||
fn may_leak(self) -> bool {
|
||||
match self {
|
||||
MemoryKind::Heap => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl interpret::MayLeak for ! {
|
||||
#[inline(always)]
|
||||
fn may_leak(self) -> bool {
|
||||
|
@ -222,6 +245,8 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> {
|
|||
impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, 'tcx> {
|
||||
compile_time_machine!(<'mir, 'tcx>);
|
||||
|
||||
type MemoryKind = MemoryKind;
|
||||
|
||||
type MemoryExtra = MemoryExtra;
|
||||
|
||||
fn find_mir_or_eval_fn(
|
||||
|
@ -317,7 +342,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
|
|||
let ptr = ecx.memory.allocate(
|
||||
Size::from_bytes(size as u64),
|
||||
align,
|
||||
interpret::MemoryKind::ConstHeap,
|
||||
interpret::MemoryKind::Machine(MemoryKind::Heap),
|
||||
);
|
||||
ecx.write_scalar(Scalar::Ptr(ptr), dest)?;
|
||||
}
|
||||
|
|
|
@ -25,19 +25,20 @@ use rustc_target::abi::Size;
|
|||
use rustc_ast::Mutability;
|
||||
|
||||
use super::{AllocId, Allocation, InterpCx, MPlaceTy, Machine, MemoryKind, Scalar, ValueVisitor};
|
||||
use crate::const_eval;
|
||||
|
||||
pub trait CompileTimeMachine<'mir, 'tcx> = Machine<
|
||||
pub trait CompileTimeMachine<'mir, 'tcx, T> = Machine<
|
||||
'mir,
|
||||
'tcx,
|
||||
MemoryKind = !,
|
||||
MemoryKind = T,
|
||||
PointerTag = (),
|
||||
ExtraFnVal = !,
|
||||
FrameExtra = (),
|
||||
AllocExtra = (),
|
||||
MemoryMap = FxHashMap<AllocId, (MemoryKind<!>, Allocation)>,
|
||||
MemoryMap = FxHashMap<AllocId, (MemoryKind<T>, Allocation)>,
|
||||
>;
|
||||
|
||||
struct InternVisitor<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>> {
|
||||
struct InternVisitor<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx, const_eval::MemoryKind>> {
|
||||
/// The ectx from which we intern.
|
||||
ecx: &'rt mut InterpCx<'mir, 'tcx, M>,
|
||||
/// Previously encountered safe references.
|
||||
|
@ -74,7 +75,7 @@ struct IsStaticOrFn;
|
|||
/// `immutable` things might become mutable if `ty` is not frozen.
|
||||
/// `ty` can be `None` if there is no potential interior mutability
|
||||
/// to account for (e.g. for vtables).
|
||||
fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>>(
|
||||
fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx, const_eval::MemoryKind>>(
|
||||
ecx: &'rt mut InterpCx<'mir, 'tcx, M>,
|
||||
leftover_allocations: &'rt mut FxHashSet<AllocId>,
|
||||
alloc_id: AllocId,
|
||||
|
@ -105,7 +106,7 @@ fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>>(
|
|||
// changes in this function.
|
||||
match kind {
|
||||
MemoryKind::Stack
|
||||
| MemoryKind::ConstHeap
|
||||
| MemoryKind::Machine(const_eval::MemoryKind::Heap)
|
||||
| MemoryKind::Vtable
|
||||
| MemoryKind::CallerLocation => {}
|
||||
}
|
||||
|
@ -141,7 +142,9 @@ fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>>(
|
|||
None
|
||||
}
|
||||
|
||||
impl<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>> InternVisitor<'rt, 'mir, 'tcx, M> {
|
||||
impl<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx, const_eval::MemoryKind>>
|
||||
InternVisitor<'rt, 'mir, 'tcx, M>
|
||||
{
|
||||
fn intern_shallow(
|
||||
&mut self,
|
||||
alloc_id: AllocId,
|
||||
|
@ -152,8 +155,8 @@ impl<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>> InternVisitor<'rt, 'mir
|
|||
}
|
||||
}
|
||||
|
||||
impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
|
||||
for InternVisitor<'rt, 'mir, 'tcx, M>
|
||||
impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx, const_eval::MemoryKind>>
|
||||
ValueVisitor<'mir, 'tcx, M> for InternVisitor<'rt, 'mir, 'tcx, M>
|
||||
{
|
||||
type V = MPlaceTy<'tcx>;
|
||||
|
||||
|
@ -290,7 +293,7 @@ pub enum InternKind {
|
|||
/// Any errors here would anyway be turned into `const_err` lints, whereas validation failures
|
||||
/// are hard errors.
|
||||
#[tracing::instrument(skip(ecx))]
|
||||
pub fn intern_const_alloc_recursive<M: CompileTimeMachine<'mir, 'tcx>>(
|
||||
pub fn intern_const_alloc_recursive<M: CompileTimeMachine<'mir, 'tcx, const_eval::MemoryKind>>(
|
||||
ecx: &mut InterpCx<'mir, 'tcx, M>,
|
||||
intern_kind: InternKind,
|
||||
ret: MPlaceTy<'tcx>,
|
||||
|
@ -421,7 +424,9 @@ where
|
|||
Ok(())
|
||||
}
|
||||
|
||||
impl<'mir, 'tcx: 'mir, M: super::intern::CompileTimeMachine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
impl<'mir, 'tcx: 'mir, M: super::intern::CompileTimeMachine<'mir, 'tcx, !>>
|
||||
InterpCx<'mir, 'tcx, M>
|
||||
{
|
||||
/// A helper function that allocates memory for the layout given and gives you access to mutate
|
||||
/// it. Once your own mutation code is done, the backing `Allocation` is removed from the
|
||||
/// current `Memory` and returned.
|
||||
|
|
|
@ -366,9 +366,9 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
|
|||
type PointerTag = ();
|
||||
type ExtraFnVal = !;
|
||||
|
||||
type MemoryKind = !;
|
||||
type MemoryMap = rustc_data_structures::fx::FxHashMap<AllocId, (MemoryKind<!>, Allocation)>;
|
||||
const GLOBAL_KIND: Option<!> = None; // no copying of globals from `tcx` to machine memory
|
||||
type MemoryMap =
|
||||
rustc_data_structures::fx::FxHashMap<AllocId, (MemoryKind<Self::MemoryKind>, Allocation)>;
|
||||
const GLOBAL_KIND: Option<Self::MemoryKind> = None; // no copying of globals from `tcx` to machine memory
|
||||
|
||||
type AllocExtra = ();
|
||||
type FrameExtra = ();
|
||||
|
@ -407,7 +407,7 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
|
|||
_memory_extra: &Self::MemoryExtra,
|
||||
_id: AllocId,
|
||||
alloc: Cow<'b, Allocation>,
|
||||
_kind: Option<MemoryKind<!>>,
|
||||
_kind: Option<MemoryKind<Self::MemoryKind>>,
|
||||
) -> (Cow<'b, Allocation<Self::PointerTag>>, Self::PointerTag) {
|
||||
// We do not use a tag so we can just cheaply forward the allocation
|
||||
(alloc, ())
|
||||
|
|
|
@ -27,9 +27,6 @@ use crate::util::pretty;
|
|||
pub enum MemoryKind<T> {
|
||||
/// Stack memory. Error if deallocated except during a stack pop.
|
||||
Stack,
|
||||
/// Heap memory.
|
||||
/// FIXME: this variant should be in const_eval
|
||||
ConstHeap,
|
||||
/// Memory backing vtables. Error if ever deallocated.
|
||||
Vtable,
|
||||
/// Memory allocated by `caller_location` intrinsic. Error if ever deallocated.
|
||||
|
@ -43,7 +40,6 @@ impl<T: MayLeak> MayLeak for MemoryKind<T> {
|
|||
fn may_leak(self) -> bool {
|
||||
match self {
|
||||
MemoryKind::Stack => false,
|
||||
MemoryKind::ConstHeap => false,
|
||||
MemoryKind::Vtable => true,
|
||||
MemoryKind::CallerLocation => true,
|
||||
MemoryKind::Machine(k) => k.may_leak(),
|
||||
|
@ -55,7 +51,6 @@ impl<T: fmt::Display> fmt::Display for MemoryKind<T> {
|
|||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
MemoryKind::Stack => write!(f, "stack variable"),
|
||||
MemoryKind::ConstHeap => write!(f, "heap allocation"),
|
||||
MemoryKind::Vtable => write!(f, "vtable"),
|
||||
MemoryKind::CallerLocation => write!(f, "caller location"),
|
||||
MemoryKind::Machine(m) => write!(f, "{}", m),
|
||||
|
|
|
@ -180,6 +180,8 @@ impl<'mir, 'tcx> ConstPropMachine<'mir, 'tcx> {
|
|||
impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx> {
|
||||
compile_time_machine!(<'mir, 'tcx>);
|
||||
|
||||
type MemoryKind = !;
|
||||
|
||||
type MemoryExtra = ();
|
||||
|
||||
fn find_mir_or_eval_fn(
|
||||
|
|
|
@ -1859,7 +1859,7 @@ impl<T: Iterator<Item = char>> Parser<T> {
|
|||
}
|
||||
|
||||
let n2 = self.decode_hex_escape()?;
|
||||
if n2 < 0xDC00 || n2 > 0xDFFF {
|
||||
if !(0xDC00..=0xDFFF).contains(&n2) {
|
||||
return self.error(LoneLeadingSurrogateInHexEscape);
|
||||
}
|
||||
let c =
|
||||
|
|
|
@ -97,7 +97,7 @@ cfg_if::cfg_if! {
|
|||
let ptr = src_bytes.as_ptr() as *const __m128i;
|
||||
// We don't know if the pointer is aligned to 16 bytes, so we
|
||||
// use `loadu`, which supports unaligned loading.
|
||||
let chunk = _mm_loadu_si128(ptr.offset(chunk_index as isize));
|
||||
let chunk = _mm_loadu_si128(ptr.add(chunk_index));
|
||||
|
||||
// For character in the chunk, see if its byte value is < 0, which
|
||||
// indicates that it's part of a UTF-8 char.
|
||||
|
@ -253,7 +253,7 @@ fn analyze_source_file_generic(
|
|||
let pos = BytePos::from_usize(i) + output_offset;
|
||||
|
||||
if char_len > 1 {
|
||||
assert!(char_len >= 2 && char_len <= 4);
|
||||
assert!((2..=4).contains(&char_len));
|
||||
let mbc = MultiByteChar { pos, bytes: char_len as u8 };
|
||||
multi_byte_chars.push(mbc);
|
||||
}
|
||||
|
|
|
@ -1015,10 +1015,7 @@ pub enum ExternalSourceKind {
|
|||
|
||||
impl ExternalSource {
|
||||
pub fn is_absent(&self) -> bool {
|
||||
match self {
|
||||
ExternalSource::Foreign { kind: ExternalSourceKind::Present(_), .. } => false,
|
||||
_ => true,
|
||||
}
|
||||
!matches!(self, ExternalSource::Foreign { kind: ExternalSourceKind::Present(_), .. })
|
||||
}
|
||||
|
||||
pub fn get_source(&self) -> Option<&Lrc<String>> {
|
||||
|
|
|
@ -623,7 +623,7 @@ impl SourceMap {
|
|||
self.span_to_source(sp, |src, start_index, end_index| {
|
||||
src.get(start_index..end_index)
|
||||
.map(|s| s.to_string())
|
||||
.ok_or_else(|| SpanSnippetError::IllFormedSpan(sp))
|
||||
.ok_or(SpanSnippetError::IllFormedSpan(sp))
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -640,9 +640,7 @@ impl SourceMap {
|
|||
/// Returns the source snippet as `String` before the given `Span`.
|
||||
pub fn span_to_prev_source(&self, sp: Span) -> Result<String, SpanSnippetError> {
|
||||
self.span_to_source(sp, |src, start_index, _| {
|
||||
src.get(..start_index)
|
||||
.map(|s| s.to_string())
|
||||
.ok_or_else(|| SpanSnippetError::IllFormedSpan(sp))
|
||||
src.get(..start_index).map(|s| s.to_string()).ok_or(SpanSnippetError::IllFormedSpan(sp))
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -1363,8 +1363,7 @@ impl fmt::Display for IdentPrinter {
|
|||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
if self.is_raw {
|
||||
f.write_str("r#")?;
|
||||
} else {
|
||||
if self.symbol == kw::DollarCrate {
|
||||
} else if self.symbol == kw::DollarCrate {
|
||||
if let Some(span) = self.convert_dollar_crate {
|
||||
let converted = span.ctxt().dollar_crate_name();
|
||||
if !converted.is_path_segment_keyword() {
|
||||
|
@ -1373,7 +1372,6 @@ impl fmt::Display for IdentPrinter {
|
|||
return fmt::Display::fmt(&converted, f);
|
||||
}
|
||||
}
|
||||
}
|
||||
fmt::Display::fmt(&self.symbol, f)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1978,9 +1978,14 @@ fn const_str_ptr() {
|
|||
const B: &'static [u8; 2] = &A;
|
||||
const C: *const u8 = B as *const u8;
|
||||
|
||||
unsafe {
|
||||
// Miri does not deduplicate consts (https://github.com/rust-lang/miri/issues/131)
|
||||
#[cfg(not(miri))]
|
||||
{
|
||||
let foo = &A as *const u8;
|
||||
assert_eq!(foo, C);
|
||||
}
|
||||
|
||||
unsafe {
|
||||
assert_eq!(from_utf8_unchecked(&A), "hi");
|
||||
assert_eq!(*C, A[0]);
|
||||
assert_eq!(*(&B[0] as *const u8), A[0]);
|
||||
|
|
|
@ -403,7 +403,7 @@ impl<'a> Arguments<'a> {
|
|||
/// ```rust
|
||||
/// #![feature(fmt_as_str)]
|
||||
///
|
||||
/// use core::fmt::Arguments;
|
||||
/// use std::fmt::Arguments;
|
||||
///
|
||||
/// fn write_str(_: &str) { /* ... */ }
|
||||
///
|
||||
|
|
|
@ -21,7 +21,7 @@ pub struct Pending<T> {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use core::future;
|
||||
/// use std::future;
|
||||
///
|
||||
/// # async fn run() {
|
||||
/// let future = future::pending();
|
||||
|
|
|
@ -3,7 +3,7 @@ use crate::future::Future;
|
|||
use crate::pin::Pin;
|
||||
use crate::task::{Context, Poll};
|
||||
|
||||
/// Creates a future that wraps a function returning `Poll`.
|
||||
/// Creates a future that wraps a function returning [`Poll`].
|
||||
///
|
||||
/// Polling the future delegates to the wrapped function.
|
||||
///
|
||||
|
@ -13,7 +13,7 @@ use crate::task::{Context, Poll};
|
|||
/// #![feature(future_poll_fn)]
|
||||
/// # async fn run() {
|
||||
/// use core::future::poll_fn;
|
||||
/// use core::task::{Context, Poll};
|
||||
/// use std::task::{Context, Poll};
|
||||
///
|
||||
/// fn read_line(_cx: &mut Context<'_>) -> Poll<String> {
|
||||
/// Poll::Ready("Hello, World!".into())
|
||||
|
@ -31,7 +31,7 @@ where
|
|||
PollFn { f }
|
||||
}
|
||||
|
||||
/// A Future that wraps a function returning `Poll`.
|
||||
/// A Future that wraps a function returning [`Poll`].
|
||||
///
|
||||
/// This `struct` is created by [`poll_fn()`]. See its
|
||||
/// documentation for more.
|
||||
|
|
|
@ -33,7 +33,7 @@ impl<T> Future for Ready<T> {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use core::future;
|
||||
/// use std::future;
|
||||
///
|
||||
/// # async fn run() {
|
||||
/// let a = future::ready(1);
|
||||
|
|
|
@ -189,7 +189,7 @@ impl<'a> Location<'a> {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use core::panic::Location;
|
||||
/// use std::panic::Location;
|
||||
///
|
||||
/// /// Returns the [`Location`] at which it is called.
|
||||
/// #[track_caller]
|
||||
|
|
|
@ -1,15 +1,18 @@
|
|||
/// Extracts the successful type of a `Poll<T>`.
|
||||
/// Extracts the successful type of a [`Poll<T>`].
|
||||
///
|
||||
/// This macro bakes in propagation of `Pending` signals by returning early.
|
||||
/// This macro bakes in propagation of [`Pending`] signals by returning early.
|
||||
///
|
||||
/// [`Poll<T>`]: crate::task::Poll
|
||||
/// [`Pending`]: crate::task::Poll::Pending
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(ready_macro)]
|
||||
///
|
||||
/// use core::task::{ready, Context, Poll};
|
||||
/// use core::future::{self, Future};
|
||||
/// use core::pin::Pin;
|
||||
/// use std::task::{ready, Context, Poll};
|
||||
/// use std::future::{self, Future};
|
||||
/// use std::pin::Pin;
|
||||
///
|
||||
/// pub fn do_poll(cx: &mut Context<'_>) -> Poll<()> {
|
||||
/// let mut fut = future::ready(42);
|
||||
|
@ -28,9 +31,9 @@
|
|||
/// ```
|
||||
/// # #![feature(ready_macro)]
|
||||
/// #
|
||||
/// # use core::task::{Context, Poll};
|
||||
/// # use core::future::{self, Future};
|
||||
/// # use core::pin::Pin;
|
||||
/// # use std::task::{Context, Poll};
|
||||
/// # use std::future::{self, Future};
|
||||
/// # use std::pin::Pin;
|
||||
/// #
|
||||
/// # pub fn do_poll(cx: &mut Context<'_>) -> Poll<()> {
|
||||
/// # let mut fut = future::ready(42);
|
||||
|
|
|
@ -212,6 +212,7 @@
|
|||
all(target_vendor = "fortanix", target_env = "sgx"),
|
||||
feature(slice_index_methods, coerce_unsized, sgx_platform)
|
||||
)]
|
||||
#![deny(rustc::existing_doc_keyword)]
|
||||
#![cfg_attr(all(test, target_vendor = "fortanix", target_env = "sgx"), feature(fixed_size_array))]
|
||||
// std is implemented with unstable features, many of which are internal
|
||||
// compiler details that will never be stable
|
||||
|
|
|
@ -198,7 +198,7 @@ mod prim_bool {}
|
|||
/// words, they can't return `!` from every code path. As an example, this code doesn't compile:
|
||||
///
|
||||
/// ```compile_fail
|
||||
/// use core::ops::Add;
|
||||
/// use std::ops::Add;
|
||||
///
|
||||
/// fn foo() -> impl Add<u32> {
|
||||
/// unimplemented!()
|
||||
|
@ -208,7 +208,7 @@ mod prim_bool {}
|
|||
/// But this code does:
|
||||
///
|
||||
/// ```
|
||||
/// use core::ops::Add;
|
||||
/// use std::ops::Add;
|
||||
///
|
||||
/// fn foo() -> impl Add<u32> {
|
||||
/// if true {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use std::env::*;
|
||||
use std::ffi::{OsStr, OsString};
|
||||
use std::path::PathBuf;
|
||||
|
||||
use rand::distributions::Alphanumeric;
|
||||
use rand::{thread_rng, Rng};
|
||||
|
@ -92,6 +91,8 @@ fn env_home_dir() {
|
|||
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(unix)] {
|
||||
use std::path::PathBuf;
|
||||
|
||||
let oldhome = var_to_os_string(var("HOME"));
|
||||
|
||||
set_var("HOME", "/home/MountainView");
|
||||
|
@ -109,6 +110,8 @@ fn env_home_dir() {
|
|||
|
||||
if let Some(oldhome) = oldhome { set_var("HOME", oldhome); }
|
||||
} else if #[cfg(windows)] {
|
||||
use std::path::PathBuf;
|
||||
|
||||
let oldhome = var_to_os_string(var("HOME"));
|
||||
let olduserprofile = var_to_os_string(var("USERPROFILE"));
|
||||
|
||||
|
|
|
@ -1000,7 +1000,7 @@ impl<'tcx> Clean<FnDecl> for (DefId, ty::PolyFnSig<'tcx>) {
|
|||
.iter()
|
||||
.map(|t| Argument {
|
||||
type_: t.clean(cx),
|
||||
name: names.next().map_or(String::new(), |name| name.to_string()),
|
||||
name: names.next().map_or_else(|| String::new(), |name| name.to_string()),
|
||||
})
|
||||
.collect(),
|
||||
},
|
||||
|
@ -1974,16 +1974,13 @@ impl Clean<BareFunctionDecl> for hir::BareFnTy<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
impl Clean<Vec<Item>> for (&hir::Item<'_>, Option<Ident>) {
|
||||
impl Clean<Vec<Item>> for (&hir::Item<'_>, Option<Symbol>) {
|
||||
fn clean(&self, cx: &DocContext<'_>) -> Vec<Item> {
|
||||
use hir::ItemKind;
|
||||
|
||||
let (item, renamed) = self;
|
||||
let def_id = cx.tcx.hir().local_def_id(item.hir_id).to_def_id();
|
||||
let mut name = match renamed {
|
||||
Some(ident) => ident.name,
|
||||
None => cx.tcx.hir().name(item.hir_id),
|
||||
};
|
||||
let mut name = renamed.unwrap_or_else(|| cx.tcx.hir().name(item.hir_id));
|
||||
cx.with_param_env(def_id, || {
|
||||
let kind = match item.kind {
|
||||
ItemKind::Static(ty, mutability, body_id) => StaticItem(Static {
|
||||
|
@ -2276,7 +2273,7 @@ impl Clean<Vec<Item>> for doctree::Import<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
impl Clean<Item> for (&hir::ForeignItem<'_>, Option<Ident>) {
|
||||
impl Clean<Item> for (&hir::ForeignItem<'_>, Option<Symbol>) {
|
||||
fn clean(&self, cx: &DocContext<'_>) -> Item {
|
||||
let (item, renamed) = self;
|
||||
cx.with_param_env(cx.tcx.hir().local_def_id(item.hir_id).to_def_id(), || {
|
||||
|
@ -2310,7 +2307,7 @@ impl Clean<Item> for (&hir::ForeignItem<'_>, Option<Ident>) {
|
|||
|
||||
Item::from_hir_id_and_parts(
|
||||
item.hir_id,
|
||||
Some(renamed.unwrap_or(item.ident).name),
|
||||
Some(renamed.unwrap_or(item.ident.name)),
|
||||
kind,
|
||||
cx,
|
||||
)
|
||||
|
@ -2318,10 +2315,10 @@ impl Clean<Item> for (&hir::ForeignItem<'_>, Option<Ident>) {
|
|||
}
|
||||
}
|
||||
|
||||
impl Clean<Item> for (&hir::MacroDef<'_>, Option<Ident>) {
|
||||
impl Clean<Item> for (&hir::MacroDef<'_>, Option<Symbol>) {
|
||||
fn clean(&self, cx: &DocContext<'_>) -> Item {
|
||||
let (item, renamed) = self;
|
||||
let name = renamed.unwrap_or(item.ident).name;
|
||||
let name = renamed.unwrap_or(item.ident.name);
|
||||
let tts = item.ast.body.inner_tokens().trees().collect::<Vec<_>>();
|
||||
// Extract the spans of all matchers. They represent the "interface" of the macro.
|
||||
let matchers = tts.chunks(4).map(|arm| arm[0].span()).collect::<Vec<_>>();
|
||||
|
|
|
@ -13,7 +13,6 @@ use rustc_hir::{
|
|||
};
|
||||
use rustc_interface::interface;
|
||||
use rustc_middle::hir::map::Map;
|
||||
use rustc_middle::middle::cstore::CrateStore;
|
||||
use rustc_middle::middle::privacy::AccessLevels;
|
||||
use rustc_middle::ty::{ParamEnv, Ty, TyCtxt};
|
||||
use rustc_resolve as resolve;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
crate use self::StructType::*;
|
||||
|
||||
use rustc_ast as ast;
|
||||
use rustc_span::{self, symbol::Ident, Span, Symbol};
|
||||
use rustc_span::{self, Span, Symbol};
|
||||
|
||||
use rustc_hir as hir;
|
||||
|
||||
|
@ -16,9 +16,9 @@ crate struct Module<'hir> {
|
|||
crate mods: Vec<Module<'hir>>,
|
||||
crate id: hir::HirId,
|
||||
// (item, renamed)
|
||||
crate items: Vec<(&'hir hir::Item<'hir>, Option<Ident>)>,
|
||||
crate foreigns: Vec<(&'hir hir::ForeignItem<'hir>, Option<Ident>)>,
|
||||
crate macros: Vec<(&'hir hir::MacroDef<'hir>, Option<Ident>)>,
|
||||
crate items: Vec<(&'hir hir::Item<'hir>, Option<Symbol>)>,
|
||||
crate foreigns: Vec<(&'hir hir::ForeignItem<'hir>, Option<Symbol>)>,
|
||||
crate macros: Vec<(&'hir hir::MacroDef<'hir>, Option<Symbol>)>,
|
||||
crate is_crate: bool,
|
||||
}
|
||||
|
||||
|
|
|
@ -14,13 +14,13 @@ use crate::config::RenderInfo;
|
|||
use crate::fold::DocFolder;
|
||||
use crate::formats::item_type::ItemType;
|
||||
use crate::formats::Impl;
|
||||
use crate::html::markdown::short_markdown_summary;
|
||||
use crate::html::render::cache::{extern_location, get_index_search_type, ExternalLocation};
|
||||
use crate::html::render::IndexItem;
|
||||
use crate::html::render::{plain_text_summary, shorten};
|
||||
|
||||
thread_local!(crate static CACHE_KEY: RefCell<Arc<Cache>> = Default::default());
|
||||
|
||||
/// This cache is used to store information about the `clean::Crate` being
|
||||
/// This cache is used to store information about the [`clean::Crate`] being
|
||||
/// rendered in order to provide more useful documentation. This contains
|
||||
/// information like all implementors of a trait, all traits a type implements,
|
||||
/// documentation for all known traits, etc.
|
||||
|
@ -313,7 +313,9 @@ impl DocFolder for Cache {
|
|||
ty: item.type_(),
|
||||
name: s.to_string(),
|
||||
path: path.join("::"),
|
||||
desc: shorten(plain_text_summary(item.doc_value())),
|
||||
desc: item
|
||||
.doc_value()
|
||||
.map_or_else(|| String::new(), short_markdown_summary),
|
||||
parent,
|
||||
parent_idx: None,
|
||||
search_type: get_index_search_type(&item),
|
||||
|
|
|
@ -17,8 +17,6 @@
|
|||
//! // ... something using html
|
||||
//! ```
|
||||
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::HirId;
|
||||
|
@ -1037,7 +1035,95 @@ impl MarkdownSummaryLine<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Renders a subset of Markdown in the first paragraph of the provided Markdown.
|
||||
///
|
||||
/// - *Italics*, **bold**, and `inline code` styles **are** rendered.
|
||||
/// - Headings and links are stripped (though the text *is* rendered).
|
||||
/// - HTML, code blocks, and everything else are ignored.
|
||||
///
|
||||
/// Returns a tuple of the rendered HTML string and whether the output was shortened
|
||||
/// due to the provided `length_limit`.
|
||||
fn markdown_summary_with_limit(md: &str, length_limit: usize) -> (String, bool) {
|
||||
if md.is_empty() {
|
||||
return (String::new(), false);
|
||||
}
|
||||
|
||||
let mut s = String::with_capacity(md.len() * 3 / 2);
|
||||
let mut text_length = 0;
|
||||
let mut stopped_early = false;
|
||||
|
||||
fn push(s: &mut String, text_length: &mut usize, text: &str) {
|
||||
s.push_str(text);
|
||||
*text_length += text.len();
|
||||
};
|
||||
|
||||
'outer: for event in Parser::new_ext(md, Options::ENABLE_STRIKETHROUGH) {
|
||||
match &event {
|
||||
Event::Text(text) => {
|
||||
for word in text.split_inclusive(char::is_whitespace) {
|
||||
if text_length + word.len() >= length_limit {
|
||||
stopped_early = true;
|
||||
break 'outer;
|
||||
}
|
||||
|
||||
push(&mut s, &mut text_length, word);
|
||||
}
|
||||
}
|
||||
Event::Code(code) => {
|
||||
if text_length + code.len() >= length_limit {
|
||||
stopped_early = true;
|
||||
break;
|
||||
}
|
||||
|
||||
s.push_str("<code>");
|
||||
push(&mut s, &mut text_length, code);
|
||||
s.push_str("</code>");
|
||||
}
|
||||
Event::Start(tag) => match tag {
|
||||
Tag::Emphasis => s.push_str("<em>"),
|
||||
Tag::Strong => s.push_str("<strong>"),
|
||||
Tag::CodeBlock(..) => break,
|
||||
_ => {}
|
||||
},
|
||||
Event::End(tag) => match tag {
|
||||
Tag::Emphasis => s.push_str("</em>"),
|
||||
Tag::Strong => s.push_str("</strong>"),
|
||||
Tag::Paragraph => break,
|
||||
_ => {}
|
||||
},
|
||||
Event::HardBreak | Event::SoftBreak => {
|
||||
if text_length + 1 >= length_limit {
|
||||
stopped_early = true;
|
||||
break;
|
||||
}
|
||||
|
||||
push(&mut s, &mut text_length, " ");
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
(s, stopped_early)
|
||||
}
|
||||
|
||||
/// Renders a shortened first paragraph of the given Markdown as a subset of Markdown,
|
||||
/// making it suitable for contexts like the search index.
|
||||
///
|
||||
/// Will shorten to 59 or 60 characters, including an ellipsis (…) if it was shortened.
|
||||
///
|
||||
/// See [`markdown_summary_with_limit`] for details about what is rendered and what is not.
|
||||
crate fn short_markdown_summary(markdown: &str) -> String {
|
||||
let (mut s, was_shortened) = markdown_summary_with_limit(markdown, 59);
|
||||
|
||||
if was_shortened {
|
||||
s.push('…');
|
||||
}
|
||||
|
||||
s
|
||||
}
|
||||
|
||||
/// Renders the first paragraph of the provided markdown as plain text.
|
||||
/// Useful for alt-text.
|
||||
///
|
||||
/// - Headings, links, and formatting are stripped.
|
||||
/// - Inline code is rendered as-is, surrounded by backticks.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use super::plain_text_summary;
|
||||
use super::{plain_text_summary, short_markdown_summary};
|
||||
use super::{ErrorCodes, IdMap, Ignore, LangString, Markdown, MarkdownHtml};
|
||||
use rustc_span::edition::{Edition, DEFAULT_EDITION};
|
||||
use std::cell::RefCell;
|
||||
|
@ -204,6 +204,33 @@ fn test_header_ids_multiple_blocks() {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_short_markdown_summary() {
|
||||
fn t(input: &str, expect: &str) {
|
||||
let output = short_markdown_summary(input);
|
||||
assert_eq!(output, expect, "original: {}", input);
|
||||
}
|
||||
|
||||
t("hello [Rust](https://www.rust-lang.org) :)", "hello Rust :)");
|
||||
t("*italic*", "<em>italic</em>");
|
||||
t("**bold**", "<strong>bold</strong>");
|
||||
t("Multi-line\nsummary", "Multi-line summary");
|
||||
t("Hard-break \nsummary", "Hard-break summary");
|
||||
t("hello [Rust] :)\n\n[Rust]: https://www.rust-lang.org", "hello Rust :)");
|
||||
t("hello [Rust](https://www.rust-lang.org \"Rust\") :)", "hello Rust :)");
|
||||
t("code `let x = i32;` ...", "code <code>let x = i32;</code> ...");
|
||||
t("type `Type<'static>` ...", "type <code>Type<'static></code> ...");
|
||||
t("# top header", "top header");
|
||||
t("## header", "header");
|
||||
t("first paragraph\n\nsecond paragraph", "first paragraph");
|
||||
t("```\nfn main() {}\n```", "");
|
||||
t("<div>hello</div>", "");
|
||||
t(
|
||||
"a *very*, **very** long first paragraph. it has lots of `inline code: Vec<T>`. and it has a [link](https://www.rust-lang.org).\nthat was a soft line break! \nthat was a hard one\n\nsecond paragraph.",
|
||||
"a <em>very</em>, <strong>very</strong> long first paragraph. it has lots of …",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_plain_text_summary() {
|
||||
fn t(input: &str, expect: &str) {
|
||||
|
@ -224,6 +251,10 @@ fn test_plain_text_summary() {
|
|||
t("first paragraph\n\nsecond paragraph", "first paragraph");
|
||||
t("```\nfn main() {}\n```", "");
|
||||
t("<div>hello</div>", "");
|
||||
t(
|
||||
"a *very*, **very** long first paragraph. it has lots of `inline code: Vec<T>`. and it has a [link](https://www.rust-lang.org).\nthat was a soft line break! \nthat was a hard one\n\nsecond paragraph.",
|
||||
"a very, very long first paragraph. it has lots of `inline code: Vec<T>`. and it has a link. that was a soft line break! that was a hard one",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -9,7 +9,7 @@ use crate::clean::types::GetDefId;
|
|||
use crate::clean::{self, AttributesExt};
|
||||
use crate::formats::cache::Cache;
|
||||
use crate::formats::item_type::ItemType;
|
||||
use crate::html::render::{plain_text_summary, shorten};
|
||||
use crate::html::markdown::short_markdown_summary;
|
||||
use crate::html::render::{Generic, IndexItem, IndexItemFunctionType, RenderType, TypeWithKind};
|
||||
|
||||
/// Indicates where an external crate can be found.
|
||||
|
@ -78,7 +78,7 @@ crate fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String {
|
|||
ty: item.type_(),
|
||||
name: item.name.clone().unwrap(),
|
||||
path: fqp[..fqp.len() - 1].join("::"),
|
||||
desc: shorten(plain_text_summary(item.doc_value())),
|
||||
desc: item.doc_value().map_or_else(|| String::new(), short_markdown_summary),
|
||||
parent: Some(did),
|
||||
parent_idx: None,
|
||||
search_type: get_index_search_type(&item),
|
||||
|
@ -127,7 +127,7 @@ crate fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String {
|
|||
let crate_doc = krate
|
||||
.module
|
||||
.as_ref()
|
||||
.map(|module| shorten(plain_text_summary(module.doc_value())))
|
||||
.map(|module| module.doc_value().map_or_else(|| String::new(), short_markdown_summary))
|
||||
.unwrap_or_default();
|
||||
|
||||
#[derive(Serialize)]
|
||||
|
|
|
@ -76,7 +76,9 @@ use crate::html::format::fmt_impl_for_trait_page;
|
|||
use crate::html::format::Function;
|
||||
use crate::html::format::{href, print_default_space, print_generic_bounds, WhereClause};
|
||||
use crate::html::format::{print_abi_with_space, Buffer, PrintWithSpace};
|
||||
use crate::html::markdown::{self, ErrorCodes, IdMap, Markdown, MarkdownHtml, MarkdownSummaryLine};
|
||||
use crate::html::markdown::{
|
||||
self, plain_text_summary, ErrorCodes, IdMap, Markdown, MarkdownHtml, MarkdownSummaryLine,
|
||||
};
|
||||
use crate::html::sources;
|
||||
use crate::html::{highlight, layout, static_files};
|
||||
use cache::{build_index, ExternalLocation};
|
||||
|
@ -1604,9 +1606,10 @@ impl Context {
|
|||
Some(ref s) => s.to_string(),
|
||||
};
|
||||
let short = short.to_string();
|
||||
map.entry(short)
|
||||
.or_default()
|
||||
.push((myname, Some(plain_text_summary(item.doc_value()))));
|
||||
map.entry(short).or_default().push((
|
||||
myname,
|
||||
Some(item.doc_value().map_or_else(|| String::new(), plain_text_summary)),
|
||||
));
|
||||
}
|
||||
|
||||
if self.shared.sort_modules_alphabetically {
|
||||
|
@ -1810,36 +1813,6 @@ fn full_path(cx: &Context, item: &clean::Item) -> String {
|
|||
s
|
||||
}
|
||||
|
||||
/// Renders the first paragraph of the given markdown as plain text, making it suitable for
|
||||
/// contexts like alt-text or the search index.
|
||||
///
|
||||
/// If no markdown is supplied, the empty string is returned.
|
||||
///
|
||||
/// See [`markdown::plain_text_summary`] for further details.
|
||||
#[inline]
|
||||
crate fn plain_text_summary(s: Option<&str>) -> String {
|
||||
s.map(markdown::plain_text_summary).unwrap_or_default()
|
||||
}
|
||||
|
||||
crate fn shorten(s: String) -> String {
|
||||
if s.chars().count() > 60 {
|
||||
let mut len = 0;
|
||||
let mut ret = s
|
||||
.split_whitespace()
|
||||
.take_while(|p| {
|
||||
// + 1 for the added character after the word.
|
||||
len += p.chars().count() + 1;
|
||||
len < 60
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join(" ");
|
||||
ret.push('…');
|
||||
ret
|
||||
} else {
|
||||
s
|
||||
}
|
||||
}
|
||||
|
||||
fn document(w: &mut Buffer, cx: &Context, item: &clean::Item, parent: Option<&clean::Item>) {
|
||||
if let Some(ref name) = item.name {
|
||||
info!("Documenting {}", name);
|
||||
|
|
|
@ -1611,7 +1611,7 @@ function defocusSearchBar() {
|
|||
item.displayPath + "<span class=\"" + type + "\">" +
|
||||
name + "</span></a></td><td>" +
|
||||
"<a href=\"" + item.href + "\">" +
|
||||
"<span class=\"desc\">" + escape(item.desc) +
|
||||
"<span class=\"desc\">" + item.desc +
|
||||
" </span></a></td></tr>";
|
||||
});
|
||||
output += "</table>";
|
||||
|
@ -2013,7 +2013,9 @@ function defocusSearchBar() {
|
|||
}
|
||||
var link = document.createElement("a");
|
||||
link.href = rootPath + crates[i] + "/index.html";
|
||||
link.title = rawSearchIndex[crates[i]].doc;
|
||||
// The summary in the search index has HTML, so we need to
|
||||
// dynamically render it as plaintext.
|
||||
link.title = convertHTMLToPlaintext(rawSearchIndex[crates[i]].doc);
|
||||
link.className = klass;
|
||||
link.textContent = crates[i];
|
||||
|
||||
|
@ -2026,6 +2028,23 @@ function defocusSearchBar() {
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert HTML to plaintext:
|
||||
*
|
||||
* * Replace "<code>foo</code>" with "`foo`"
|
||||
* * Strip all other HTML tags
|
||||
*
|
||||
* Used by the dynamic sidebar crate list renderer.
|
||||
*
|
||||
* @param {[string]} html [The HTML to convert]
|
||||
* @return {[string]} [The resulting plaintext]
|
||||
*/
|
||||
function convertHTMLToPlaintext(html) {
|
||||
var x = document.createElement("div");
|
||||
x.innerHTML = html.replace('<code>', '`').replace('</code>', '`');
|
||||
return x.innerText;
|
||||
}
|
||||
|
||||
|
||||
// delayed sidebar rendering.
|
||||
window.initSidebarItems = function(items) {
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#![feature(never_type)]
|
||||
#![feature(once_cell)]
|
||||
#![feature(type_ascription)]
|
||||
#![feature(split_inclusive)]
|
||||
#![recursion_limit = "256"]
|
||||
|
||||
#[macro_use]
|
||||
|
|
|
@ -847,12 +847,17 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
|
|||
|
||||
// FIXME(jynelson): this shouldn't go through stringification, rustdoc should just use the DefId directly
|
||||
let self_name = self_id.and_then(|self_id| {
|
||||
use ty::TyKind;
|
||||
if matches!(self.cx.tcx.def_kind(self_id), DefKind::Impl) {
|
||||
// using `ty.to_string()` directly has issues with shortening paths
|
||||
// using `ty.to_string()` (or any variant) has issues with raw idents
|
||||
let ty = self.cx.tcx.type_of(self_id);
|
||||
let name = ty::print::with_crate_prefix(|| ty.to_string());
|
||||
debug!("using type_of(): {}", name);
|
||||
Some(name)
|
||||
let name = match ty.kind() {
|
||||
TyKind::Adt(def, _) => Some(self.cx.tcx.item_name(def.did).to_string()),
|
||||
other if other.is_primitive() => Some(ty.to_string()),
|
||||
_ => None,
|
||||
};
|
||||
debug!("using type_of(): {:?}", name);
|
||||
name
|
||||
} else {
|
||||
let name = self.cx.tcx.opt_item_name(self_id).map(|sym| sym.to_string());
|
||||
debug!("using item_name(): {:?}", name);
|
||||
|
|
|
@ -10,7 +10,7 @@ use rustc_hir::Node;
|
|||
use rustc_middle::middle::privacy::AccessLevel;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||
use rustc_span::symbol::{kw, sym, Symbol};
|
||||
use rustc_span::{self, Span};
|
||||
|
||||
use std::mem;
|
||||
|
@ -116,7 +116,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
|||
&mut self,
|
||||
id: hir::HirId,
|
||||
res: Res,
|
||||
renamed: Option<Ident>,
|
||||
renamed: Option<Symbol>,
|
||||
glob: bool,
|
||||
om: &mut Module<'tcx>,
|
||||
please_inline: bool,
|
||||
|
@ -226,11 +226,11 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
|||
fn visit_item(
|
||||
&mut self,
|
||||
item: &'tcx hir::Item<'_>,
|
||||
renamed: Option<Ident>,
|
||||
renamed: Option<Symbol>,
|
||||
om: &mut Module<'tcx>,
|
||||
) {
|
||||
debug!("visiting item {:?}", item);
|
||||
let ident = renamed.unwrap_or(item.ident);
|
||||
let name = renamed.unwrap_or(item.ident.name);
|
||||
|
||||
if item.vis.node.is_pub() {
|
||||
let def_id = self.cx.tcx.hir().local_def_id(item.hir_id);
|
||||
|
@ -266,7 +266,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
|||
}
|
||||
_ => false,
|
||||
});
|
||||
let ident = if is_glob { None } else { Some(ident) };
|
||||
let ident = if is_glob { None } else { Some(name) };
|
||||
if self.maybe_inline_local(
|
||||
item.hir_id,
|
||||
path.res,
|
||||
|
@ -280,7 +280,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
|||
}
|
||||
|
||||
om.imports.push(Import {
|
||||
name: ident.name,
|
||||
name,
|
||||
id: item.hir_id,
|
||||
vis: &item.vis,
|
||||
attrs: &item.attrs,
|
||||
|
@ -296,7 +296,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
|||
&item.vis,
|
||||
item.hir_id,
|
||||
m,
|
||||
Some(ident.name),
|
||||
Some(name),
|
||||
));
|
||||
}
|
||||
hir::ItemKind::Fn(..)
|
||||
|
@ -312,7 +312,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
|||
hir::ItemKind::Const(..) => {
|
||||
// Underscore constants do not correspond to a nameable item and
|
||||
// so are never useful in documentation.
|
||||
if ident.name != kw::Underscore {
|
||||
if name != kw::Underscore {
|
||||
om.items.push((item, renamed));
|
||||
}
|
||||
}
|
||||
|
@ -329,7 +329,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
|||
fn visit_foreign_item(
|
||||
&mut self,
|
||||
item: &'tcx hir::ForeignItem<'_>,
|
||||
renamed: Option<Ident>,
|
||||
renamed: Option<Symbol>,
|
||||
om: &mut Module<'tcx>,
|
||||
) {
|
||||
// If inlining we only want to include public functions.
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
/// Foo
|
||||
/// Docs for Foo
|
||||
pub struct Foo;
|
||||
|
|
21
src/test/rustdoc-js/summaries.js
Normal file
21
src/test/rustdoc-js/summaries.js
Normal file
|
@ -0,0 +1,21 @@
|
|||
// ignore-tidy-linelength
|
||||
|
||||
const QUERY = ['summaries', 'summaries::Sidebar', 'summaries::Sidebar2'];
|
||||
|
||||
const EXPECTED = [
|
||||
{
|
||||
'others': [
|
||||
{ 'path': '', 'name': 'summaries', 'desc': 'This <em>summary</em> has a link and <code>code</code>.' },
|
||||
],
|
||||
},
|
||||
{
|
||||
'others': [
|
||||
{ 'path': 'summaries', 'name': 'Sidebar', 'desc': 'This <code>code</code> will be rendered in a code tag.' },
|
||||
],
|
||||
},
|
||||
{
|
||||
'others': [
|
||||
{ 'path': 'summaries', 'name': 'Sidebar2', 'desc': '' },
|
||||
],
|
||||
},
|
||||
];
|
18
src/test/rustdoc-js/summaries.rs
Normal file
18
src/test/rustdoc-js/summaries.rs
Normal file
|
@ -0,0 +1,18 @@
|
|||
#![crate_type = "lib"]
|
||||
#![crate_name = "summaries"]
|
||||
|
||||
//! This *summary* has a [link] and `code`.
|
||||
//!
|
||||
//! This is the second paragraph.
|
||||
//!
|
||||
//! [link]: https://example.com
|
||||
|
||||
/// This `code` will be rendered in a code tag.
|
||||
///
|
||||
/// This text should not be rendered.
|
||||
pub struct Sidebar;
|
||||
|
||||
/// ```text
|
||||
/// this block should not be rendered
|
||||
/// ```
|
||||
pub struct Sidebar2;
|
13
src/test/rustdoc/intra-doc/raw-ident-self.rs
Normal file
13
src/test/rustdoc/intra-doc/raw-ident-self.rs
Normal file
|
@ -0,0 +1,13 @@
|
|||
#![deny(broken_intra_doc_links)]
|
||||
pub mod r#impl {
|
||||
pub struct S;
|
||||
|
||||
impl S {
|
||||
/// See [Self::b].
|
||||
// @has raw_ident_self/impl/struct.S.html
|
||||
// @has - '//a[@href="../../raw_ident_self/impl/struct.S.html#method.b"]' 'Self::b'
|
||||
pub fn a() {}
|
||||
|
||||
pub fn b() {}
|
||||
}
|
||||
}
|
|
@ -1,21 +1,22 @@
|
|||
#![crate_type = "lib"]
|
||||
#![crate_name = "summaries"]
|
||||
|
||||
//! This summary has a [link] and `code`.
|
||||
//! This *summary* has a [link] and `code`.
|
||||
//!
|
||||
//! This is the second paragraph.
|
||||
//!
|
||||
//! [link]: https://example.com
|
||||
|
||||
// @has search-index.js 'This summary has a link and `code`.'
|
||||
// @has search-index.js 'This <em>summary</em> has a link and <code>code</code>.'
|
||||
// @!has - 'second paragraph'
|
||||
|
||||
/// This `code` should be in backticks.
|
||||
/// This `code` will be rendered in a code tag.
|
||||
///
|
||||
/// This text should not be rendered.
|
||||
pub struct Sidebar;
|
||||
|
||||
// @has summaries/sidebar-items.js 'This `code` should be in backticks.'
|
||||
// @has search-index.js 'This <code>code</code> will be rendered in a code tag.'
|
||||
// @has summaries/sidebar-items.js 'This `code` will be rendered in a code tag.'
|
||||
// @!has - 'text should not be rendered'
|
||||
|
||||
/// ```text
|
11
src/test/ui-fulldeps/internal-lints/existing_doc_keyword.rs
Normal file
11
src/test/ui-fulldeps/internal-lints/existing_doc_keyword.rs
Normal file
|
@ -0,0 +1,11 @@
|
|||
// compile-flags: -Z unstable-options
|
||||
|
||||
#![feature(rustc_private)]
|
||||
#![feature(doc_keyword)]
|
||||
|
||||
#![crate_type = "lib"]
|
||||
|
||||
#![deny(rustc::existing_doc_keyword)]
|
||||
|
||||
#[doc(keyword = "tadam")] //~ ERROR
|
||||
mod tadam {}
|
|
@ -0,0 +1,15 @@
|
|||
error: Found non-existing keyword `tadam` used in `#[doc(keyword = "...")]`
|
||||
--> $DIR/existing_doc_keyword.rs:10:1
|
||||
|
|
||||
LL | #[doc(keyword = "tadam")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/existing_doc_keyword.rs:8:9
|
||||
|
|
||||
LL | #![deny(rustc::existing_doc_keyword)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= help: only existing keywords are allowed in core/std
|
||||
|
||||
error: aborting due to previous error
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit bfca1cd22bf514d5f2b6c1089b0ded0ba7dfaa6e
|
||||
Subproject commit 63d0fe43449adcb316d34d98a982b597faca4178
|
Loading…
Add table
Add a link
Reference in a new issue