Auto merge of #54660 - kennytm:rollup, r=kennytm
Rollup of 8 pull requests Successful merges: - #54564 (Add 1.29.1 release notes) - #54567 (Include path in stamp hash for debuginfo tests) - #54577 (rustdoc: give proc-macros their own pages) - #54590 (std: Don't let `rust_panic` get inlined) - #54598 (Remove useless lifetimes from `Pin` `impl`s.) - #54604 (Added help message for `self_in_typedefs` feature gate) - #54635 (Improve docs for std::io::Seek) - #54645 (Compute Android gdb version in compiletest)
This commit is contained in:
commit
9653f79033
13
RELEASES.md
13
RELEASES.md
@ -1,3 +1,16 @@
|
|||||||
|
Version 1.29.1 (2018-09-25)
|
||||||
|
===========================
|
||||||
|
|
||||||
|
Security Notes
|
||||||
|
--------------
|
||||||
|
|
||||||
|
- The standard library's `str::repeat` function contained an out of bounds write
|
||||||
|
caused by an integer overflow. This has been fixed by deterministically
|
||||||
|
panicking when an overflow happens.
|
||||||
|
|
||||||
|
Thank you to Scott McMurray for responsibily disclosing this vulnerability to
|
||||||
|
us.
|
||||||
|
|
||||||
Version 1.29.0 (2018-09-13)
|
Version 1.29.0 (2018-09-13)
|
||||||
==========================
|
==========================
|
||||||
|
|
||||||
|
@ -293,21 +293,21 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[unstable(feature = "pin", issue = "49150")]
|
#[unstable(feature = "pin", issue = "49150")]
|
||||||
impl<'a, P: fmt::Debug> fmt::Debug for Pin<P> {
|
impl<P: fmt::Debug> fmt::Debug for Pin<P> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
fmt::Debug::fmt(&self.pointer, f)
|
fmt::Debug::fmt(&self.pointer, f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unstable(feature = "pin", issue = "49150")]
|
#[unstable(feature = "pin", issue = "49150")]
|
||||||
impl<'a, P: fmt::Display> fmt::Display for Pin<P> {
|
impl<P: fmt::Display> fmt::Display for Pin<P> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
fmt::Display::fmt(&self.pointer, f)
|
fmt::Display::fmt(&self.pointer, f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unstable(feature = "pin", issue = "49150")]
|
#[unstable(feature = "pin", issue = "49150")]
|
||||||
impl<'a, P: fmt::Pointer> fmt::Pointer for Pin<P> {
|
impl<P: fmt::Pointer> fmt::Pointer for Pin<P> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
fmt::Pointer::fmt(&self.pointer, f)
|
fmt::Pointer::fmt(&self.pointer, f)
|
||||||
}
|
}
|
||||||
@ -319,10 +319,10 @@ impl<'a, P: fmt::Pointer> fmt::Pointer for Pin<P> {
|
|||||||
// for other reasons, though, so we just need to take care not to allow such
|
// for other reasons, though, so we just need to take care not to allow such
|
||||||
// impls to land in std.
|
// impls to land in std.
|
||||||
#[unstable(feature = "pin", issue = "49150")]
|
#[unstable(feature = "pin", issue = "49150")]
|
||||||
impl<'a, P, U> CoerceUnsized<Pin<U>> for Pin<P>
|
impl<P, U> CoerceUnsized<Pin<U>> for Pin<P>
|
||||||
where
|
where
|
||||||
P: CoerceUnsized<U>,
|
P: CoerceUnsized<U>,
|
||||||
{}
|
{}
|
||||||
|
|
||||||
#[unstable(feature = "pin", issue = "49150")]
|
#[unstable(feature = "pin", issue = "49150")]
|
||||||
impl<'a, P> Unpin for Pin<P> {}
|
impl<P> Unpin for Pin<P> {}
|
||||||
|
@ -539,7 +539,7 @@ fn check_legality_of_move_bindings(cx: &MatchVisitor,
|
|||||||
.emit();
|
.emit();
|
||||||
} else if has_guard && !cx.tcx.allow_bind_by_move_patterns_with_guards() {
|
} else if has_guard && !cx.tcx.allow_bind_by_move_patterns_with_guards() {
|
||||||
let mut err = struct_span_err!(cx.tcx.sess, p.span, E0008,
|
let mut err = struct_span_err!(cx.tcx.sess, p.span, E0008,
|
||||||
"cannot bind by-move into a pattern guard");
|
"cannot bind by-move into a pattern guard");
|
||||||
err.span_label(p.span, "moves value into pattern guard");
|
err.span_label(p.span, "moves value into pattern guard");
|
||||||
if cx.tcx.sess.opts.unstable_features.is_nightly_build() && cx.tcx.use_mir_borrowck() {
|
if cx.tcx.sess.opts.unstable_features.is_nightly_build() && cx.tcx.use_mir_borrowck() {
|
||||||
err.help("add #![feature(bind_by_move_pattern_guards)] to the \
|
err.help("add #![feature(bind_by_move_pattern_guards)] to the \
|
||||||
|
@ -42,8 +42,9 @@ use rustc::lint;
|
|||||||
use rustc::hir::def::*;
|
use rustc::hir::def::*;
|
||||||
use rustc::hir::def::Namespace::*;
|
use rustc::hir::def::Namespace::*;
|
||||||
use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, DefId};
|
use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, DefId};
|
||||||
use rustc::ty;
|
|
||||||
use rustc::hir::{Freevar, FreevarMap, TraitCandidate, TraitMap, GlobMap};
|
use rustc::hir::{Freevar, FreevarMap, TraitCandidate, TraitMap, GlobMap};
|
||||||
|
use rustc::session::config::nightly_options;
|
||||||
|
use rustc::ty;
|
||||||
use rustc::util::nodemap::{NodeMap, NodeSet, FxHashMap, FxHashSet, DefIdMap};
|
use rustc::util::nodemap::{NodeMap, NodeSet, FxHashMap, FxHashSet, DefIdMap};
|
||||||
|
|
||||||
use rustc_metadata::creader::CrateLoader;
|
use rustc_metadata::creader::CrateLoader;
|
||||||
@ -1381,6 +1382,9 @@ pub struct Resolver<'a, 'b: 'a> {
|
|||||||
/// The current self type if inside an impl (used for better errors).
|
/// The current self type if inside an impl (used for better errors).
|
||||||
current_self_type: Option<Ty>,
|
current_self_type: Option<Ty>,
|
||||||
|
|
||||||
|
/// The current self item if inside an ADT (used for better errors).
|
||||||
|
current_self_item: Option<NodeId>,
|
||||||
|
|
||||||
/// The idents for the primitive types.
|
/// The idents for the primitive types.
|
||||||
primitive_type_table: PrimitiveTypeTable,
|
primitive_type_table: PrimitiveTypeTable,
|
||||||
|
|
||||||
@ -1710,6 +1714,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
|||||||
|
|
||||||
current_trait_ref: None,
|
current_trait_ref: None,
|
||||||
current_self_type: None,
|
current_self_type: None,
|
||||||
|
current_self_item: None,
|
||||||
|
|
||||||
primitive_type_table: PrimitiveTypeTable::new(),
|
primitive_type_table: PrimitiveTypeTable::new(),
|
||||||
|
|
||||||
@ -2186,15 +2191,17 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_adt(&mut self, item: &Item, generics: &Generics) {
|
fn resolve_adt(&mut self, item: &Item, generics: &Generics) {
|
||||||
self.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind), |this| {
|
self.with_current_self_item(item, |this| {
|
||||||
let item_def_id = this.definitions.local_def_id(item.id);
|
this.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind), |this| {
|
||||||
if this.session.features_untracked().self_in_typedefs {
|
let item_def_id = this.definitions.local_def_id(item.id);
|
||||||
this.with_self_rib(Def::SelfTy(None, Some(item_def_id)), |this| {
|
if this.session.features_untracked().self_in_typedefs {
|
||||||
|
this.with_self_rib(Def::SelfTy(None, Some(item_def_id)), |this| {
|
||||||
|
visit::walk_item(this, item);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
visit::walk_item(this, item);
|
visit::walk_item(this, item);
|
||||||
});
|
}
|
||||||
} else {
|
});
|
||||||
visit::walk_item(this, item);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2435,6 +2442,15 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
|||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn with_current_self_item<T, F>(&mut self, self_item: &Item, f: F) -> T
|
||||||
|
where F: FnOnce(&mut Resolver) -> T
|
||||||
|
{
|
||||||
|
let previous_value = replace(&mut self.current_self_item, Some(self_item.id));
|
||||||
|
let result = f(self);
|
||||||
|
self.current_self_item = previous_value;
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
/// This is called to resolve a trait reference from an `impl` (i.e. `impl Trait for Foo`)
|
/// This is called to resolve a trait reference from an `impl` (i.e. `impl Trait for Foo`)
|
||||||
fn with_optional_trait_ref<T, F>(&mut self, opt_trait_ref: Option<&TraitRef>, f: F) -> T
|
fn with_optional_trait_ref<T, F>(&mut self, opt_trait_ref: Option<&TraitRef>, f: F) -> T
|
||||||
where F: FnOnce(&mut Resolver, Option<DefId>) -> T
|
where F: FnOnce(&mut Resolver, Option<DefId>) -> T
|
||||||
@ -3004,6 +3020,10 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
|||||||
"traits and impls"
|
"traits and impls"
|
||||||
};
|
};
|
||||||
err.span_label(span, format!("`Self` is only available in {}", available_in));
|
err.span_label(span, format!("`Self` is only available in {}", available_in));
|
||||||
|
if this.current_self_item.is_some() && nightly_options::is_nightly_build() {
|
||||||
|
err.help("add #![feature(self_in_typedefs)] to the crate attributes \
|
||||||
|
to enable");
|
||||||
|
}
|
||||||
return (err, Vec::new());
|
return (err, Vec::new());
|
||||||
}
|
}
|
||||||
if is_self_value(path, ns) {
|
if is_self_value(path, ns) {
|
||||||
|
@ -17,6 +17,9 @@ use check::FnCtxt;
|
|||||||
use hir::def_id::DefId;
|
use hir::def_id::DefId;
|
||||||
use hir::def::Def;
|
use hir::def::Def;
|
||||||
use namespace::Namespace;
|
use namespace::Namespace;
|
||||||
|
use rustc::hir;
|
||||||
|
use rustc::lint;
|
||||||
|
use rustc::session::config::nightly_options;
|
||||||
use rustc::ty::subst::{Subst, Substs};
|
use rustc::ty::subst::{Subst, Substs};
|
||||||
use rustc::traits::{self, ObligationCause};
|
use rustc::traits::{self, ObligationCause};
|
||||||
use rustc::ty::{self, Ty, ToPolyTraitRef, ToPredicate, TraitRef, TypeFoldable};
|
use rustc::ty::{self, Ty, ToPolyTraitRef, ToPredicate, TraitRef, TypeFoldable};
|
||||||
@ -28,8 +31,6 @@ use rustc::middle::stability;
|
|||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
use syntax::util::lev_distance::{lev_distance, find_best_match_for_name};
|
use syntax::util::lev_distance::{lev_distance, find_best_match_for_name};
|
||||||
use syntax_pos::{Span, symbol::Symbol};
|
use syntax_pos::{Span, symbol::Symbol};
|
||||||
use rustc::hir;
|
|
||||||
use rustc::lint;
|
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
@ -1073,9 +1074,9 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
|||||||
self.tcx.item_path_str(stable_pick.item.def_id),
|
self.tcx.item_path_str(stable_pick.item.def_id),
|
||||||
));
|
));
|
||||||
|
|
||||||
if ::rustc::session::config::nightly_options::is_nightly_build() {
|
if nightly_options::is_nightly_build() {
|
||||||
for (candidate, feature) in unstable_candidates {
|
for (candidate, feature) in unstable_candidates {
|
||||||
diag.note(&format!(
|
diag.help(&format!(
|
||||||
"add #![feature({})] to the crate attributes to enable `{}`",
|
"add #![feature({})] to the crate attributes to enable `{}`",
|
||||||
feature,
|
feature,
|
||||||
self.tcx.item_path_str(candidate.item.def_id),
|
self.tcx.item_path_str(candidate.item.def_id),
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
use std::iter::once;
|
use std::iter::once;
|
||||||
|
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
use syntax::ext::base::MacroKind;
|
use syntax::ext::base::{MacroKind, SyntaxExtension};
|
||||||
use syntax_pos::Span;
|
use syntax_pos::Span;
|
||||||
|
|
||||||
use rustc::hir;
|
use rustc::hir;
|
||||||
@ -105,12 +105,12 @@ pub fn try_inline(cx: &DocContext, def: Def, name: ast::Name, visited: &mut FxHa
|
|||||||
record_extern_fqn(cx, did, clean::TypeKind::Const);
|
record_extern_fqn(cx, did, clean::TypeKind::Const);
|
||||||
clean::ConstantItem(build_const(cx, did))
|
clean::ConstantItem(build_const(cx, did))
|
||||||
}
|
}
|
||||||
// FIXME(misdreavus): if attributes/derives come down here we should probably document them
|
// FIXME: proc-macros don't propagate attributes or spans across crates, so they look empty
|
||||||
// separately
|
|
||||||
Def::Macro(did, MacroKind::Bang) => {
|
Def::Macro(did, MacroKind::Bang) => {
|
||||||
record_extern_fqn(cx, did, clean::TypeKind::Macro);
|
let mac = build_macro(cx, did, name);
|
||||||
if let Some(mac) = build_macro(cx, did, name) {
|
if let clean::MacroItem(..) = mac {
|
||||||
clean::MacroItem(mac)
|
record_extern_fqn(cx, did, clean::TypeKind::Macro);
|
||||||
|
mac
|
||||||
} else {
|
} else {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
@ -442,31 +442,41 @@ fn build_static(cx: &DocContext, did: DefId, mutable: bool) -> clean::Static {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_macro(cx: &DocContext, did: DefId, name: ast::Name) -> Option<clean::Macro> {
|
fn build_macro(cx: &DocContext, did: DefId, name: ast::Name) -> clean::ItemEnum {
|
||||||
let imported_from = cx.tcx.original_crate_name(did.krate);
|
let imported_from = cx.tcx.original_crate_name(did.krate);
|
||||||
let def = match cx.cstore.load_macro_untracked(did, cx.sess()) {
|
match cx.cstore.load_macro_untracked(did, cx.sess()) {
|
||||||
LoadedMacro::MacroDef(macro_def) => macro_def,
|
LoadedMacro::MacroDef(def) => {
|
||||||
// FIXME(jseyfried): document proc macro re-exports
|
let matchers: hir::HirVec<Span> = if let ast::ItemKind::MacroDef(ref def) = def.node {
|
||||||
LoadedMacro::ProcMacro(..) => return None,
|
let tts: Vec<_> = def.stream().into_trees().collect();
|
||||||
};
|
tts.chunks(4).map(|arm| arm[0].span()).collect()
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
};
|
||||||
|
|
||||||
let matchers: hir::HirVec<Span> = if let ast::ItemKind::MacroDef(ref def) = def.node {
|
let source = format!("macro_rules! {} {{\n{}}}",
|
||||||
let tts: Vec<_> = def.stream().into_trees().collect();
|
name.clean(cx),
|
||||||
tts.chunks(4).map(|arm| arm[0].span()).collect()
|
matchers.iter().map(|span| {
|
||||||
} else {
|
format!(" {} => {{ ... }};\n", span.to_src(cx))
|
||||||
unreachable!()
|
}).collect::<String>());
|
||||||
};
|
|
||||||
|
|
||||||
let source = format!("macro_rules! {} {{\n{}}}",
|
clean::MacroItem(clean::Macro {
|
||||||
name.clean(cx),
|
source,
|
||||||
matchers.iter().map(|span| {
|
imported_from: Some(imported_from).clean(cx),
|
||||||
format!(" {} => {{ ... }};\n", span.to_src(cx))
|
})
|
||||||
}).collect::<String>());
|
}
|
||||||
|
LoadedMacro::ProcMacro(ext) => {
|
||||||
|
let helpers = match &*ext {
|
||||||
|
&SyntaxExtension::ProcMacroDerive(_, ref syms, ..) => { syms.clean(cx) }
|
||||||
|
_ => Vec::new(),
|
||||||
|
};
|
||||||
|
|
||||||
|
clean::ProcMacroItem(clean::ProcMacro {
|
||||||
|
kind: ext.kind(),
|
||||||
|
helpers,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Some(clean::Macro {
|
|
||||||
source,
|
|
||||||
imported_from: Some(imported_from).clean(cx),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A trait's generics clause actually contains all of the predicates for all of
|
/// A trait's generics clause actually contains all of the predicates for all of
|
||||||
|
@ -21,6 +21,7 @@ pub use self::Visibility::{Public, Inherited};
|
|||||||
use rustc_target::spec::abi::Abi;
|
use rustc_target::spec::abi::Abi;
|
||||||
use syntax::ast::{self, AttrStyle, Ident};
|
use syntax::ast::{self, AttrStyle, Ident};
|
||||||
use syntax::attr;
|
use syntax::attr;
|
||||||
|
use syntax::ext::base::MacroKind;
|
||||||
use syntax::source_map::{dummy_spanned, Spanned};
|
use syntax::source_map::{dummy_spanned, Spanned};
|
||||||
use syntax::ptr::P;
|
use syntax::ptr::P;
|
||||||
use syntax::symbol::keywords::{self, Keyword};
|
use syntax::symbol::keywords::{self, Keyword};
|
||||||
@ -527,6 +528,7 @@ pub enum ItemEnum {
|
|||||||
/// `type`s from an extern block
|
/// `type`s from an extern block
|
||||||
ForeignTypeItem,
|
ForeignTypeItem,
|
||||||
MacroItem(Macro),
|
MacroItem(Macro),
|
||||||
|
ProcMacroItem(ProcMacro),
|
||||||
PrimitiveItem(PrimitiveType),
|
PrimitiveItem(PrimitiveType),
|
||||||
AssociatedConstItem(Type, Option<String>),
|
AssociatedConstItem(Type, Option<String>),
|
||||||
AssociatedTypeItem(Vec<GenericBound>, Option<Type>),
|
AssociatedTypeItem(Vec<GenericBound>, Option<Type>),
|
||||||
@ -588,6 +590,7 @@ impl Clean<Item> for doctree::Module {
|
|||||||
items.extend(self.traits.iter().map(|x| x.clean(cx)));
|
items.extend(self.traits.iter().map(|x| x.clean(cx)));
|
||||||
items.extend(self.impls.iter().flat_map(|x| x.clean(cx)));
|
items.extend(self.impls.iter().flat_map(|x| x.clean(cx)));
|
||||||
items.extend(self.macros.iter().map(|x| x.clean(cx)));
|
items.extend(self.macros.iter().map(|x| x.clean(cx)));
|
||||||
|
items.extend(self.proc_macros.iter().map(|x| x.clean(cx)));
|
||||||
|
|
||||||
// determine if we should display the inner contents or
|
// determine if we should display the inner contents or
|
||||||
// the outer `mod` item for the source code.
|
// the outer `mod` item for the source code.
|
||||||
@ -2191,6 +2194,8 @@ pub enum TypeKind {
|
|||||||
Typedef,
|
Typedef,
|
||||||
Foreign,
|
Foreign,
|
||||||
Macro,
|
Macro,
|
||||||
|
Attr,
|
||||||
|
Derive,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait GetDefId {
|
pub trait GetDefId {
|
||||||
@ -3727,7 +3732,12 @@ pub fn register_def(cx: &DocContext, def: Def) -> DefId {
|
|||||||
Def::Static(i, _) => (i, TypeKind::Static),
|
Def::Static(i, _) => (i, TypeKind::Static),
|
||||||
Def::Variant(i) => (cx.tcx.parent_def_id(i).expect("cannot get parent def id"),
|
Def::Variant(i) => (cx.tcx.parent_def_id(i).expect("cannot get parent def id"),
|
||||||
TypeKind::Enum),
|
TypeKind::Enum),
|
||||||
Def::Macro(i, _) => (i, TypeKind::Macro),
|
Def::Macro(i, mac_kind) => match mac_kind {
|
||||||
|
MacroKind::Bang => (i, TypeKind::Macro),
|
||||||
|
MacroKind::Attr => (i, TypeKind::Attr),
|
||||||
|
MacroKind::Derive => (i, TypeKind::Derive),
|
||||||
|
MacroKind::ProcMacroStub => unreachable!(),
|
||||||
|
},
|
||||||
Def::SelfTy(Some(def_id), _) => (def_id, TypeKind::Trait),
|
Def::SelfTy(Some(def_id), _) => (def_id, TypeKind::Trait),
|
||||||
Def::SelfTy(_, Some(impl_def_id)) => {
|
Def::SelfTy(_, Some(impl_def_id)) => {
|
||||||
return impl_def_id
|
return impl_def_id
|
||||||
@ -3782,6 +3792,30 @@ impl Clean<Item> for doctree::Macro {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||||
|
pub struct ProcMacro {
|
||||||
|
pub kind: MacroKind,
|
||||||
|
pub helpers: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Clean<Item> for doctree::ProcMacro {
|
||||||
|
fn clean(&self, cx: &DocContext) -> Item {
|
||||||
|
Item {
|
||||||
|
name: Some(self.name.clean(cx)),
|
||||||
|
attrs: self.attrs.clean(cx),
|
||||||
|
source: self.whence.clean(cx),
|
||||||
|
visibility: Some(Public),
|
||||||
|
stability: self.stab.clean(cx),
|
||||||
|
deprecation: self.depr.clean(cx),
|
||||||
|
def_id: cx.tcx.hir.local_def_id(self.id),
|
||||||
|
inner: ProcMacroItem(ProcMacro {
|
||||||
|
kind: self.kind,
|
||||||
|
helpers: self.helpers.clean(cx),
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||||
pub struct Stability {
|
pub struct Stability {
|
||||||
pub level: stability::StabilityLevel,
|
pub level: stability::StabilityLevel,
|
||||||
|
@ -15,6 +15,7 @@ pub use self::StructType::*;
|
|||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
use syntax::ast::{Name, NodeId};
|
use syntax::ast::{Name, NodeId};
|
||||||
use syntax::attr;
|
use syntax::attr;
|
||||||
|
use syntax::ext::base::MacroKind;
|
||||||
use syntax::ptr::P;
|
use syntax::ptr::P;
|
||||||
use syntax::source_map::Spanned;
|
use syntax::source_map::Spanned;
|
||||||
use syntax_pos::{self, Span};
|
use syntax_pos::{self, Span};
|
||||||
@ -46,6 +47,7 @@ pub struct Module {
|
|||||||
pub impls: Vec<Impl>,
|
pub impls: Vec<Impl>,
|
||||||
pub foreigns: Vec<hir::ForeignMod>,
|
pub foreigns: Vec<hir::ForeignMod>,
|
||||||
pub macros: Vec<Macro>,
|
pub macros: Vec<Macro>,
|
||||||
|
pub proc_macros: Vec<ProcMacro>,
|
||||||
pub is_crate: bool,
|
pub is_crate: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,6 +77,7 @@ impl Module {
|
|||||||
impls : Vec::new(),
|
impls : Vec::new(),
|
||||||
foreigns : Vec::new(),
|
foreigns : Vec::new(),
|
||||||
macros : Vec::new(),
|
macros : Vec::new(),
|
||||||
|
proc_macros: Vec::new(),
|
||||||
is_crate : false,
|
is_crate : false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -264,6 +267,17 @@ pub struct Import {
|
|||||||
pub whence: Span,
|
pub whence: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct ProcMacro {
|
||||||
|
pub name: Name,
|
||||||
|
pub id: NodeId,
|
||||||
|
pub kind: MacroKind,
|
||||||
|
pub helpers: Vec<Name>,
|
||||||
|
pub attrs: hir::HirVec<ast::Attribute>,
|
||||||
|
pub whence: Span,
|
||||||
|
pub stab: Option<attr::Stability>,
|
||||||
|
pub depr: Option<attr::Deprecation>,
|
||||||
|
}
|
||||||
|
|
||||||
pub fn struct_type_from_def(vdata: &hir::VariantData) -> StructType {
|
pub fn struct_type_from_def(vdata: &hir::VariantData) -> StructType {
|
||||||
match *vdata {
|
match *vdata {
|
||||||
hir::VariantData::Struct(..) => Plain,
|
hir::VariantData::Struct(..) => Plain,
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
//! Item types.
|
//! Item types.
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use syntax::ext::base::MacroKind;
|
||||||
use clean;
|
use clean;
|
||||||
|
|
||||||
/// Item type. Corresponds to `clean::ItemEnum` variants.
|
/// Item type. Corresponds to `clean::ItemEnum` variants.
|
||||||
@ -19,6 +20,11 @@ use clean;
|
|||||||
/// discriminants. JavaScript then is used to decode them into the original value.
|
/// discriminants. JavaScript then is used to decode them into the original value.
|
||||||
/// Consequently, every change to this type should be synchronized to
|
/// Consequently, every change to this type should be synchronized to
|
||||||
/// the `itemTypes` mapping table in `static/main.js`.
|
/// the `itemTypes` mapping table in `static/main.js`.
|
||||||
|
///
|
||||||
|
/// In addition, code in `html::render` uses this enum to generate CSS classes, page prefixes, and
|
||||||
|
/// module headings. If you are adding to this enum and want to ensure that the sidebar also prints
|
||||||
|
/// a heading, edit the listing in `html/render.rs`, function `sidebar_module`. This uses an
|
||||||
|
/// ordering based on a helper function inside `item_module`, in the same file.
|
||||||
#[derive(Copy, PartialEq, Clone, Debug)]
|
#[derive(Copy, PartialEq, Clone, Debug)]
|
||||||
pub enum ItemType {
|
pub enum ItemType {
|
||||||
Module = 0,
|
Module = 0,
|
||||||
@ -44,6 +50,8 @@ pub enum ItemType {
|
|||||||
ForeignType = 20,
|
ForeignType = 20,
|
||||||
Keyword = 21,
|
Keyword = 21,
|
||||||
Existential = 22,
|
Existential = 22,
|
||||||
|
ProcAttribute = 23,
|
||||||
|
ProcDerive = 24,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -88,6 +96,12 @@ impl<'a> From<&'a clean::Item> for ItemType {
|
|||||||
clean::AssociatedTypeItem(..) => ItemType::AssociatedType,
|
clean::AssociatedTypeItem(..) => ItemType::AssociatedType,
|
||||||
clean::ForeignTypeItem => ItemType::ForeignType,
|
clean::ForeignTypeItem => ItemType::ForeignType,
|
||||||
clean::KeywordItem(..) => ItemType::Keyword,
|
clean::KeywordItem(..) => ItemType::Keyword,
|
||||||
|
clean::ProcMacroItem(ref mac) => match mac.kind {
|
||||||
|
MacroKind::Bang => ItemType::Macro,
|
||||||
|
MacroKind::Attr => ItemType::ProcAttribute,
|
||||||
|
MacroKind::Derive => ItemType::ProcDerive,
|
||||||
|
MacroKind::ProcMacroStub => unreachable!(),
|
||||||
|
}
|
||||||
clean::StrippedItem(..) => unreachable!(),
|
clean::StrippedItem(..) => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -107,7 +121,9 @@ impl From<clean::TypeKind> for ItemType {
|
|||||||
clean::TypeKind::Variant => ItemType::Variant,
|
clean::TypeKind::Variant => ItemType::Variant,
|
||||||
clean::TypeKind::Typedef => ItemType::Typedef,
|
clean::TypeKind::Typedef => ItemType::Typedef,
|
||||||
clean::TypeKind::Foreign => ItemType::ForeignType,
|
clean::TypeKind::Foreign => ItemType::ForeignType,
|
||||||
clean::TypeKind::Macro => ItemType::Macro,
|
clean::TypeKind::Macro => ItemType::Macro,
|
||||||
|
clean::TypeKind::Attr => ItemType::ProcAttribute,
|
||||||
|
clean::TypeKind::Derive => ItemType::ProcDerive,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -138,6 +154,8 @@ impl ItemType {
|
|||||||
ItemType::ForeignType => "foreigntype",
|
ItemType::ForeignType => "foreigntype",
|
||||||
ItemType::Keyword => "keyword",
|
ItemType::Keyword => "keyword",
|
||||||
ItemType::Existential => "existential",
|
ItemType::Existential => "existential",
|
||||||
|
ItemType::ProcAttribute => "attr",
|
||||||
|
ItemType::ProcDerive => "derive",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,7 +184,9 @@ impl ItemType {
|
|||||||
ItemType::Constant |
|
ItemType::Constant |
|
||||||
ItemType::AssociatedConst => NameSpace::Value,
|
ItemType::AssociatedConst => NameSpace::Value,
|
||||||
|
|
||||||
ItemType::Macro => NameSpace::Macro,
|
ItemType::Macro |
|
||||||
|
ItemType::ProcAttribute |
|
||||||
|
ItemType::ProcDerive => NameSpace::Macro,
|
||||||
|
|
||||||
ItemType::Keyword => NameSpace::Keyword,
|
ItemType::Keyword => NameSpace::Keyword,
|
||||||
}
|
}
|
||||||
|
@ -56,6 +56,7 @@ use externalfiles::ExternalHtml;
|
|||||||
|
|
||||||
use serialize::json::{ToJson, Json, as_json};
|
use serialize::json::{ToJson, Json, as_json};
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
|
use syntax::ext::base::MacroKind;
|
||||||
use syntax::source_map::FileName;
|
use syntax::source_map::FileName;
|
||||||
use syntax::feature_gate::UnstableFeatures;
|
use syntax::feature_gate::UnstableFeatures;
|
||||||
use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId};
|
use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId};
|
||||||
@ -1595,6 +1596,8 @@ struct AllTypes {
|
|||||||
statics: FxHashSet<ItemEntry>,
|
statics: FxHashSet<ItemEntry>,
|
||||||
constants: FxHashSet<ItemEntry>,
|
constants: FxHashSet<ItemEntry>,
|
||||||
keywords: FxHashSet<ItemEntry>,
|
keywords: FxHashSet<ItemEntry>,
|
||||||
|
attributes: FxHashSet<ItemEntry>,
|
||||||
|
derives: FxHashSet<ItemEntry>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AllTypes {
|
impl AllTypes {
|
||||||
@ -1613,6 +1616,8 @@ impl AllTypes {
|
|||||||
statics: new_set(100),
|
statics: new_set(100),
|
||||||
constants: new_set(100),
|
constants: new_set(100),
|
||||||
keywords: new_set(100),
|
keywords: new_set(100),
|
||||||
|
attributes: new_set(100),
|
||||||
|
derives: new_set(100),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1634,6 +1639,8 @@ impl AllTypes {
|
|||||||
ItemType::Existential => self.existentials.insert(ItemEntry::new(new_url, name)),
|
ItemType::Existential => self.existentials.insert(ItemEntry::new(new_url, name)),
|
||||||
ItemType::Static => self.statics.insert(ItemEntry::new(new_url, name)),
|
ItemType::Static => self.statics.insert(ItemEntry::new(new_url, name)),
|
||||||
ItemType::Constant => self.constants.insert(ItemEntry::new(new_url, name)),
|
ItemType::Constant => self.constants.insert(ItemEntry::new(new_url, name)),
|
||||||
|
ItemType::ProcAttribute => self.attributes.insert(ItemEntry::new(new_url, name)),
|
||||||
|
ItemType::ProcDerive => self.derives.insert(ItemEntry::new(new_url, name)),
|
||||||
_ => true,
|
_ => true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -1673,6 +1680,8 @@ impl fmt::Display for AllTypes {
|
|||||||
print_entries(f, &self.primitives, "Primitives", "primitives")?;
|
print_entries(f, &self.primitives, "Primitives", "primitives")?;
|
||||||
print_entries(f, &self.traits, "Traits", "traits")?;
|
print_entries(f, &self.traits, "Traits", "traits")?;
|
||||||
print_entries(f, &self.macros, "Macros", "macros")?;
|
print_entries(f, &self.macros, "Macros", "macros")?;
|
||||||
|
print_entries(f, &self.attributes, "Attribute Macros", "attributes")?;
|
||||||
|
print_entries(f, &self.derives, "Derive Macros", "derives")?;
|
||||||
print_entries(f, &self.functions, "Functions", "functions")?;
|
print_entries(f, &self.functions, "Functions", "functions")?;
|
||||||
print_entries(f, &self.typedefs, "Typedefs", "typedefs")?;
|
print_entries(f, &self.typedefs, "Typedefs", "typedefs")?;
|
||||||
print_entries(f, &self.existentials, "Existentials", "existentials")?;
|
print_entries(f, &self.existentials, "Existentials", "existentials")?;
|
||||||
@ -2155,6 +2164,12 @@ impl<'a> fmt::Display for Item<'a> {
|
|||||||
clean::EnumItem(..) => write!(fmt, "Enum ")?,
|
clean::EnumItem(..) => write!(fmt, "Enum ")?,
|
||||||
clean::TypedefItem(..) => write!(fmt, "Type Definition ")?,
|
clean::TypedefItem(..) => write!(fmt, "Type Definition ")?,
|
||||||
clean::MacroItem(..) => write!(fmt, "Macro ")?,
|
clean::MacroItem(..) => write!(fmt, "Macro ")?,
|
||||||
|
clean::ProcMacroItem(ref mac) => match mac.kind {
|
||||||
|
MacroKind::Bang => write!(fmt, "Macro ")?,
|
||||||
|
MacroKind::Attr => write!(fmt, "Attribute Macro ")?,
|
||||||
|
MacroKind::Derive => write!(fmt, "Derive Macro ")?,
|
||||||
|
MacroKind::ProcMacroStub => unreachable!(),
|
||||||
|
}
|
||||||
clean::PrimitiveItem(..) => write!(fmt, "Primitive Type ")?,
|
clean::PrimitiveItem(..) => write!(fmt, "Primitive Type ")?,
|
||||||
clean::StaticItem(..) | clean::ForeignStaticItem(..) => write!(fmt, "Static ")?,
|
clean::StaticItem(..) | clean::ForeignStaticItem(..) => write!(fmt, "Static ")?,
|
||||||
clean::ConstantItem(..) => write!(fmt, "Constant ")?,
|
clean::ConstantItem(..) => write!(fmt, "Constant ")?,
|
||||||
@ -2191,6 +2206,7 @@ impl<'a> fmt::Display for Item<'a> {
|
|||||||
clean::EnumItem(ref e) => item_enum(fmt, self.cx, self.item, e),
|
clean::EnumItem(ref e) => item_enum(fmt, self.cx, self.item, e),
|
||||||
clean::TypedefItem(ref t, _) => item_typedef(fmt, self.cx, self.item, t),
|
clean::TypedefItem(ref t, _) => item_typedef(fmt, self.cx, self.item, t),
|
||||||
clean::MacroItem(ref m) => item_macro(fmt, self.cx, self.item, m),
|
clean::MacroItem(ref m) => item_macro(fmt, self.cx, self.item, m),
|
||||||
|
clean::ProcMacroItem(ref m) => item_proc_macro(fmt, self.cx, self.item, m),
|
||||||
clean::PrimitiveItem(ref p) => item_primitive(fmt, self.cx, self.item, p),
|
clean::PrimitiveItem(ref p) => item_primitive(fmt, self.cx, self.item, p),
|
||||||
clean::StaticItem(ref i) | clean::ForeignStaticItem(ref i) =>
|
clean::StaticItem(ref i) | clean::ForeignStaticItem(ref i) =>
|
||||||
item_static(fmt, self.cx, self.item, i),
|
item_static(fmt, self.cx, self.item, i),
|
||||||
@ -4079,11 +4095,12 @@ impl<'a> fmt::Display for Sidebar<'a> {
|
|||||||
write!(fmt,
|
write!(fmt,
|
||||||
"<div class='block version'>\
|
"<div class='block version'>\
|
||||||
<p>Version {}</p>\
|
<p>Version {}</p>\
|
||||||
</div>
|
</div>",
|
||||||
<a id='all-types' href='all.html'><p>See all {}'s items</p></a>",
|
version)?;
|
||||||
version,
|
|
||||||
it.name.as_ref().unwrap())?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
write!(fmt, "<a id='all-types' href='all.html'><p>See all {}'s items</p></a>",
|
||||||
|
it.name.as_ref().expect("crates always have a name"))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
write!(fmt, "<div class=\"sidebar-elems\">")?;
|
write!(fmt, "<div class=\"sidebar-elems\">")?;
|
||||||
@ -4523,6 +4540,8 @@ fn item_ty_to_strs(ty: &ItemType) -> (&'static str, &'static str) {
|
|||||||
ItemType::ForeignType => ("foreign-types", "Foreign Types"),
|
ItemType::ForeignType => ("foreign-types", "Foreign Types"),
|
||||||
ItemType::Keyword => ("keywords", "Keywords"),
|
ItemType::Keyword => ("keywords", "Keywords"),
|
||||||
ItemType::Existential => ("existentials", "Existentials"),
|
ItemType::Existential => ("existentials", "Existentials"),
|
||||||
|
ItemType::ProcAttribute => ("attributes", "Attribute Macros"),
|
||||||
|
ItemType::ProcDerive => ("derives", "Derive Macros"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4598,6 +4617,39 @@ fn item_macro(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
|
|||||||
document(w, cx, it)
|
document(w, cx, it)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn item_proc_macro(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, m: &clean::ProcMacro)
|
||||||
|
-> fmt::Result
|
||||||
|
{
|
||||||
|
let name = it.name.as_ref().expect("proc-macros always have names");
|
||||||
|
match m.kind {
|
||||||
|
MacroKind::Bang => {
|
||||||
|
write!(w, "<pre class='rust macro'>")?;
|
||||||
|
write!(w, "{}!() {{ /* proc-macro */ }}", name)?;
|
||||||
|
write!(w, "</pre>")?;
|
||||||
|
}
|
||||||
|
MacroKind::Attr => {
|
||||||
|
write!(w, "<pre class='rust attr'>")?;
|
||||||
|
write!(w, "#[{}]", name)?;
|
||||||
|
write!(w, "</pre>")?;
|
||||||
|
}
|
||||||
|
MacroKind::Derive => {
|
||||||
|
write!(w, "<pre class='rust derive'>")?;
|
||||||
|
write!(w, "#[derive({})]", name)?;
|
||||||
|
if !m.helpers.is_empty() {
|
||||||
|
writeln!(w, "\n{{")?;
|
||||||
|
writeln!(w, " // Attributes available to this derive:")?;
|
||||||
|
for attr in &m.helpers {
|
||||||
|
writeln!(w, " #[{}]", attr)?;
|
||||||
|
}
|
||||||
|
write!(w, "}}")?;
|
||||||
|
}
|
||||||
|
write!(w, "</pre>")?;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
document(w, cx, it)
|
||||||
|
}
|
||||||
|
|
||||||
fn item_primitive(w: &mut fmt::Formatter, cx: &Context,
|
fn item_primitive(w: &mut fmt::Formatter, cx: &Context,
|
||||||
it: &clean::Item,
|
it: &clean::Item,
|
||||||
_p: &clean::PrimitiveType) -> fmt::Result {
|
_p: &clean::PrimitiveType) -> fmt::Result {
|
||||||
|
@ -39,7 +39,10 @@
|
|||||||
"associatedconstant",
|
"associatedconstant",
|
||||||
"union",
|
"union",
|
||||||
"foreigntype",
|
"foreigntype",
|
||||||
"keyword"];
|
"keyword",
|
||||||
|
"existential",
|
||||||
|
"attr",
|
||||||
|
"derive"];
|
||||||
|
|
||||||
var search_input = document.getElementsByClassName('search-input')[0];
|
var search_input = document.getElementsByClassName('search-input')[0];
|
||||||
|
|
||||||
|
@ -124,6 +124,8 @@ pre {
|
|||||||
.content .highlighted.tymethod { background-color: #4950ed; }
|
.content .highlighted.tymethod { background-color: #4950ed; }
|
||||||
.content .highlighted.type { background-color: #38902c; }
|
.content .highlighted.type { background-color: #38902c; }
|
||||||
.content .highlighted.foreigntype { background-color: #b200d6; }
|
.content .highlighted.foreigntype { background-color: #b200d6; }
|
||||||
|
.content .highlighted.attr,
|
||||||
|
.content .highlighted.derive,
|
||||||
.content .highlighted.macro { background-color: #217d1c; }
|
.content .highlighted.macro { background-color: #217d1c; }
|
||||||
.content .highlighted.constant,
|
.content .highlighted.constant,
|
||||||
.content .highlighted.static { background-color: #0063cc; }
|
.content .highlighted.static { background-color: #0063cc; }
|
||||||
@ -134,6 +136,8 @@ pre {
|
|||||||
.content span.struct, .content a.struct, .block a.current.struct { color: #2dbfb8; }
|
.content span.struct, .content a.struct, .block a.current.struct { color: #2dbfb8; }
|
||||||
.content span.type, .content a.type, .block a.current.type { color: #ff7f00; }
|
.content span.type, .content a.type, .block a.current.type { color: #ff7f00; }
|
||||||
.content span.foreigntype, .content a.foreigntype, .block a.current.foreigntype { color: #dd7de8; }
|
.content span.foreigntype, .content a.foreigntype, .block a.current.foreigntype { color: #dd7de8; }
|
||||||
|
.content span.attr, .content a.attr, .block a.current.attr,
|
||||||
|
.content span.derive, .content a.derive, .block a.current.derive,
|
||||||
.content span.macro, .content a.macro, .block a.current.macro { color: #09bd00; }
|
.content span.macro, .content a.macro, .block a.current.macro { color: #09bd00; }
|
||||||
.content span.union, .content a.union, .block a.current.union { color: #a6ae37; }
|
.content span.union, .content a.union, .block a.current.union { color: #a6ae37; }
|
||||||
.content span.constant, .content a.constant, .block a.current.constant,
|
.content span.constant, .content a.constant, .block a.current.constant,
|
||||||
|
@ -124,6 +124,8 @@ pre {
|
|||||||
.content .highlighted.tymethod { background-color: #c6afb3; }
|
.content .highlighted.tymethod { background-color: #c6afb3; }
|
||||||
.content .highlighted.type { background-color: #ffc891; }
|
.content .highlighted.type { background-color: #ffc891; }
|
||||||
.content .highlighted.foreigntype { background-color: #f5c4ff; }
|
.content .highlighted.foreigntype { background-color: #f5c4ff; }
|
||||||
|
.content .highlighted.attr,
|
||||||
|
.content .highlighted.derive,
|
||||||
.content .highlighted.macro { background-color: #8ce488; }
|
.content .highlighted.macro { background-color: #8ce488; }
|
||||||
.content .highlighted.constant,
|
.content .highlighted.constant,
|
||||||
.content .highlighted.static { background-color: #c3e0ff; }
|
.content .highlighted.static { background-color: #c3e0ff; }
|
||||||
@ -134,6 +136,8 @@ pre {
|
|||||||
.content span.struct, .content a.struct, .block a.current.struct { color: #ad448e; }
|
.content span.struct, .content a.struct, .block a.current.struct { color: #ad448e; }
|
||||||
.content span.type, .content a.type, .block a.current.type { color: #ba5d00; }
|
.content span.type, .content a.type, .block a.current.type { color: #ba5d00; }
|
||||||
.content span.foreigntype, .content a.foreigntype, .block a.current.foreigntype { color: #cd00e2; }
|
.content span.foreigntype, .content a.foreigntype, .block a.current.foreigntype { color: #cd00e2; }
|
||||||
|
.content span.attr, .content a.attr, .block a.current.attr,
|
||||||
|
.content span.derive, .content a.derive, .block a.current.derive,
|
||||||
.content span.macro, .content a.macro, .block a.current.macro { color: #068000; }
|
.content span.macro, .content a.macro, .block a.current.macro { color: #068000; }
|
||||||
.content span.union, .content a.union, .block a.current.union { color: #767b27; }
|
.content span.union, .content a.union, .block a.current.union { color: #767b27; }
|
||||||
.content span.constant, .content a.constant, .block a.current.constant,
|
.content span.constant, .content a.constant, .block a.current.constant,
|
||||||
|
@ -249,6 +249,9 @@ impl<'a> fold::DocFolder for Stripper<'a> {
|
|||||||
// tymethods/macros have no control over privacy
|
// tymethods/macros have no control over privacy
|
||||||
clean::MacroItem(..) | clean::TyMethodItem(..) => {}
|
clean::MacroItem(..) | clean::TyMethodItem(..) => {}
|
||||||
|
|
||||||
|
// Proc-macros are always public
|
||||||
|
clean::ProcMacroItem(..) => {}
|
||||||
|
|
||||||
// Primitives are never stripped
|
// Primitives are never stripped
|
||||||
clean::PrimitiveItem(..) => {}
|
clean::PrimitiveItem(..) => {}
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ use std::mem;
|
|||||||
|
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
use syntax::attr;
|
use syntax::attr;
|
||||||
|
use syntax::ext::base::MacroKind;
|
||||||
use syntax::source_map::Spanned;
|
use syntax::source_map::Spanned;
|
||||||
use syntax_pos::{self, Span};
|
use syntax_pos::{self, Span};
|
||||||
|
|
||||||
@ -168,24 +169,75 @@ impl<'a, 'tcx, 'rcx, 'cstore> RustdocVisitor<'a, 'tcx, 'rcx, 'cstore> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn visit_fn(&mut self, item: &hir::Item,
|
pub fn visit_fn(&mut self, om: &mut Module, item: &hir::Item,
|
||||||
name: ast::Name, fd: &hir::FnDecl,
|
name: ast::Name, fd: &hir::FnDecl,
|
||||||
header: hir::FnHeader,
|
header: hir::FnHeader,
|
||||||
gen: &hir::Generics,
|
gen: &hir::Generics,
|
||||||
body: hir::BodyId) -> Function {
|
body: hir::BodyId) {
|
||||||
debug!("Visiting fn");
|
debug!("Visiting fn");
|
||||||
Function {
|
let macro_kind = item.attrs.iter().filter_map(|a| {
|
||||||
id: item.id,
|
if a.check_name("proc_macro") {
|
||||||
vis: item.vis.clone(),
|
Some(MacroKind::Bang)
|
||||||
stab: self.stability(item.id),
|
} else if a.check_name("proc_macro_derive") {
|
||||||
depr: self.deprecation(item.id),
|
Some(MacroKind::Derive)
|
||||||
attrs: item.attrs.clone(),
|
} else if a.check_name("proc_macro_attribute") {
|
||||||
decl: fd.clone(),
|
Some(MacroKind::Attr)
|
||||||
name,
|
} else {
|
||||||
whence: item.span,
|
None
|
||||||
generics: gen.clone(),
|
}
|
||||||
header,
|
}).next();
|
||||||
body,
|
match macro_kind {
|
||||||
|
Some(kind) => {
|
||||||
|
let name = if kind == MacroKind::Derive {
|
||||||
|
item.attrs.lists("proc_macro_derive")
|
||||||
|
.filter_map(|mi| mi.name())
|
||||||
|
.next()
|
||||||
|
.expect("proc-macro derives require a name")
|
||||||
|
} else {
|
||||||
|
name
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut helpers = Vec::new();
|
||||||
|
for mi in item.attrs.lists("proc_macro_derive") {
|
||||||
|
if !mi.check_name("attributes") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(list) = mi.meta_item_list() {
|
||||||
|
for inner_mi in list {
|
||||||
|
if let Some(name) = inner_mi.name() {
|
||||||
|
helpers.push(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
om.proc_macros.push(ProcMacro {
|
||||||
|
name,
|
||||||
|
id: item.id,
|
||||||
|
kind,
|
||||||
|
helpers,
|
||||||
|
attrs: item.attrs.clone(),
|
||||||
|
whence: item.span,
|
||||||
|
stab: self.stability(item.id),
|
||||||
|
depr: self.deprecation(item.id),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
om.fns.push(Function {
|
||||||
|
id: item.id,
|
||||||
|
vis: item.vis.clone(),
|
||||||
|
stab: self.stability(item.id),
|
||||||
|
depr: self.deprecation(item.id),
|
||||||
|
attrs: item.attrs.clone(),
|
||||||
|
decl: fd.clone(),
|
||||||
|
name,
|
||||||
|
whence: item.span,
|
||||||
|
generics: gen.clone(),
|
||||||
|
header,
|
||||||
|
body,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -425,7 +477,7 @@ impl<'a, 'tcx, 'rcx, 'cstore> RustdocVisitor<'a, 'tcx, 'rcx, 'cstore> {
|
|||||||
hir::ItemKind::Union(ref sd, ref gen) =>
|
hir::ItemKind::Union(ref sd, ref gen) =>
|
||||||
om.unions.push(self.visit_union_data(item, name, sd, gen)),
|
om.unions.push(self.visit_union_data(item, name, sd, gen)),
|
||||||
hir::ItemKind::Fn(ref fd, header, ref gen, body) =>
|
hir::ItemKind::Fn(ref fd, header, ref gen, body) =>
|
||||||
om.fns.push(self.visit_fn(item, name, &**fd, header, gen, body)),
|
self.visit_fn(om, item, name, &**fd, header, gen, body),
|
||||||
hir::ItemKind::Ty(ref ty, ref gen) => {
|
hir::ItemKind::Ty(ref ty, ref gen) => {
|
||||||
let t = Typedef {
|
let t = Typedef {
|
||||||
ty: ty.clone(),
|
ty: ty.clone(),
|
||||||
|
@ -1204,8 +1204,8 @@ pub trait Write {
|
|||||||
pub trait Seek {
|
pub trait Seek {
|
||||||
/// Seek to an offset, in bytes, in a stream.
|
/// Seek to an offset, in bytes, in a stream.
|
||||||
///
|
///
|
||||||
/// A seek beyond the end of a stream is allowed, but implementation
|
/// A seek beyond the end of a stream is allowed, but behavior is defined
|
||||||
/// defined.
|
/// by the implementation.
|
||||||
///
|
///
|
||||||
/// If the seek operation completed successfully,
|
/// If the seek operation completed successfully,
|
||||||
/// this method returns the new position from the start of the stream.
|
/// this method returns the new position from the start of the stream.
|
||||||
|
@ -517,6 +517,7 @@ pub fn update_count_then_panic(msg: Box<dyn Any + Send>) -> ! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A private no-mangle function on which to slap yer breakpoints.
|
/// A private no-mangle function on which to slap yer breakpoints.
|
||||||
|
#[inline(never)]
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
#[allow(private_no_mangle_fns)] // yes we get it, but we like breakpoints
|
#[allow(private_no_mangle_fns)] // yes we get it, but we like breakpoints
|
||||||
pub fn rust_panic(mut msg: &mut dyn BoxMeUp) -> ! {
|
pub fn rust_panic(mut msg: &mut dyn BoxMeUp) -> ! {
|
||||||
|
37
src/test/rustdoc/inline_cross/auxiliary/proc_macro.rs
Normal file
37
src/test/rustdoc/inline_cross/auxiliary/proc_macro.rs
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
// no-prefer-dynamic
|
||||||
|
|
||||||
|
#![crate_type="proc-macro"]
|
||||||
|
#![crate_name="some_macros"]
|
||||||
|
|
||||||
|
extern crate proc_macro;
|
||||||
|
|
||||||
|
use proc_macro::TokenStream;
|
||||||
|
|
||||||
|
/// a proc-macro that swallows its input and does nothing.
|
||||||
|
#[proc_macro]
|
||||||
|
pub fn some_proc_macro(_input: TokenStream) -> TokenStream {
|
||||||
|
TokenStream::new()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// a proc-macro attribute that passes its item through verbatim.
|
||||||
|
#[proc_macro_attribute]
|
||||||
|
pub fn some_proc_attr(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||||
|
item
|
||||||
|
}
|
||||||
|
|
||||||
|
/// a derive attribute that adds nothing to its input.
|
||||||
|
#[proc_macro_derive(SomeDerive)]
|
||||||
|
pub fn some_derive(_item: TokenStream) -> TokenStream {
|
||||||
|
TokenStream::new()
|
||||||
|
}
|
||||||
|
|
27
src/test/rustdoc/inline_cross/proc_macro.rs
Normal file
27
src/test/rustdoc/inline_cross/proc_macro.rs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
// ignore-stage1
|
||||||
|
// aux-build:proc_macro.rs
|
||||||
|
// build-aux-docs
|
||||||
|
|
||||||
|
// FIXME: if/when proc-macros start exporting their doc attributes across crates, we can turn on
|
||||||
|
// cross-crate inlining for them
|
||||||
|
|
||||||
|
extern crate some_macros;
|
||||||
|
|
||||||
|
// @has proc_macro/index.html
|
||||||
|
// @has - '//a/@href' '../some_macros/macro.some_proc_macro.html'
|
||||||
|
// @has - '//a/@href' '../some_macros/attr.some_proc_attr.html'
|
||||||
|
// @has - '//a/@href' '../some_macros/derive.SomeDerive.html'
|
||||||
|
// @!has proc_macro/macro.some_proc_macro.html
|
||||||
|
// @!has proc_macro/attr.some_proc_attr.html
|
||||||
|
// @!has proc_macro/derive.SomeDerive.html
|
||||||
|
pub use some_macros::{some_proc_macro, some_proc_attr, SomeDerive};
|
62
src/test/rustdoc/proc-macro.rs
Normal file
62
src/test/rustdoc/proc-macro.rs
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
// ignore-stage1
|
||||||
|
|
||||||
|
#![crate_type="proc-macro"]
|
||||||
|
#![crate_name="some_macros"]
|
||||||
|
|
||||||
|
extern crate proc_macro;
|
||||||
|
|
||||||
|
use proc_macro::TokenStream;
|
||||||
|
|
||||||
|
// @has some_macros/index.html
|
||||||
|
// @has - '//h2' 'Macros'
|
||||||
|
// @has - '//h2' 'Attribute Macros'
|
||||||
|
// @has - '//h2' 'Derive Macros'
|
||||||
|
// @!has - '//h2' 'Functions'
|
||||||
|
|
||||||
|
// @has some_macros/all.html
|
||||||
|
// @has - '//a[@href="macro.some_proc_macro.html"]' 'some_proc_macro'
|
||||||
|
// @has - '//a[@href="attr.some_proc_attr.html"]' 'some_proc_attr'
|
||||||
|
// @has - '//a[@href="derive.SomeDerive.html"]' 'SomeDerive'
|
||||||
|
// @!has - '//a/@href' 'fn.some_proc_macro.html'
|
||||||
|
// @!has - '//a/@href' 'fn.some_proc_attr.html'
|
||||||
|
// @!has - '//a/@href' 'fn.some_derive.html'
|
||||||
|
|
||||||
|
// @has some_macros/index.html '//a/@href' 'macro.some_proc_macro.html'
|
||||||
|
// @!has - '//a/@href' 'fn.some_proc_macro.html'
|
||||||
|
// @has some_macros/macro.some_proc_macro.html
|
||||||
|
// @!has some_macros/fn.some_proc_macro.html
|
||||||
|
/// a proc-macro that swallows its input and does nothing.
|
||||||
|
#[proc_macro]
|
||||||
|
pub fn some_proc_macro(_input: TokenStream) -> TokenStream {
|
||||||
|
TokenStream::new()
|
||||||
|
}
|
||||||
|
|
||||||
|
// @has some_macros/index.html '//a/@href' 'attr.some_proc_attr.html'
|
||||||
|
// @!has - '//a/@href' 'fn.some_proc_attr.html'
|
||||||
|
// @has some_macros/attr.some_proc_attr.html
|
||||||
|
// @!has some_macros/fn.some_proc_attr.html
|
||||||
|
/// a proc-macro attribute that passes its item through verbatim.
|
||||||
|
#[proc_macro_attribute]
|
||||||
|
pub fn some_proc_attr(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||||
|
item
|
||||||
|
}
|
||||||
|
|
||||||
|
// @has some_macros/index.html '//a/@href' 'derive.SomeDerive.html'
|
||||||
|
// @!has - '//a/@href' 'fn.some_derive.html'
|
||||||
|
// @has some_macros/derive.SomeDerive.html
|
||||||
|
// @!has some_macros/fn.some_derive.html
|
||||||
|
/// a derive attribute that adds nothing to its input.
|
||||||
|
#[proc_macro_derive(SomeDerive)]
|
||||||
|
pub fn some_derive(_item: TokenStream) -> TokenStream {
|
||||||
|
TokenStream::new()
|
||||||
|
}
|
@ -3,6 +3,8 @@ error[E0411]: cannot find type `Self` in this scope
|
|||||||
|
|
|
|
||||||
LL | Cons(T, &'a Self)
|
LL | Cons(T, &'a Self)
|
||||||
| ^^^^ `Self` is only available in traits and impls
|
| ^^^^ `Self` is only available in traits and impls
|
||||||
|
|
|
||||||
|
= help: add #![feature(self_in_typedefs)] to the crate attributes to enable
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
@ -8,5 +8,5 @@ LL | assert_eq!('x'.ipu_flatten(), 1);
|
|||||||
= warning: once this method is added to the standard library, the ambiguity may cause an error or change in behavior!
|
= warning: once this method is added to the standard library, the ambiguity may cause an error or change in behavior!
|
||||||
= note: for more information, see issue #48919 <https://github.com/rust-lang/rust/issues/48919>
|
= note: for more information, see issue #48919 <https://github.com/rust-lang/rust/issues/48919>
|
||||||
= help: call with fully qualified syntax `inference_unstable_itertools::IpuItertools::ipu_flatten(...)` to keep using the current method
|
= help: call with fully qualified syntax `inference_unstable_itertools::IpuItertools::ipu_flatten(...)` to keep using the current method
|
||||||
= note: add #![feature(ipu_flatten)] to the crate attributes to enable `inference_unstable_iterator::IpuIterator::ipu_flatten`
|
= help: add #![feature(ipu_flatten)] to the crate attributes to enable `inference_unstable_iterator::IpuIterator::ipu_flatten`
|
||||||
|
|
||||||
|
@ -278,7 +278,10 @@ pub fn parse_config(args: Vec<String>) -> Config {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let (gdb, gdb_version, gdb_native_rust) = analyze_gdb(matches.opt_str("gdb"));
|
let target = opt_str2(matches.opt_str("target"));
|
||||||
|
let android_cross_path = opt_path(matches, "android-cross-path");
|
||||||
|
let (gdb, gdb_version, gdb_native_rust) = analyze_gdb(matches.opt_str("gdb"), &target,
|
||||||
|
&android_cross_path);
|
||||||
|
|
||||||
let color = match matches.opt_str("color").as_ref().map(|x| &**x) {
|
let color = match matches.opt_str("color").as_ref().map(|x| &**x) {
|
||||||
Some("auto") | None => ColorConfig::AutoColor,
|
Some("auto") | None => ColorConfig::AutoColor,
|
||||||
@ -318,7 +321,7 @@ pub fn parse_config(args: Vec<String>) -> Config {
|
|||||||
runtool: matches.opt_str("runtool"),
|
runtool: matches.opt_str("runtool"),
|
||||||
host_rustcflags: matches.opt_str("host-rustcflags"),
|
host_rustcflags: matches.opt_str("host-rustcflags"),
|
||||||
target_rustcflags: matches.opt_str("target-rustcflags"),
|
target_rustcflags: matches.opt_str("target-rustcflags"),
|
||||||
target: opt_str2(matches.opt_str("target")),
|
target: target,
|
||||||
host: opt_str2(matches.opt_str("host")),
|
host: opt_str2(matches.opt_str("host")),
|
||||||
gdb,
|
gdb,
|
||||||
gdb_version,
|
gdb_version,
|
||||||
@ -326,7 +329,7 @@ pub fn parse_config(args: Vec<String>) -> Config {
|
|||||||
lldb_version: extract_lldb_version(matches.opt_str("lldb-version")),
|
lldb_version: extract_lldb_version(matches.opt_str("lldb-version")),
|
||||||
llvm_version: matches.opt_str("llvm-version"),
|
llvm_version: matches.opt_str("llvm-version"),
|
||||||
system_llvm: matches.opt_present("system-llvm"),
|
system_llvm: matches.opt_present("system-llvm"),
|
||||||
android_cross_path: opt_path(matches, "android-cross-path"),
|
android_cross_path: android_cross_path,
|
||||||
adb_path: opt_str2(matches.opt_str("adb-path")),
|
adb_path: opt_str2(matches.opt_str("adb-path")),
|
||||||
adb_test_dir: opt_str2(matches.opt_str("adb-test-dir")),
|
adb_test_dir: opt_str2(matches.opt_str("adb-test-dir")),
|
||||||
adb_device_status: opt_str2(matches.opt_str("target")).contains("android")
|
adb_device_status: opt_str2(matches.opt_str("target")).contains("android")
|
||||||
@ -780,8 +783,18 @@ fn make_test_closure(
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns true if the given target is an Android target for the
|
||||||
|
/// purposes of GDB testing.
|
||||||
|
fn is_android_gdb_target(target: &String) -> bool {
|
||||||
|
match &target[..] {
|
||||||
|
"arm-linux-androideabi" | "armv7-linux-androideabi" | "aarch64-linux-android" => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns (Path to GDB, GDB Version, GDB has Rust Support)
|
/// Returns (Path to GDB, GDB Version, GDB has Rust Support)
|
||||||
fn analyze_gdb(gdb: Option<String>) -> (Option<String>, Option<u32>, bool) {
|
fn analyze_gdb(gdb: Option<String>, target: &String, android_cross_path: &PathBuf)
|
||||||
|
-> (Option<String>, Option<u32>, bool) {
|
||||||
#[cfg(not(windows))]
|
#[cfg(not(windows))]
|
||||||
const GDB_FALLBACK: &str = "gdb";
|
const GDB_FALLBACK: &str = "gdb";
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
@ -789,14 +802,27 @@ fn analyze_gdb(gdb: Option<String>) -> (Option<String>, Option<u32>, bool) {
|
|||||||
|
|
||||||
const MIN_GDB_WITH_RUST: u32 = 7011010;
|
const MIN_GDB_WITH_RUST: u32 = 7011010;
|
||||||
|
|
||||||
|
let fallback_gdb = || {
|
||||||
|
if is_android_gdb_target(target) {
|
||||||
|
let mut gdb_path = match android_cross_path.to_str() {
|
||||||
|
Some(x) => x.to_owned(),
|
||||||
|
None => panic!("cannot find android cross path"),
|
||||||
|
};
|
||||||
|
gdb_path.push_str("/bin/gdb");
|
||||||
|
gdb_path
|
||||||
|
} else {
|
||||||
|
GDB_FALLBACK.to_owned()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let gdb = match gdb {
|
let gdb = match gdb {
|
||||||
None => GDB_FALLBACK,
|
None => fallback_gdb(),
|
||||||
Some(ref s) if s.is_empty() => GDB_FALLBACK, // may be empty if configure found no gdb
|
Some(ref s) if s.is_empty() => fallback_gdb(), // may be empty if configure found no gdb
|
||||||
Some(ref s) => s,
|
Some(ref s) => s.to_owned(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut version_line = None;
|
let mut version_line = None;
|
||||||
if let Ok(output) = Command::new(gdb).arg("--version").output() {
|
if let Ok(output) = Command::new(&gdb).arg("--version").output() {
|
||||||
if let Some(first_line) = String::from_utf8_lossy(&output.stdout).lines().next() {
|
if let Some(first_line) = String::from_utf8_lossy(&output.stdout).lines().next() {
|
||||||
version_line = Some(first_line.to_string());
|
version_line = Some(first_line.to_string());
|
||||||
}
|
}
|
||||||
@ -809,7 +835,7 @@ fn analyze_gdb(gdb: Option<String>) -> (Option<String>, Option<u32>, bool) {
|
|||||||
|
|
||||||
let gdb_native_rust = version.map_or(false, |v| v >= MIN_GDB_WITH_RUST);
|
let gdb_native_rust = version.map_or(false, |v| v >= MIN_GDB_WITH_RUST);
|
||||||
|
|
||||||
(Some(gdb.to_owned()), version, gdb_native_rust)
|
(Some(gdb), version, gdb_native_rust)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extract_gdb_version(full_version_line: &str) -> Option<u32> {
|
fn extract_gdb_version(full_version_line: &str) -> Option<u32> {
|
||||||
|
@ -38,6 +38,7 @@ use std::process::{Child, Command, ExitStatus, Output, Stdio};
|
|||||||
use std::str;
|
use std::str;
|
||||||
|
|
||||||
use extract_gdb_version;
|
use extract_gdb_version;
|
||||||
|
use is_android_gdb_target;
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
fn disable_error_reporting<F: FnOnce() -> R, R>(f: F) -> R {
|
fn disable_error_reporting<F: FnOnce() -> R, R>(f: F) -> R {
|
||||||
@ -224,6 +225,19 @@ pub fn run(config: Config, testpaths: &TestPaths, revision: Option<&str>) {
|
|||||||
pub fn compute_stamp_hash(config: &Config) -> String {
|
pub fn compute_stamp_hash(config: &Config) -> String {
|
||||||
let mut hash = DefaultHasher::new();
|
let mut hash = DefaultHasher::new();
|
||||||
config.stage_id.hash(&mut hash);
|
config.stage_id.hash(&mut hash);
|
||||||
|
match config.mode {
|
||||||
|
DebugInfoGdb => match config.gdb {
|
||||||
|
None => env::var_os("PATH").hash(&mut hash),
|
||||||
|
Some(ref s) if s.is_empty() => env::var_os("PATH").hash(&mut hash),
|
||||||
|
Some(ref s) => s.hash(&mut hash),
|
||||||
|
},
|
||||||
|
DebugInfoLldb => {
|
||||||
|
env::var_os("PATH").hash(&mut hash);
|
||||||
|
env::var_os("PYTHONPATH").hash(&mut hash);
|
||||||
|
},
|
||||||
|
|
||||||
|
_ => {},
|
||||||
|
};
|
||||||
format!("{:x}", hash.finish())
|
format!("{:x}", hash.finish())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -666,222 +680,217 @@ impl<'test> TestCx<'test> {
|
|||||||
let exe_file = self.make_exe_name();
|
let exe_file = self.make_exe_name();
|
||||||
|
|
||||||
let debugger_run_result;
|
let debugger_run_result;
|
||||||
match &*self.config.target {
|
if is_android_gdb_target(&self.config.target) {
|
||||||
"arm-linux-androideabi" | "armv7-linux-androideabi" | "aarch64-linux-android" => {
|
cmds = cmds.replace("run", "continue");
|
||||||
cmds = cmds.replace("run", "continue");
|
|
||||||
|
|
||||||
let tool_path = match self.config.android_cross_path.to_str() {
|
let tool_path = match self.config.android_cross_path.to_str() {
|
||||||
Some(x) => x.to_owned(),
|
Some(x) => x.to_owned(),
|
||||||
None => self.fatal("cannot find android cross path"),
|
None => self.fatal("cannot find android cross path"),
|
||||||
};
|
};
|
||||||
|
|
||||||
// write debugger script
|
// write debugger script
|
||||||
let mut script_str = String::with_capacity(2048);
|
let mut script_str = String::with_capacity(2048);
|
||||||
script_str.push_str(&format!("set charset {}\n", Self::charset()));
|
script_str.push_str(&format!("set charset {}\n", Self::charset()));
|
||||||
script_str.push_str(&format!("set sysroot {}\n", tool_path));
|
script_str.push_str(&format!("set sysroot {}\n", tool_path));
|
||||||
script_str.push_str(&format!("file {}\n", exe_file.to_str().unwrap()));
|
script_str.push_str(&format!("file {}\n", exe_file.to_str().unwrap()));
|
||||||
script_str.push_str("target remote :5039\n");
|
script_str.push_str("target remote :5039\n");
|
||||||
script_str.push_str(&format!(
|
script_str.push_str(&format!(
|
||||||
"set solib-search-path \
|
"set solib-search-path \
|
||||||
./{}/stage2/lib/rustlib/{}/lib/\n",
|
./{}/stage2/lib/rustlib/{}/lib/\n",
|
||||||
self.config.host, self.config.target
|
self.config.host, self.config.target
|
||||||
));
|
));
|
||||||
for line in &breakpoint_lines {
|
for line in &breakpoint_lines {
|
||||||
script_str.push_str(
|
script_str.push_str(
|
||||||
&format!(
|
&format!(
|
||||||
"break {:?}:{}\n",
|
"break {:?}:{}\n",
|
||||||
self.testpaths.file.file_name().unwrap().to_string_lossy(),
|
|
||||||
*line
|
|
||||||
)[..],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
script_str.push_str(&cmds);
|
|
||||||
script_str.push_str("\nquit\n");
|
|
||||||
|
|
||||||
debug!("script_str = {}", script_str);
|
|
||||||
self.dump_output_file(&script_str, "debugger.script");
|
|
||||||
|
|
||||||
let adb_path = &self.config.adb_path;
|
|
||||||
|
|
||||||
Command::new(adb_path)
|
|
||||||
.arg("push")
|
|
||||||
.arg(&exe_file)
|
|
||||||
.arg(&self.config.adb_test_dir)
|
|
||||||
.status()
|
|
||||||
.expect(&format!("failed to exec `{:?}`", adb_path));
|
|
||||||
|
|
||||||
Command::new(adb_path)
|
|
||||||
.args(&["forward", "tcp:5039", "tcp:5039"])
|
|
||||||
.status()
|
|
||||||
.expect(&format!("failed to exec `{:?}`", adb_path));
|
|
||||||
|
|
||||||
let adb_arg = format!(
|
|
||||||
"export LD_LIBRARY_PATH={}; \
|
|
||||||
gdbserver{} :5039 {}/{}",
|
|
||||||
self.config.adb_test_dir.clone(),
|
|
||||||
if self.config.target.contains("aarch64") {
|
|
||||||
"64"
|
|
||||||
} else {
|
|
||||||
""
|
|
||||||
},
|
|
||||||
self.config.adb_test_dir.clone(),
|
|
||||||
exe_file.file_name().unwrap().to_str().unwrap()
|
|
||||||
);
|
|
||||||
|
|
||||||
debug!("adb arg: {}", adb_arg);
|
|
||||||
let mut adb = Command::new(adb_path)
|
|
||||||
.args(&["shell", &adb_arg])
|
|
||||||
.stdout(Stdio::piped())
|
|
||||||
.stderr(Stdio::inherit())
|
|
||||||
.spawn()
|
|
||||||
.expect(&format!("failed to exec `{:?}`", adb_path));
|
|
||||||
|
|
||||||
// Wait for the gdbserver to print out "Listening on port ..."
|
|
||||||
// at which point we know that it's started and then we can
|
|
||||||
// execute the debugger below.
|
|
||||||
let mut stdout = BufReader::new(adb.stdout.take().unwrap());
|
|
||||||
let mut line = String::new();
|
|
||||||
loop {
|
|
||||||
line.truncate(0);
|
|
||||||
stdout.read_line(&mut line).unwrap();
|
|
||||||
if line.starts_with("Listening on port 5039") {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
drop(stdout);
|
|
||||||
|
|
||||||
let debugger_script = self.make_out_name("debugger.script");
|
|
||||||
// FIXME (#9639): This needs to handle non-utf8 paths
|
|
||||||
let debugger_opts = vec![
|
|
||||||
"-quiet".to_owned(),
|
|
||||||
"-batch".to_owned(),
|
|
||||||
"-nx".to_owned(),
|
|
||||||
format!("-command={}", debugger_script.to_str().unwrap()),
|
|
||||||
];
|
|
||||||
|
|
||||||
let mut gdb_path = tool_path;
|
|
||||||
gdb_path.push_str("/bin/gdb");
|
|
||||||
let Output {
|
|
||||||
status,
|
|
||||||
stdout,
|
|
||||||
stderr,
|
|
||||||
} = Command::new(&gdb_path)
|
|
||||||
.args(&debugger_opts)
|
|
||||||
.output()
|
|
||||||
.expect(&format!("failed to exec `{:?}`", gdb_path));
|
|
||||||
let cmdline = {
|
|
||||||
let mut gdb = Command::new(&format!("{}-gdb", self.config.target));
|
|
||||||
gdb.args(&debugger_opts);
|
|
||||||
let cmdline = self.make_cmdline(&gdb, "");
|
|
||||||
logv(self.config, format!("executing {}", cmdline));
|
|
||||||
cmdline
|
|
||||||
};
|
|
||||||
|
|
||||||
debugger_run_result = ProcRes {
|
|
||||||
status,
|
|
||||||
stdout: String::from_utf8(stdout).unwrap(),
|
|
||||||
stderr: String::from_utf8(stderr).unwrap(),
|
|
||||||
cmdline,
|
|
||||||
};
|
|
||||||
if adb.kill().is_err() {
|
|
||||||
println!("Adb process is already finished.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_ => {
|
|
||||||
let rust_src_root = self
|
|
||||||
.config
|
|
||||||
.find_rust_src_root()
|
|
||||||
.expect("Could not find Rust source root");
|
|
||||||
let rust_pp_module_rel_path = Path::new("./src/etc");
|
|
||||||
let rust_pp_module_abs_path = rust_src_root
|
|
||||||
.join(rust_pp_module_rel_path)
|
|
||||||
.to_str()
|
|
||||||
.unwrap()
|
|
||||||
.to_owned();
|
|
||||||
// write debugger script
|
|
||||||
let mut script_str = String::with_capacity(2048);
|
|
||||||
script_str.push_str(&format!("set charset {}\n", Self::charset()));
|
|
||||||
script_str.push_str("show version\n");
|
|
||||||
|
|
||||||
match self.config.gdb_version {
|
|
||||||
Some(version) => {
|
|
||||||
println!(
|
|
||||||
"NOTE: compiletest thinks it is using GDB version {}",
|
|
||||||
version
|
|
||||||
);
|
|
||||||
|
|
||||||
if version > extract_gdb_version("7.4").unwrap() {
|
|
||||||
// Add the directory containing the pretty printers to
|
|
||||||
// GDB's script auto loading safe path
|
|
||||||
script_str.push_str(&format!(
|
|
||||||
"add-auto-load-safe-path {}\n",
|
|
||||||
rust_pp_module_abs_path.replace(r"\", r"\\")
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
println!(
|
|
||||||
"NOTE: compiletest does not know which version of \
|
|
||||||
GDB it is using"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// The following line actually doesn't have to do anything with
|
|
||||||
// pretty printing, it just tells GDB to print values on one line:
|
|
||||||
script_str.push_str("set print pretty off\n");
|
|
||||||
|
|
||||||
// Add the pretty printer directory to GDB's source-file search path
|
|
||||||
script_str.push_str(&format!("directory {}\n", rust_pp_module_abs_path));
|
|
||||||
|
|
||||||
// Load the target executable
|
|
||||||
script_str.push_str(&format!(
|
|
||||||
"file {}\n",
|
|
||||||
exe_file.to_str().unwrap().replace(r"\", r"\\")
|
|
||||||
));
|
|
||||||
|
|
||||||
// Force GDB to print values in the Rust format.
|
|
||||||
if self.config.gdb_native_rust {
|
|
||||||
script_str.push_str("set language rust\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add line breakpoints
|
|
||||||
for line in &breakpoint_lines {
|
|
||||||
script_str.push_str(&format!(
|
|
||||||
"break '{}':{}\n",
|
|
||||||
self.testpaths.file.file_name().unwrap().to_string_lossy(),
|
self.testpaths.file.file_name().unwrap().to_string_lossy(),
|
||||||
*line
|
*line
|
||||||
));
|
)[..],
|
||||||
}
|
|
||||||
|
|
||||||
script_str.push_str(&cmds);
|
|
||||||
script_str.push_str("\nquit\n");
|
|
||||||
|
|
||||||
debug!("script_str = {}", script_str);
|
|
||||||
self.dump_output_file(&script_str, "debugger.script");
|
|
||||||
|
|
||||||
let debugger_script = self.make_out_name("debugger.script");
|
|
||||||
|
|
||||||
// FIXME (#9639): This needs to handle non-utf8 paths
|
|
||||||
let debugger_opts = vec![
|
|
||||||
"-quiet".to_owned(),
|
|
||||||
"-batch".to_owned(),
|
|
||||||
"-nx".to_owned(),
|
|
||||||
format!("-command={}", debugger_script.to_str().unwrap()),
|
|
||||||
];
|
|
||||||
|
|
||||||
let mut gdb = Command::new(self.config.gdb.as_ref().unwrap());
|
|
||||||
gdb.args(&debugger_opts)
|
|
||||||
.env("PYTHONPATH", rust_pp_module_abs_path);
|
|
||||||
|
|
||||||
debugger_run_result = self.compose_and_run(
|
|
||||||
gdb,
|
|
||||||
self.config.run_lib_path.to_str().unwrap(),
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
script_str.push_str(&cmds);
|
||||||
|
script_str.push_str("\nquit\n");
|
||||||
|
|
||||||
|
debug!("script_str = {}", script_str);
|
||||||
|
self.dump_output_file(&script_str, "debugger.script");
|
||||||
|
|
||||||
|
let adb_path = &self.config.adb_path;
|
||||||
|
|
||||||
|
Command::new(adb_path)
|
||||||
|
.arg("push")
|
||||||
|
.arg(&exe_file)
|
||||||
|
.arg(&self.config.adb_test_dir)
|
||||||
|
.status()
|
||||||
|
.expect(&format!("failed to exec `{:?}`", adb_path));
|
||||||
|
|
||||||
|
Command::new(adb_path)
|
||||||
|
.args(&["forward", "tcp:5039", "tcp:5039"])
|
||||||
|
.status()
|
||||||
|
.expect(&format!("failed to exec `{:?}`", adb_path));
|
||||||
|
|
||||||
|
let adb_arg = format!(
|
||||||
|
"export LD_LIBRARY_PATH={}; \
|
||||||
|
gdbserver{} :5039 {}/{}",
|
||||||
|
self.config.adb_test_dir.clone(),
|
||||||
|
if self.config.target.contains("aarch64") {
|
||||||
|
"64"
|
||||||
|
} else {
|
||||||
|
""
|
||||||
|
},
|
||||||
|
self.config.adb_test_dir.clone(),
|
||||||
|
exe_file.file_name().unwrap().to_str().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
debug!("adb arg: {}", adb_arg);
|
||||||
|
let mut adb = Command::new(adb_path)
|
||||||
|
.args(&["shell", &adb_arg])
|
||||||
|
.stdout(Stdio::piped())
|
||||||
|
.stderr(Stdio::inherit())
|
||||||
|
.spawn()
|
||||||
|
.expect(&format!("failed to exec `{:?}`", adb_path));
|
||||||
|
|
||||||
|
// Wait for the gdbserver to print out "Listening on port ..."
|
||||||
|
// at which point we know that it's started and then we can
|
||||||
|
// execute the debugger below.
|
||||||
|
let mut stdout = BufReader::new(adb.stdout.take().unwrap());
|
||||||
|
let mut line = String::new();
|
||||||
|
loop {
|
||||||
|
line.truncate(0);
|
||||||
|
stdout.read_line(&mut line).unwrap();
|
||||||
|
if line.starts_with("Listening on port 5039") {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
drop(stdout);
|
||||||
|
|
||||||
|
let debugger_script = self.make_out_name("debugger.script");
|
||||||
|
// FIXME (#9639): This needs to handle non-utf8 paths
|
||||||
|
let debugger_opts = vec![
|
||||||
|
"-quiet".to_owned(),
|
||||||
|
"-batch".to_owned(),
|
||||||
|
"-nx".to_owned(),
|
||||||
|
format!("-command={}", debugger_script.to_str().unwrap()),
|
||||||
|
];
|
||||||
|
|
||||||
|
let gdb_path = self.config.gdb.as_ref().unwrap();
|
||||||
|
let Output {
|
||||||
|
status,
|
||||||
|
stdout,
|
||||||
|
stderr,
|
||||||
|
} = Command::new(&gdb_path)
|
||||||
|
.args(&debugger_opts)
|
||||||
|
.output()
|
||||||
|
.expect(&format!("failed to exec `{:?}`", gdb_path));
|
||||||
|
let cmdline = {
|
||||||
|
let mut gdb = Command::new(&format!("{}-gdb", self.config.target));
|
||||||
|
gdb.args(&debugger_opts);
|
||||||
|
let cmdline = self.make_cmdline(&gdb, "");
|
||||||
|
logv(self.config, format!("executing {}", cmdline));
|
||||||
|
cmdline
|
||||||
|
};
|
||||||
|
|
||||||
|
debugger_run_result = ProcRes {
|
||||||
|
status,
|
||||||
|
stdout: String::from_utf8(stdout).unwrap(),
|
||||||
|
stderr: String::from_utf8(stderr).unwrap(),
|
||||||
|
cmdline,
|
||||||
|
};
|
||||||
|
if adb.kill().is_err() {
|
||||||
|
println!("Adb process is already finished.");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let rust_src_root = self
|
||||||
|
.config
|
||||||
|
.find_rust_src_root()
|
||||||
|
.expect("Could not find Rust source root");
|
||||||
|
let rust_pp_module_rel_path = Path::new("./src/etc");
|
||||||
|
let rust_pp_module_abs_path = rust_src_root
|
||||||
|
.join(rust_pp_module_rel_path)
|
||||||
|
.to_str()
|
||||||
|
.unwrap()
|
||||||
|
.to_owned();
|
||||||
|
// write debugger script
|
||||||
|
let mut script_str = String::with_capacity(2048);
|
||||||
|
script_str.push_str(&format!("set charset {}\n", Self::charset()));
|
||||||
|
script_str.push_str("show version\n");
|
||||||
|
|
||||||
|
match self.config.gdb_version {
|
||||||
|
Some(version) => {
|
||||||
|
println!(
|
||||||
|
"NOTE: compiletest thinks it is using GDB version {}",
|
||||||
|
version
|
||||||
|
);
|
||||||
|
|
||||||
|
if version > extract_gdb_version("7.4").unwrap() {
|
||||||
|
// Add the directory containing the pretty printers to
|
||||||
|
// GDB's script auto loading safe path
|
||||||
|
script_str.push_str(&format!(
|
||||||
|
"add-auto-load-safe-path {}\n",
|
||||||
|
rust_pp_module_abs_path.replace(r"\", r"\\")
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
println!(
|
||||||
|
"NOTE: compiletest does not know which version of \
|
||||||
|
GDB it is using"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The following line actually doesn't have to do anything with
|
||||||
|
// pretty printing, it just tells GDB to print values on one line:
|
||||||
|
script_str.push_str("set print pretty off\n");
|
||||||
|
|
||||||
|
// Add the pretty printer directory to GDB's source-file search path
|
||||||
|
script_str.push_str(&format!("directory {}\n", rust_pp_module_abs_path));
|
||||||
|
|
||||||
|
// Load the target executable
|
||||||
|
script_str.push_str(&format!(
|
||||||
|
"file {}\n",
|
||||||
|
exe_file.to_str().unwrap().replace(r"\", r"\\")
|
||||||
|
));
|
||||||
|
|
||||||
|
// Force GDB to print values in the Rust format.
|
||||||
|
if self.config.gdb_native_rust {
|
||||||
|
script_str.push_str("set language rust\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add line breakpoints
|
||||||
|
for line in &breakpoint_lines {
|
||||||
|
script_str.push_str(&format!(
|
||||||
|
"break '{}':{}\n",
|
||||||
|
self.testpaths.file.file_name().unwrap().to_string_lossy(),
|
||||||
|
*line
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
script_str.push_str(&cmds);
|
||||||
|
script_str.push_str("\nquit\n");
|
||||||
|
|
||||||
|
debug!("script_str = {}", script_str);
|
||||||
|
self.dump_output_file(&script_str, "debugger.script");
|
||||||
|
|
||||||
|
let debugger_script = self.make_out_name("debugger.script");
|
||||||
|
|
||||||
|
// FIXME (#9639): This needs to handle non-utf8 paths
|
||||||
|
let debugger_opts = vec![
|
||||||
|
"-quiet".to_owned(),
|
||||||
|
"-batch".to_owned(),
|
||||||
|
"-nx".to_owned(),
|
||||||
|
format!("-command={}", debugger_script.to_str().unwrap()),
|
||||||
|
];
|
||||||
|
|
||||||
|
let mut gdb = Command::new(self.config.gdb.as_ref().unwrap());
|
||||||
|
gdb.args(&debugger_opts)
|
||||||
|
.env("PYTHONPATH", rust_pp_module_abs_path);
|
||||||
|
|
||||||
|
debugger_run_result = self.compose_and_run(
|
||||||
|
gdb,
|
||||||
|
self.config.run_lib_path.to_str().unwrap(),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if !debugger_run_result.status.success() {
|
if !debugger_run_result.status.success() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user