diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 630993d829120..677916b53989b 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -69,6 +69,7 @@ #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/", + issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/", test(no_crate_inject))] #![no_std] #![cfg_attr(not(stage0), needs_allocator)] diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index 702b01f0e2eee..2639e6dce468f 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -26,6 +26,7 @@ html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/", html_playground_url = "https://play.rust-lang.org/", + issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/", test(no_crate_inject))] #![allow(trivial_casts)] diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index ae85e2712ce81..de7bdd410b7c8 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -58,7 +58,8 @@ #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/", - html_playground_url = "https://play.rust-lang.org/")] + html_playground_url = "https://play.rust-lang.org/", + issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/")] #![doc(test(no_crate_inject))] #![no_core] diff --git a/src/liblibc/lib.rs b/src/liblibc/lib.rs index 08f0b2aa895b0..6273c1214ec4e 100644 --- a/src/liblibc/lib.rs +++ b/src/liblibc/lib.rs @@ -21,7 +21,8 @@ #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/", - html_playground_url = "https://play.rust-lang.org/")] + html_playground_url = "https://play.rust-lang.org/", + issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/")] #![cfg_attr(test, feature(test))] //! Bindings for the C standard library and other platform libraries diff --git a/src/librustc_unicode/lib.rs b/src/librustc_unicode/lib.rs index 99284fee2d9d5..d046393cdeb08 100644 --- a/src/librustc_unicode/lib.rs +++ b/src/librustc_unicode/lib.rs @@ -30,6 +30,7 @@ html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/", html_playground_url = "https://play.rust-lang.org/", + issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/", test(no_crate_inject))] #![no_std] diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 04b1f8ee1b1d3..05be445820d10 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2688,7 +2688,8 @@ pub struct Stability { pub feature: String, pub since: String, pub deprecated_since: String, - pub reason: String + pub reason: String, + pub issue: Option } impl Clean for attr::Stability { @@ -2702,6 +2703,7 @@ impl Clean for attr::Stability { |istr| istr.to_string()), reason: self.reason.as_ref().map_or("".to_string(), |interned| interned.to_string()), + issue: self.issue, } } } @@ -2717,6 +2719,7 @@ impl<'a> Clean for &'a attr::Stability { |istr| istr.to_string()), reason: self.reason.as_ref().map_or("".to_string(), |interned| interned.to_string()), + issue: self.issue, } } } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 83e77a5c03865..d2c8078e62a40 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -103,6 +103,9 @@ pub struct Context { pub render_redirect_pages: bool, /// All the passes that were run on this crate. pub passes: HashSet, + /// The base-URL of the issue tracker for when an item has been tagged with + /// an issue number. + pub issue_tracker_base_url: Option, } /// Indicates where an external crate can be found. @@ -323,6 +326,7 @@ pub fn run(mut krate: clean::Crate, }, include_sources: true, render_redirect_pages: false, + issue_tracker_base_url: None, }; try!(mkdir(&cx.dst)); @@ -352,6 +356,10 @@ pub fn run(mut krate: clean::Crate, } }); } + clean::NameValue(ref x, ref s) + if "issue_tracker_base_url" == *x => { + cx.issue_tracker_base_url = Some(s.to_string()); + } clean::Word(ref x) if "html_no_source" == *x => { cx.include_sources = false; @@ -1485,16 +1493,16 @@ impl<'a> fmt::Display for Item<'a> { item_module(fmt, self.cx, self.item, &m.items) } clean::FunctionItem(ref f) | clean::ForeignFunctionItem(ref f) => - item_function(fmt, self.item, f), + item_function(fmt, self.cx, self.item, f), clean::TraitItem(ref t) => item_trait(fmt, self.cx, self.item, t), - clean::StructItem(ref s) => item_struct(fmt, self.item, s), - clean::EnumItem(ref e) => item_enum(fmt, self.item, e), - clean::TypedefItem(ref t, _) => item_typedef(fmt, self.item, t), - clean::MacroItem(ref m) => item_macro(fmt, self.item, m), - clean::PrimitiveItem(ref p) => item_primitive(fmt, self.item, p), + clean::StructItem(ref s) => item_struct(fmt, self.cx, self.item, s), + 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::PrimitiveItem(ref p) => item_primitive(fmt, self.cx, self.item, p), clean::StaticItem(ref i) | clean::ForeignStaticItem(ref i) => - item_static(fmt, self.item, i), - clean::ConstantItem(ref c) => item_constant(fmt, self.item, c), + item_static(fmt, self.cx, self.item, i), + clean::ConstantItem(ref c) => item_constant(fmt, self.cx, self.item, c), _ => Ok(()) } } @@ -1537,8 +1545,8 @@ fn plain_summary_line(s: Option<&str>) -> String { markdown::plain_summary_line(&line[..]) } -fn document(w: &mut fmt::Formatter, item: &clean::Item) -> fmt::Result { - if let Some(s) = short_stability(item, true) { +fn document(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item) -> fmt::Result { + if let Some(s) = short_stability(item, cx, true) { try!(write!(w, "
{}
", s)); } if let Some(s) = item.doc_value() { @@ -1549,7 +1557,7 @@ fn document(w: &mut fmt::Formatter, item: &clean::Item) -> fmt::Result { fn item_module(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item, items: &[clean::Item]) -> fmt::Result { - try!(document(w, item)); + try!(document(w, cx, item)); let mut indices = (0..items.len()).filter(|i| { !cx.ignore_private_item(&items[*i]) @@ -1657,7 +1665,7 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context, _ => { if myitem.name.is_none() { continue } - let stab_docs = if let Some(s) = short_stability(myitem, false) { + let stab_docs = if let Some(s) = short_stability(myitem, cx, false) { format!("[{}]", s) } else { String::new() @@ -1685,7 +1693,7 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context, write!(w, "") } -fn short_stability(item: &clean::Item, show_reason: bool) -> Option { +fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Option { item.stability.as_ref().and_then(|stab| { let reason = if show_reason && !stab.reason.is_empty() { format!(": {}", stab.reason) @@ -1700,7 +1708,22 @@ fn short_stability(item: &clean::Item, show_reason: bool) -> Option { }; format!("Deprecated{}{}", since, Markdown(&reason)) } else if stab.level == attr::Unstable { - format!("Unstable{}", Markdown(&reason)) + let unstable_extra = if show_reason { + match (!stab.feature.is_empty(), &cx.issue_tracker_base_url, stab.issue) { + (true, &Some(ref tracker_url), Some(issue_no)) => + format!(" ({} #{})", + Escape(&stab.feature), tracker_url, issue_no, issue_no), + (false, &Some(ref tracker_url), Some(issue_no)) => + format!(" (#{})", Escape(&tracker_url), issue_no, + issue_no), + (true, _, _) => + format!(" ({})", Escape(&stab.feature)), + _ => String::new(), + } + } else { + String::new() + }; + format!("Unstable{}{}", unstable_extra, Markdown(&reason)) } else { return None }; @@ -1720,7 +1743,7 @@ impl<'a> fmt::Display for Initializer<'a> { } } -fn item_constant(w: &mut fmt::Formatter, it: &clean::Item, +fn item_constant(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, c: &clean::Constant) -> fmt::Result { try!(write!(w, "
{vis}const \
                     {name}: {typ}{init}
", @@ -1728,10 +1751,10 @@ fn item_constant(w: &mut fmt::Formatter, it: &clean::Item, name = it.name.as_ref().unwrap(), typ = c.type_, init = Initializer(&c.expr))); - document(w, it) + document(w, cx, it) } -fn item_static(w: &mut fmt::Formatter, it: &clean::Item, +fn item_static(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, s: &clean::Static) -> fmt::Result { try!(write!(w, "
{vis}static {mutability}\
                     {name}: {typ}{init}
", @@ -1740,10 +1763,10 @@ fn item_static(w: &mut fmt::Formatter, it: &clean::Item, name = it.name.as_ref().unwrap(), typ = s.type_, init = Initializer(&s.expr))); - document(w, it) + document(w, cx, it) } -fn item_function(w: &mut fmt::Formatter, it: &clean::Item, +fn item_function(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, f: &clean::Function) -> fmt::Result { try!(write!(w, "
{vis}{unsafety}{abi}{constness}fn \
                     {name}{generics}{decl}{where_clause}
", @@ -1755,7 +1778,7 @@ fn item_function(w: &mut fmt::Formatter, it: &clean::Item, generics = f.generics, where_clause = WhereClause(&f.generics), decl = f.decl)); - document(w, it) + document(w, cx, it) } fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, @@ -1832,9 +1855,9 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, try!(write!(w, "")); // Trait documentation - try!(document(w, it)); + try!(document(w, cx, it)); - fn trait_item(w: &mut fmt::Formatter, m: &clean::Item) + fn trait_item(w: &mut fmt::Formatter, cx: &Context, m: &clean::Item) -> fmt::Result { try!(write!(w, "

", ty = shortty(m), @@ -1842,7 +1865,7 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, stab = m.stability_class())); try!(render_assoc_item(w, m, AssocItemLink::Anchor)); try!(write!(w, "

")); - try!(document(w, m)); + try!(document(w, cx, m)); Ok(()) } @@ -1852,7 +1875,7 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
")); for t in &types { - try!(trait_item(w, *t)); + try!(trait_item(w, cx, *t)); } try!(write!(w, "
")); } @@ -1863,7 +1886,7 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
")); for t in &consts { - try!(trait_item(w, *t)); + try!(trait_item(w, cx, *t)); } try!(write!(w, "
")); } @@ -1875,7 +1898,7 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
")); for m in &required { - try!(trait_item(w, *m)); + try!(trait_item(w, cx, *m)); } try!(write!(w, "
")); } @@ -1885,13 +1908,13 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
")); for m in &provided { - try!(trait_item(w, *m)); + try!(trait_item(w, cx, *m)); } try!(write!(w, "
")); } // If there are methods directly on this trait object, render them here. - try!(render_assoc_items(w, it.def_id, AssocItemRender::All)); + try!(render_assoc_items(w, cx, it.def_id, AssocItemRender::All)); let cache = cache(); try!(write!(w, " @@ -2003,7 +2026,7 @@ fn render_assoc_item(w: &mut fmt::Formatter, meth: &clean::Item, } } -fn item_struct(w: &mut fmt::Formatter, it: &clean::Item, +fn item_struct(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, s: &clean::Struct) -> fmt::Result { try!(write!(w, "
"));
     try!(render_attributes(w, it));
@@ -2016,7 +2039,7 @@ fn item_struct(w: &mut fmt::Formatter, it: &clean::Item,
                        true));
     try!(write!(w, "
")); - try!(document(w, it)); + try!(document(w, cx, it)); let mut fields = s.fields.iter().filter(|f| { match f.inner { clean::StructFieldItem(clean::HiddenStructField) => false, @@ -2033,16 +2056,16 @@ fn item_struct(w: &mut fmt::Formatter, it: &clean::Item, {name}", stab = field.stability_class(), name = field.name.as_ref().unwrap())); - try!(document(w, field)); + try!(document(w, cx, field)); try!(write!(w, "")); } try!(write!(w, "")); } } - render_assoc_items(w, it.def_id, AssocItemRender::All) + render_assoc_items(w, cx, it.def_id, AssocItemRender::All) } -fn item_enum(w: &mut fmt::Formatter, it: &clean::Item, +fn item_enum(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, e: &clean::Enum) -> fmt::Result { try!(write!(w, "
"));
     try!(render_attributes(w, it));
@@ -2095,13 +2118,13 @@ fn item_enum(w: &mut fmt::Formatter, it: &clean::Item,
     }
     try!(write!(w, "
")); - try!(document(w, it)); + try!(document(w, cx, it)); if !e.variants.is_empty() { try!(write!(w, "

Variants

\n")); for variant in &e.variants { try!(write!(w, "")); } try!(write!(w, "
{name}", name = variant.name.as_ref().unwrap())); - try!(document(w, variant)); + try!(document(w, cx, variant)); match variant.inner { clean::VariantItem(ref var) => { match var.kind { @@ -2123,7 +2146,7 @@ fn item_enum(w: &mut fmt::Formatter, it: &clean::Item, {f}", v = variant.name.as_ref().unwrap(), f = field.name.as_ref().unwrap())); - try!(document(w, field)); + try!(document(w, cx, field)); try!(write!(w, "
")); @@ -2138,7 +2161,7 @@ fn item_enum(w: &mut fmt::Formatter, it: &clean::Item, try!(write!(w, "")); } - try!(render_assoc_items(w, it.def_id, AssocItemRender::All)); + try!(render_assoc_items(w, cx, it.def_id, AssocItemRender::All)); Ok(()) } @@ -2233,6 +2256,7 @@ enum AssocItemRender<'a> { } fn render_assoc_items(w: &mut fmt::Formatter, + cx: &Context, it: ast::DefId, what: AssocItemRender) -> fmt::Result { let c = cache(); @@ -2256,7 +2280,7 @@ fn render_assoc_items(w: &mut fmt::Formatter, } }; for i in &non_trait { - try!(render_impl(w, i, AssocItemLink::Anchor, render_header)); + try!(render_impl(w, cx, i, AssocItemLink::Anchor, render_header)); } } if let AssocItemRender::DerefFor { .. } = what { @@ -2272,7 +2296,7 @@ fn render_assoc_items(w: &mut fmt::Formatter, } }); if let Some(impl_) = deref_impl { - try!(render_deref_methods(w, impl_)); + try!(render_deref_methods(w, cx, impl_)); } try!(write!(w, "

Trait \ Implementations

")); @@ -2281,7 +2305,7 @@ fn render_assoc_items(w: &mut fmt::Formatter, }); for i in &manual { let did = i.trait_did().unwrap(); - try!(render_impl(w, i, AssocItemLink::GotoSource(did), true)); + try!(render_impl(w, cx, i, AssocItemLink::GotoSource(did), true)); } if !derived.is_empty() { try!(write!(w, "

\ @@ -2289,14 +2313,14 @@ fn render_assoc_items(w: &mut fmt::Formatter,

")); for i in &derived { let did = i.trait_did().unwrap(); - try!(render_impl(w, i, AssocItemLink::GotoSource(did), true)); + try!(render_impl(w, cx, i, AssocItemLink::GotoSource(did), true)); } } } Ok(()) } -fn render_deref_methods(w: &mut fmt::Formatter, impl_: &Impl) -> fmt::Result { +fn render_deref_methods(w: &mut fmt::Formatter, cx: &Context, impl_: &Impl) -> fmt::Result { let deref_type = impl_.impl_.trait_.as_ref().unwrap(); let target = impl_.impl_.items.iter().filter_map(|item| { match item.inner { @@ -2306,12 +2330,12 @@ fn render_deref_methods(w: &mut fmt::Formatter, impl_: &Impl) -> fmt::Result { }).next().expect("Expected associated type binding"); let what = AssocItemRender::DerefFor { trait_: deref_type, type_: target }; match *target { - clean::ResolvedPath { did, .. } => render_assoc_items(w, did, what), + clean::ResolvedPath { did, .. } => render_assoc_items(w, cx, did, what), _ => { if let Some(prim) = target.primitive_type() { if let Some(c) = cache().primitive_locations.get(&prim) { let did = ast::DefId { krate: *c, node: prim.to_node_id() }; - try!(render_assoc_items(w, did, what)); + try!(render_assoc_items(w, cx, did, what)); } } Ok(()) @@ -2322,7 +2346,7 @@ fn render_deref_methods(w: &mut fmt::Formatter, impl_: &Impl) -> fmt::Result { // Render_header is false when we are rendering a `Deref` impl and true // otherwise. If render_header is false, we will avoid rendering static // methods, since they are not accessible for the type implementing `Deref` -fn render_impl(w: &mut fmt::Formatter, i: &Impl, link: AssocItemLink, +fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLink, render_header: bool) -> fmt::Result { if render_header { try!(write!(w, "

{}

", i.impl_)); @@ -2331,7 +2355,7 @@ fn render_impl(w: &mut fmt::Formatter, i: &Impl, link: AssocItemLink, } } - fn doctraititem(w: &mut fmt::Formatter, item: &clean::Item, + fn doctraititem(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item, link: AssocItemLink, render_static: bool) -> fmt::Result { match item.inner { clean::MethodItem(..) | clean::TyMethodItem(..) => { @@ -2381,7 +2405,7 @@ fn render_impl(w: &mut fmt::Formatter, i: &Impl, link: AssocItemLink, if is_static_method(item) && !render_static { Ok(()) } else { - document(w, item) + document(w, cx, item) } } else { Ok(()) @@ -2398,10 +2422,11 @@ fn render_impl(w: &mut fmt::Formatter, i: &Impl, link: AssocItemLink, try!(write!(w, "
")); for trait_item in &i.impl_.items { - try!(doctraititem(w, trait_item, link, render_header)); + try!(doctraititem(w, cx, trait_item, link, render_header)); } fn render_default_items(w: &mut fmt::Formatter, + cx: &Context, did: ast::DefId, t: &clean::Trait, i: &clean::Impl, @@ -2413,7 +2438,7 @@ fn render_impl(w: &mut fmt::Formatter, i: &Impl, link: AssocItemLink, None => {} } - try!(doctraititem(w, trait_item, AssocItemLink::GotoSource(did), render_static)); + try!(doctraititem(w, cx, trait_item, AssocItemLink::GotoSource(did), render_static)); } Ok(()) } @@ -2424,7 +2449,7 @@ fn render_impl(w: &mut fmt::Formatter, i: &Impl, link: AssocItemLink, // for them work. if let Some(clean::ResolvedPath { did, .. }) = i.impl_.trait_ { if let Some(t) = cache().traits.get(&did) { - try!(render_default_items(w, did, t, &i.impl_, render_header)); + try!(render_default_items(w, cx, did, t, &i.impl_, render_header)); } } @@ -2432,7 +2457,7 @@ fn render_impl(w: &mut fmt::Formatter, i: &Impl, link: AssocItemLink, Ok(()) } -fn item_typedef(w: &mut fmt::Formatter, it: &clean::Item, +fn item_typedef(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, t: &clean::Typedef) -> fmt::Result { try!(write!(w, "
type {}{}{where_clause} = {type_};
", it.name.as_ref().unwrap(), @@ -2440,7 +2465,7 @@ fn item_typedef(w: &mut fmt::Formatter, it: &clean::Item, where_clause = WhereClause(&t.generics), type_ = t.type_)); - document(w, it) + document(w, cx, it) } impl<'a> fmt::Display for Sidebar<'a> { @@ -2511,19 +2536,19 @@ impl<'a> fmt::Display for Source<'a> { } } -fn item_macro(w: &mut fmt::Formatter, it: &clean::Item, +fn item_macro(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, t: &clean::Macro) -> fmt::Result { try!(w.write_str(&highlight::highlight(&t.source, Some("macro"), None))); - document(w, it) + document(w, cx, it) } -fn item_primitive(w: &mut fmt::Formatter, +fn item_primitive(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, _p: &clean::PrimitiveType) -> fmt::Result { - try!(document(w, it)); - render_assoc_items(w, it.def_id, AssocItemRender::All) + try!(document(w, cx, it)); + render_assoc_items(w, cx, it.def_id, AssocItemRender::All) } fn get_basic_keywords() -> &'static str { diff --git a/src/librustdoc/html/static/main.css b/src/librustdoc/html/static/main.css index 774d413fffa15..c98b7825795b5 100644 --- a/src/librustdoc/html/static/main.css +++ b/src/librustdoc/html/static/main.css @@ -355,6 +355,10 @@ nav.sub { margin-left: 20px; } +.content .stability code { + font-size: 90%; +} + nav { border-bottom: 1px solid #e0e0e0; padding-bottom: 10px; @@ -387,11 +391,11 @@ a { background: transparent; } -.docblock a { +.docblock a, .stability a { color: #4e8bca; } -.docblock a:hover { +.docblock a:hover, .stability a { text-decoration: underline; } diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 655fa04c2644e..ca293347d04da 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -195,6 +195,7 @@ html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/", html_playground_url = "https://play.rust-lang.org/", + issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/", test(no_crate_inject, attr(deny(warnings))), test(attr(allow(dead_code, deprecated, unused_variables, unused_mut))))] diff --git a/src/test/rustdoc/issue-27759.rs b/src/test/rustdoc/issue-27759.rs new file mode 100644 index 0000000000000..2d5f97b1f9331 --- /dev/null +++ b/src/test/rustdoc/issue-27759.rs @@ -0,0 +1,25 @@ +// Copyright 2015 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(staged_api)] +#![staged_api] +#![doc(issue_tracker_base_url = "http://issue_url/")] + +// @has issue_27759/unstable/index.html +// @has - 'test' +// @has - '#27759' +#[unstable(feature="test", issue="27759")] +pub mod unstable { + // @has issue_27759/unstable/fn.issue.html + // @has - 'test_function' + // @has - '#1234567890' + #[unstable(feature="test_function", issue="1234567890")] + pub fn issue() {} +}