Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 4946c07

Browse files
committedAug 13, 2024
drustdoc-search: make unboxing a special-case type feature
1 parent 29d228b commit 4946c07

29 files changed

+305
-79
lines changed
 

‎compiler/rustc_ast_passes/src/feature_gate.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
218218
"meant for internal use only" {
219219
keyword => rustdoc_internals
220220
fake_variadic => rustdoc_internals
221+
search_unbox => rustdoc_internals
221222
}
222223
);
223224
}

‎compiler/rustc_passes/messages.ftl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,9 @@ passes_doc_masked_only_extern_crate =
222222
.not_an_extern_crate_label = not an `extern crate` item
223223
.note = read <https://doc.rust-lang.org/unstable-book/language-features/doc-masked.html> for more information
224224
225+
passes_doc_search_unbox_invalid =
226+
`#[doc(search_unbox)]` should be used on generic structs and enums
227+
225228
passes_doc_test_literal = `#![doc(test(...)]` does not take a literal
226229
227230
passes_doc_test_takes_list =

‎compiler/rustc_passes/src/check_attr.rs

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,12 @@ use rustc_data_structures::fx::FxHashMap;
1111
use rustc_errors::{Applicability, IntoDiagArg, MultiSpan};
1212
use rustc_errors::{DiagCtxtHandle, StashKey};
1313
use rustc_feature::{AttributeDuplicates, AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
14+
use rustc_hir as hir;
1415
use rustc_hir::def_id::LocalModDefId;
1516
use rustc_hir::intravisit::{self, Visitor};
16-
use rustc_hir::{self as hir};
1717
use rustc_hir::{
18-
self, FnSig, ForeignItem, HirId, Item, ItemKind, TraitItem, CRATE_HIR_ID, CRATE_OWNER_ID,
18+
self, AssocItemKind, FnSig, ForeignItem, HirId, Item, ItemKind, TraitItem, CRATE_HIR_ID,
19+
CRATE_OWNER_ID,
1920
};
2021
use rustc_hir::{MethodKind, Safety, Target};
2122
use rustc_macros::LintDiagnostic;
@@ -875,6 +876,30 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
875876
true
876877
}
877878

879+
fn check_doc_search_unbox(&self, meta: &NestedMetaItem, hir_id: HirId) -> bool {
880+
let hir::Node::Item(item) = self.tcx.hir_node(hir_id) else {
881+
self.dcx().emit_err(errors::DocSearchUnboxInvalid { span: meta.span() });
882+
return false;
883+
};
884+
match item.kind {
885+
ItemKind::Enum(_, generics) | ItemKind::Struct(_, generics)
886+
if generics.params.len() != 0 =>
887+
{
888+
true
889+
}
890+
ItemKind::Trait(_, _, generics, _, items)
891+
if generics.params.len() != 0
892+
|| items.iter().any(|item| matches!(item.kind, AssocItemKind::Type)) =>
893+
{
894+
true
895+
}
896+
_ => {
897+
self.dcx().emit_err(errors::DocSearchUnboxInvalid { span: meta.span() });
898+
false
899+
}
900+
}
901+
}
902+
878903
/// Checks `#[doc(inline)]`/`#[doc(no_inline)]` attributes. Returns `true` if valid.
879904
///
880905
/// A doc inlining attribute is invalid if it is applied to a non-`use` item, or
@@ -1108,6 +1133,13 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
11081133
is_valid = false
11091134
}
11101135

1136+
sym::search_unbox
1137+
if !self.check_attr_not_crate_level(meta, hir_id, "search_unbox")
1138+
|| !self.check_doc_search_unbox(meta, hir_id) =>
1139+
{
1140+
is_valid = false
1141+
}
1142+
11111143
sym::html_favicon_url
11121144
| sym::html_logo_url
11131145
| sym::html_playground_url
@@ -1165,6 +1197,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
11651197
| sym::notable_trait
11661198
| sym::passes
11671199
| sym::plugins
1200+
| sym::search_unbox
11681201
| sym::fake_variadic => {}
11691202

11701203
sym::rust_logo => {

‎compiler/rustc_passes/src/errors.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,13 @@ pub struct DocKeywordOnlyImpl {
234234
pub span: Span,
235235
}
236236

237+
#[derive(Diagnostic)]
238+
#[diag(passes_doc_search_unbox_invalid)]
239+
pub struct DocSearchUnboxInvalid {
240+
#[primary_span]
241+
pub span: Span,
242+
}
243+
237244
#[derive(Diagnostic)]
238245
#[diag(passes_doc_inline_conflict)]
239246
#[help]

‎compiler/rustc_span/src/symbol.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1702,6 +1702,7 @@ symbols! {
17021702
saturating_add,
17031703
saturating_div,
17041704
saturating_sub,
1705+
search_unbox,
17051706
self_in_typedefs,
17061707
self_struct_ctor,
17071708
semitransparent,

‎library/alloc/src/boxed.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,7 @@ mod thin;
233233
#[lang = "owned_box"]
234234
#[fundamental]
235235
#[stable(feature = "rust1", since = "1.0.0")]
236+
#[cfg_attr(not(bootstrap), doc(search_unbox))]
236237
// The declaration of the `Box` struct must be kept in sync with the
237238
// compiler or ICEs will happen.
238239
pub struct Box<

‎library/core/src/future/future.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ use crate::task::{Context, Poll};
2525
/// [`async`]: ../../std/keyword.async.html
2626
/// [`Waker`]: crate::task::Waker
2727
#[doc(notable_trait)]
28+
#[cfg_attr(not(bootstrap), doc(search_unbox))]
2829
#[must_use = "futures do nothing unless you `.await` or poll them"]
2930
#[stable(feature = "futures_api", since = "1.36.0")]
3031
#[lang = "future_trait"]

‎library/core/src/option.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,7 @@ use crate::{
571571
#[lang = "Option"]
572572
#[stable(feature = "rust1", since = "1.0.0")]
573573
#[allow(clippy::derived_hash_with_manual_eq)] // PartialEq is manually implemented equivalently
574+
#[cfg_attr(not(bootstrap), doc(search_unbox))]
574575
pub enum Option<T> {
575576
/// No value.
576577
#[lang = "None"]

‎library/core/src/result.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,7 @@ use crate::{convert, fmt, hint};
524524
#[must_use = "this `Result` may be an `Err` variant, which should be handled"]
525525
#[rustc_diagnostic_item = "Result"]
526526
#[stable(feature = "rust1", since = "1.0.0")]
527+
#[cfg_attr(not(bootstrap), doc(search_unbox))]
527528
pub enum Result<T, E> {
528529
/// Contains the success value
529530
#[lang = "Ok"]

‎src/librustdoc/html/render/search_index.rs

Lines changed: 62 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ use rustc_span::symbol::{kw, Symbol};
1111
use serde::ser::{Serialize, SerializeSeq, SerializeStruct, Serializer};
1212
use thin_vec::ThinVec;
1313

14-
use crate::clean;
1514
use crate::clean::types::{Function, Generics, ItemId, Type, WherePredicate};
15+
use crate::clean::{self, utils};
1616
use crate::formats::cache::{Cache, OrphanImplItem};
1717
use crate::formats::item_type::ItemType;
1818
use crate::html::format::join_with_double_colon;
@@ -65,7 +65,7 @@ pub(crate) fn build_index<'tcx>(
6565
let mut associated_types = FxHashMap::default();
6666

6767
// item type, display path, re-exported internal path
68-
let mut crate_paths: Vec<(ItemType, Vec<Symbol>, Option<Vec<Symbol>>)> = vec![];
68+
let mut crate_paths: Vec<(ItemType, Vec<Symbol>, Option<Vec<Symbol>>, bool)> = vec![];
6969

7070
// Attach all orphan items to the type's definition if the type
7171
// has since been learned.
@@ -131,10 +131,11 @@ pub(crate) fn build_index<'tcx>(
131131
map: &mut FxHashMap<F, isize>,
132132
itemid: F,
133133
lastpathid: &mut isize,
134-
crate_paths: &mut Vec<(ItemType, Vec<Symbol>, Option<Vec<Symbol>>)>,
134+
crate_paths: &mut Vec<(ItemType, Vec<Symbol>, Option<Vec<Symbol>>, bool)>,
135135
item_type: ItemType,
136136
path: &[Symbol],
137137
exact_path: Option<&[Symbol]>,
138+
search_unbox: bool,
138139
) -> RenderTypeId {
139140
match map.entry(itemid) {
140141
Entry::Occupied(entry) => RenderTypeId::Index(*entry.get()),
@@ -146,6 +147,7 @@ pub(crate) fn build_index<'tcx>(
146147
item_type,
147148
path.to_vec(),
148149
exact_path.map(|path| path.to_vec()),
150+
search_unbox,
149151
));
150152
RenderTypeId::Index(pathid)
151153
}
@@ -159,9 +161,21 @@ pub(crate) fn build_index<'tcx>(
159161
primitives: &mut FxHashMap<Symbol, isize>,
160162
associated_types: &mut FxHashMap<Symbol, isize>,
161163
lastpathid: &mut isize,
162-
crate_paths: &mut Vec<(ItemType, Vec<Symbol>, Option<Vec<Symbol>>)>,
164+
crate_paths: &mut Vec<(ItemType, Vec<Symbol>, Option<Vec<Symbol>>, bool)>,
165+
tcx: TyCtxt<'_>,
163166
) -> Option<RenderTypeId> {
167+
use crate::clean::PrimitiveType;
164168
let Cache { ref paths, ref external_paths, ref exact_paths, .. } = *cache;
169+
let search_unbox = match id {
170+
RenderTypeId::Mut => false,
171+
RenderTypeId::DefId(defid) => utils::has_doc_flag(tcx, defid, sym::search_unbox),
172+
RenderTypeId::Primitive(PrimitiveType::Reference | PrimitiveType::Tuple) => true,
173+
RenderTypeId::Primitive(..) => false,
174+
RenderTypeId::AssociatedType(..) => false,
175+
// this bool is only used by `insert_into_map`, so it doesn't matter what we set here
176+
// because Index means we've already inserted into the map
177+
RenderTypeId::Index(_) => false,
178+
};
165179
match id {
166180
RenderTypeId::Mut => Some(insert_into_map(
167181
primitives,
@@ -171,6 +185,7 @@ pub(crate) fn build_index<'tcx>(
171185
ItemType::Keyword,
172186
&[kw::Mut],
173187
None,
188+
search_unbox,
174189
)),
175190
RenderTypeId::DefId(defid) => {
176191
if let Some(&(ref fqp, item_type)) =
@@ -194,6 +209,7 @@ pub(crate) fn build_index<'tcx>(
194209
item_type,
195210
fqp,
196211
exact_fqp.map(|x| &x[..]).filter(|exact_fqp| exact_fqp != fqp),
212+
search_unbox,
197213
))
198214
} else {
199215
None
@@ -209,6 +225,7 @@ pub(crate) fn build_index<'tcx>(
209225
ItemType::Primitive,
210226
&[sym],
211227
None,
228+
search_unbox,
212229
))
213230
}
214231
RenderTypeId::Index(_) => Some(id),
@@ -220,6 +237,7 @@ pub(crate) fn build_index<'tcx>(
220237
ItemType::AssocType,
221238
&[sym],
222239
None,
240+
search_unbox,
223241
)),
224242
}
225243
}
@@ -231,7 +249,8 @@ pub(crate) fn build_index<'tcx>(
231249
primitives: &mut FxHashMap<Symbol, isize>,
232250
associated_types: &mut FxHashMap<Symbol, isize>,
233251
lastpathid: &mut isize,
234-
crate_paths: &mut Vec<(ItemType, Vec<Symbol>, Option<Vec<Symbol>>)>,
252+
crate_paths: &mut Vec<(ItemType, Vec<Symbol>, Option<Vec<Symbol>>, bool)>,
253+
tcx: TyCtxt<'_>,
235254
) {
236255
if let Some(generics) = &mut ty.generics {
237256
for item in generics {
@@ -243,6 +262,7 @@ pub(crate) fn build_index<'tcx>(
243262
associated_types,
244263
lastpathid,
245264
crate_paths,
265+
tcx,
246266
);
247267
}
248268
}
@@ -256,6 +276,7 @@ pub(crate) fn build_index<'tcx>(
256276
associated_types,
257277
lastpathid,
258278
crate_paths,
279+
tcx,
259280
);
260281
let Some(converted_associated_type) = converted_associated_type else {
261282
return false;
@@ -270,6 +291,7 @@ pub(crate) fn build_index<'tcx>(
270291
associated_types,
271292
lastpathid,
272293
crate_paths,
294+
tcx,
273295
);
274296
}
275297
true
@@ -287,6 +309,7 @@ pub(crate) fn build_index<'tcx>(
287309
associated_types,
288310
lastpathid,
289311
crate_paths,
312+
tcx,
290313
);
291314
}
292315
if let Some(search_type) = &mut item.search_type {
@@ -299,6 +322,7 @@ pub(crate) fn build_index<'tcx>(
299322
&mut associated_types,
300323
&mut lastpathid,
301324
&mut crate_paths,
325+
tcx,
302326
);
303327
}
304328
for item in &mut search_type.output {
@@ -310,6 +334,7 @@ pub(crate) fn build_index<'tcx>(
310334
&mut associated_types,
311335
&mut lastpathid,
312336
&mut crate_paths,
337+
tcx,
313338
);
314339
}
315340
for constraint in &mut search_type.where_clause {
@@ -322,6 +347,7 @@ pub(crate) fn build_index<'tcx>(
322347
&mut associated_types,
323348
&mut lastpathid,
324349
&mut crate_paths,
350+
tcx,
325351
);
326352
}
327353
}
@@ -349,7 +375,12 @@ pub(crate) fn build_index<'tcx>(
349375
.filter(|exact_fqp| {
350376
exact_fqp.last() == Some(&item.name) && *exact_fqp != fqp
351377
});
352-
crate_paths.push((short, fqp.clone(), exact_fqp.cloned()));
378+
crate_paths.push((
379+
short,
380+
fqp.clone(),
381+
exact_fqp.cloned(),
382+
utils::has_doc_flag(tcx, defid, sym::search_unbox),
383+
));
353384
Some(pathid)
354385
} else {
355386
None
@@ -430,7 +461,7 @@ pub(crate) fn build_index<'tcx>(
430461

431462
struct CrateData<'a> {
432463
items: Vec<&'a IndexItem>,
433-
paths: Vec<(ItemType, Vec<Symbol>, Option<Vec<Symbol>>)>,
464+
paths: Vec<(ItemType, Vec<Symbol>, Option<Vec<Symbol>>, bool)>,
434465
// The String is alias name and the vec is the list of the elements with this alias.
435466
//
436467
// To be noted: the `usize` elements are indexes to `items`.
@@ -449,6 +480,7 @@ pub(crate) fn build_index<'tcx>(
449480
name: Symbol,
450481
path: Option<usize>,
451482
exact_path: Option<usize>,
483+
search_unbox: bool,
452484
}
453485

454486
impl Serialize for Paths {
@@ -466,6 +498,15 @@ pub(crate) fn build_index<'tcx>(
466498
assert!(self.path.is_some());
467499
seq.serialize_element(path)?;
468500
}
501+
if self.search_unbox {
502+
if self.path.is_none() {
503+
seq.serialize_element(&None::<u8>)?;
504+
}
505+
if self.exact_path.is_none() {
506+
seq.serialize_element(&None::<u8>)?;
507+
}
508+
seq.serialize_element(&1)?;
509+
}
469510
seq.end()
470511
}
471512
}
@@ -488,9 +529,15 @@ pub(crate) fn build_index<'tcx>(
488529
mod_paths.insert(&item.path, index);
489530
}
490531
let mut paths = Vec::with_capacity(self.paths.len());
491-
for (ty, path, exact) in &self.paths {
532+
for &(ty, ref path, ref exact, search_unbox) in &self.paths {
492533
if path.len() < 2 {
493-
paths.push(Paths { ty: *ty, name: path[0], path: None, exact_path: None });
534+
paths.push(Paths {
535+
ty,
536+
name: path[0],
537+
path: None,
538+
exact_path: None,
539+
search_unbox,
540+
});
494541
continue;
495542
}
496543
let full_path = join_with_double_colon(&path[..path.len() - 1]);
@@ -516,10 +563,11 @@ pub(crate) fn build_index<'tcx>(
516563
});
517564
if let Some(index) = mod_paths.get(&full_path) {
518565
paths.push(Paths {
519-
ty: *ty,
566+
ty,
520567
name: *path.last().unwrap(),
521568
path: Some(*index),
522569
exact_path,
570+
search_unbox,
523571
});
524572
continue;
525573
}
@@ -531,10 +579,11 @@ pub(crate) fn build_index<'tcx>(
531579
match extra_paths.entry(full_path.clone()) {
532580
Entry::Occupied(entry) => {
533581
paths.push(Paths {
534-
ty: *ty,
582+
ty,
535583
name: *path.last().unwrap(),
536584
path: Some(*entry.get()),
537585
exact_path,
586+
search_unbox,
538587
});
539588
}
540589
Entry::Vacant(entry) => {
@@ -543,10 +592,11 @@ pub(crate) fn build_index<'tcx>(
543592
revert_extra_paths.insert(index, full_path);
544593
}
545594
paths.push(Paths {
546-
ty: *ty,
595+
ty,
547596
name: *path.last().unwrap(),
548597
path: Some(index),
549598
exact_path,
599+
search_unbox,
550600
});
551601
}
552602
}

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

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2547,7 +2547,8 @@ function initSearch(rawSearchIndex) {
25472547
mgens,
25482548
unboxingDepth,
25492549
);
2550-
} else if (fnType.generics.length > 0 || fnType.bindings.size > 0) {
2550+
} else if (fnType.unboxFlag &&
2551+
(fnType.generics.length > 0 || fnType.bindings.size > 0)) {
25512552
const simplifiedGenerics = [
25522553
...fnType.generics,
25532554
...Array.from(fnType.bindings.values()).flat(),
@@ -3690,6 +3691,7 @@ ${item.displayPath}<span class="${type}">${name}</span>\
36903691
exactPath: null,
36913692
generics,
36923693
bindings,
3694+
unboxFlag: true,
36933695
};
36943696
} else if (pathIndex === 0) {
36953697
// `0` is used as a sentinel because it's fewer bytes than `null`
@@ -3701,6 +3703,7 @@ ${item.displayPath}<span class="${type}">${name}</span>\
37013703
exactPath: null,
37023704
generics,
37033705
bindings,
3706+
unboxFlag: true,
37043707
};
37053708
} else {
37063709
const item = lowercasePaths[pathIndex - 1];
@@ -3716,6 +3719,7 @@ ${item.displayPath}<span class="${type}">${name}</span>\
37163719
exactPath: item.exactPath,
37173720
generics,
37183721
bindings,
3722+
unboxFlag: item.unboxFlag,
37193723
};
37203724
}
37213725
const cr = TYPES_POOL.get(result.id);
@@ -3753,6 +3757,7 @@ ${item.displayPath}<span class="${type}">${name}</span>\
37533757
if (cr.ty === result.ty && cr.path === result.path
37543758
&& cr.bindings === result.bindings && cr.generics === result.generics
37553759
&& cr.ty === result.ty && cr.name === result.name
3760+
&& cr.unboxFlag === result.unboxFlag
37563761
) {
37573762
return cr;
37583763
}
@@ -4247,14 +4252,17 @@ ${item.displayPath}<span class="${type}">${name}</span>\
42474252
const ty = elem[0];
42484253
const name = elem[1];
42494254
let path = null;
4250-
if (elem.length > 2) {
4255+
if (elem.length > 2 && elem[2] !== null) {
42514256
path = itemPaths.has(elem[2]) ? itemPaths.get(elem[2]) : lastPath;
42524257
lastPath = path;
42534258
}
4254-
const exactPath = elem.length > 3 ? itemPaths.get(elem[3]) : path;
4259+
const exactPath = elem.length > 3 && elem[3] !== null ?
4260+
itemPaths.get(elem[3]) :
4261+
path;
4262+
const unboxFlag = elem.length > 4 && !!elem[4];
42554263

4256-
lowercasePaths.push({ty, name: name.toLowerCase(), path, exactPath});
4257-
paths[i] = {ty, name, path, exactPath};
4264+
lowercasePaths.push({ty, name: name.toLowerCase(), path, exactPath, unboxFlag});
4265+
paths[i] = {ty, name, path, exactPath, unboxFlag};
42584266
}
42594267

42604268
// convert `item*` into an object form, and construct word indices.

‎tests/rustdoc-js-std/bufread-fill-buf.js

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,15 @@
22

33
const EXPECTED = [
44
{
5-
'query': 'bufread -> result<u8>',
5+
'query': 'bufread -> result<[u8]>',
66
'others': [
7-
{ 'path': 'std::io::Split', 'name': 'next' },
87
{ 'path': 'std::boxed::Box', 'name': 'fill_buf' },
9-
{ 'path': 'std::io::Chain', 'name': 'fill_buf' },
10-
{ 'path': 'std::io::Take', 'name': 'fill_buf' },
8+
],
9+
},
10+
{
11+
'query': 'split<bufread> -> option<result<vec<u8>>>',
12+
'others': [
13+
{ 'path': 'std::io::Split', 'name': 'next' },
1114
],
1215
},
1316
];

‎tests/rustdoc-js-std/option-type-signatures.js

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -186,20 +186,6 @@ const EXPECTED = [
186186
'displayMappedNames': `t = U, u = R`,
187187
'displayWhereClause': "F: `FnOnce` (T, U) -> `R`",
188188
},
189-
{
190-
'path': 'std::task::Poll',
191-
'name': 'map_ok',
192-
'displayType': 'Poll<`Option`<Result<`T`, E>>>, F -> Poll<`Option`<Result<U, E>>>',
193-
'displayMappedNames': `t = T, u = U`,
194-
'displayWhereClause': "F: `FnOnce` (T) -> `U`",
195-
},
196-
{
197-
'path': 'std::task::Poll',
198-
'name': 'map_err',
199-
'displayType': 'Poll<`Option`<Result<`T`, E>>>, F -> Poll<`Option`<Result<T, U>>>',
200-
'displayMappedNames': `t = T, u = U`,
201-
'displayWhereClause': "F: `FnOnce` (E) -> `U`",
202-
},
203189
],
204190
},
205191
{

‎tests/rustdoc-js/assoc-type-backtrack.js

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,26 @@ const EXPECTED = [
66
'correction': null,
77
'others': [
88
{ 'path': 'assoc_type_backtrack::MyTrait', 'name': 'fold' },
9-
{ 'path': 'assoc_type_backtrack::Cloned', 'name': 'fold' },
109
],
1110
},
1211
{
1312
'query': 'mytrait<U>, mytrait2 -> T',
1413
'correction': null,
1514
'others': [
1615
{ 'path': 'assoc_type_backtrack::MyTrait', 'name': 'fold' },
16+
],
17+
},
18+
{
19+
'query': 'cloned<mytrait>, mytrait2 -> T',
20+
'correction': null,
21+
'others': [
22+
{ 'path': 'assoc_type_backtrack::Cloned', 'name': 'fold' },
23+
],
24+
},
25+
{
26+
'query': 'cloned<mytrait<U>>, mytrait2 -> T',
27+
'correction': null,
28+
'others': [
1729
{ 'path': 'assoc_type_backtrack::Cloned', 'name': 'fold' },
1830
],
1931
},
@@ -22,7 +34,6 @@ const EXPECTED = [
2234
'correction': null,
2335
'others': [
2436
{ 'path': 'assoc_type_backtrack::MyTrait', 'name': 'fold' },
25-
{ 'path': 'assoc_type_backtrack::Cloned', 'name': 'fold' },
2637
],
2738
},
2839
{
@@ -50,14 +61,14 @@ const EXPECTED = [
5061
],
5162
},
5263
{
53-
'query': 'mytrait<U> -> Option<T>',
64+
'query': 'cloned<mytrait<U>> -> Option<T>',
5465
'correction': null,
5566
'others': [
5667
{ 'path': 'assoc_type_backtrack::Cloned', 'name': 'next' },
5768
],
5869
},
5970
{
60-
'query': 'mytrait<Item=U> -> Option<T>',
71+
'query': 'cloned<mytrait<Item=U>> -> Option<T>',
6172
'correction': null,
6273
'others': [
6374
{ 'path': 'assoc_type_backtrack::Cloned', 'name': 'next' },

‎tests/rustdoc-js/assoc-type-backtrack.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#![feature(rustdoc_internals)]
2+
13
pub trait MyTrait2<X> {
24
type Output;
35
}
@@ -31,10 +33,12 @@ where
3133
}
3234
}
3335

36+
#[doc(search_unbox)]
3437
pub trait MyFuture {
3538
type Output;
3639
}
3740

41+
#[doc(search_unbox)]
3842
pub trait MyIntoFuture {
3943
type Output;
4044
type Fut: MyFuture<Output = Self::Output>;

‎tests/rustdoc-js/assoc-type.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,22 @@
1-
pub fn my_fn<X: Iterator<Item = Something>>(_x: X) -> u32 {
1+
#![feature(rustdoc_internals)]
2+
3+
pub fn my_fn<X: other::Iterator<Item = Something>>(_x: X) -> u32 {
24
3
35
}
46

57
pub struct Something;
68

79
pub mod my {
10+
#[doc(search_unbox)]
811
pub trait Iterator<T> {}
912
pub fn other_fn<X: Iterator<crate::Something>>(_: X) -> u32 {
1013
3
1114
}
1215
}
16+
17+
pub mod other {
18+
#[doc(search_unbox)]
19+
pub trait Iterator {
20+
type Item;
21+
}
22+
}

‎tests/rustdoc-js/generics-impl.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ const EXPECTED = [
1414
],
1515
},
1616
{
17-
'query': 'Aaaaaaa -> usize',
17+
'query': 'Aaaaaaa -> Result<usize>',
1818
'others': [
1919
{ 'path': 'generics_impl::Aaaaaaa', 'name': 'read' },
2020
],
@@ -23,14 +23,18 @@ const EXPECTED = [
2323
'query': 'Read -> u64',
2424
'others': [
2525
{ 'path': 'generics_impl::Ddddddd', 'name': 'eeeeeee' },
26+
],
27+
},
28+
{
29+
'query': 'Ddddddd<Read> -> u64',
30+
'others': [
2631
{ 'path': 'generics_impl::Ddddddd', 'name': 'ggggggg' },
2732
],
2833
},
2934
{
3035
'query': 'trait:Read -> u64',
3136
'others': [
3237
{ 'path': 'generics_impl::Ddddddd', 'name': 'eeeeeee' },
33-
{ 'path': 'generics_impl::Ddddddd', 'name': 'ggggggg' },
3438
],
3539
},
3640
{

‎tests/rustdoc-js/generics-impl.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::io::{Read, Result as IoResult};
1+
use std::io::{self, Read};
22

33
pub struct Aaaaaaa;
44

@@ -12,7 +12,7 @@ impl Aaaaaaa {
1212
}
1313

1414
impl Read for Aaaaaaa {
15-
fn read(&mut self, out: &mut [u8]) -> IoResult<usize> {
15+
fn read(&mut self, out: &mut [u8]) -> io::Result<usize> {
1616
Ok(out.len())
1717
}
1818
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// ignore-order
2+
// exact-check
3+
4+
// Make sure that results are order-agnostic, even when there's search items that only differ
5+
// by generics.
6+
7+
const EXPECTED = [
8+
{
9+
'query': 'Wrap',
10+
'in_args': [
11+
{ 'path': 'generics_match_ambiguity', 'name': 'bar' },
12+
{ 'path': 'generics_match_ambiguity', 'name': 'foo' },
13+
],
14+
},
15+
{
16+
'query': 'Wrap<i32>',
17+
'in_args': [
18+
{ 'path': 'generics_match_ambiguity', 'name': 'bar' },
19+
{ 'path': 'generics_match_ambiguity', 'name': 'foo' },
20+
],
21+
},
22+
{
23+
'query': 'Wrap<i32>, Wrap<i32, u32>',
24+
'others': [
25+
{ 'path': 'generics_match_ambiguity', 'name': 'bar' },
26+
{ 'path': 'generics_match_ambiguity', 'name': 'foo' },
27+
],
28+
},
29+
{
30+
'query': 'Wrap<i32, u32>, Wrap<i32>',
31+
'others': [
32+
{ 'path': 'generics_match_ambiguity', 'name': 'bar' },
33+
{ 'path': 'generics_match_ambiguity', 'name': 'foo' },
34+
],
35+
},
36+
{
37+
'query': 'W3<i32>, W3<i32, u32>',
38+
'others': [
39+
{ 'path': 'generics_match_ambiguity', 'name': 'baaa' },
40+
{ 'path': 'generics_match_ambiguity', 'name': 'baab' },
41+
],
42+
},
43+
{
44+
'query': 'W3<i32, u32>, W3<i32>',
45+
'others': [
46+
{ 'path': 'generics_match_ambiguity', 'name': 'baaa' },
47+
{ 'path': 'generics_match_ambiguity', 'name': 'baab' },
48+
],
49+
},
50+
{
51+
// strict generics matching; W2<i32, u32> doesn't match W2<W3<i32, u32>>,
52+
// even though W2<i32> works just fine (ignoring the W3)
53+
'query': 'W2<i32>, W2<i32, u32>',
54+
'others': [],
55+
},
56+
{
57+
'query': 'W2<i32, u32>, W2<i32>',
58+
'others': [],
59+
},
60+
{
61+
'query': 'W2<i32>, W3<i32, u32>',
62+
'others': [],
63+
},
64+
{
65+
'query': 'W2<i32>, W2<i32>',
66+
'others': [],
67+
},
68+
];
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#![crate_name = "generics_match_ambiguity"]
2+
3+
pub struct Wrap<T, U = ()>(pub T, pub U);
4+
5+
pub fn foo(a: Wrap<i32>, b: Wrap<i32, u32>) {}
6+
pub fn bar(a: Wrap<i32, u32>, b: Wrap<i32>) {}
7+
8+
pub struct W2<T>(pub T);
9+
pub struct W3<T, U = ()>(pub T, pub U);
10+
11+
pub fn baaa(a: W3<i32>, b: W3<i32, u32>) {}
12+
pub fn baab(a: W3<i32, u32>, b: W3<i32>) {}
13+
pub fn baac(a: W2<W3<i32>>, b: W3<i32, u32>) {}
14+
pub fn baad(a: W2<W3<i32, u32>>, b: W3<i32>) {}
15+
pub fn baae(a: W3<i32>, b: W2<W3<i32, u32>>) {}
16+
pub fn baaf(a: W3<i32, u32>, b: W2<W3<i32>>) {}
17+
pub fn baag(a: W2<W3<i32>>, b: W2<W3<i32, u32>>) {}
18+
pub fn baah(a: W2<W3<i32, u32>>, b: W2<W3<i32>>) {}

‎tests/rustdoc-js/generics-match-ambiguity.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
1+
#![feature(rustdoc_internals)]
2+
3+
#[doc(search_unbox)]
14
pub struct Wrap<T, U = ()>(pub T, pub U);
25

36
pub fn foo(a: Wrap<i32>, b: Wrap<i32, u32>) {}
47
pub fn bar(a: Wrap<i32, u32>, b: Wrap<i32>) {}
58

9+
#[doc(search_unbox)]
610
pub struct W2<T>(pub T);
11+
#[doc(search_unbox)]
712
pub struct W3<T, U = ()>(pub T, pub U);
813

914
pub fn baaa(a: W3<i32>, b: W3<i32, u32>) {}
@@ -14,4 +19,3 @@ pub fn baae(a: W3<i32>, b: W2<W3<i32, u32>>) {}
1419
pub fn baaf(a: W3<i32, u32>, b: W2<W3<i32>>) {}
1520
pub fn baag(a: W2<W3<i32>>, b: W2<W3<i32, u32>>) {}
1621
pub fn baah(a: W2<W3<i32, u32>>, b: W2<W3<i32>>) {}
17-
//

‎tests/rustdoc-js/generics-unbox.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,34 @@
1+
#![feature(rustdoc_internals)]
2+
3+
#[doc(search_unbox)]
14
pub struct Out<A, B = ()> {
25
a: A,
36
b: B,
47
}
58

9+
#[doc(search_unbox)]
610
pub struct Out1<A, const N: usize> {
711
a: [A; N],
812
}
913

14+
#[doc(search_unbox)]
1015
pub struct Out2<A, const N: usize> {
1116
a: [A; N],
1217
}
1318

19+
#[doc(search_unbox)]
1420
pub struct Out3<A, B> {
1521
a: A,
1622
b: B,
1723
}
1824

25+
#[doc(search_unbox)]
1926
pub struct Out4<A, B> {
2027
a: A,
2128
b: B,
2229
}
2330

31+
#[doc(search_unbox)]
2432
pub struct Inside<T>(T);
2533

2634
pub fn alpha<const N: usize, T>(_: Inside<T>) -> Out<Out1<T, N>, Out2<T, N>> {

‎tests/rustdoc-js/generics.js

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -30,21 +30,8 @@ const EXPECTED = [
3030
'others': [
3131
{ 'path': 'generics', 'name': 'P' },
3232
],
33-
'returned': [
34-
{ 'path': 'generics', 'name': 'alef' },
35-
],
36-
'in_args': [
37-
{ 'path': 'generics', 'name': 'alpha' },
38-
],
39-
},
40-
{
41-
'query': 'P',
42-
'returned': [
43-
{ 'path': 'generics', 'name': 'alef' },
44-
],
45-
'in_args': [
46-
{ 'path': 'generics', 'name': 'alpha' },
47-
],
33+
'returned': [],
34+
'in_args': [],
4835
},
4936
{
5037
'query': '"ExtraCreditStructMulti"<ExtraCreditInnerMulti, ExtraCreditInnerMulti>',

‎tests/rustdoc-js/hof.js

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,19 @@ const EXPECTED = [
99

1010
// ML-style higher-order function notation
1111
{
12-
'query': 'bool, (u32 -> !) -> ()',
12+
'query': 'bool, (first<u32> -> !) -> ()',
1313
'others': [
1414
{"path": "hof", "name": "fn_ptr"},
1515
],
1616
},
1717
{
18-
'query': 'u8, (u32 -> !) -> ()',
18+
'query': 'u8, (second<u32> -> !) -> ()',
1919
'others': [
2020
{"path": "hof", "name": "fn_once"},
2121
],
2222
},
2323
{
24-
'query': 'i8, (u32 -> !) -> ()',
24+
'query': 'i8, (third<u32> -> !) -> ()',
2525
'others': [
2626
{"path": "hof", "name": "fn_mut"},
2727
],
@@ -54,9 +54,6 @@ const EXPECTED = [
5454
'query': '(u32 -> !) -> ()',
5555
'others': [
5656
{"path": "hof", "name": "fn_"},
57-
{"path": "hof", "name": "fn_ptr"},
58-
{"path": "hof", "name": "fn_mut"},
59-
{"path": "hof", "name": "fn_once"},
6057
],
6158
},
6259
{
@@ -95,30 +92,30 @@ const EXPECTED = [
9592

9693
// Rust-style higher-order function notation
9794
{
98-
'query': 'bool, fn(u32) -> ! -> ()',
95+
'query': 'bool, fn(first<u32>) -> ! -> ()',
9996
'others': [
10097
{"path": "hof", "name": "fn_ptr"},
10198
],
10299
},
103100
{
104-
'query': 'u8, fnonce(u32) -> ! -> ()',
101+
'query': 'u8, fnonce(second<u32>) -> ! -> ()',
105102
'others': [
106103
{"path": "hof", "name": "fn_once"},
107104
],
108105
},
109106
{
110-
'query': 'u8, fn(u32) -> ! -> ()',
107+
'query': 'u8, fn(second<u32>) -> ! -> ()',
111108
// fnonce != fn
112109
'others': [],
113110
},
114111
{
115-
'query': 'i8, fnmut(u32) -> ! -> ()',
112+
'query': 'i8, fnmut(third<u32>) -> ! -> ()',
116113
'others': [
117114
{"path": "hof", "name": "fn_mut"},
118115
],
119116
},
120117
{
121-
'query': 'i8, fn(u32) -> ! -> ()',
118+
'query': 'i8, fn(third<u32>) -> ! -> ()',
122119
// fnmut != fn
123120
'others': [],
124121
},
@@ -152,22 +149,22 @@ const EXPECTED = [
152149
],
153150
},
154151
{
155-
'query': 'fn(u32) -> ! -> ()',
152+
'query': 'fn() -> ! -> ()',
156153
'others': [
157154
// fn matches primitive:fn and trait:Fn
158155
{"path": "hof", "name": "fn_"},
159156
{"path": "hof", "name": "fn_ptr"},
160157
],
161158
},
162159
{
163-
'query': 'trait:fn(u32) -> ! -> ()',
160+
'query': 'trait:fn() -> ! -> ()',
164161
'others': [
165162
// fn matches primitive:fn and trait:Fn
166163
{"path": "hof", "name": "fn_"},
167164
],
168165
},
169166
{
170-
'query': 'primitive:fn(u32) -> ! -> ()',
167+
'query': 'primitive:fn() -> ! -> ()',
171168
'others': [
172169
// fn matches primitive:fn and trait:Fn
173170
{"path": "hof", "name": "fn_ptr"},

‎tests/rustdoc-js/looks-like-rustc-interner.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
const EXPECTED = {
55
'query': 'canonicalvarinfo, intoiterator -> intoiterator',
6+
'others': [],
7+
'query': '[canonicalvarinfo], interner<tys=intoiterator> -> intoiterator',
68
'others': [
79
{ 'path': 'looks_like_rustc_interner::Interner', 'name': 'mk_canonical_var_infos' },
810
],

‎tests/rustdoc-js/nested-unboxed.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
#![feature(rustdoc_internals)]
2+
3+
#[doc(search_unbox)]
14
pub struct Object<T, U>(T, U);
25

36
pub fn something() -> Result<Object<i32, u32>, bool> {

‎tests/rustdoc-js/tuple-unit.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ const EXPECTED = [
5757
'in_args': [],
5858
},
5959
{
60-
'query': '(Q, ())',
60+
'query': '(Q, R<()>)',
6161
'returned': [
6262
{ 'path': 'tuple_unit', 'name': 'nest' },
6363
],
@@ -71,7 +71,7 @@ const EXPECTED = [
7171
'in_args': [],
7272
},
7373
{
74-
'query': '(u32)',
74+
'query': 'R<(u32)>',
7575
'returned': [
7676
{ 'path': 'tuple_unit', 'name': 'nest' },
7777
],

‎tests/ui/feature-gates/feature-gate-rustdoc_internals.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,8 @@ trait Mine {}
77
#[doc(fake_variadic)] //~ ERROR: `#[doc(fake_variadic)]` is meant for internal use only
88
impl<T> Mine for (T,) {}
99

10+
11+
#[doc(search_unbox)] //~ ERROR: `#[doc(search_unbox)]` is meant for internal use only
12+
struct Wrap<T> (T);
13+
1014
fn main() {}

‎tests/ui/feature-gates/feature-gate-rustdoc_internals.stderr

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,16 @@ LL | #[doc(fake_variadic)]
1818
= help: add `#![feature(rustdoc_internals)]` to the crate attributes to enable
1919
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
2020

21-
error: aborting due to 2 previous errors
21+
error[E0658]: `#[doc(search_unbox)]` is meant for internal use only
22+
--> $DIR/feature-gate-rustdoc_internals.rs:11:1
23+
|
24+
LL | #[doc(search_unbox)]
25+
| ^^^^^^^^^^^^^^^^^^^^
26+
|
27+
= note: see issue #90418 <https://github.com/rust-lang/rust/issues/90418> for more information
28+
= help: add `#![feature(rustdoc_internals)]` to the crate attributes to enable
29+
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
30+
31+
error: aborting due to 3 previous errors
2232

2333
For more information about this error, try `rustc --explain E0658`.

0 commit comments

Comments
 (0)
Please sign in to comment.