Skip to content

Commit 9a7b7d5

Browse files
committed
Auto merge of rust-lang#98180 - notriddle:notriddle/rustdoc-fn, r=petrochenkov,GuillaumeGomez
Improve the function pointer docs This is rust-lang#97842 but for function pointers instead of tuples. The concept is basically the same. * Reduce duplicate impls; show `fn (T₁, T₂, …, Tₙ)` and include a sentence saying that there exists up to twelve of them. * Show `Copy` and `Clone`. * Show auto traits like `Send` and `Sync`, and blanket impls like `Any`. https://notriddle.com/notriddle-rustdoc-test/std/primitive.fn.html
2 parents 29c5a02 + ddb5a26 commit 9a7b7d5

File tree

29 files changed

+278
-106
lines changed

29 files changed

+278
-106
lines changed

compiler/rustc_ast_passes/src/feature_gate.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -404,8 +404,8 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
404404
gate_feature_post!(self, rustdoc_internals, attr.span, msg);
405405
}
406406

407-
if nested_meta.has_name(sym::tuple_variadic) {
408-
let msg = "`#[doc(tuple_variadic)]` is meant for internal use only";
407+
if nested_meta.has_name(sym::fake_variadic) {
408+
let msg = "`#[doc(fake_variadic)]` is meant for internal use only";
409409
gate_feature_post!(self, rustdoc_internals, attr.span, msg);
410410
}
411411
}

compiler/rustc_error_codes/src/error_codes/E0118.md

+5-5
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ enum, union, or trait object.
44
Erroneous code example:
55

66
```compile_fail,E0118
7-
impl fn(u8) { // error: no nominal type found for inherent implementation
7+
impl<T> T { // error: no nominal type found for inherent implementation
88
fn get_state(&self) -> String {
99
// ...
1010
}
@@ -20,8 +20,8 @@ trait LiveLongAndProsper {
2020
fn get_state(&self) -> String;
2121
}
2222
23-
// and now you can implement it on fn(u8)
24-
impl LiveLongAndProsper for fn(u8) {
23+
// and now you can implement it on T
24+
impl<T> LiveLongAndProsper for T {
2525
fn get_state(&self) -> String {
2626
"He's dead, Jim!".to_owned()
2727
}
@@ -33,9 +33,9 @@ For example, `NewType` is a newtype over `Foo` in `struct NewType(Foo)`.
3333
Example:
3434

3535
```
36-
struct TypeWrapper(fn(u8));
36+
struct TypeWrapper<T>(T);
3737
38-
impl TypeWrapper {
38+
impl<T> TypeWrapper<T> {
3939
fn get_state(&self) -> String {
4040
"Fascinating!".to_owned()
4141
}

compiler/rustc_error_messages/locales/en-US/passes.ftl

+2-2
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,8 @@ passes-doc-keyword-not-mod = `#[doc(keyword = "...")]` should be used on modules
8181
8282
passes-doc-keyword-invalid-ident = `{$doc_keyword}` is not a valid identifier
8383
84-
passes-doc-tuple-variadic-not-first =
85-
`#[doc(tuple_variadic)]` must be used on the first of a set of tuple trait impls with varying arity
84+
passes-doc-fake-variadic-not-valid =
85+
`#[doc(fake_variadic)]` must be used on the first of a set of tuple or fn pointer trait impls with varying arity
8686
8787
passes-doc-keyword-only-impl = `#[doc(keyword = "...")]` should be used on impl blocks
8888

compiler/rustc_passes/src/check_attr.rs

+13-7
Original file line numberDiff line numberDiff line change
@@ -706,14 +706,20 @@ impl CheckAttrVisitor<'_> {
706706
true
707707
}
708708

709-
fn check_doc_tuple_variadic(&self, meta: &NestedMetaItem, hir_id: HirId) -> bool {
709+
fn check_doc_fake_variadic(&self, meta: &NestedMetaItem, hir_id: HirId) -> bool {
710710
match self.tcx.hir().find(hir_id).and_then(|node| match node {
711711
hir::Node::Item(item) => Some(&item.kind),
712712
_ => None,
713713
}) {
714714
Some(ItemKind::Impl(ref i)) => {
715-
if !matches!(&i.self_ty.kind, hir::TyKind::Tup([_])) {
716-
self.tcx.sess.emit_err(errors::DocTupleVariadicNotFirst { span: meta.span() });
715+
let is_valid = matches!(&i.self_ty.kind, hir::TyKind::Tup([_]))
716+
|| if let hir::TyKind::BareFn(bare_fn_ty) = &i.self_ty.kind {
717+
bare_fn_ty.decl.inputs.len() == 1
718+
} else {
719+
false
720+
};
721+
if !is_valid {
722+
self.tcx.sess.emit_err(errors::DocFakeVariadicNotValid { span: meta.span() });
717723
return false;
718724
}
719725
}
@@ -887,9 +893,9 @@ impl CheckAttrVisitor<'_> {
887893
is_valid = false
888894
}
889895

890-
sym::tuple_variadic
891-
if !self.check_attr_not_crate_level(meta, hir_id, "tuple_variadic")
892-
|| !self.check_doc_tuple_variadic(meta, hir_id) =>
896+
sym::fake_variadic
897+
if !self.check_attr_not_crate_level(meta, hir_id, "fake_variadic")
898+
|| !self.check_doc_fake_variadic(meta, hir_id) =>
893899
{
894900
is_valid = false
895901
}
@@ -939,7 +945,7 @@ impl CheckAttrVisitor<'_> {
939945
| sym::notable_trait
940946
| sym::passes
941947
| sym::plugins
942-
| sym::tuple_variadic => {}
948+
| sym::fake_variadic => {}
943949

944950
sym::test => {
945951
if !self.check_test_attr(meta, hir_id) {

compiler/rustc_passes/src/errors.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -212,8 +212,8 @@ pub struct DocKeywordInvalidIdent {
212212
}
213213

214214
#[derive(SessionDiagnostic)]
215-
#[error(passes::doc_tuple_variadic_not_first)]
216-
pub struct DocTupleVariadicNotFirst {
215+
#[error(passes::doc_fake_variadic_not_valid)]
216+
pub struct DocFakeVariadicNotValid {
217217
#[primary_span]
218218
pub span: Span,
219219
}

compiler/rustc_span/src/symbol.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -696,6 +696,7 @@ symbols! {
696696
fabsf32,
697697
fabsf64,
698698
fadd_fast,
699+
fake_variadic,
699700
fdiv_fast,
700701
feature,
701702
fence,
@@ -1471,7 +1472,6 @@ symbols! {
14711472
tuple,
14721473
tuple_from_req,
14731474
tuple_indexing,
1474-
tuple_variadic,
14751475
two_phase,
14761476
ty,
14771477
type_alias_enum_variants,

compiler/rustc_typeck/src/coherence/inherent_impls.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -219,8 +219,9 @@ impl<'tcx> InherentCollect<'tcx> {
219219
| ty::RawPtr(_)
220220
| ty::Ref(..)
221221
| ty::Never
222+
| ty::FnPtr(_)
222223
| ty::Tuple(..) => self.check_primitive_impl(item.def_id, self_ty, items, ty.span),
223-
ty::FnPtr(_) | ty::Projection(..) | ty::Opaque(..) | ty::Param(_) => {
224+
ty::Projection(..) | ty::Opaque(..) | ty::Param(_) => {
224225
let mut err = struct_span_err!(
225226
self.tcx.sess,
226227
ty.span,

library/core/src/fmt/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2562,7 +2562,7 @@ macro_rules! tuple {
25622562

25632563
macro_rules! maybe_tuple_doc {
25642564
($a:ident @ #[$meta:meta] $item:item) => {
2565-
#[doc(tuple_variadic)]
2565+
#[cfg_attr(not(bootstrap), doc(fake_variadic))]
25662566
#[doc = "This trait is implemented for tuples up to twelve items long."]
25672567
#[$meta]
25682568
$item

library/core/src/hash/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -900,7 +900,7 @@ mod impls {
900900

901901
macro_rules! maybe_tuple_doc {
902902
($a:ident @ #[$meta:meta] $item:item) => {
903-
#[doc(tuple_variadic)]
903+
#[cfg_attr(not(bootstrap), doc(fake_variadic))]
904904
#[doc = "This trait is implemented for tuples up to twelve items long."]
905905
#[$meta]
906906
$item

library/core/src/primitive_docs.rs

+52-12
Original file line numberDiff line numberDiff line change
@@ -996,7 +996,7 @@ impl<T> (T,) {}
996996
// Fake impl that's only really used for docs.
997997
#[cfg(doc)]
998998
#[stable(feature = "rust1", since = "1.0.0")]
999-
#[doc(tuple_variadic)]
999+
#[cfg_attr(not(bootstrap), doc(fake_variadic))]
10001000
/// This trait is implemented on arbitrary-length tuples.
10011001
impl<T: Clone> Clone for (T,) {
10021002
fn clone(&self) -> Self {
@@ -1007,7 +1007,7 @@ impl<T: Clone> Clone for (T,) {
10071007
// Fake impl that's only really used for docs.
10081008
#[cfg(doc)]
10091009
#[stable(feature = "rust1", since = "1.0.0")]
1010-
#[doc(tuple_variadic)]
1010+
#[cfg_attr(not(bootstrap), doc(fake_variadic))]
10111011
/// This trait is implemented on arbitrary-length tuples.
10121012
impl<T: Copy> Copy for (T,) {
10131013
// empty
@@ -1441,11 +1441,16 @@ mod prim_ref {}
14411441
/// Note that all of this is not portable to platforms where function pointers and data pointers
14421442
/// have different sizes.
14431443
///
1444-
/// ### Traits
1444+
/// ### Trait implementations
14451445
///
1446-
/// Function pointers implement the following traits:
1446+
/// In this documentation the shorthand `fn (T₁, T₂, …, Tₙ)` is used to represent non-variadic
1447+
/// function pointers of varying length. Note that this is a convenience notation to avoid
1448+
/// repetitive documentation, not valid Rust syntax.
1449+
///
1450+
/// Due to a temporary restriction in Rust's type system, these traits are only implemented on
1451+
/// functions that take 12 arguments or less, with the `"Rust"` and `"C"` ABIs. In the future, this
1452+
/// may change:
14471453
///
1448-
/// * [`Clone`]
14491454
/// * [`PartialEq`]
14501455
/// * [`Eq`]
14511456
/// * [`PartialOrd`]
@@ -1454,15 +1459,50 @@ mod prim_ref {}
14541459
/// * [`Pointer`]
14551460
/// * [`Debug`]
14561461
///
1462+
/// The following traits are implemented for function pointers with any number of arguments and
1463+
/// any ABI. These traits have implementations that are automatically generated by the compiler,
1464+
/// so are not limited by missing language features:
1465+
///
1466+
/// * [`Clone`]
1467+
/// * [`Copy`]
1468+
/// * [`Send`]
1469+
/// * [`Sync`]
1470+
/// * [`Unpin`]
1471+
/// * [`UnwindSafe`]
1472+
/// * [`RefUnwindSafe`]
1473+
///
14571474
/// [`Hash`]: hash::Hash
14581475
/// [`Pointer`]: fmt::Pointer
1476+
/// [`UnwindSafe`]: panic::UnwindSafe
1477+
/// [`RefUnwindSafe`]: panic::RefUnwindSafe
14591478
///
1460-
/// Due to a temporary restriction in Rust's type system, these traits are only implemented on
1461-
/// functions that take 12 arguments or less, with the `"Rust"` and `"C"` ABIs. In the future, this
1462-
/// may change.
1463-
///
1464-
/// In addition, function pointers of *any* signature, ABI, or safety are [`Copy`], and all *safe*
1465-
/// function pointers implement [`Fn`], [`FnMut`], and [`FnOnce`]. This works because these traits
1466-
/// are specially known to the compiler.
1479+
/// In addition, all *safe* function pointers implement [`Fn`], [`FnMut`], and [`FnOnce`], because
1480+
/// these traits are specially known to the compiler.
14671481
#[stable(feature = "rust1", since = "1.0.0")]
14681482
mod prim_fn {}
1483+
1484+
// Required to make auto trait impls render.
1485+
// See src/librustdoc/passes/collect_trait_impls.rs:collect_trait_impls
1486+
#[doc(hidden)]
1487+
#[cfg(not(bootstrap))]
1488+
impl<Ret, T> fn(T) -> Ret {}
1489+
1490+
// Fake impl that's only really used for docs.
1491+
#[cfg(doc)]
1492+
#[stable(feature = "rust1", since = "1.0.0")]
1493+
#[cfg_attr(not(bootstrap), doc(fake_variadic))]
1494+
/// This trait is implemented on function pointers with any number of arguments.
1495+
impl<Ret, T> Clone for fn(T) -> Ret {
1496+
fn clone(&self) -> Self {
1497+
loop {}
1498+
}
1499+
}
1500+
1501+
// Fake impl that's only really used for docs.
1502+
#[cfg(doc)]
1503+
#[stable(feature = "rust1", since = "1.0.0")]
1504+
#[cfg_attr(not(bootstrap), doc(fake_variadic))]
1505+
/// This trait is implemented on function pointers with any number of arguments.
1506+
impl<Ret, T> Copy for fn(T) -> Ret {
1507+
// empty
1508+
}

library/core/src/ptr/mod.rs

+72-30
Original file line numberDiff line numberDiff line change
@@ -1819,6 +1819,27 @@ pub fn hash<T: ?Sized, S: hash::Hasher>(hashee: *const T, into: &mut S) {
18191819
hashee.hash(into);
18201820
}
18211821

1822+
// If this is a unary fn pointer, it adds a doc comment.
1823+
// Otherwise, it hides the docs entirely.
1824+
macro_rules! maybe_fnptr_doc {
1825+
(@ #[$meta:meta] $item:item) => {
1826+
#[doc(hidden)]
1827+
#[$meta]
1828+
$item
1829+
};
1830+
($a:ident @ #[$meta:meta] $item:item) => {
1831+
#[cfg_attr(not(bootstrap), doc(fake_variadic))]
1832+
#[doc = "This trait is implemented for function pointers with up to twelve arguments."]
1833+
#[$meta]
1834+
$item
1835+
};
1836+
($a:ident $($rest_a:ident)+ @ #[$meta:meta] $item:item) => {
1837+
#[doc(hidden)]
1838+
#[$meta]
1839+
$item
1840+
};
1841+
}
1842+
18221843
// FIXME(strict_provenance_magic): function pointers have buggy codegen that
18231844
// necessitates casting to a usize to get the backend to do the right thing.
18241845
// for now I will break AVR to silence *a billion* lints. We should probably
@@ -1827,51 +1848,72 @@ pub fn hash<T: ?Sized, S: hash::Hasher>(hashee: *const T, into: &mut S) {
18271848
// Impls for function pointers
18281849
macro_rules! fnptr_impls_safety_abi {
18291850
($FnTy: ty, $($Arg: ident),*) => {
1830-
#[stable(feature = "fnptr_impls", since = "1.4.0")]
1831-
impl<Ret, $($Arg),*> PartialEq for $FnTy {
1832-
#[inline]
1833-
fn eq(&self, other: &Self) -> bool {
1834-
*self as usize == *other as usize
1851+
maybe_fnptr_doc! {
1852+
$($Arg)* @
1853+
#[stable(feature = "fnptr_impls", since = "1.4.0")]
1854+
impl<Ret, $($Arg),*> PartialEq for $FnTy {
1855+
#[inline]
1856+
fn eq(&self, other: &Self) -> bool {
1857+
*self as usize == *other as usize
1858+
}
18351859
}
18361860
}
18371861

1838-
#[stable(feature = "fnptr_impls", since = "1.4.0")]
1839-
impl<Ret, $($Arg),*> Eq for $FnTy {}
1862+
maybe_fnptr_doc! {
1863+
$($Arg)* @
1864+
#[stable(feature = "fnptr_impls", since = "1.4.0")]
1865+
impl<Ret, $($Arg),*> Eq for $FnTy {}
1866+
}
18401867

1841-
#[stable(feature = "fnptr_impls", since = "1.4.0")]
1842-
impl<Ret, $($Arg),*> PartialOrd for $FnTy {
1843-
#[inline]
1844-
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1845-
(*self as usize).partial_cmp(&(*other as usize))
1868+
maybe_fnptr_doc! {
1869+
$($Arg)* @
1870+
#[stable(feature = "fnptr_impls", since = "1.4.0")]
1871+
impl<Ret, $($Arg),*> PartialOrd for $FnTy {
1872+
#[inline]
1873+
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1874+
(*self as usize).partial_cmp(&(*other as usize))
1875+
}
18461876
}
18471877
}
18481878

1849-
#[stable(feature = "fnptr_impls", since = "1.4.0")]
1850-
impl<Ret, $($Arg),*> Ord for $FnTy {
1851-
#[inline]
1852-
fn cmp(&self, other: &Self) -> Ordering {
1853-
(*self as usize).cmp(&(*other as usize))
1879+
maybe_fnptr_doc! {
1880+
$($Arg)* @
1881+
#[stable(feature = "fnptr_impls", since = "1.4.0")]
1882+
impl<Ret, $($Arg),*> Ord for $FnTy {
1883+
#[inline]
1884+
fn cmp(&self, other: &Self) -> Ordering {
1885+
(*self as usize).cmp(&(*other as usize))
1886+
}
18541887
}
18551888
}
18561889

1857-
#[stable(feature = "fnptr_impls", since = "1.4.0")]
1858-
impl<Ret, $($Arg),*> hash::Hash for $FnTy {
1859-
fn hash<HH: hash::Hasher>(&self, state: &mut HH) {
1860-
state.write_usize(*self as usize)
1890+
maybe_fnptr_doc! {
1891+
$($Arg)* @
1892+
#[stable(feature = "fnptr_impls", since = "1.4.0")]
1893+
impl<Ret, $($Arg),*> hash::Hash for $FnTy {
1894+
fn hash<HH: hash::Hasher>(&self, state: &mut HH) {
1895+
state.write_usize(*self as usize)
1896+
}
18611897
}
18621898
}
18631899

1864-
#[stable(feature = "fnptr_impls", since = "1.4.0")]
1865-
impl<Ret, $($Arg),*> fmt::Pointer for $FnTy {
1866-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1867-
fmt::pointer_fmt_inner(*self as usize, f)
1900+
maybe_fnptr_doc! {
1901+
$($Arg)* @
1902+
#[stable(feature = "fnptr_impls", since = "1.4.0")]
1903+
impl<Ret, $($Arg),*> fmt::Pointer for $FnTy {
1904+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1905+
fmt::pointer_fmt_inner(*self as usize, f)
1906+
}
18681907
}
18691908
}
18701909

1871-
#[stable(feature = "fnptr_impls", since = "1.4.0")]
1872-
impl<Ret, $($Arg),*> fmt::Debug for $FnTy {
1873-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1874-
fmt::pointer_fmt_inner(*self as usize, f)
1910+
maybe_fnptr_doc! {
1911+
$($Arg)* @
1912+
#[stable(feature = "fnptr_impls", since = "1.4.0")]
1913+
impl<Ret, $($Arg),*> fmt::Debug for $FnTy {
1914+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1915+
fmt::pointer_fmt_inner(*self as usize, f)
1916+
}
18751917
}
18761918
}
18771919
}
@@ -1896,7 +1938,7 @@ macro_rules! fnptr_impls_args {
18961938
}
18971939

18981940
fnptr_impls_args! {}
1899-
fnptr_impls_args! { A }
1941+
fnptr_impls_args! { T }
19001942
fnptr_impls_args! { A, B }
19011943
fnptr_impls_args! { A, B, C }
19021944
fnptr_impls_args! { A, B, C, D }

library/core/src/tuple.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ macro_rules! tuple_impls {
107107
// Otherwise, it hides the docs entirely.
108108
macro_rules! maybe_tuple_doc {
109109
($a:ident @ #[$meta:meta] $item:item) => {
110-
#[doc(tuple_variadic)]
110+
#[cfg_attr(not(bootstrap), doc(fake_variadic))]
111111
#[doc = "This trait is implemented for tuples up to twelve items long."]
112112
#[$meta]
113113
$item

0 commit comments

Comments
 (0)