Skip to content

Commit 421a211

Browse files
committedNov 21, 2017
Auto merge of #45039 - QuietMisdreavus:doc-spotlight, r=GuillaumeGomez,QuietMisdreavus
show in docs whether the return type of a function impls Iterator/Read/Write Closes #25928 This PR makes it so that when rustdoc documents a function, it checks the return type to see whether it implements a handful of specific traits. If so, it will print the impl and any associated types. Rather than doing this via a whitelist within rustdoc, i chose to do this by a new `#[doc]` attribute parameter, so things like `Future` could tap into this if desired. ### Known shortcomings ~~The printing of impls currently uses the `where` class over the whole thing to shrink the font size relative to the function definition itself. Naturally, when the impl has a where clause of its own, it gets shrunken even further:~~ (This is no longer a problem because the design changed and rendered this concern moot.) The lookup currently just looks at the top-level type, not looking inside things like Result or Option, which renders the spotlights on Read/Write a little less useful: <details><summary>`File::{open, create}` don't have spotlight info (pic of old design)</summary> ![image](https://user-images.githubusercontent.com/5217170/31209495-e59d027e-a950-11e7-9998-ceefceb71c07.png) </details> All three of the initially spotlighted traits are generically implemented on `&mut` references. Rustdoc currently treats a `&mut T` reference-to-a-generic as an impl on the reference primitive itself. `&mut Self` counts as a generic in the eyes of rustdoc. All this combines to create this lovely scene on `Iterator::by_ref`: <details><summary>`Iterator::by_ref` spotlights Iterator, Read, and Write (pic of old design)</summary> ![image](https://user-images.githubusercontent.com/5217170/31209554-50b271ca-a951-11e7-928b-4f83416c8681.png) </details>
2 parents 1e44fee + 6047a03 commit 421a211

File tree

13 files changed

+345
-14
lines changed

13 files changed

+345
-14
lines changed
 
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# `doc_spotlight`
2+
3+
The tracking issue for this feature is: [#45040]
4+
5+
The `doc_spotlight` feature allows the use of the `spotlight` parameter to the `#[doc]` attribute,
6+
to "spotlight" a specific trait on the return values of functions. Adding a `#[doc(spotlight)]`
7+
attribute to a trait definition will make rustdoc print extra information for functions which return
8+
a type that implements that trait. This attribute is applied to the `Iterator`, `io::Read`, and
9+
`io::Write` traits in the standard library.
10+
11+
You can do this on your own traits, like this:
12+
13+
```
14+
#![feature(doc_spotlight)]
15+
16+
#[doc(spotlight)]
17+
pub trait MyTrait {}
18+
19+
pub struct MyStruct;
20+
impl MyTrait for MyStruct {}
21+
22+
/// The docs for this function will have an extra line about `MyStruct` implementing `MyTrait`,
23+
/// without having to write that yourself!
24+
pub fn my_fn() -> MyStruct { MyStruct }
25+
```
26+
27+
This feature was originally implemented in PR [#45039].
28+
29+
[#45040]: https://github.com/rust-lang/rust/issues/45040
30+
[#45039]: https://github.com/rust-lang/rust/pull/45039

‎src/libcore/iter/iterator.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ fn _assert_is_object_safe(_: &Iterator<Item=()>) {}
3030
#[stable(feature = "rust1", since = "1.0.0")]
3131
#[rustc_on_unimplemented = "`{Self}` is not an iterator; maybe try calling \
3232
`.iter()` or a similar method"]
33+
#[doc(spotlight)]
3334
pub trait Iterator {
3435
/// The type of the elements being iterated over.
3536
#[stable(feature = "rust1", since = "1.0.0")]

‎src/libcore/lib.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,24 @@
107107
#![feature(const_unsafe_cell_new)]
108108
#![feature(const_cell_new)]
109109
#![feature(const_nonzero_new)]
110+
#![cfg_attr(not(stage0), feature(doc_spotlight))]
111+
112+
#![cfg_attr(not(stage0), feature(const_min_value))]
113+
#![cfg_attr(not(stage0), feature(const_max_value))]
114+
#![cfg_attr(not(stage0), feature(const_atomic_bool_new))]
115+
#![cfg_attr(not(stage0), feature(const_atomic_isize_new))]
116+
#![cfg_attr(not(stage0), feature(const_atomic_usize_new))]
117+
#![cfg_attr(not(stage0), feature(const_atomic_i8_new))]
118+
#![cfg_attr(not(stage0), feature(const_atomic_u8_new))]
119+
#![cfg_attr(not(stage0), feature(const_atomic_i16_new))]
120+
#![cfg_attr(not(stage0), feature(const_atomic_u16_new))]
121+
#![cfg_attr(not(stage0), feature(const_atomic_i32_new))]
122+
#![cfg_attr(not(stage0), feature(const_atomic_u32_new))]
123+
#![cfg_attr(not(stage0), feature(const_atomic_i64_new))]
124+
#![cfg_attr(not(stage0), feature(const_atomic_u64_new))]
125+
#![cfg_attr(not(stage0), feature(const_unsafe_cell_new))]
126+
#![cfg_attr(not(stage0), feature(const_cell_new))]
127+
#![cfg_attr(not(stage0), feature(const_nonzero_new))]
110128

111129
#[prelude_import]
112130
#[allow(unused)]

‎src/librustdoc/clean/inline.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,11 +145,13 @@ pub fn build_external_trait(cx: &DocContext, did: DefId) -> clean::Trait {
145145
let generics = (cx.tcx.generics_of(did), &predicates).clean(cx);
146146
let generics = filter_non_trait_generics(did, generics);
147147
let (generics, supertrait_bounds) = separate_supertrait_bounds(generics);
148+
let is_spotlight = load_attrs(cx, did).has_doc_flag("spotlight");
148149
clean::Trait {
149150
unsafety: cx.tcx.trait_def(did).unsafety,
150151
generics,
151152
items: trait_items,
152153
bounds: supertrait_bounds,
154+
is_spotlight,
153155
}
154156
}
155157

‎src/librustdoc/clean/mod.rs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ impl<'a, 'tcx> Clean<Crate> for visit_ast::RustdocVisitor<'a, 'tcx> {
151151
match module.inner {
152152
ModuleItem(ref module) => {
153153
for it in &module.items {
154-
if it.is_extern_crate() && it.attrs.has_doc_masked() {
154+
if it.is_extern_crate() && it.attrs.has_doc_flag("masked") {
155155
masked_crates.insert(it.def_id.krate);
156156
}
157157
}
@@ -596,12 +596,12 @@ impl Attributes {
596596
None
597597
}
598598

599-
pub fn has_doc_masked(&self) -> bool {
599+
pub fn has_doc_flag(&self, flag: &str) -> bool {
600600
for attr in &self.other_attrs {
601601
if !attr.check_name("doc") { continue; }
602602

603603
if let Some(items) = attr.meta_item_list() {
604-
if items.iter().filter_map(|i| i.meta_item()).any(|it| it.check_name("masked")) {
604+
if items.iter().filter_map(|i| i.meta_item()).any(|it| it.check_name(flag)) {
605605
return true;
606606
}
607607
}
@@ -1331,19 +1331,31 @@ impl Clean<FunctionRetTy> for hir::FunctionRetTy {
13311331
}
13321332
}
13331333

1334+
impl GetDefId for FunctionRetTy {
1335+
fn def_id(&self) -> Option<DefId> {
1336+
match *self {
1337+
Return(ref ty) => ty.def_id(),
1338+
DefaultReturn => None,
1339+
}
1340+
}
1341+
}
1342+
13341343
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
13351344
pub struct Trait {
13361345
pub unsafety: hir::Unsafety,
13371346
pub items: Vec<Item>,
13381347
pub generics: Generics,
13391348
pub bounds: Vec<TyParamBound>,
1349+
pub is_spotlight: bool,
13401350
}
13411351

13421352
impl Clean<Item> for doctree::Trait {
13431353
fn clean(&self, cx: &DocContext) -> Item {
1354+
let attrs = self.attrs.clean(cx);
1355+
let is_spotlight = attrs.has_doc_flag("spotlight");
13441356
Item {
13451357
name: Some(self.name.clean(cx)),
1346-
attrs: self.attrs.clean(cx),
1358+
attrs: attrs,
13471359
source: self.whence.clean(cx),
13481360
def_id: cx.tcx.hir.local_def_id(self.id),
13491361
visibility: self.vis.clean(cx),
@@ -1354,6 +1366,7 @@ impl Clean<Item> for doctree::Trait {
13541366
items: self.items.clean(cx),
13551367
generics: self.generics.clean(cx),
13561368
bounds: self.bounds.clean(cx),
1369+
is_spotlight: is_spotlight,
13571370
}),
13581371
}
13591372
}

‎src/librustdoc/html/render.rs

Lines changed: 74 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2268,7 +2268,7 @@ fn item_function(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
22682268
AbiSpace(f.abi),
22692269
it.name.as_ref().unwrap(),
22702270
f.generics).len();
2271-
write!(w, "<pre class='rust fn'>")?;
2271+
write!(w, "{}<pre class='rust fn'>", render_spotlight_traits(it)?)?;
22722272
render_attributes(w, it)?;
22732273
write!(w, "{vis}{constness}{unsafety}{abi}fn \
22742274
{name}{generics}{decl}{where_clause}</pre>",
@@ -2402,8 +2402,9 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
24022402
let item_type = m.type_();
24032403
let id = derive_id(format!("{}.{}", item_type, name));
24042404
let ns_id = derive_id(format!("{}.{}", name, item_type.name_space()));
2405-
write!(w, "<h3 id='{id}' class='method'>\
2405+
write!(w, "{extra}<h3 id='{id}' class='method'>\
24062406
<span id='{ns_id}' class='invisible'><code>",
2407+
extra = render_spotlight_traits(m)?,
24072408
id = id,
24082409
ns_id = ns_id)?;
24092410
render_assoc_item(w, m, AssocItemLink::Anchor(Some(&id)), ItemType::Impl)?;
@@ -2605,10 +2606,10 @@ fn assoc_const(w: &mut fmt::Formatter,
26052606
Ok(())
26062607
}
26072608

2608-
fn assoc_type(w: &mut fmt::Formatter, it: &clean::Item,
2609-
bounds: &Vec<clean::TyParamBound>,
2610-
default: Option<&clean::Type>,
2611-
link: AssocItemLink) -> fmt::Result {
2609+
fn assoc_type<W: fmt::Write>(w: &mut W, it: &clean::Item,
2610+
bounds: &Vec<clean::TyParamBound>,
2611+
default: Option<&clean::Type>,
2612+
link: AssocItemLink) -> fmt::Result {
26122613
write!(w, "type <a href='{}' class=\"type\">{}</a>",
26132614
naive_assoc_href(it, link),
26142615
it.name.as_ref().unwrap())?;
@@ -3239,6 +3240,69 @@ fn should_render_item(item: &clean::Item, deref_mut_: bool) -> bool {
32393240
}
32403241
}
32413242

3243+
fn render_spotlight_traits(item: &clean::Item) -> Result<String, fmt::Error> {
3244+
let mut out = String::new();
3245+
3246+
match item.inner {
3247+
clean::FunctionItem(clean::Function { ref decl, .. }) |
3248+
clean::TyMethodItem(clean::TyMethod { ref decl, .. }) |
3249+
clean::MethodItem(clean::Method { ref decl, .. }) |
3250+
clean::ForeignFunctionItem(clean::Function { ref decl, .. }) => {
3251+
out = spotlight_decl(decl)?;
3252+
}
3253+
_ => {}
3254+
}
3255+
3256+
Ok(out)
3257+
}
3258+
3259+
fn spotlight_decl(decl: &clean::FnDecl) -> Result<String, fmt::Error> {
3260+
let mut out = String::new();
3261+
let mut trait_ = String::new();
3262+
3263+
if let Some(did) = decl.output.def_id() {
3264+
let c = cache();
3265+
if let Some(impls) = c.impls.get(&did) {
3266+
for i in impls {
3267+
let impl_ = i.inner_impl();
3268+
if impl_.trait_.def_id().and_then(|d| c.traits.get(&d))
3269+
.map_or(false, |t| t.is_spotlight) {
3270+
if out.is_empty() {
3271+
out.push_str(
3272+
&format!("<h3 class=\"important\">Important traits for {}</h3>\
3273+
<code class=\"content\">",
3274+
impl_.for_));
3275+
trait_.push_str(&format!("{}", impl_.for_));
3276+
}
3277+
3278+
//use the "where" class here to make it small
3279+
out.push_str(&format!("<span class=\"where fmt-newline\">{}</span>", impl_));
3280+
let t_did = impl_.trait_.def_id().unwrap();
3281+
for it in &impl_.items {
3282+
if let clean::TypedefItem(ref tydef, _) = it.inner {
3283+
out.push_str("<span class=\"where fmt-newline\"> ");
3284+
assoc_type(&mut out, it, &vec![],
3285+
Some(&tydef.type_),
3286+
AssocItemLink::GotoSource(t_did, &FxHashSet()))?;
3287+
out.push_str(";</span>");
3288+
}
3289+
}
3290+
}
3291+
}
3292+
}
3293+
}
3294+
3295+
if !out.is_empty() {
3296+
out.insert_str(0, &format!("<div class=\"important-traits\"><div class='tooltip'>ⓘ\
3297+
<span class='tooltiptext'>Important traits for {}</span></div>\
3298+
<div class=\"content hidden\">",
3299+
trait_));
3300+
out.push_str("</code></div></div>");
3301+
}
3302+
3303+
Ok(out)
3304+
}
3305+
32423306
fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLink,
32433307
render_mode: RenderMode, outer_version: Option<&str>,
32443308
show_def_docs: bool) -> fmt::Result {
@@ -3280,12 +3344,14 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi
32803344
};
32813345

32823346
match item.inner {
3283-
clean::MethodItem(..) | clean::TyMethodItem(..) => {
3347+
clean::MethodItem(clean::Method { ref decl, .. }) |
3348+
clean::TyMethodItem(clean::TyMethod{ ref decl, .. }) => {
32843349
// Only render when the method is not static or we allow static methods
32853350
if render_method_item {
32863351
let id = derive_id(format!("{}.{}", item_type, name));
32873352
let ns_id = derive_id(format!("{}.{}", name, item_type.name_space()));
32883353
write!(w, "<h4 id='{}' class=\"{}\">", id, item_type)?;
3354+
write!(w, "{}", spotlight_decl(decl)?)?;
32893355
write!(w, "<span id='{}' class='invisible'>", ns_id)?;
32903356
write!(w, "<code>")?;
32913357
render_assoc_item(w, item, link.anchor(&id), ItemType::Impl)?;
@@ -3332,6 +3398,7 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi
33323398

33333399
if render_method_item || render_mode == RenderMode::Normal {
33343400
let prefix = render_assoc_const_value(item);
3401+
33353402
if !is_default_item {
33363403
if let Some(t) = trait_ {
33373404
// The trait item may have been stripped so we might not

‎src/librustdoc/html/static/main.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@
216216
var help = document.getElementById("help");
217217
switch (getVirtualKey(ev)) {
218218
case "Escape":
219+
hideModal();
219220
var search = document.getElementById("search");
220221
if (!hasClass(help, "hidden")) {
221222
displayHelp(false, ev);
@@ -229,6 +230,7 @@
229230
case "s":
230231
case "S":
231232
displayHelp(false, ev);
233+
hideModal();
232234
ev.preventDefault();
233235
focusSearchBar();
234236
break;
@@ -241,6 +243,7 @@
241243

242244
case "?":
243245
if (ev.shiftKey) {
246+
hideModal();
244247
displayHelp(true, ev);
245248
}
246249
break;
@@ -1713,6 +1716,31 @@
17131716
}
17141717
});
17151718

1719+
function showModal(content) {
1720+
var modal = document.createElement('div');
1721+
modal.id = "important";
1722+
addClass(modal, 'modal');
1723+
modal.innerHTML = '<div class="modal-content"><div class="close" id="modal-close">✕</div>' +
1724+
'<div class="whiter"></div><span class="docblock">' + content +
1725+
'</span></div>';
1726+
document.getElementsByTagName('body')[0].appendChild(modal);
1727+
document.getElementById('modal-close').onclick = hideModal;
1728+
modal.onclick = hideModal;
1729+
}
1730+
1731+
function hideModal() {
1732+
var modal = document.getElementById("important");
1733+
if (modal) {
1734+
modal.parentNode.removeChild(modal);
1735+
}
1736+
}
1737+
1738+
onEach(document.getElementsByClassName('important-traits'), function(e) {
1739+
e.onclick = function() {
1740+
showModal(e.lastElementChild.innerHTML);
1741+
};
1742+
});
1743+
17161744
var search_input = document.getElementsByClassName("search-input")[0];
17171745

17181746
if (search_input) {

‎src/librustdoc/html/static/rustdoc.css

Lines changed: 106 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ h2 {
8989
h3 {
9090
font-size: 1.3em;
9191
}
92-
h1, h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), h4:not(.method):not(.type):not(.tymethod):not(.associatedconstant) {
92+
h1, h2, h3:not(.impl):not(.method):not(.type):not(.tymethod):not(.important), h4:not(.method):not(.type):not(.tymethod):not(.associatedconstant) {
9393
font-weight: 500;
9494
margin: 20px 0 15px 0;
9595
padding-bottom: 6px;
@@ -141,9 +141,12 @@ code, pre {
141141
border-radius: 3px;
142142
padding: 0 0.2em;
143143
}
144-
.docblock pre code, .docblock-short pre code {
144+
.docblock pre code, .docblock-short pre code, .docblock code.spotlight {
145145
padding: 0;
146146
}
147+
.docblock code.spotlight :last-child {
148+
padding-bottom: 0.6em;
149+
}
147150
pre {
148151
padding: 14px;
149152
}
@@ -435,10 +438,11 @@ h4 > code, h3 > code, .invisible > code {
435438
font-size: 0.8em;
436439
}
437440

438-
.content .methods > div { margin-left: 40px; }
441+
.content .methods > div:not(.important-traits) { margin-left: 40px; }
439442

440443
.content .impl-items .docblock, .content .impl-items .stability {
441444
margin-left: 40px;
445+
margin-bottom: .6em;
442446
}
443447
.content .impl-items .method, .content .impl-items > .type, .impl-items > .associatedconstant {
444448
margin-left: 20px;
@@ -951,3 +955,102 @@ pre.rust {
951955
color: #888;
952956
font-size: 16px;
953957
}
958+
959+
.important-traits {
960+
cursor: pointer;
961+
z-index: 2;
962+
}
963+
964+
h4 > .important-traits {
965+
position: absolute;
966+
left: -44px;
967+
top: 2px;
968+
}
969+
970+
.modal {
971+
position: fixed;
972+
width: 100vw;
973+
height: 100vh;
974+
background-color: rgba(0,0,0,0.3);
975+
z-index: 10000;
976+
top: 0;
977+
left: 0;
978+
}
979+
980+
.modal-content {
981+
display: block;
982+
max-width: 60%;
983+
min-width: 200px;
984+
background-color: #eee;
985+
padding: 8px;
986+
top: 40%;
987+
position: absolute;
988+
left: 50%;
989+
transform: translate(-50%, -40%);
990+
border: 1px solid #999;
991+
border-radius: 4px;
992+
border-top-right-radius: 0;
993+
}
994+
995+
.modal-content > .docblock {
996+
margin: 0;
997+
}
998+
999+
h3.important {
1000+
margin: 0;
1001+
margin-bottom: 13px;
1002+
font-size: 19px;
1003+
}
1004+
1005+
.modal-content > .docblock > code.content {
1006+
margin: 0;
1007+
padding: 0;
1008+
font-size: 20px;
1009+
}
1010+
1011+
.modal-content > .close {
1012+
position: absolute;
1013+
font-weight: 900;
1014+
right: -25px;
1015+
top: -1px;
1016+
font-size: 18px;
1017+
background-color: #eee;
1018+
width: 25px;
1019+
padding-right: 2px;
1020+
border-top-right-radius: 5px;
1021+
border-bottom-right-radius: 5px;
1022+
text-align: center;
1023+
border: 1px solid #999;
1024+
border-right: 0;
1025+
cursor: pointer;
1026+
}
1027+
1028+
.modal-content > .close:hover {
1029+
background-color: #ff1f1f;
1030+
color: white;
1031+
}
1032+
1033+
.modal-content > .whiter {
1034+
height: 25px;
1035+
position: absolute;
1036+
width: 3px;
1037+
background-color: #eee;
1038+
right: -2px;
1039+
top: 0px;
1040+
}
1041+
1042+
.modal-content > .close:hover + .whiter {
1043+
background-color: #ff1f1f;
1044+
}
1045+
1046+
#main > div.important-traits {
1047+
position: absolute;
1048+
left: -24px;
1049+
margin-top: 16px;
1050+
}
1051+
1052+
.content > .methods > div.important-traits {
1053+
position: absolute;
1054+
left: -42px;
1055+
margin-top: 2px;
1056+
}

‎src/libstd/io/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,7 @@ fn read_to_end<R: Read + ?Sized>(r: &mut R, buf: &mut Vec<u8>) -> Result<usize>
470470
/// [`&[u8]`]: primitive.slice.html
471471
///
472472
#[stable(feature = "rust1", since = "1.0.0")]
473+
#[doc(spotlight)]
473474
pub trait Read {
474475
/// Pull some bytes from this source into the specified buffer, returning
475476
/// how many bytes were read.
@@ -988,6 +989,7 @@ impl Initializer {
988989
/// # }
989990
/// ```
990991
#[stable(feature = "rust1", since = "1.0.0")]
992+
#[doc(spotlight)]
991993
pub trait Write {
992994
/// Write a buffer into this object, returning how many bytes were written.
993995
///

‎src/libstd/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,7 @@
329329
#![feature(vec_push_all)]
330330
#![feature(doc_cfg)]
331331
#![feature(doc_masked)]
332+
#![feature(doc_spotlight)]
332333
#![cfg_attr(test, feature(update_panic_count))]
333334
#![cfg_attr(windows, feature(const_atomic_ptr_new))]
334335

‎src/libsyntax/feature_gate.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,8 @@ declare_features! (
381381
(active, doc_cfg, "1.21.0", Some(43781)),
382382
// #[doc(masked)]
383383
(active, doc_masked, "1.21.0", Some(44027)),
384+
// #[doc(spotlight)]
385+
(active, doc_spotlight, "1.22.0", Some(45040)),
384386

385387
// allow `#[must_use]` on functions and comparison operators (RFC 1940)
386388
(active, fn_must_use, "1.21.0", Some(43302)),
@@ -1300,6 +1302,10 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
13001302
gate_feature_post!(&self, doc_masked, attr.span,
13011303
"#[doc(masked)] is experimental"
13021304
);
1305+
} else if content.iter().any(|c| c.check_name("spotlight")) {
1306+
gate_feature_post!(&self, doc_spotlight, attr.span,
1307+
"#[doc(spotlight)] is experimental"
1308+
);
13031309
}
13041310
}
13051311
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#[doc(spotlight)] //~ ERROR: #[doc(spotlight)] is experimental
12+
trait SomeTrait {}
13+
14+
fn main() {}

‎src/test/rustdoc/doc-spotlight.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(doc_spotlight)]
12+
13+
pub struct Wrapper<T> {
14+
inner: T,
15+
}
16+
17+
impl<T: SomeTrait> SomeTrait for Wrapper<T> {}
18+
19+
#[doc(spotlight)]
20+
pub trait SomeTrait {
21+
// @has doc_spotlight/trait.SomeTrait.html
22+
// @has - '//code[@class="content"]' 'impl<T: SomeTrait> SomeTrait for Wrapper<T>'
23+
fn wrap_me(self) -> Wrapper<Self> where Self: Sized {
24+
Wrapper {
25+
inner: self,
26+
}
27+
}
28+
}
29+
30+
pub struct SomeStruct;
31+
impl SomeTrait for SomeStruct {}
32+
33+
impl SomeStruct {
34+
// @has doc_spotlight/struct.SomeStruct.html
35+
// @has - '//code[@class="content"]' 'impl SomeTrait for SomeStruct'
36+
// @has - '//code[@class="content"]' 'impl<T: SomeTrait> SomeTrait for Wrapper<T>'
37+
pub fn new() -> SomeStruct {
38+
SomeStruct
39+
}
40+
}
41+
42+
// @has doc_spotlight/fn.bare_fn.html
43+
// @has - '//code[@class="content"]' 'impl SomeTrait for SomeStruct'
44+
pub fn bare_fn() -> SomeStruct {
45+
SomeStruct
46+
}

0 commit comments

Comments
 (0)
Please sign in to comment.