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 {
|
pub fn derive_allowed(&self) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
Annotatable::Stmt(ref stmt) => match stmt.kind {
|
Annotatable::Stmt(ref stmt) => match stmt.kind {
|
||||||
ast::StmtKind::Item(ref item) => match item.kind {
|
ast::StmtKind::Item(ref item) => matches!(
|
||||||
ast::ItemKind::Struct(..)
|
item.kind,
|
||||||
| ast::ItemKind::Enum(..)
|
ast::ItemKind::Struct(..) | ast::ItemKind::Enum(..) | ast::ItemKind::Union(..)
|
||||||
| ast::ItemKind::Union(..) => true,
|
),
|
||||||
_ => false,
|
|
||||||
},
|
|
||||||
_ => false,
|
_ => false,
|
||||||
},
|
},
|
||||||
Annotatable::Item(ref item) => match item.kind {
|
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) {
|
if let Some(attr) = self.take_first_attr_no_derive(&mut expr) {
|
||||||
// Collect the invoc regardless of whether or not attributes are permitted here
|
// Collect the invoc regardless of whether or not attributes are permitted here
|
||||||
// expansion will eat the attribute so it won't error later.
|
// 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.
|
// AstFragmentKind::Expr requires the macro to emit an expression.
|
||||||
return self
|
return self
|
||||||
|
@ -1231,7 +1233,9 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
|
||||||
self.cfg.configure_expr_kind(&mut expr.kind);
|
self.cfg.configure_expr_kind(&mut expr.kind);
|
||||||
|
|
||||||
if let Some(attr) = self.take_first_attr_no_derive(&mut expr) {
|
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
|
return self
|
||||||
.collect_attr(attr, Annotatable::Expr(P(expr)), AstFragmentKind::OptExpr)
|
.collect_attr(attr, Annotatable::Expr(P(expr)), AstFragmentKind::OptExpr)
|
||||||
|
|
|
@ -2401,7 +2401,7 @@ impl StructField<'_> {
|
||||||
// Still necessary in couple of places
|
// Still necessary in couple of places
|
||||||
pub fn is_positional(&self) -> bool {
|
pub fn is_positional(&self) -> bool {
|
||||||
let first = self.ident.as_str().as_bytes()[0];
|
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 {
|
pub fn is_id_start(c: char) -> bool {
|
||||||
// This is XID_Start OR '_' (which formally is not a XID_Start).
|
// This is XID_Start OR '_' (which formally is not a XID_Start).
|
||||||
// We also add fast-path for ascii idents
|
// We also add fast-path for ascii idents
|
||||||
('a' <= c && c <= 'z')
|
('a'..='z').contains(&c)
|
||||||
|| ('A' <= c && c <= 'Z')
|
|| ('A'..='Z').contains(&c)
|
||||||
|| c == '_'
|
|| c == '_'
|
||||||
|| (c > '\x7f' && unicode_xid::UnicodeXID::is_xid_start(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 {
|
pub fn is_id_continue(c: char) -> bool {
|
||||||
// This is exactly XID_Continue.
|
// This is exactly XID_Continue.
|
||||||
// We also add fast-path for ascii idents
|
// We also add fast-path for ascii idents
|
||||||
('a' <= c && c <= 'z')
|
('a'..='z').contains(&c)
|
||||||
|| ('A' <= c && c <= 'Z')
|
|| ('A'..='Z').contains(&c)
|
||||||
|| ('0' <= c && c <= '9')
|
|| ('0'..='9').contains(&c)
|
||||||
|| c == '_'
|
|| c == '_'
|
||||||
|| (c > '\x7f' && unicode_xid::UnicodeXID::is_xid_continue(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_middle::ty;
|
||||||
use rustc_session::{declare_lint_pass, declare_tool_lint, impl_lint_pass};
|
use rustc_session::{declare_lint_pass, declare_tool_lint, impl_lint_pass};
|
||||||
use rustc_span::hygiene::{ExpnKind, MacroKind};
|
use rustc_span::hygiene::{ExpnKind, MacroKind};
|
||||||
use rustc_span::symbol::{sym, Ident, Symbol};
|
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||||
|
|
||||||
declare_tool_lint! {
|
declare_tool_lint! {
|
||||||
pub rustc::DEFAULT_HASH_TYPES,
|
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_early_pass(|| box DefaultHashTypes::new());
|
||||||
store.register_lints(&LintPassImpl::get_lints());
|
store.register_lints(&LintPassImpl::get_lints());
|
||||||
store.register_early_pass(|| box LintPassImpl);
|
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_lints(&TyTyKind::get_lints());
|
||||||
store.register_late_pass(|| box TyTyKind);
|
store.register_late_pass(|| box TyTyKind);
|
||||||
store.register_group(
|
store.register_group(
|
||||||
|
@ -475,6 +477,7 @@ fn register_internals(store: &mut LintStore) {
|
||||||
LintId::of(LINT_PASS_IMPL_WITHOUT_MACRO),
|
LintId::of(LINT_PASS_IMPL_WITHOUT_MACRO),
|
||||||
LintId::of(TY_PASS_BY_REFERENCE),
|
LintId::of(TY_PASS_BY_REFERENCE),
|
||||||
LintId::of(USAGE_OF_QUALIFIED_TY),
|
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)
|
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
|
/// Get the `DepNodeIndex` corresponding this crate. The result of this
|
||||||
/// method is cached in the `dep_node_index` field.
|
/// method is cached in the `dep_node_index` field.
|
||||||
fn get_crate_dep_node_index(&self, tcx: TyCtxt<'tcx>) -> DepNodeIndex {
|
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 {
|
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)
|
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 {
|
impl CrateStore for CStore {
|
||||||
|
@ -498,14 +502,6 @@ impl CrateStore for CStore {
|
||||||
self.get_crate_data(def.krate).def_path_hash(def.index)
|
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
|
// See `CrateMetadataRef::def_path_hash_to_def_id` for more details
|
||||||
fn def_path_hash_to_def_id(
|
fn def_path_hash_to_def_id(
|
||||||
&self,
|
&self,
|
||||||
|
|
|
@ -189,8 +189,6 @@ pub trait CrateStore {
|
||||||
fn def_kind(&self, def: DefId) -> DefKind;
|
fn def_kind(&self, def: DefId) -> DefKind;
|
||||||
fn def_path(&self, def: DefId) -> DefPath;
|
fn def_path(&self, def: DefId) -> DefPath;
|
||||||
fn def_path_hash(&self, def: DefId) -> DefPathHash;
|
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(
|
fn def_path_hash_to_def_id(
|
||||||
&self,
|
&self,
|
||||||
cnum: CrateNum,
|
cnum: CrateNum,
|
||||||
|
|
|
@ -7,6 +7,7 @@ use std::collections::hash_map::Entry;
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
|
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
use rustc_ast::Mutability;
|
use rustc_ast::Mutability;
|
||||||
use rustc_hir::def_id::DefId;
|
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> =
|
crate type CompileTimeEvalContext<'mir, 'tcx> =
|
||||||
InterpCx<'mir, 'tcx, CompileTimeInterpreter<'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 ! {
|
impl interpret::MayLeak for ! {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn may_leak(self) -> bool {
|
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> {
|
impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, 'tcx> {
|
||||||
compile_time_machine!(<'mir, 'tcx>);
|
compile_time_machine!(<'mir, 'tcx>);
|
||||||
|
|
||||||
|
type MemoryKind = MemoryKind;
|
||||||
|
|
||||||
type MemoryExtra = MemoryExtra;
|
type MemoryExtra = MemoryExtra;
|
||||||
|
|
||||||
fn find_mir_or_eval_fn(
|
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(
|
let ptr = ecx.memory.allocate(
|
||||||
Size::from_bytes(size as u64),
|
Size::from_bytes(size as u64),
|
||||||
align,
|
align,
|
||||||
interpret::MemoryKind::ConstHeap,
|
interpret::MemoryKind::Machine(MemoryKind::Heap),
|
||||||
);
|
);
|
||||||
ecx.write_scalar(Scalar::Ptr(ptr), dest)?;
|
ecx.write_scalar(Scalar::Ptr(ptr), dest)?;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,19 +25,20 @@ use rustc_target::abi::Size;
|
||||||
use rustc_ast::Mutability;
|
use rustc_ast::Mutability;
|
||||||
|
|
||||||
use super::{AllocId, Allocation, InterpCx, MPlaceTy, Machine, MemoryKind, Scalar, ValueVisitor};
|
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,
|
'mir,
|
||||||
'tcx,
|
'tcx,
|
||||||
MemoryKind = !,
|
MemoryKind = T,
|
||||||
PointerTag = (),
|
PointerTag = (),
|
||||||
ExtraFnVal = !,
|
ExtraFnVal = !,
|
||||||
FrameExtra = (),
|
FrameExtra = (),
|
||||||
AllocExtra = (),
|
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.
|
/// The ectx from which we intern.
|
||||||
ecx: &'rt mut InterpCx<'mir, 'tcx, M>,
|
ecx: &'rt mut InterpCx<'mir, 'tcx, M>,
|
||||||
/// Previously encountered safe references.
|
/// Previously encountered safe references.
|
||||||
|
@ -74,7 +75,7 @@ struct IsStaticOrFn;
|
||||||
/// `immutable` things might become mutable if `ty` is not frozen.
|
/// `immutable` things might become mutable if `ty` is not frozen.
|
||||||
/// `ty` can be `None` if there is no potential interior mutability
|
/// `ty` can be `None` if there is no potential interior mutability
|
||||||
/// to account for (e.g. for vtables).
|
/// 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>,
|
ecx: &'rt mut InterpCx<'mir, 'tcx, M>,
|
||||||
leftover_allocations: &'rt mut FxHashSet<AllocId>,
|
leftover_allocations: &'rt mut FxHashSet<AllocId>,
|
||||||
alloc_id: AllocId,
|
alloc_id: AllocId,
|
||||||
|
@ -105,7 +106,7 @@ fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>>(
|
||||||
// changes in this function.
|
// changes in this function.
|
||||||
match kind {
|
match kind {
|
||||||
MemoryKind::Stack
|
MemoryKind::Stack
|
||||||
| MemoryKind::ConstHeap
|
| MemoryKind::Machine(const_eval::MemoryKind::Heap)
|
||||||
| MemoryKind::Vtable
|
| MemoryKind::Vtable
|
||||||
| MemoryKind::CallerLocation => {}
|
| MemoryKind::CallerLocation => {}
|
||||||
}
|
}
|
||||||
|
@ -141,7 +142,9 @@ fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>>(
|
||||||
None
|
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(
|
fn intern_shallow(
|
||||||
&mut self,
|
&mut self,
|
||||||
alloc_id: AllocId,
|
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>
|
impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx, const_eval::MemoryKind>>
|
||||||
for InternVisitor<'rt, 'mir, 'tcx, M>
|
ValueVisitor<'mir, 'tcx, M> for InternVisitor<'rt, 'mir, 'tcx, M>
|
||||||
{
|
{
|
||||||
type V = MPlaceTy<'tcx>;
|
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
|
/// Any errors here would anyway be turned into `const_err` lints, whereas validation failures
|
||||||
/// are hard errors.
|
/// are hard errors.
|
||||||
#[tracing::instrument(skip(ecx))]
|
#[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>,
|
ecx: &mut InterpCx<'mir, 'tcx, M>,
|
||||||
intern_kind: InternKind,
|
intern_kind: InternKind,
|
||||||
ret: MPlaceTy<'tcx>,
|
ret: MPlaceTy<'tcx>,
|
||||||
|
@ -421,7 +424,9 @@ where
|
||||||
Ok(())
|
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
|
/// 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
|
/// it. Once your own mutation code is done, the backing `Allocation` is removed from the
|
||||||
/// current `Memory` and returned.
|
/// current `Memory` and returned.
|
||||||
|
|
|
@ -366,9 +366,9 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
|
||||||
type PointerTag = ();
|
type PointerTag = ();
|
||||||
type ExtraFnVal = !;
|
type ExtraFnVal = !;
|
||||||
|
|
||||||
type MemoryKind = !;
|
type MemoryMap =
|
||||||
type MemoryMap = rustc_data_structures::fx::FxHashMap<AllocId, (MemoryKind<!>, Allocation)>;
|
rustc_data_structures::fx::FxHashMap<AllocId, (MemoryKind<Self::MemoryKind>, Allocation)>;
|
||||||
const GLOBAL_KIND: Option<!> = None; // no copying of globals from `tcx` to machine memory
|
const GLOBAL_KIND: Option<Self::MemoryKind> = None; // no copying of globals from `tcx` to machine memory
|
||||||
|
|
||||||
type AllocExtra = ();
|
type AllocExtra = ();
|
||||||
type FrameExtra = ();
|
type FrameExtra = ();
|
||||||
|
@ -407,7 +407,7 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
|
||||||
_memory_extra: &Self::MemoryExtra,
|
_memory_extra: &Self::MemoryExtra,
|
||||||
_id: AllocId,
|
_id: AllocId,
|
||||||
alloc: Cow<'b, Allocation>,
|
alloc: Cow<'b, Allocation>,
|
||||||
_kind: Option<MemoryKind<!>>,
|
_kind: Option<MemoryKind<Self::MemoryKind>>,
|
||||||
) -> (Cow<'b, Allocation<Self::PointerTag>>, Self::PointerTag) {
|
) -> (Cow<'b, Allocation<Self::PointerTag>>, Self::PointerTag) {
|
||||||
// We do not use a tag so we can just cheaply forward the allocation
|
// We do not use a tag so we can just cheaply forward the allocation
|
||||||
(alloc, ())
|
(alloc, ())
|
||||||
|
|
|
@ -27,9 +27,6 @@ use crate::util::pretty;
|
||||||
pub enum MemoryKind<T> {
|
pub enum MemoryKind<T> {
|
||||||
/// Stack memory. Error if deallocated except during a stack pop.
|
/// Stack memory. Error if deallocated except during a stack pop.
|
||||||
Stack,
|
Stack,
|
||||||
/// Heap memory.
|
|
||||||
/// FIXME: this variant should be in const_eval
|
|
||||||
ConstHeap,
|
|
||||||
/// Memory backing vtables. Error if ever deallocated.
|
/// Memory backing vtables. Error if ever deallocated.
|
||||||
Vtable,
|
Vtable,
|
||||||
/// Memory allocated by `caller_location` intrinsic. Error if ever deallocated.
|
/// 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 {
|
fn may_leak(self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
MemoryKind::Stack => false,
|
MemoryKind::Stack => false,
|
||||||
MemoryKind::ConstHeap => false,
|
|
||||||
MemoryKind::Vtable => true,
|
MemoryKind::Vtable => true,
|
||||||
MemoryKind::CallerLocation => true,
|
MemoryKind::CallerLocation => true,
|
||||||
MemoryKind::Machine(k) => k.may_leak(),
|
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 {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
MemoryKind::Stack => write!(f, "stack variable"),
|
MemoryKind::Stack => write!(f, "stack variable"),
|
||||||
MemoryKind::ConstHeap => write!(f, "heap allocation"),
|
|
||||||
MemoryKind::Vtable => write!(f, "vtable"),
|
MemoryKind::Vtable => write!(f, "vtable"),
|
||||||
MemoryKind::CallerLocation => write!(f, "caller location"),
|
MemoryKind::CallerLocation => write!(f, "caller location"),
|
||||||
MemoryKind::Machine(m) => write!(f, "{}", m),
|
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> {
|
impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx> {
|
||||||
compile_time_machine!(<'mir, 'tcx>);
|
compile_time_machine!(<'mir, 'tcx>);
|
||||||
|
|
||||||
|
type MemoryKind = !;
|
||||||
|
|
||||||
type MemoryExtra = ();
|
type MemoryExtra = ();
|
||||||
|
|
||||||
fn find_mir_or_eval_fn(
|
fn find_mir_or_eval_fn(
|
||||||
|
|
|
@ -1859,7 +1859,7 @@ impl<T: Iterator<Item = char>> Parser<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let n2 = self.decode_hex_escape()?;
|
let n2 = self.decode_hex_escape()?;
|
||||||
if n2 < 0xDC00 || n2 > 0xDFFF {
|
if !(0xDC00..=0xDFFF).contains(&n2) {
|
||||||
return self.error(LoneLeadingSurrogateInHexEscape);
|
return self.error(LoneLeadingSurrogateInHexEscape);
|
||||||
}
|
}
|
||||||
let c =
|
let c =
|
||||||
|
|
|
@ -97,7 +97,7 @@ cfg_if::cfg_if! {
|
||||||
let ptr = src_bytes.as_ptr() as *const __m128i;
|
let ptr = src_bytes.as_ptr() as *const __m128i;
|
||||||
// We don't know if the pointer is aligned to 16 bytes, so we
|
// We don't know if the pointer is aligned to 16 bytes, so we
|
||||||
// use `loadu`, which supports unaligned loading.
|
// 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
|
// For character in the chunk, see if its byte value is < 0, which
|
||||||
// indicates that it's part of a UTF-8 char.
|
// 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;
|
let pos = BytePos::from_usize(i) + output_offset;
|
||||||
|
|
||||||
if char_len > 1 {
|
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 };
|
let mbc = MultiByteChar { pos, bytes: char_len as u8 };
|
||||||
multi_byte_chars.push(mbc);
|
multi_byte_chars.push(mbc);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1015,10 +1015,7 @@ pub enum ExternalSourceKind {
|
||||||
|
|
||||||
impl ExternalSource {
|
impl ExternalSource {
|
||||||
pub fn is_absent(&self) -> bool {
|
pub fn is_absent(&self) -> bool {
|
||||||
match self {
|
!matches!(self, ExternalSource::Foreign { kind: ExternalSourceKind::Present(_), .. })
|
||||||
ExternalSource::Foreign { kind: ExternalSourceKind::Present(_), .. } => false,
|
|
||||||
_ => true,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_source(&self) -> Option<&Lrc<String>> {
|
pub fn get_source(&self) -> Option<&Lrc<String>> {
|
||||||
|
|
|
@ -623,7 +623,7 @@ impl SourceMap {
|
||||||
self.span_to_source(sp, |src, start_index, end_index| {
|
self.span_to_source(sp, |src, start_index, end_index| {
|
||||||
src.get(start_index..end_index)
|
src.get(start_index..end_index)
|
||||||
.map(|s| s.to_string())
|
.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`.
|
/// Returns the source snippet as `String` before the given `Span`.
|
||||||
pub fn span_to_prev_source(&self, sp: Span) -> Result<String, SpanSnippetError> {
|
pub fn span_to_prev_source(&self, sp: Span) -> Result<String, SpanSnippetError> {
|
||||||
self.span_to_source(sp, |src, start_index, _| {
|
self.span_to_source(sp, |src, start_index, _| {
|
||||||
src.get(..start_index)
|
src.get(..start_index).map(|s| s.to_string()).ok_or(SpanSnippetError::IllFormedSpan(sp))
|
||||||
.map(|s| s.to_string())
|
|
||||||
.ok_or_else(|| SpanSnippetError::IllFormedSpan(sp))
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1363,15 +1363,13 @@ impl fmt::Display for IdentPrinter {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
if self.is_raw {
|
if self.is_raw {
|
||||||
f.write_str("r#")?;
|
f.write_str("r#")?;
|
||||||
} else {
|
} else if self.symbol == kw::DollarCrate {
|
||||||
if self.symbol == kw::DollarCrate {
|
if let Some(span) = self.convert_dollar_crate {
|
||||||
if let Some(span) = self.convert_dollar_crate {
|
let converted = span.ctxt().dollar_crate_name();
|
||||||
let converted = span.ctxt().dollar_crate_name();
|
if !converted.is_path_segment_keyword() {
|
||||||
if !converted.is_path_segment_keyword() {
|
f.write_str("::")?;
|
||||||
f.write_str("::")?;
|
|
||||||
}
|
|
||||||
return fmt::Display::fmt(&converted, f);
|
|
||||||
}
|
}
|
||||||
|
return fmt::Display::fmt(&converted, f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fmt::Display::fmt(&self.symbol, f)
|
fmt::Display::fmt(&self.symbol, f)
|
||||||
|
|
|
@ -1978,9 +1978,14 @@ fn const_str_ptr() {
|
||||||
const B: &'static [u8; 2] = &A;
|
const B: &'static [u8; 2] = &A;
|
||||||
const C: *const u8 = B as *const u8;
|
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;
|
let foo = &A as *const u8;
|
||||||
assert_eq!(foo, C);
|
assert_eq!(foo, C);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
assert_eq!(from_utf8_unchecked(&A), "hi");
|
assert_eq!(from_utf8_unchecked(&A), "hi");
|
||||||
assert_eq!(*C, A[0]);
|
assert_eq!(*C, A[0]);
|
||||||
assert_eq!(*(&B[0] as *const u8), A[0]);
|
assert_eq!(*(&B[0] as *const u8), A[0]);
|
||||||
|
|
|
@ -403,7 +403,7 @@ impl<'a> Arguments<'a> {
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// #![feature(fmt_as_str)]
|
/// #![feature(fmt_as_str)]
|
||||||
///
|
///
|
||||||
/// use core::fmt::Arguments;
|
/// use std::fmt::Arguments;
|
||||||
///
|
///
|
||||||
/// fn write_str(_: &str) { /* ... */ }
|
/// fn write_str(_: &str) { /* ... */ }
|
||||||
///
|
///
|
||||||
|
|
|
@ -21,7 +21,7 @@ pub struct Pending<T> {
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```no_run
|
/// ```no_run
|
||||||
/// use core::future;
|
/// use std::future;
|
||||||
///
|
///
|
||||||
/// # async fn run() {
|
/// # async fn run() {
|
||||||
/// let future = future::pending();
|
/// let future = future::pending();
|
||||||
|
|
|
@ -3,7 +3,7 @@ use crate::future::Future;
|
||||||
use crate::pin::Pin;
|
use crate::pin::Pin;
|
||||||
use crate::task::{Context, Poll};
|
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.
|
/// Polling the future delegates to the wrapped function.
|
||||||
///
|
///
|
||||||
|
@ -13,7 +13,7 @@ use crate::task::{Context, Poll};
|
||||||
/// #![feature(future_poll_fn)]
|
/// #![feature(future_poll_fn)]
|
||||||
/// # async fn run() {
|
/// # async fn run() {
|
||||||
/// use core::future::poll_fn;
|
/// use core::future::poll_fn;
|
||||||
/// use core::task::{Context, Poll};
|
/// use std::task::{Context, Poll};
|
||||||
///
|
///
|
||||||
/// fn read_line(_cx: &mut Context<'_>) -> Poll<String> {
|
/// fn read_line(_cx: &mut Context<'_>) -> Poll<String> {
|
||||||
/// Poll::Ready("Hello, World!".into())
|
/// Poll::Ready("Hello, World!".into())
|
||||||
|
@ -31,7 +31,7 @@ where
|
||||||
PollFn { f }
|
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
|
/// This `struct` is created by [`poll_fn()`]. See its
|
||||||
/// documentation for more.
|
/// documentation for more.
|
||||||
|
|
|
@ -33,7 +33,7 @@ impl<T> Future for Ready<T> {
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use core::future;
|
/// use std::future;
|
||||||
///
|
///
|
||||||
/// # async fn run() {
|
/// # async fn run() {
|
||||||
/// let a = future::ready(1);
|
/// let a = future::ready(1);
|
||||||
|
|
|
@ -189,7 +189,7 @@ impl<'a> Location<'a> {
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use core::panic::Location;
|
/// use std::panic::Location;
|
||||||
///
|
///
|
||||||
/// /// Returns the [`Location`] at which it is called.
|
/// /// Returns the [`Location`] at which it is called.
|
||||||
/// #[track_caller]
|
/// #[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
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// #![feature(ready_macro)]
|
/// #![feature(ready_macro)]
|
||||||
///
|
///
|
||||||
/// use core::task::{ready, Context, Poll};
|
/// use std::task::{ready, Context, Poll};
|
||||||
/// use core::future::{self, Future};
|
/// use std::future::{self, Future};
|
||||||
/// use core::pin::Pin;
|
/// use std::pin::Pin;
|
||||||
///
|
///
|
||||||
/// pub fn do_poll(cx: &mut Context<'_>) -> Poll<()> {
|
/// pub fn do_poll(cx: &mut Context<'_>) -> Poll<()> {
|
||||||
/// let mut fut = future::ready(42);
|
/// let mut fut = future::ready(42);
|
||||||
|
@ -28,9 +31,9 @@
|
||||||
/// ```
|
/// ```
|
||||||
/// # #![feature(ready_macro)]
|
/// # #![feature(ready_macro)]
|
||||||
/// #
|
/// #
|
||||||
/// # use core::task::{Context, Poll};
|
/// # use std::task::{Context, Poll};
|
||||||
/// # use core::future::{self, Future};
|
/// # use std::future::{self, Future};
|
||||||
/// # use core::pin::Pin;
|
/// # use std::pin::Pin;
|
||||||
/// #
|
/// #
|
||||||
/// # pub fn do_poll(cx: &mut Context<'_>) -> Poll<()> {
|
/// # pub fn do_poll(cx: &mut Context<'_>) -> Poll<()> {
|
||||||
/// # let mut fut = future::ready(42);
|
/// # let mut fut = future::ready(42);
|
||||||
|
|
|
@ -212,6 +212,7 @@
|
||||||
all(target_vendor = "fortanix", target_env = "sgx"),
|
all(target_vendor = "fortanix", target_env = "sgx"),
|
||||||
feature(slice_index_methods, coerce_unsized, sgx_platform)
|
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))]
|
#![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
|
// std is implemented with unstable features, many of which are internal
|
||||||
// compiler details that will never be stable
|
// 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:
|
/// words, they can't return `!` from every code path. As an example, this code doesn't compile:
|
||||||
///
|
///
|
||||||
/// ```compile_fail
|
/// ```compile_fail
|
||||||
/// use core::ops::Add;
|
/// use std::ops::Add;
|
||||||
///
|
///
|
||||||
/// fn foo() -> impl Add<u32> {
|
/// fn foo() -> impl Add<u32> {
|
||||||
/// unimplemented!()
|
/// unimplemented!()
|
||||||
|
@ -208,7 +208,7 @@ mod prim_bool {}
|
||||||
/// But this code does:
|
/// But this code does:
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use core::ops::Add;
|
/// use std::ops::Add;
|
||||||
///
|
///
|
||||||
/// fn foo() -> impl Add<u32> {
|
/// fn foo() -> impl Add<u32> {
|
||||||
/// if true {
|
/// if true {
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use std::env::*;
|
use std::env::*;
|
||||||
use std::ffi::{OsStr, OsString};
|
use std::ffi::{OsStr, OsString};
|
||||||
use std::path::PathBuf;
|
|
||||||
|
|
||||||
use rand::distributions::Alphanumeric;
|
use rand::distributions::Alphanumeric;
|
||||||
use rand::{thread_rng, Rng};
|
use rand::{thread_rng, Rng};
|
||||||
|
@ -92,6 +91,8 @@ fn env_home_dir() {
|
||||||
|
|
||||||
cfg_if::cfg_if! {
|
cfg_if::cfg_if! {
|
||||||
if #[cfg(unix)] {
|
if #[cfg(unix)] {
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
let oldhome = var_to_os_string(var("HOME"));
|
let oldhome = var_to_os_string(var("HOME"));
|
||||||
|
|
||||||
set_var("HOME", "/home/MountainView");
|
set_var("HOME", "/home/MountainView");
|
||||||
|
@ -109,6 +110,8 @@ fn env_home_dir() {
|
||||||
|
|
||||||
if let Some(oldhome) = oldhome { set_var("HOME", oldhome); }
|
if let Some(oldhome) = oldhome { set_var("HOME", oldhome); }
|
||||||
} else if #[cfg(windows)] {
|
} else if #[cfg(windows)] {
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
let oldhome = var_to_os_string(var("HOME"));
|
let oldhome = var_to_os_string(var("HOME"));
|
||||||
let olduserprofile = var_to_os_string(var("USERPROFILE"));
|
let olduserprofile = var_to_os_string(var("USERPROFILE"));
|
||||||
|
|
||||||
|
|
|
@ -1000,7 +1000,7 @@ impl<'tcx> Clean<FnDecl> for (DefId, ty::PolyFnSig<'tcx>) {
|
||||||
.iter()
|
.iter()
|
||||||
.map(|t| Argument {
|
.map(|t| Argument {
|
||||||
type_: t.clean(cx),
|
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(),
|
.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> {
|
fn clean(&self, cx: &DocContext<'_>) -> Vec<Item> {
|
||||||
use hir::ItemKind;
|
use hir::ItemKind;
|
||||||
|
|
||||||
let (item, renamed) = self;
|
let (item, renamed) = self;
|
||||||
let def_id = cx.tcx.hir().local_def_id(item.hir_id).to_def_id();
|
let def_id = cx.tcx.hir().local_def_id(item.hir_id).to_def_id();
|
||||||
let mut name = match renamed {
|
let mut name = renamed.unwrap_or_else(|| cx.tcx.hir().name(item.hir_id));
|
||||||
Some(ident) => ident.name,
|
|
||||||
None => cx.tcx.hir().name(item.hir_id),
|
|
||||||
};
|
|
||||||
cx.with_param_env(def_id, || {
|
cx.with_param_env(def_id, || {
|
||||||
let kind = match item.kind {
|
let kind = match item.kind {
|
||||||
ItemKind::Static(ty, mutability, body_id) => StaticItem(Static {
|
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 {
|
fn clean(&self, cx: &DocContext<'_>) -> Item {
|
||||||
let (item, renamed) = self;
|
let (item, renamed) = self;
|
||||||
cx.with_param_env(cx.tcx.hir().local_def_id(item.hir_id).to_def_id(), || {
|
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::from_hir_id_and_parts(
|
||||||
item.hir_id,
|
item.hir_id,
|
||||||
Some(renamed.unwrap_or(item.ident).name),
|
Some(renamed.unwrap_or(item.ident.name)),
|
||||||
kind,
|
kind,
|
||||||
cx,
|
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 {
|
fn clean(&self, cx: &DocContext<'_>) -> Item {
|
||||||
let (item, renamed) = self;
|
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<_>>();
|
let tts = item.ast.body.inner_tokens().trees().collect::<Vec<_>>();
|
||||||
// Extract the spans of all matchers. They represent the "interface" of the macro.
|
// 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<_>>();
|
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_interface::interface;
|
||||||
use rustc_middle::hir::map::Map;
|
use rustc_middle::hir::map::Map;
|
||||||
use rustc_middle::middle::cstore::CrateStore;
|
|
||||||
use rustc_middle::middle::privacy::AccessLevels;
|
use rustc_middle::middle::privacy::AccessLevels;
|
||||||
use rustc_middle::ty::{ParamEnv, Ty, TyCtxt};
|
use rustc_middle::ty::{ParamEnv, Ty, TyCtxt};
|
||||||
use rustc_resolve as resolve;
|
use rustc_resolve as resolve;
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
crate use self::StructType::*;
|
crate use self::StructType::*;
|
||||||
|
|
||||||
use rustc_ast as ast;
|
use rustc_ast as ast;
|
||||||
use rustc_span::{self, symbol::Ident, Span, Symbol};
|
use rustc_span::{self, Span, Symbol};
|
||||||
|
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
|
|
||||||
|
@ -16,9 +16,9 @@ crate struct Module<'hir> {
|
||||||
crate mods: Vec<Module<'hir>>,
|
crate mods: Vec<Module<'hir>>,
|
||||||
crate id: hir::HirId,
|
crate id: hir::HirId,
|
||||||
// (item, renamed)
|
// (item, renamed)
|
||||||
crate items: Vec<(&'hir hir::Item<'hir>, Option<Ident>)>,
|
crate items: Vec<(&'hir hir::Item<'hir>, Option<Symbol>)>,
|
||||||
crate foreigns: Vec<(&'hir hir::ForeignItem<'hir>, Option<Ident>)>,
|
crate foreigns: Vec<(&'hir hir::ForeignItem<'hir>, Option<Symbol>)>,
|
||||||
crate macros: Vec<(&'hir hir::MacroDef<'hir>, Option<Ident>)>,
|
crate macros: Vec<(&'hir hir::MacroDef<'hir>, Option<Symbol>)>,
|
||||||
crate is_crate: bool,
|
crate is_crate: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,13 +14,13 @@ use crate::config::RenderInfo;
|
||||||
use crate::fold::DocFolder;
|
use crate::fold::DocFolder;
|
||||||
use crate::formats::item_type::ItemType;
|
use crate::formats::item_type::ItemType;
|
||||||
use crate::formats::Impl;
|
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::cache::{extern_location, get_index_search_type, ExternalLocation};
|
||||||
use crate::html::render::IndexItem;
|
use crate::html::render::IndexItem;
|
||||||
use crate::html::render::{plain_text_summary, shorten};
|
|
||||||
|
|
||||||
thread_local!(crate static CACHE_KEY: RefCell<Arc<Cache>> = Default::default());
|
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
|
/// rendered in order to provide more useful documentation. This contains
|
||||||
/// information like all implementors of a trait, all traits a type implements,
|
/// information like all implementors of a trait, all traits a type implements,
|
||||||
/// documentation for all known traits, etc.
|
/// documentation for all known traits, etc.
|
||||||
|
@ -313,7 +313,9 @@ impl DocFolder for Cache {
|
||||||
ty: item.type_(),
|
ty: item.type_(),
|
||||||
name: s.to_string(),
|
name: s.to_string(),
|
||||||
path: path.join("::"),
|
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,
|
||||||
parent_idx: None,
|
parent_idx: None,
|
||||||
search_type: get_index_search_type(&item),
|
search_type: get_index_search_type(&item),
|
||||||
|
|
|
@ -17,8 +17,6 @@
|
||||||
//! // ... something using html
|
//! // ... something using html
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
#![allow(non_camel_case_types)]
|
|
||||||
|
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_hir::HirId;
|
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.
|
/// Renders the first paragraph of the provided markdown as plain text.
|
||||||
|
/// Useful for alt-text.
|
||||||
///
|
///
|
||||||
/// - Headings, links, and formatting are stripped.
|
/// - Headings, links, and formatting are stripped.
|
||||||
/// - Inline code is rendered as-is, surrounded by backticks.
|
/// - 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 super::{ErrorCodes, IdMap, Ignore, LangString, Markdown, MarkdownHtml};
|
||||||
use rustc_span::edition::{Edition, DEFAULT_EDITION};
|
use rustc_span::edition::{Edition, DEFAULT_EDITION};
|
||||||
use std::cell::RefCell;
|
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]
|
#[test]
|
||||||
fn test_plain_text_summary() {
|
fn test_plain_text_summary() {
|
||||||
fn t(input: &str, expect: &str) {
|
fn t(input: &str, expect: &str) {
|
||||||
|
@ -224,6 +251,10 @@ fn test_plain_text_summary() {
|
||||||
t("first paragraph\n\nsecond paragraph", "first paragraph");
|
t("first paragraph\n\nsecond paragraph", "first paragraph");
|
||||||
t("```\nfn main() {}\n```", "");
|
t("```\nfn main() {}\n```", "");
|
||||||
t("<div>hello</div>", "");
|
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]
|
#[test]
|
||||||
|
|
|
@ -9,7 +9,7 @@ use crate::clean::types::GetDefId;
|
||||||
use crate::clean::{self, AttributesExt};
|
use crate::clean::{self, AttributesExt};
|
||||||
use crate::formats::cache::Cache;
|
use crate::formats::cache::Cache;
|
||||||
use crate::formats::item_type::ItemType;
|
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};
|
use crate::html::render::{Generic, IndexItem, IndexItemFunctionType, RenderType, TypeWithKind};
|
||||||
|
|
||||||
/// Indicates where an external crate can be found.
|
/// 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_(),
|
ty: item.type_(),
|
||||||
name: item.name.clone().unwrap(),
|
name: item.name.clone().unwrap(),
|
||||||
path: fqp[..fqp.len() - 1].join("::"),
|
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: Some(did),
|
||||||
parent_idx: None,
|
parent_idx: None,
|
||||||
search_type: get_index_search_type(&item),
|
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
|
let crate_doc = krate
|
||||||
.module
|
.module
|
||||||
.as_ref()
|
.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();
|
.unwrap_or_default();
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
|
|
|
@ -76,7 +76,9 @@ use crate::html::format::fmt_impl_for_trait_page;
|
||||||
use crate::html::format::Function;
|
use crate::html::format::Function;
|
||||||
use crate::html::format::{href, print_default_space, print_generic_bounds, WhereClause};
|
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::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::sources;
|
||||||
use crate::html::{highlight, layout, static_files};
|
use crate::html::{highlight, layout, static_files};
|
||||||
use cache::{build_index, ExternalLocation};
|
use cache::{build_index, ExternalLocation};
|
||||||
|
@ -1604,9 +1606,10 @@ impl Context {
|
||||||
Some(ref s) => s.to_string(),
|
Some(ref s) => s.to_string(),
|
||||||
};
|
};
|
||||||
let short = short.to_string();
|
let short = short.to_string();
|
||||||
map.entry(short)
|
map.entry(short).or_default().push((
|
||||||
.or_default()
|
myname,
|
||||||
.push((myname, Some(plain_text_summary(item.doc_value()))));
|
Some(item.doc_value().map_or_else(|| String::new(), plain_text_summary)),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.shared.sort_modules_alphabetically {
|
if self.shared.sort_modules_alphabetically {
|
||||||
|
@ -1810,36 +1813,6 @@ fn full_path(cx: &Context, item: &clean::Item) -> String {
|
||||||
s
|
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>) {
|
fn document(w: &mut Buffer, cx: &Context, item: &clean::Item, parent: Option<&clean::Item>) {
|
||||||
if let Some(ref name) = item.name {
|
if let Some(ref name) = item.name {
|
||||||
info!("Documenting {}", name);
|
info!("Documenting {}", name);
|
||||||
|
|
|
@ -1611,7 +1611,7 @@ function defocusSearchBar() {
|
||||||
item.displayPath + "<span class=\"" + type + "\">" +
|
item.displayPath + "<span class=\"" + type + "\">" +
|
||||||
name + "</span></a></td><td>" +
|
name + "</span></a></td><td>" +
|
||||||
"<a href=\"" + item.href + "\">" +
|
"<a href=\"" + item.href + "\">" +
|
||||||
"<span class=\"desc\">" + escape(item.desc) +
|
"<span class=\"desc\">" + item.desc +
|
||||||
" </span></a></td></tr>";
|
" </span></a></td></tr>";
|
||||||
});
|
});
|
||||||
output += "</table>";
|
output += "</table>";
|
||||||
|
@ -2013,7 +2013,9 @@ function defocusSearchBar() {
|
||||||
}
|
}
|
||||||
var link = document.createElement("a");
|
var link = document.createElement("a");
|
||||||
link.href = rootPath + crates[i] + "/index.html";
|
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.className = klass;
|
||||||
link.textContent = crates[i];
|
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.
|
// delayed sidebar rendering.
|
||||||
window.initSidebarItems = function(items) {
|
window.initSidebarItems = function(items) {
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#![feature(never_type)]
|
#![feature(never_type)]
|
||||||
#![feature(once_cell)]
|
#![feature(once_cell)]
|
||||||
#![feature(type_ascription)]
|
#![feature(type_ascription)]
|
||||||
|
#![feature(split_inclusive)]
|
||||||
#![recursion_limit = "256"]
|
#![recursion_limit = "256"]
|
||||||
|
|
||||||
#[macro_use]
|
#[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
|
// FIXME(jynelson): this shouldn't go through stringification, rustdoc should just use the DefId directly
|
||||||
let self_name = self_id.and_then(|self_id| {
|
let self_name = self_id.and_then(|self_id| {
|
||||||
|
use ty::TyKind;
|
||||||
if matches!(self.cx.tcx.def_kind(self_id), DefKind::Impl) {
|
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 ty = self.cx.tcx.type_of(self_id);
|
||||||
let name = ty::print::with_crate_prefix(|| ty.to_string());
|
let name = match ty.kind() {
|
||||||
debug!("using type_of(): {}", name);
|
TyKind::Adt(def, _) => Some(self.cx.tcx.item_name(def.did).to_string()),
|
||||||
Some(name)
|
other if other.is_primitive() => Some(ty.to_string()),
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
debug!("using type_of(): {:?}", name);
|
||||||
|
name
|
||||||
} else {
|
} else {
|
||||||
let name = self.cx.tcx.opt_item_name(self_id).map(|sym| sym.to_string());
|
let name = self.cx.tcx.opt_item_name(self_id).map(|sym| sym.to_string());
|
||||||
debug!("using item_name(): {:?}", name);
|
debug!("using item_name(): {:?}", name);
|
||||||
|
|
|
@ -10,7 +10,7 @@ use rustc_hir::Node;
|
||||||
use rustc_middle::middle::privacy::AccessLevel;
|
use rustc_middle::middle::privacy::AccessLevel;
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
use rustc_span::source_map::Spanned;
|
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 rustc_span::{self, Span};
|
||||||
|
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
@ -116,7 +116,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
||||||
&mut self,
|
&mut self,
|
||||||
id: hir::HirId,
|
id: hir::HirId,
|
||||||
res: Res,
|
res: Res,
|
||||||
renamed: Option<Ident>,
|
renamed: Option<Symbol>,
|
||||||
glob: bool,
|
glob: bool,
|
||||||
om: &mut Module<'tcx>,
|
om: &mut Module<'tcx>,
|
||||||
please_inline: bool,
|
please_inline: bool,
|
||||||
|
@ -226,11 +226,11 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
||||||
fn visit_item(
|
fn visit_item(
|
||||||
&mut self,
|
&mut self,
|
||||||
item: &'tcx hir::Item<'_>,
|
item: &'tcx hir::Item<'_>,
|
||||||
renamed: Option<Ident>,
|
renamed: Option<Symbol>,
|
||||||
om: &mut Module<'tcx>,
|
om: &mut Module<'tcx>,
|
||||||
) {
|
) {
|
||||||
debug!("visiting item {:?}", item);
|
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() {
|
if item.vis.node.is_pub() {
|
||||||
let def_id = self.cx.tcx.hir().local_def_id(item.hir_id);
|
let def_id = self.cx.tcx.hir().local_def_id(item.hir_id);
|
||||||
|
@ -266,7 +266,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
_ => false,
|
_ => false,
|
||||||
});
|
});
|
||||||
let ident = if is_glob { None } else { Some(ident) };
|
let ident = if is_glob { None } else { Some(name) };
|
||||||
if self.maybe_inline_local(
|
if self.maybe_inline_local(
|
||||||
item.hir_id,
|
item.hir_id,
|
||||||
path.res,
|
path.res,
|
||||||
|
@ -280,7 +280,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
om.imports.push(Import {
|
om.imports.push(Import {
|
||||||
name: ident.name,
|
name,
|
||||||
id: item.hir_id,
|
id: item.hir_id,
|
||||||
vis: &item.vis,
|
vis: &item.vis,
|
||||||
attrs: &item.attrs,
|
attrs: &item.attrs,
|
||||||
|
@ -296,7 +296,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
||||||
&item.vis,
|
&item.vis,
|
||||||
item.hir_id,
|
item.hir_id,
|
||||||
m,
|
m,
|
||||||
Some(ident.name),
|
Some(name),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
hir::ItemKind::Fn(..)
|
hir::ItemKind::Fn(..)
|
||||||
|
@ -312,7 +312,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
||||||
hir::ItemKind::Const(..) => {
|
hir::ItemKind::Const(..) => {
|
||||||
// Underscore constants do not correspond to a nameable item and
|
// Underscore constants do not correspond to a nameable item and
|
||||||
// so are never useful in documentation.
|
// so are never useful in documentation.
|
||||||
if ident.name != kw::Underscore {
|
if name != kw::Underscore {
|
||||||
om.items.push((item, renamed));
|
om.items.push((item, renamed));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -329,7 +329,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
||||||
fn visit_foreign_item(
|
fn visit_foreign_item(
|
||||||
&mut self,
|
&mut self,
|
||||||
item: &'tcx hir::ForeignItem<'_>,
|
item: &'tcx hir::ForeignItem<'_>,
|
||||||
renamed: Option<Ident>,
|
renamed: Option<Symbol>,
|
||||||
om: &mut Module<'tcx>,
|
om: &mut Module<'tcx>,
|
||||||
) {
|
) {
|
||||||
// If inlining we only want to include public functions.
|
// If inlining we only want to include public functions.
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
/// Foo
|
/// Docs for Foo
|
||||||
pub struct 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_type = "lib"]
|
||||||
#![crate_name = "summaries"]
|
#![crate_name = "summaries"]
|
||||||
|
|
||||||
//! This summary has a [link] and `code`.
|
//! This *summary* has a [link] and `code`.
|
||||||
//!
|
//!
|
||||||
//! This is the second paragraph.
|
//! This is the second paragraph.
|
||||||
//!
|
//!
|
||||||
//! [link]: https://example.com
|
//! [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'
|
// @!has - 'second paragraph'
|
||||||
|
|
||||||
/// This `code` should be in backticks.
|
/// This `code` will be rendered in a code tag.
|
||||||
///
|
///
|
||||||
/// This text should not be rendered.
|
/// This text should not be rendered.
|
||||||
pub struct Sidebar;
|
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'
|
// @!has - 'text should not be rendered'
|
||||||
|
|
||||||
/// ```text
|
/// ```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