diff --git a/RELEASES.md b/RELEASES.md
index 819c9184364..08470e731d8 100644
--- a/RELEASES.md
+++ b/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)
==========================
diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs
index d09a545aecf..0224560af4c 100644
--- a/src/libcore/pin.rs
+++ b/src/libcore/pin.rs
@@ -293,21 +293,21 @@ where
}
#[unstable(feature = "pin", issue = "49150")]
-impl<'a, P: fmt::Debug> fmt::Debug for Pin
{
+impl fmt::Debug for Pin {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(&self.pointer, f)
}
}
#[unstable(feature = "pin", issue = "49150")]
-impl<'a, P: fmt::Display> fmt::Display for Pin
{
+impl fmt::Display for Pin {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&self.pointer, f)
}
}
#[unstable(feature = "pin", issue = "49150")]
-impl<'a, P: fmt::Pointer> fmt::Pointer for Pin
{
+impl fmt::Pointer for Pin {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Pointer::fmt(&self.pointer, f)
}
@@ -319,10 +319,10 @@ impl<'a, P: fmt::Pointer> fmt::Pointer for Pin
{
// for other reasons, though, so we just need to take care not to allow such
// impls to land in std.
#[unstable(feature = "pin", issue = "49150")]
-impl<'a, P, U> CoerceUnsized> for Pin
+impl
CoerceUnsized> for Pin
where
P: CoerceUnsized,
{}
#[unstable(feature = "pin", issue = "49150")]
-impl<'a, P> Unpin for Pin
{}
+impl
Unpin for Pin
{}
diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs
index 23667d1b331..6187e091319 100644
--- a/src/librustc_mir/hair/pattern/check_match.rs
+++ b/src/librustc_mir/hair/pattern/check_match.rs
@@ -539,7 +539,7 @@ fn check_legality_of_move_bindings(cx: &MatchVisitor,
.emit();
} 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,
- "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");
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 \
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 91b0e9c1dca..5e3f7470099 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -42,8 +42,9 @@ use rustc::lint;
use rustc::hir::def::*;
use rustc::hir::def::Namespace::*;
use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, DefId};
-use rustc::ty;
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_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).
current_self_type: Option,
+ /// The current self item if inside an ADT (used for better errors).
+ current_self_item: Option,
+
/// The idents for the primitive types.
primitive_type_table: PrimitiveTypeTable,
@@ -1710,6 +1714,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
current_trait_ref: None,
current_self_type: None,
+ current_self_item: None,
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) {
- self.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind), |this| {
- let item_def_id = this.definitions.local_def_id(item.id);
- if this.session.features_untracked().self_in_typedefs {
- this.with_self_rib(Def::SelfTy(None, Some(item_def_id)), |this| {
+ self.with_current_self_item(item, |this| {
+ this.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind), |this| {
+ let item_def_id = this.definitions.local_def_id(item.id);
+ 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);
- });
- } else {
- visit::walk_item(this, item);
- }
+ }
+ });
});
}
@@ -2435,6 +2442,15 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
result
}
+ fn with_current_self_item(&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`)
fn with_optional_trait_ref(&mut self, opt_trait_ref: Option<&TraitRef>, f: F) -> T
where F: FnOnce(&mut Resolver, Option) -> T
@@ -3004,6 +3020,10 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
"traits and impls"
};
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());
}
if is_self_value(path, ns) {
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index 4af3790450c..ec4483204f0 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -17,6 +17,9 @@ use check::FnCtxt;
use hir::def_id::DefId;
use hir::def::Def;
use namespace::Namespace;
+use rustc::hir;
+use rustc::lint;
+use rustc::session::config::nightly_options;
use rustc::ty::subst::{Subst, Substs};
use rustc::traits::{self, ObligationCause};
use rustc::ty::{self, Ty, ToPolyTraitRef, ToPredicate, TraitRef, TypeFoldable};
@@ -28,8 +31,6 @@ use rustc::middle::stability;
use syntax::ast;
use syntax::util::lev_distance::{lev_distance, find_best_match_for_name};
use syntax_pos::{Span, symbol::Symbol};
-use rustc::hir;
-use rustc::lint;
use std::mem;
use std::ops::Deref;
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),
));
- if ::rustc::session::config::nightly_options::is_nightly_build() {
+ if nightly_options::is_nightly_build() {
for (candidate, feature) in unstable_candidates {
- diag.note(&format!(
+ diag.help(&format!(
"add #![feature({})] to the crate attributes to enable `{}`",
feature,
self.tcx.item_path_str(candidate.item.def_id),
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 1ea130cf16a..a435712ac3d 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -13,7 +13,7 @@
use std::iter::once;
use syntax::ast;
-use syntax::ext::base::MacroKind;
+use syntax::ext::base::{MacroKind, SyntaxExtension};
use syntax_pos::Span;
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);
clean::ConstantItem(build_const(cx, did))
}
- // FIXME(misdreavus): if attributes/derives come down here we should probably document them
- // separately
+ // FIXME: proc-macros don't propagate attributes or spans across crates, so they look empty
Def::Macro(did, MacroKind::Bang) => {
- record_extern_fqn(cx, did, clean::TypeKind::Macro);
- if let Some(mac) = build_macro(cx, did, name) {
- clean::MacroItem(mac)
+ let mac = build_macro(cx, did, name);
+ if let clean::MacroItem(..) = mac {
+ record_extern_fqn(cx, did, clean::TypeKind::Macro);
+ mac
} else {
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 {
+fn build_macro(cx: &DocContext, did: DefId, name: ast::Name) -> clean::ItemEnum {
let imported_from = cx.tcx.original_crate_name(did.krate);
- let def = match cx.cstore.load_macro_untracked(did, cx.sess()) {
- LoadedMacro::MacroDef(macro_def) => macro_def,
- // FIXME(jseyfried): document proc macro re-exports
- LoadedMacro::ProcMacro(..) => return None,
- };
+ match cx.cstore.load_macro_untracked(did, cx.sess()) {
+ LoadedMacro::MacroDef(def) => {
+ let matchers: hir::HirVec = if let ast::ItemKind::MacroDef(ref def) = def.node {
+ let tts: Vec<_> = def.stream().into_trees().collect();
+ tts.chunks(4).map(|arm| arm[0].span()).collect()
+ } else {
+ unreachable!()
+ };
- let matchers: hir::HirVec = if let ast::ItemKind::MacroDef(ref def) = def.node {
- let tts: Vec<_> = def.stream().into_trees().collect();
- tts.chunks(4).map(|arm| arm[0].span()).collect()
- } else {
- unreachable!()
- };
+ let source = format!("macro_rules! {} {{\n{}}}",
+ name.clean(cx),
+ matchers.iter().map(|span| {
+ format!(" {} => {{ ... }};\n", span.to_src(cx))
+ }).collect::());
- let source = format!("macro_rules! {} {{\n{}}}",
- name.clean(cx),
- matchers.iter().map(|span| {
- format!(" {} => {{ ... }};\n", span.to_src(cx))
- }).collect::());
+ clean::MacroItem(clean::Macro {
+ source,
+ imported_from: Some(imported_from).clean(cx),
+ })
+ }
+ 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
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 537905c3008..a91f2fd7474 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -21,6 +21,7 @@ pub use self::Visibility::{Public, Inherited};
use rustc_target::spec::abi::Abi;
use syntax::ast::{self, AttrStyle, Ident};
use syntax::attr;
+use syntax::ext::base::MacroKind;
use syntax::source_map::{dummy_spanned, Spanned};
use syntax::ptr::P;
use syntax::symbol::keywords::{self, Keyword};
@@ -527,6 +528,7 @@ pub enum ItemEnum {
/// `type`s from an extern block
ForeignTypeItem,
MacroItem(Macro),
+ ProcMacroItem(ProcMacro),
PrimitiveItem(PrimitiveType),
AssociatedConstItem(Type, Option),
AssociatedTypeItem(Vec, Option),
@@ -588,6 +590,7 @@ impl Clean- for doctree::Module {
items.extend(self.traits.iter().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.proc_macros.iter().map(|x| x.clean(cx)));
// determine if we should display the inner contents or
// the outer `mod` item for the source code.
@@ -2191,6 +2194,8 @@ pub enum TypeKind {
Typedef,
Foreign,
Macro,
+ Attr,
+ Derive,
}
pub trait GetDefId {
@@ -3727,7 +3732,12 @@ pub fn register_def(cx: &DocContext, def: Def) -> DefId {
Def::Static(i, _) => (i, TypeKind::Static),
Def::Variant(i) => (cx.tcx.parent_def_id(i).expect("cannot get parent def id"),
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(impl_def_id)) => {
return impl_def_id
@@ -3782,6 +3792,30 @@ impl Clean
- for doctree::Macro {
}
}
+#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+pub struct ProcMacro {
+ pub kind: MacroKind,
+ pub helpers: Vec,
+}
+
+impl Clean
- 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)]
pub struct Stability {
pub level: stability::StabilityLevel,
diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs
index dd1e1e99957..4a6a4ee09ea 100644
--- a/src/librustdoc/doctree.rs
+++ b/src/librustdoc/doctree.rs
@@ -15,6 +15,7 @@ pub use self::StructType::*;
use syntax::ast;
use syntax::ast::{Name, NodeId};
use syntax::attr;
+use syntax::ext::base::MacroKind;
use syntax::ptr::P;
use syntax::source_map::Spanned;
use syntax_pos::{self, Span};
@@ -46,6 +47,7 @@ pub struct Module {
pub impls: Vec,
pub foreigns: Vec,
pub macros: Vec,
+ pub proc_macros: Vec,
pub is_crate: bool,
}
@@ -75,6 +77,7 @@ impl Module {
impls : Vec::new(),
foreigns : Vec::new(),
macros : Vec::new(),
+ proc_macros: Vec::new(),
is_crate : false,
}
}
@@ -264,6 +267,17 @@ pub struct Import {
pub whence: Span,
}
+pub struct ProcMacro {
+ pub name: Name,
+ pub id: NodeId,
+ pub kind: MacroKind,
+ pub helpers: Vec,
+ pub attrs: hir::HirVec,
+ pub whence: Span,
+ pub stab: Option,
+ pub depr: Option,
+}
+
pub fn struct_type_from_def(vdata: &hir::VariantData) -> StructType {
match *vdata {
hir::VariantData::Struct(..) => Plain,
diff --git a/src/librustdoc/html/item_type.rs b/src/librustdoc/html/item_type.rs
index a5131e327e0..acb8f6a66df 100644
--- a/src/librustdoc/html/item_type.rs
+++ b/src/librustdoc/html/item_type.rs
@@ -11,6 +11,7 @@
//! Item types.
use std::fmt;
+use syntax::ext::base::MacroKind;
use clean;
/// 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.
/// Consequently, every change to this type should be synchronized to
/// 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)]
pub enum ItemType {
Module = 0,
@@ -44,6 +50,8 @@ pub enum ItemType {
ForeignType = 20,
Keyword = 21,
Existential = 22,
+ ProcAttribute = 23,
+ ProcDerive = 24,
}
@@ -88,6 +96,12 @@ impl<'a> From<&'a clean::Item> for ItemType {
clean::AssociatedTypeItem(..) => ItemType::AssociatedType,
clean::ForeignTypeItem => ItemType::ForeignType,
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!(),
}
}
@@ -107,7 +121,9 @@ impl From for ItemType {
clean::TypeKind::Variant => ItemType::Variant,
clean::TypeKind::Typedef => ItemType::Typedef,
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::Keyword => "keyword",
ItemType::Existential => "existential",
+ ItemType::ProcAttribute => "attr",
+ ItemType::ProcDerive => "derive",
}
}
@@ -166,7 +184,9 @@ impl ItemType {
ItemType::Constant |
ItemType::AssociatedConst => NameSpace::Value,
- ItemType::Macro => NameSpace::Macro,
+ ItemType::Macro |
+ ItemType::ProcAttribute |
+ ItemType::ProcDerive => NameSpace::Macro,
ItemType::Keyword => NameSpace::Keyword,
}
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index 3e1720f8b8a..1c61e73fae0 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -56,6 +56,7 @@ use externalfiles::ExternalHtml;
use serialize::json::{ToJson, Json, as_json};
use syntax::ast;
+use syntax::ext::base::MacroKind;
use syntax::source_map::FileName;
use syntax::feature_gate::UnstableFeatures;
use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId};
@@ -1595,6 +1596,8 @@ struct AllTypes {
statics: FxHashSet,
constants: FxHashSet,
keywords: FxHashSet,
+ attributes: FxHashSet,
+ derives: FxHashSet,
}
impl AllTypes {
@@ -1613,6 +1616,8 @@ impl AllTypes {
statics: new_set(100),
constants: 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::Static => self.statics.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,
};
}
@@ -1673,6 +1680,8 @@ impl fmt::Display for AllTypes {
print_entries(f, &self.primitives, "Primitives", "primitives")?;
print_entries(f, &self.traits, "Traits", "traits")?;
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.typedefs, "Typedefs", "typedefs")?;
print_entries(f, &self.existentials, "Existentials", "existentials")?;
@@ -2155,6 +2164,12 @@ impl<'a> fmt::Display for Item<'a> {
clean::EnumItem(..) => write!(fmt, "Enum ")?,
clean::TypedefItem(..) => write!(fmt, "Type Definition ")?,
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::StaticItem(..) | clean::ForeignStaticItem(..) => write!(fmt, "Static ")?,
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::TypedefItem(ref t, _) => item_typedef(fmt, self.cx, self.item, t),
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::StaticItem(ref i) | clean::ForeignStaticItem(ref i) =>
item_static(fmt, self.cx, self.item, i),
@@ -4079,11 +4095,12 @@ impl<'a> fmt::Display for Sidebar<'a> {
write!(fmt,
"
-
See all {}'s items
",
- version,
- it.name.as_ref().unwrap())?;
+ ",
+ version)?;
}
+
+ write!(fmt, "See all {}'s items
",
+ it.name.as_ref().expect("crates always have a name"))?;
}
write!(fmt, "