diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs
index 41657e290ea21..dddc087d124df 100644
--- a/src/librustdoc/html/render/search_index.rs
+++ b/src/librustdoc/html/render/search_index.rs
@@ -1494,7 +1494,9 @@ pub(crate) fn build_index(
let search_unbox = match id {
RenderTypeId::Mut => false,
RenderTypeId::DefId(defid) => utils::has_doc_flag(tcx, defid, sym::search_unbox),
- RenderTypeId::Primitive(PrimitiveType::Reference | PrimitiveType::Tuple) => true,
+ RenderTypeId::Primitive(
+ PrimitiveType::Reference | PrimitiveType::RawPointer | PrimitiveType::Tuple,
+ ) => true,
RenderTypeId::Primitive(..) => false,
RenderTypeId::AssociatedType(..) => false,
// this bool is only used by `insert_into_map`, so it doesn't matter what we set here
@@ -1855,7 +1857,7 @@ fn get_index_type_id(
}
clean::Primitive(p) => Some(RenderTypeId::Primitive(p)),
clean::BorrowedRef { .. } => Some(RenderTypeId::Primitive(clean::PrimitiveType::Reference)),
- clean::RawPointer(_, ref type_) => get_index_type_id(type_, rgen),
+ clean::RawPointer { .. } => Some(RenderTypeId::Primitive(clean::PrimitiveType::RawPointer)),
// The type parameters are converted to generics in `simplify_fn_type`
clean::Slice(_) => Some(RenderTypeId::Primitive(clean::PrimitiveType::Slice)),
clean::Array(_, _) => Some(RenderTypeId::Primitive(clean::PrimitiveType::Array)),
@@ -2113,7 +2115,8 @@ fn simplify_fn_type<'a, 'tcx>(
generics: Some(ty_generics),
});
}
- Type::BorrowedRef { lifetime: _, mutability, ref type_ } => {
+ Type::BorrowedRef { lifetime: _, mutability, ref type_ }
+ | Type::RawPointer(mutability, ref type_) => {
let mut ty_generics = Vec::new();
if mutability.is_mut() {
ty_generics.push(RenderType {
diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js
index 42b87d562529b..5e65791bb6695 100644
--- a/src/librustdoc/html/static/js/search.js
+++ b/src/librustdoc/html/static/js/search.js
@@ -587,6 +587,45 @@ function getNextElem(query, parserState, elems, isInGenerics) {
/** @type {rustdoc.ParserQueryElement[]} */
const generics = [];
+ /** @type {function(string, string): void} */
+ const handleRefOrPtr = (chr, name) => {
+ if (parserState.typeFilter !== null && parserState.typeFilter !== "primitive") {
+ throw [
+ "Invalid search type: primitive ",
+ chr,
+ " and ",
+ parserState.typeFilter,
+ " both specified",
+ ];
+ }
+ parserState.typeFilter = null;
+ parserState.pos += 1;
+ let c = parserState.userQuery[parserState.pos];
+ while (c === " " && parserState.pos < parserState.length) {
+ parserState.pos += 1;
+ c = parserState.userQuery[parserState.pos];
+ }
+ const generics = [];
+ const pos = parserState.pos;
+ if (parserState.userQuery.slice(pos, pos + 3) === "mut") {
+ generics.push(makePrimitiveElement("mut", { typeFilter: "keyword" }));
+ parserState.pos += 3;
+ c = parserState.userQuery[parserState.pos];
+ } else if (chr === "*" && parserState.userQuery.slice(pos, pos + 5) === "const") {
+ // make *const T parse the same as *T
+ parserState.pos += 5;
+ c = parserState.userQuery[parserState.pos];
+ }
+ while (c === " " && parserState.pos < parserState.length) {
+ parserState.pos += 1;
+ c = parserState.userQuery[parserState.pos];
+ }
+ if (!isEndCharacter(c) && parserState.pos < parserState.length) {
+ getFilteredNextElem(query, parserState, generics, isInGenerics);
+ }
+ elems.push(makePrimitiveElement(name, { generics }));
+ };
+
skipWhitespace(parserState);
let start = parserState.pos;
let end;
@@ -636,36 +675,9 @@ function getNextElem(query, parserState, elems, isInGenerics) {
elems.push(makePrimitiveElement(name, { bindingName, generics }));
}
} else if (parserState.userQuery[parserState.pos] === "&") {
- if (parserState.typeFilter !== null && parserState.typeFilter !== "primitive") {
- throw [
- "Invalid search type: primitive ",
- "&",
- " and ",
- parserState.typeFilter,
- " both specified",
- ];
- }
- parserState.typeFilter = null;
- parserState.pos += 1;
- let c = parserState.userQuery[parserState.pos];
- while (c === " " && parserState.pos < parserState.length) {
- parserState.pos += 1;
- c = parserState.userQuery[parserState.pos];
- }
- const generics = [];
- if (parserState.userQuery.slice(parserState.pos, parserState.pos + 3) === "mut") {
- generics.push(makePrimitiveElement("mut", { typeFilter: "keyword" }));
- parserState.pos += 3;
- c = parserState.userQuery[parserState.pos];
- }
- while (c === " " && parserState.pos < parserState.length) {
- parserState.pos += 1;
- c = parserState.userQuery[parserState.pos];
- }
- if (!isEndCharacter(c) && parserState.pos < parserState.length) {
- getFilteredNextElem(query, parserState, generics, isInGenerics);
- }
- elems.push(makePrimitiveElement("reference", { generics }));
+ handleRefOrPtr("&", "reference");
+ } else if (parserState.userQuery[parserState.pos] === "*") {
+ handleRefOrPtr("*", "pointer");
} else {
const isStringElem = parserState.userQuery[start] === "\"";
// We handle the strings on their own mostly to make code easier to follow.
@@ -1185,6 +1197,7 @@ class DocSearch {
this.typeNameIdOfUnit = -1;
this.typeNameIdOfTupleOrUnit = -1;
this.typeNameIdOfReference = -1;
+ this.typeNameIdOfPointer = -1;
this.typeNameIdOfHof = -1;
this.utf8decoder = new TextDecoder();
@@ -1224,6 +1237,7 @@ class DocSearch {
tupleOrUnit,
// reference matches `&`
reference,
+ pointer,
// never matches `!`
never,
] = await Promise.all([
@@ -1239,6 +1253,7 @@ class DocSearch {
nn.search("unit"),
nn.search("()"),
nn.search("reference"),
+ nn.search("pointer"),
nn.search("never"),
]);
/**
@@ -1270,6 +1285,7 @@ class DocSearch {
this.typeNameIdOfUnit = await first(unit, TY_PRIMITIVE, "");
this.typeNameIdOfTupleOrUnit = await first(tupleOrUnit, TY_PRIMITIVE, "");
this.typeNameIdOfReference = await first(reference, TY_PRIMITIVE, "");
+ this.typeNameIdOfPointer = await first(pointer, TY_PRIMITIVE, "");
this.typeNameIdOfHof = await first(hof, TY_PRIMITIVE, "");
this.typeNameIdOfNever = await first(never, TY_PRIMITIVE, "");
}
@@ -2309,6 +2325,25 @@ class DocSearch {
}, result),
);
return true;
+ } else if (fnType.id === this.typeNameIdOfPointer) {
+ pushText({ name: "*", highlighted: fnType.highlighted }, result);
+ if (fnType.generics.length < 2) {
+ pushText({ name: "const ", highlighted: fnType.highlighted }, result);
+ }
+ let prevHighlighted = false;
+ await onEachBtwnAsync(
+ fnType.generics,
+ async value => {
+ prevHighlighted = !!value.highlighted;
+ await writeFn(value, result);
+ },
+ // @ts-expect-error
+ value => pushText({
+ name: " ",
+ highlighted: prevHighlighted && value.highlighted,
+ }, result),
+ );
+ return true;
} else if (
fnType.id === this.typeNameIdOfFn ||
fnType.id === this.typeNameIdOfFnMut ||
diff --git a/tests/rustdoc-js-std/parser-errors.js b/tests/rustdoc-js-std/parser-errors.js
index 49150cbd570ac..6e11dda8532fa 100644
--- a/tests/rustdoc-js-std/parser-errors.js
+++ b/tests/rustdoc-js-std/parser-errors.js
@@ -15,14 +15,6 @@ const PARSED = [
returned: [],
error: "Found generics without a path",
},
- {
- query: '-> *',
- elems: [],
- foundElems: 0,
- userQuery: "-> *",
- returned: [],
- error: "Unexpected `*` after ` ` (not a valid identifier)",
- },
{
query: 'a<"P">',
elems: [],
diff --git a/tests/rustdoc-js/pointer.js b/tests/rustdoc-js/pointer.js
new file mode 100644
index 0000000000000..b2b556858fdbb
--- /dev/null
+++ b/tests/rustdoc-js/pointer.js
@@ -0,0 +1,240 @@
+// exact-check
+
+const EXPECTED = [
+ // pinkie with explicit names
+ {
+ 'query': 'usize, usize -> ()',
+ 'others': [
+ { 'path': 'pointer', 'name': 'pinky' },
+ ],
+ },
+ {
+ 'query': 'pointer, usize -> ()',
+ 'others': [
+ { 'path': 'pointer', 'name': 'pinky' },
+ ],
+ },
+ {
+ 'query': 'pointer, pointer -> ()',
+ 'others': [],
+ },
+ {
+ 'query': 'pointer, usize -> ()',
+ 'others': [],
+ },
+ // thumb with explicit names
+ {
+ 'query': 'thumb, thumb -> ()',
+ 'others': [
+ { 'path': 'pointer::Thumb', 'name': 'up' },
+ ],
+ },
+ {
+ 'query': 'pointer, thumb -> ()',
+ 'others': [
+ { 'path': 'pointer::Thumb', 'name': 'up' },
+ ],
+ },
+ {
+ 'query': 'pointer, pointer -> ()',
+ 'others': [],
+ },
+ {
+ 'query': 'pointer, thumb -> ()',
+ 'others': [],
+ },
+ // index with explicit names
+ {
+ 'query': 'index, index -> ()',
+ 'others': [
+ { 'path': 'pointer::Index', 'name': 'point' },
+ ],
+ },
+ {
+ 'query': 'pointer, index -> ()',
+ 'others': [
+ { 'path': 'pointer::Index', 'name': 'point' },
+ ],
+ },
+ {
+ 'query': 'pointer, pointer -> ()',
+ 'others': [],
+ },
+ {
+ 'query': 'pointer, index -> ()',
+ 'others': [],
+ },
+ // ring with explicit names
+ {
+ 'query': 'ring, ring -> ()',
+ 'others': [
+ { 'path': 'pointer::Ring', 'name': 'wear' },
+ ],
+ },
+ {
+ 'query': 'pointer, ring -> ()',
+ 'others': [
+ { 'path': 'pointer::Ring', 'name': 'wear' },
+ ],
+ },
+ {
+ 'query': 'pointer, pointer -> ()',
+ // can't leave out the `mut`, because can't reorder like that
+ 'others': [],
+ },
+ {
+ 'query': 'pointer, pointer -> ()',
+ 'others': [
+ { 'path': 'pointer::Ring', 'name': 'wear' },
+ ],
+ },
+ {
+ 'query': 'pointer, pointer -> ()',
+ 'others': [],
+ },
+ // middle with explicit names
+ {
+ 'query': 'middle, middle -> ()',
+ 'others': [
+ { 'path': 'pointer', 'name': 'show' },
+ ],
+ },
+ {
+ 'query': 'pointer, pointer -> ()',
+ // can't leave out the mut
+ 'others': [],
+ },
+ {
+ 'query': 'pointer, pointer -> ()',
+ 'others': [
+ { 'path': 'pointer', 'name': 'show' },
+ ],
+ },
+ {
+ 'query': 'pointer>, pointer> -> ()',
+ 'others': [
+ { 'path': 'pointer', 'name': 'show' },
+ ],
+ },
+ {
+ 'query': 'pointer>, pointer> -> ()',
+ 'others': [
+ { 'path': 'pointer', 'name': 'show' },
+ ],
+ },
+ {
+ 'query': 'pointer>, pointer> -> ()',
+ 'others': [],
+ },
+ {
+ 'query': 'pointer>, pointer> -> ()',
+ 'others': [],
+ },
+ // pinkie with shorthand
+ {
+ 'query': '*const usize, usize -> ()',
+ 'others': [
+ { 'path': 'pointer', 'name': 'pinky' },
+ ],
+ },
+ // you can omit the `const`, if you want.
+ {
+ 'query': '*usize, usize -> ()',
+ 'others': [
+ { 'path': 'pointer', 'name': 'pinky' },
+ ],
+ },
+ {
+ 'query': '*const usize, *const usize -> ()',
+ 'others': [],
+ },
+ {
+ 'query': '*mut usize, usize -> ()',
+ 'others': [],
+ },
+ // thumb with shorthand
+ {
+ 'query': '*const thumb, thumb -> ()',
+ 'others': [
+ { 'path': 'pointer::Thumb', 'name': 'up' },
+ ],
+ },
+ {
+ 'query': '*const thumb, *const thumb -> ()',
+ 'others': [],
+ },
+ {
+ 'query': '*mut thumb, thumb -> ()',
+ 'others': [],
+ },
+ // index with explicit names
+ {
+ 'query': '*const index, index -> ()',
+ 'others': [
+ { 'path': 'pointer::Index', 'name': 'point' },
+ ],
+ },
+ {
+ 'query': '*const index, *const index -> ()',
+ 'others': [],
+ },
+ {
+ 'query': '*mut index, index -> ()',
+ 'others': [],
+ },
+ // ring with shorthand
+ {
+ 'query': '*const ring, ring -> ()',
+ 'others': [
+ { 'path': 'pointer::Ring', 'name': 'wear' },
+ ],
+ },
+ {
+ 'query': '*const ring, ring -> ()',
+ 'others': [
+ { 'path': 'pointer::Ring', 'name': 'wear' },
+ ],
+ },
+ {
+ 'query': '*mut ring, *const ring -> ()',
+ 'others': [
+ { 'path': 'pointer::Ring', 'name': 'wear' },
+ ],
+ },
+ {
+ 'query': '*mut ring, *mut ring -> ()',
+ 'others': [],
+ },
+ // middle with shorthand
+ {
+ 'query': '*const middle, *const middle -> ()',
+ // can't leave out the mut
+ 'others': [],
+ },
+ {
+ 'query': '*mut middle, *mut middle -> ()',
+ 'others': [
+ { 'path': 'pointer', 'name': 'show' },
+ ],
+ },
+ {
+ 'query': '*const *mut middle, *mut *const middle -> ()',
+ 'others': [
+ { 'path': 'pointer', 'name': 'show' },
+ ],
+ },
+ {
+ 'query': '*mut *const middle, *const *mut middle -> ()',
+ 'others': [
+ { 'path': 'pointer', 'name': 'show' },
+ ],
+ },
+ {
+ 'query': '*const *mut middle, *const *mut middle -> ()',
+ 'others': [],
+ },
+ {
+ 'query': '*mut *const middle, *mut *const middle -> ()',
+ 'others': [],
+ },
+];
diff --git a/tests/rustdoc-js/pointer.rs b/tests/rustdoc-js/pointer.rs
new file mode 100644
index 0000000000000..8375a17430360
--- /dev/null
+++ b/tests/rustdoc-js/pointer.rs
@@ -0,0 +1,40 @@
+#![feature(extern_types)]
+
+pub fn pinky(input: *const usize, manage: usize) {
+ unimplemented!()
+}
+
+pub struct Thumb;
+
+impl Thumb {
+ pub fn up(this: *const Self, finger: Thumb) {
+ unimplemented!()
+ }
+}
+
+pub enum Index {}
+
+impl Index {
+ pub fn point(self, data: *const Index) {
+ unimplemented!()
+ }
+}
+
+pub union Ring {
+ magic: u32,
+ marriage: f32,
+}
+
+impl Ring {
+ pub fn wear(this: *mut Self, extra: *const Ring) {
+ unimplemented!()
+ }
+}
+
+extern "C" {
+ pub type Middle;
+}
+
+pub fn show(left: *const *mut Middle, right: *mut *const Middle) {
+ unimplemented!()
+}