mirror of https://github.com/rust-lang/rust.git
Auto merge of #98180 - notriddle:notriddle/rustdoc-fn, r=petrochenkov,GuillaumeGomez
Improve the function pointer docs This is #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
This commit is contained in:
commit
9a7b7d5e50
|
@ -404,8 +404,8 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
||||||
gate_feature_post!(self, rustdoc_internals, attr.span, msg);
|
gate_feature_post!(self, rustdoc_internals, attr.span, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
if nested_meta.has_name(sym::tuple_variadic) {
|
if nested_meta.has_name(sym::fake_variadic) {
|
||||||
let msg = "`#[doc(tuple_variadic)]` is meant for internal use only";
|
let msg = "`#[doc(fake_variadic)]` is meant for internal use only";
|
||||||
gate_feature_post!(self, rustdoc_internals, attr.span, msg);
|
gate_feature_post!(self, rustdoc_internals, attr.span, msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ enum, union, or trait object.
|
||||||
Erroneous code example:
|
Erroneous code example:
|
||||||
|
|
||||||
```compile_fail,E0118
|
```compile_fail,E0118
|
||||||
impl fn(u8) { // error: no nominal type found for inherent implementation
|
impl<T> T { // error: no nominal type found for inherent implementation
|
||||||
fn get_state(&self) -> String {
|
fn get_state(&self) -> String {
|
||||||
// ...
|
// ...
|
||||||
}
|
}
|
||||||
|
@ -20,8 +20,8 @@ trait LiveLongAndProsper {
|
||||||
fn get_state(&self) -> String;
|
fn get_state(&self) -> String;
|
||||||
}
|
}
|
||||||
|
|
||||||
// and now you can implement it on fn(u8)
|
// and now you can implement it on T
|
||||||
impl LiveLongAndProsper for fn(u8) {
|
impl<T> LiveLongAndProsper for T {
|
||||||
fn get_state(&self) -> String {
|
fn get_state(&self) -> String {
|
||||||
"He's dead, Jim!".to_owned()
|
"He's dead, Jim!".to_owned()
|
||||||
}
|
}
|
||||||
|
@ -33,9 +33,9 @@ For example, `NewType` is a newtype over `Foo` in `struct NewType(Foo)`.
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
```
|
```
|
||||||
struct TypeWrapper(fn(u8));
|
struct TypeWrapper<T>(T);
|
||||||
|
|
||||||
impl TypeWrapper {
|
impl<T> TypeWrapper<T> {
|
||||||
fn get_state(&self) -> String {
|
fn get_state(&self) -> String {
|
||||||
"Fascinating!".to_owned()
|
"Fascinating!".to_owned()
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,8 +81,8 @@ passes-doc-keyword-not-mod = `#[doc(keyword = "...")]` should be used on modules
|
||||||
|
|
||||||
passes-doc-keyword-invalid-ident = `{$doc_keyword}` is not a valid identifier
|
passes-doc-keyword-invalid-ident = `{$doc_keyword}` is not a valid identifier
|
||||||
|
|
||||||
passes-doc-tuple-variadic-not-first =
|
passes-doc-fake-variadic-not-valid =
|
||||||
`#[doc(tuple_variadic)]` must be used on the first of a set of tuple trait impls with varying arity
|
`#[doc(fake_variadic)]` must be used on the first of a set of tuple or fn pointer trait impls with varying arity
|
||||||
|
|
||||||
passes-doc-keyword-only-impl = `#[doc(keyword = "...")]` should be used on impl blocks
|
passes-doc-keyword-only-impl = `#[doc(keyword = "...")]` should be used on impl blocks
|
||||||
|
|
||||||
|
|
|
@ -706,14 +706,20 @@ impl CheckAttrVisitor<'_> {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_doc_tuple_variadic(&self, meta: &NestedMetaItem, hir_id: HirId) -> bool {
|
fn check_doc_fake_variadic(&self, meta: &NestedMetaItem, hir_id: HirId) -> bool {
|
||||||
match self.tcx.hir().find(hir_id).and_then(|node| match node {
|
match self.tcx.hir().find(hir_id).and_then(|node| match node {
|
||||||
hir::Node::Item(item) => Some(&item.kind),
|
hir::Node::Item(item) => Some(&item.kind),
|
||||||
_ => None,
|
_ => None,
|
||||||
}) {
|
}) {
|
||||||
Some(ItemKind::Impl(ref i)) => {
|
Some(ItemKind::Impl(ref i)) => {
|
||||||
if !matches!(&i.self_ty.kind, hir::TyKind::Tup([_])) {
|
let is_valid = matches!(&i.self_ty.kind, hir::TyKind::Tup([_]))
|
||||||
self.tcx.sess.emit_err(errors::DocTupleVariadicNotFirst { span: meta.span() });
|
|| if let hir::TyKind::BareFn(bare_fn_ty) = &i.self_ty.kind {
|
||||||
|
bare_fn_ty.decl.inputs.len() == 1
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
};
|
||||||
|
if !is_valid {
|
||||||
|
self.tcx.sess.emit_err(errors::DocFakeVariadicNotValid { span: meta.span() });
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -887,9 +893,9 @@ impl CheckAttrVisitor<'_> {
|
||||||
is_valid = false
|
is_valid = false
|
||||||
}
|
}
|
||||||
|
|
||||||
sym::tuple_variadic
|
sym::fake_variadic
|
||||||
if !self.check_attr_not_crate_level(meta, hir_id, "tuple_variadic")
|
if !self.check_attr_not_crate_level(meta, hir_id, "fake_variadic")
|
||||||
|| !self.check_doc_tuple_variadic(meta, hir_id) =>
|
|| !self.check_doc_fake_variadic(meta, hir_id) =>
|
||||||
{
|
{
|
||||||
is_valid = false
|
is_valid = false
|
||||||
}
|
}
|
||||||
|
@ -939,7 +945,7 @@ impl CheckAttrVisitor<'_> {
|
||||||
| sym::notable_trait
|
| sym::notable_trait
|
||||||
| sym::passes
|
| sym::passes
|
||||||
| sym::plugins
|
| sym::plugins
|
||||||
| sym::tuple_variadic => {}
|
| sym::fake_variadic => {}
|
||||||
|
|
||||||
sym::test => {
|
sym::test => {
|
||||||
if !self.check_test_attr(meta, hir_id) {
|
if !self.check_test_attr(meta, hir_id) {
|
||||||
|
|
|
@ -212,8 +212,8 @@ pub struct DocKeywordInvalidIdent {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[error(passes::doc_tuple_variadic_not_first)]
|
#[error(passes::doc_fake_variadic_not_valid)]
|
||||||
pub struct DocTupleVariadicNotFirst {
|
pub struct DocFakeVariadicNotValid {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
|
@ -696,6 +696,7 @@ symbols! {
|
||||||
fabsf32,
|
fabsf32,
|
||||||
fabsf64,
|
fabsf64,
|
||||||
fadd_fast,
|
fadd_fast,
|
||||||
|
fake_variadic,
|
||||||
fdiv_fast,
|
fdiv_fast,
|
||||||
feature,
|
feature,
|
||||||
fence,
|
fence,
|
||||||
|
@ -1471,7 +1472,6 @@ symbols! {
|
||||||
tuple,
|
tuple,
|
||||||
tuple_from_req,
|
tuple_from_req,
|
||||||
tuple_indexing,
|
tuple_indexing,
|
||||||
tuple_variadic,
|
|
||||||
two_phase,
|
two_phase,
|
||||||
ty,
|
ty,
|
||||||
type_alias_enum_variants,
|
type_alias_enum_variants,
|
||||||
|
|
|
@ -219,8 +219,9 @@ impl<'tcx> InherentCollect<'tcx> {
|
||||||
| ty::RawPtr(_)
|
| ty::RawPtr(_)
|
||||||
| ty::Ref(..)
|
| ty::Ref(..)
|
||||||
| ty::Never
|
| ty::Never
|
||||||
|
| ty::FnPtr(_)
|
||||||
| ty::Tuple(..) => self.check_primitive_impl(item.def_id, self_ty, items, ty.span),
|
| ty::Tuple(..) => self.check_primitive_impl(item.def_id, self_ty, items, ty.span),
|
||||||
ty::FnPtr(_) | ty::Projection(..) | ty::Opaque(..) | ty::Param(_) => {
|
ty::Projection(..) | ty::Opaque(..) | ty::Param(_) => {
|
||||||
let mut err = struct_span_err!(
|
let mut err = struct_span_err!(
|
||||||
self.tcx.sess,
|
self.tcx.sess,
|
||||||
ty.span,
|
ty.span,
|
||||||
|
|
|
@ -2562,7 +2562,7 @@ macro_rules! tuple {
|
||||||
|
|
||||||
macro_rules! maybe_tuple_doc {
|
macro_rules! maybe_tuple_doc {
|
||||||
($a:ident @ #[$meta:meta] $item:item) => {
|
($a:ident @ #[$meta:meta] $item:item) => {
|
||||||
#[doc(tuple_variadic)]
|
#[cfg_attr(not(bootstrap), doc(fake_variadic))]
|
||||||
#[doc = "This trait is implemented for tuples up to twelve items long."]
|
#[doc = "This trait is implemented for tuples up to twelve items long."]
|
||||||
#[$meta]
|
#[$meta]
|
||||||
$item
|
$item
|
||||||
|
|
|
@ -900,7 +900,7 @@ mod impls {
|
||||||
|
|
||||||
macro_rules! maybe_tuple_doc {
|
macro_rules! maybe_tuple_doc {
|
||||||
($a:ident @ #[$meta:meta] $item:item) => {
|
($a:ident @ #[$meta:meta] $item:item) => {
|
||||||
#[doc(tuple_variadic)]
|
#[cfg_attr(not(bootstrap), doc(fake_variadic))]
|
||||||
#[doc = "This trait is implemented for tuples up to twelve items long."]
|
#[doc = "This trait is implemented for tuples up to twelve items long."]
|
||||||
#[$meta]
|
#[$meta]
|
||||||
$item
|
$item
|
||||||
|
|
|
@ -996,7 +996,7 @@ impl<T> (T,) {}
|
||||||
// Fake impl that's only really used for docs.
|
// Fake impl that's only really used for docs.
|
||||||
#[cfg(doc)]
|
#[cfg(doc)]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[doc(tuple_variadic)]
|
#[cfg_attr(not(bootstrap), doc(fake_variadic))]
|
||||||
/// This trait is implemented on arbitrary-length tuples.
|
/// This trait is implemented on arbitrary-length tuples.
|
||||||
impl<T: Clone> Clone for (T,) {
|
impl<T: Clone> Clone for (T,) {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
|
@ -1007,7 +1007,7 @@ impl<T: Clone> Clone for (T,) {
|
||||||
// Fake impl that's only really used for docs.
|
// Fake impl that's only really used for docs.
|
||||||
#[cfg(doc)]
|
#[cfg(doc)]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[doc(tuple_variadic)]
|
#[cfg_attr(not(bootstrap), doc(fake_variadic))]
|
||||||
/// This trait is implemented on arbitrary-length tuples.
|
/// This trait is implemented on arbitrary-length tuples.
|
||||||
impl<T: Copy> Copy for (T,) {
|
impl<T: Copy> Copy for (T,) {
|
||||||
// empty
|
// empty
|
||||||
|
@ -1441,11 +1441,16 @@ mod prim_ref {}
|
||||||
/// Note that all of this is not portable to platforms where function pointers and data pointers
|
/// Note that all of this is not portable to platforms where function pointers and data pointers
|
||||||
/// have different sizes.
|
/// have different sizes.
|
||||||
///
|
///
|
||||||
/// ### Traits
|
/// ### Trait implementations
|
||||||
///
|
///
|
||||||
/// Function pointers implement the following traits:
|
/// In this documentation the shorthand `fn (T₁, T₂, …, Tₙ)` is used to represent non-variadic
|
||||||
|
/// function pointers of varying length. Note that this is a convenience notation to avoid
|
||||||
|
/// repetitive documentation, not valid Rust syntax.
|
||||||
|
///
|
||||||
|
/// Due to a temporary restriction in Rust's type system, these traits are only implemented on
|
||||||
|
/// functions that take 12 arguments or less, with the `"Rust"` and `"C"` ABIs. In the future, this
|
||||||
|
/// may change:
|
||||||
///
|
///
|
||||||
/// * [`Clone`]
|
|
||||||
/// * [`PartialEq`]
|
/// * [`PartialEq`]
|
||||||
/// * [`Eq`]
|
/// * [`Eq`]
|
||||||
/// * [`PartialOrd`]
|
/// * [`PartialOrd`]
|
||||||
|
@ -1454,15 +1459,50 @@ mod prim_ref {}
|
||||||
/// * [`Pointer`]
|
/// * [`Pointer`]
|
||||||
/// * [`Debug`]
|
/// * [`Debug`]
|
||||||
///
|
///
|
||||||
|
/// The following traits are implemented for function pointers with any number of arguments and
|
||||||
|
/// any ABI. These traits have implementations that are automatically generated by the compiler,
|
||||||
|
/// so are not limited by missing language features:
|
||||||
|
///
|
||||||
|
/// * [`Clone`]
|
||||||
|
/// * [`Copy`]
|
||||||
|
/// * [`Send`]
|
||||||
|
/// * [`Sync`]
|
||||||
|
/// * [`Unpin`]
|
||||||
|
/// * [`UnwindSafe`]
|
||||||
|
/// * [`RefUnwindSafe`]
|
||||||
|
///
|
||||||
/// [`Hash`]: hash::Hash
|
/// [`Hash`]: hash::Hash
|
||||||
/// [`Pointer`]: fmt::Pointer
|
/// [`Pointer`]: fmt::Pointer
|
||||||
|
/// [`UnwindSafe`]: panic::UnwindSafe
|
||||||
|
/// [`RefUnwindSafe`]: panic::RefUnwindSafe
|
||||||
///
|
///
|
||||||
/// Due to a temporary restriction in Rust's type system, these traits are only implemented on
|
/// In addition, all *safe* function pointers implement [`Fn`], [`FnMut`], and [`FnOnce`], because
|
||||||
/// functions that take 12 arguments or less, with the `"Rust"` and `"C"` ABIs. In the future, this
|
/// these traits are specially known to the compiler.
|
||||||
/// may change.
|
|
||||||
///
|
|
||||||
/// In addition, function pointers of *any* signature, ABI, or safety are [`Copy`], and all *safe*
|
|
||||||
/// function pointers implement [`Fn`], [`FnMut`], and [`FnOnce`]. This works because these traits
|
|
||||||
/// are specially known to the compiler.
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
mod prim_fn {}
|
mod prim_fn {}
|
||||||
|
|
||||||
|
// Required to make auto trait impls render.
|
||||||
|
// See src/librustdoc/passes/collect_trait_impls.rs:collect_trait_impls
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[cfg(not(bootstrap))]
|
||||||
|
impl<Ret, T> fn(T) -> Ret {}
|
||||||
|
|
||||||
|
// Fake impl that's only really used for docs.
|
||||||
|
#[cfg(doc)]
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
#[cfg_attr(not(bootstrap), doc(fake_variadic))]
|
||||||
|
/// This trait is implemented on function pointers with any number of arguments.
|
||||||
|
impl<Ret, T> Clone for fn(T) -> Ret {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
loop {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fake impl that's only really used for docs.
|
||||||
|
#[cfg(doc)]
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
#[cfg_attr(not(bootstrap), doc(fake_variadic))]
|
||||||
|
/// This trait is implemented on function pointers with any number of arguments.
|
||||||
|
impl<Ret, T> Copy for fn(T) -> Ret {
|
||||||
|
// empty
|
||||||
|
}
|
||||||
|
|
|
@ -1819,6 +1819,27 @@ pub fn hash<T: ?Sized, S: hash::Hasher>(hashee: *const T, into: &mut S) {
|
||||||
hashee.hash(into);
|
hashee.hash(into);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If this is a unary fn pointer, it adds a doc comment.
|
||||||
|
// Otherwise, it hides the docs entirely.
|
||||||
|
macro_rules! maybe_fnptr_doc {
|
||||||
|
(@ #[$meta:meta] $item:item) => {
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[$meta]
|
||||||
|
$item
|
||||||
|
};
|
||||||
|
($a:ident @ #[$meta:meta] $item:item) => {
|
||||||
|
#[cfg_attr(not(bootstrap), doc(fake_variadic))]
|
||||||
|
#[doc = "This trait is implemented for function pointers with up to twelve arguments."]
|
||||||
|
#[$meta]
|
||||||
|
$item
|
||||||
|
};
|
||||||
|
($a:ident $($rest_a:ident)+ @ #[$meta:meta] $item:item) => {
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[$meta]
|
||||||
|
$item
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME(strict_provenance_magic): function pointers have buggy codegen that
|
// FIXME(strict_provenance_magic): function pointers have buggy codegen that
|
||||||
// necessitates casting to a usize to get the backend to do the right thing.
|
// necessitates casting to a usize to get the backend to do the right thing.
|
||||||
// for now I will break AVR to silence *a billion* lints. We should probably
|
// for now I will break AVR to silence *a billion* lints. We should probably
|
||||||
|
@ -1827,6 +1848,8 @@ pub fn hash<T: ?Sized, S: hash::Hasher>(hashee: *const T, into: &mut S) {
|
||||||
// Impls for function pointers
|
// Impls for function pointers
|
||||||
macro_rules! fnptr_impls_safety_abi {
|
macro_rules! fnptr_impls_safety_abi {
|
||||||
($FnTy: ty, $($Arg: ident),*) => {
|
($FnTy: ty, $($Arg: ident),*) => {
|
||||||
|
maybe_fnptr_doc! {
|
||||||
|
$($Arg)* @
|
||||||
#[stable(feature = "fnptr_impls", since = "1.4.0")]
|
#[stable(feature = "fnptr_impls", since = "1.4.0")]
|
||||||
impl<Ret, $($Arg),*> PartialEq for $FnTy {
|
impl<Ret, $($Arg),*> PartialEq for $FnTy {
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -1834,10 +1857,16 @@ macro_rules! fnptr_impls_safety_abi {
|
||||||
*self as usize == *other as usize
|
*self as usize == *other as usize
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
maybe_fnptr_doc! {
|
||||||
|
$($Arg)* @
|
||||||
#[stable(feature = "fnptr_impls", since = "1.4.0")]
|
#[stable(feature = "fnptr_impls", since = "1.4.0")]
|
||||||
impl<Ret, $($Arg),*> Eq for $FnTy {}
|
impl<Ret, $($Arg),*> Eq for $FnTy {}
|
||||||
|
}
|
||||||
|
|
||||||
|
maybe_fnptr_doc! {
|
||||||
|
$($Arg)* @
|
||||||
#[stable(feature = "fnptr_impls", since = "1.4.0")]
|
#[stable(feature = "fnptr_impls", since = "1.4.0")]
|
||||||
impl<Ret, $($Arg),*> PartialOrd for $FnTy {
|
impl<Ret, $($Arg),*> PartialOrd for $FnTy {
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -1845,7 +1874,10 @@ macro_rules! fnptr_impls_safety_abi {
|
||||||
(*self as usize).partial_cmp(&(*other as usize))
|
(*self as usize).partial_cmp(&(*other as usize))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
maybe_fnptr_doc! {
|
||||||
|
$($Arg)* @
|
||||||
#[stable(feature = "fnptr_impls", since = "1.4.0")]
|
#[stable(feature = "fnptr_impls", since = "1.4.0")]
|
||||||
impl<Ret, $($Arg),*> Ord for $FnTy {
|
impl<Ret, $($Arg),*> Ord for $FnTy {
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -1853,21 +1885,30 @@ macro_rules! fnptr_impls_safety_abi {
|
||||||
(*self as usize).cmp(&(*other as usize))
|
(*self as usize).cmp(&(*other as usize))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
maybe_fnptr_doc! {
|
||||||
|
$($Arg)* @
|
||||||
#[stable(feature = "fnptr_impls", since = "1.4.0")]
|
#[stable(feature = "fnptr_impls", since = "1.4.0")]
|
||||||
impl<Ret, $($Arg),*> hash::Hash for $FnTy {
|
impl<Ret, $($Arg),*> hash::Hash for $FnTy {
|
||||||
fn hash<HH: hash::Hasher>(&self, state: &mut HH) {
|
fn hash<HH: hash::Hasher>(&self, state: &mut HH) {
|
||||||
state.write_usize(*self as usize)
|
state.write_usize(*self as usize)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
maybe_fnptr_doc! {
|
||||||
|
$($Arg)* @
|
||||||
#[stable(feature = "fnptr_impls", since = "1.4.0")]
|
#[stable(feature = "fnptr_impls", since = "1.4.0")]
|
||||||
impl<Ret, $($Arg),*> fmt::Pointer for $FnTy {
|
impl<Ret, $($Arg),*> fmt::Pointer for $FnTy {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
fmt::pointer_fmt_inner(*self as usize, f)
|
fmt::pointer_fmt_inner(*self as usize, f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
maybe_fnptr_doc! {
|
||||||
|
$($Arg)* @
|
||||||
#[stable(feature = "fnptr_impls", since = "1.4.0")]
|
#[stable(feature = "fnptr_impls", since = "1.4.0")]
|
||||||
impl<Ret, $($Arg),*> fmt::Debug for $FnTy {
|
impl<Ret, $($Arg),*> fmt::Debug for $FnTy {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
@ -1875,6 +1916,7 @@ macro_rules! fnptr_impls_safety_abi {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! fnptr_impls_args {
|
macro_rules! fnptr_impls_args {
|
||||||
|
@ -1896,7 +1938,7 @@ macro_rules! fnptr_impls_args {
|
||||||
}
|
}
|
||||||
|
|
||||||
fnptr_impls_args! {}
|
fnptr_impls_args! {}
|
||||||
fnptr_impls_args! { A }
|
fnptr_impls_args! { T }
|
||||||
fnptr_impls_args! { A, B }
|
fnptr_impls_args! { A, B }
|
||||||
fnptr_impls_args! { A, B, C }
|
fnptr_impls_args! { A, B, C }
|
||||||
fnptr_impls_args! { A, B, C, D }
|
fnptr_impls_args! { A, B, C, D }
|
||||||
|
|
|
@ -107,7 +107,7 @@ macro_rules! tuple_impls {
|
||||||
// Otherwise, it hides the docs entirely.
|
// Otherwise, it hides the docs entirely.
|
||||||
macro_rules! maybe_tuple_doc {
|
macro_rules! maybe_tuple_doc {
|
||||||
($a:ident @ #[$meta:meta] $item:item) => {
|
($a:ident @ #[$meta:meta] $item:item) => {
|
||||||
#[doc(tuple_variadic)]
|
#[cfg_attr(not(bootstrap), doc(fake_variadic))]
|
||||||
#[doc = "This trait is implemented for tuples up to twelve items long."]
|
#[doc = "This trait is implemented for tuples up to twelve items long."]
|
||||||
#[$meta]
|
#[$meta]
|
||||||
$item
|
$item
|
||||||
|
|
|
@ -996,7 +996,7 @@ impl<T> (T,) {}
|
||||||
// Fake impl that's only really used for docs.
|
// Fake impl that's only really used for docs.
|
||||||
#[cfg(doc)]
|
#[cfg(doc)]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[doc(tuple_variadic)]
|
#[cfg_attr(not(bootstrap), doc(fake_variadic))]
|
||||||
/// This trait is implemented on arbitrary-length tuples.
|
/// This trait is implemented on arbitrary-length tuples.
|
||||||
impl<T: Clone> Clone for (T,) {
|
impl<T: Clone> Clone for (T,) {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
|
@ -1007,7 +1007,7 @@ impl<T: Clone> Clone for (T,) {
|
||||||
// Fake impl that's only really used for docs.
|
// Fake impl that's only really used for docs.
|
||||||
#[cfg(doc)]
|
#[cfg(doc)]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[doc(tuple_variadic)]
|
#[cfg_attr(not(bootstrap), doc(fake_variadic))]
|
||||||
/// This trait is implemented on arbitrary-length tuples.
|
/// This trait is implemented on arbitrary-length tuples.
|
||||||
impl<T: Copy> Copy for (T,) {
|
impl<T: Copy> Copy for (T,) {
|
||||||
// empty
|
// empty
|
||||||
|
@ -1441,11 +1441,16 @@ mod prim_ref {}
|
||||||
/// Note that all of this is not portable to platforms where function pointers and data pointers
|
/// Note that all of this is not portable to platforms where function pointers and data pointers
|
||||||
/// have different sizes.
|
/// have different sizes.
|
||||||
///
|
///
|
||||||
/// ### Traits
|
/// ### Trait implementations
|
||||||
///
|
///
|
||||||
/// Function pointers implement the following traits:
|
/// In this documentation the shorthand `fn (T₁, T₂, …, Tₙ)` is used to represent non-variadic
|
||||||
|
/// function pointers of varying length. Note that this is a convenience notation to avoid
|
||||||
|
/// repetitive documentation, not valid Rust syntax.
|
||||||
|
///
|
||||||
|
/// Due to a temporary restriction in Rust's type system, these traits are only implemented on
|
||||||
|
/// functions that take 12 arguments or less, with the `"Rust"` and `"C"` ABIs. In the future, this
|
||||||
|
/// may change:
|
||||||
///
|
///
|
||||||
/// * [`Clone`]
|
|
||||||
/// * [`PartialEq`]
|
/// * [`PartialEq`]
|
||||||
/// * [`Eq`]
|
/// * [`Eq`]
|
||||||
/// * [`PartialOrd`]
|
/// * [`PartialOrd`]
|
||||||
|
@ -1454,15 +1459,50 @@ mod prim_ref {}
|
||||||
/// * [`Pointer`]
|
/// * [`Pointer`]
|
||||||
/// * [`Debug`]
|
/// * [`Debug`]
|
||||||
///
|
///
|
||||||
|
/// The following traits are implemented for function pointers with any number of arguments and
|
||||||
|
/// any ABI. These traits have implementations that are automatically generated by the compiler,
|
||||||
|
/// so are not limited by missing language features:
|
||||||
|
///
|
||||||
|
/// * [`Clone`]
|
||||||
|
/// * [`Copy`]
|
||||||
|
/// * [`Send`]
|
||||||
|
/// * [`Sync`]
|
||||||
|
/// * [`Unpin`]
|
||||||
|
/// * [`UnwindSafe`]
|
||||||
|
/// * [`RefUnwindSafe`]
|
||||||
|
///
|
||||||
/// [`Hash`]: hash::Hash
|
/// [`Hash`]: hash::Hash
|
||||||
/// [`Pointer`]: fmt::Pointer
|
/// [`Pointer`]: fmt::Pointer
|
||||||
|
/// [`UnwindSafe`]: panic::UnwindSafe
|
||||||
|
/// [`RefUnwindSafe`]: panic::RefUnwindSafe
|
||||||
///
|
///
|
||||||
/// Due to a temporary restriction in Rust's type system, these traits are only implemented on
|
/// In addition, all *safe* function pointers implement [`Fn`], [`FnMut`], and [`FnOnce`], because
|
||||||
/// functions that take 12 arguments or less, with the `"Rust"` and `"C"` ABIs. In the future, this
|
/// these traits are specially known to the compiler.
|
||||||
/// may change.
|
|
||||||
///
|
|
||||||
/// In addition, function pointers of *any* signature, ABI, or safety are [`Copy`], and all *safe*
|
|
||||||
/// function pointers implement [`Fn`], [`FnMut`], and [`FnOnce`]. This works because these traits
|
|
||||||
/// are specially known to the compiler.
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
mod prim_fn {}
|
mod prim_fn {}
|
||||||
|
|
||||||
|
// Required to make auto trait impls render.
|
||||||
|
// See src/librustdoc/passes/collect_trait_impls.rs:collect_trait_impls
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[cfg(not(bootstrap))]
|
||||||
|
impl<Ret, T> fn(T) -> Ret {}
|
||||||
|
|
||||||
|
// Fake impl that's only really used for docs.
|
||||||
|
#[cfg(doc)]
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
#[cfg_attr(not(bootstrap), doc(fake_variadic))]
|
||||||
|
/// This trait is implemented on function pointers with any number of arguments.
|
||||||
|
impl<Ret, T> Clone for fn(T) -> Ret {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
loop {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fake impl that's only really used for docs.
|
||||||
|
#[cfg(doc)]
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
#[cfg_attr(not(bootstrap), doc(fake_variadic))]
|
||||||
|
/// This trait is implemented on function pointers with any number of arguments.
|
||||||
|
impl<Ret, T> Copy for fn(T) -> Ret {
|
||||||
|
// empty
|
||||||
|
}
|
||||||
|
|
|
@ -506,8 +506,8 @@ pub(crate) fn build_impl(
|
||||||
for_,
|
for_,
|
||||||
items: trait_items,
|
items: trait_items,
|
||||||
polarity,
|
polarity,
|
||||||
kind: if utils::has_doc_flag(tcx, did, sym::tuple_variadic) {
|
kind: if utils::has_doc_flag(tcx, did, sym::fake_variadic) {
|
||||||
ImplKind::TupleVaradic
|
ImplKind::FakeVaradic
|
||||||
} else {
|
} else {
|
||||||
ImplKind::Normal
|
ImplKind::Normal
|
||||||
},
|
},
|
||||||
|
|
|
@ -2037,8 +2037,8 @@ fn clean_impl<'tcx>(
|
||||||
for_,
|
for_,
|
||||||
items,
|
items,
|
||||||
polarity: tcx.impl_polarity(def_id),
|
polarity: tcx.impl_polarity(def_id),
|
||||||
kind: if utils::has_doc_flag(tcx, def_id.to_def_id(), sym::tuple_variadic) {
|
kind: if utils::has_doc_flag(tcx, def_id.to_def_id(), sym::fake_variadic) {
|
||||||
ImplKind::TupleVaradic
|
ImplKind::FakeVaradic
|
||||||
} else {
|
} else {
|
||||||
ImplKind::Normal
|
ImplKind::Normal
|
||||||
},
|
},
|
||||||
|
|
|
@ -1841,7 +1841,7 @@ impl PrimitiveType {
|
||||||
Reference => [RefSimplifiedType(Mutability::Not), RefSimplifiedType(Mutability::Mut)].into_iter().collect(),
|
Reference => [RefSimplifiedType(Mutability::Not), RefSimplifiedType(Mutability::Mut)].into_iter().collect(),
|
||||||
// FIXME: This will be wrong if we ever add inherent impls
|
// FIXME: This will be wrong if we ever add inherent impls
|
||||||
// for function pointers.
|
// for function pointers.
|
||||||
Fn => ArrayVec::new(),
|
Fn => single(FunctionSimplifiedType(1)),
|
||||||
Never => single(NeverSimplifiedType),
|
Never => single(NeverSimplifiedType),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -2394,7 +2394,7 @@ impl Impl {
|
||||||
pub(crate) enum ImplKind {
|
pub(crate) enum ImplKind {
|
||||||
Normal,
|
Normal,
|
||||||
Auto,
|
Auto,
|
||||||
TupleVaradic,
|
FakeVaradic,
|
||||||
Blanket(Box<Type>),
|
Blanket(Box<Type>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2407,8 +2407,8 @@ impl ImplKind {
|
||||||
matches!(self, ImplKind::Blanket(_))
|
matches!(self, ImplKind::Blanket(_))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn is_tuple_variadic(&self) -> bool {
|
pub(crate) fn is_fake_variadic(&self) -> bool {
|
||||||
matches!(self, ImplKind::TupleVaradic)
|
matches!(self, ImplKind::FakeVaradic)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn as_blanket_ty(&self) -> Option<&Type> {
|
pub(crate) fn as_blanket_ty(&self) -> Option<&Type> {
|
||||||
|
|
|
@ -1165,10 +1165,43 @@ impl clean::Impl {
|
||||||
|
|
||||||
if let clean::Type::Tuple(types) = &self.for_ &&
|
if let clean::Type::Tuple(types) = &self.for_ &&
|
||||||
let [clean::Type::Generic(name)] = &types[..] &&
|
let [clean::Type::Generic(name)] = &types[..] &&
|
||||||
(self.kind.is_tuple_variadic() || self.kind.is_auto()) {
|
(self.kind.is_fake_variadic() || self.kind.is_auto())
|
||||||
|
{
|
||||||
// Hardcoded anchor library/core/src/primitive_docs.rs
|
// Hardcoded anchor library/core/src/primitive_docs.rs
|
||||||
// Link should match `# Trait implementations`
|
// Link should match `# Trait implementations`
|
||||||
primitive_link_fragment(f, PrimitiveType::Tuple, &format!("({name}₁, {name}₂, …, {name}ₙ)"), "#trait-implementations-1", cx)?;
|
primitive_link_fragment(f, PrimitiveType::Tuple, &format!("({name}₁, {name}₂, …, {name}ₙ)"), "#trait-implementations-1", cx)?;
|
||||||
|
} else if let clean::BareFunction(bare_fn) = &self.for_ &&
|
||||||
|
let [clean::Argument { type_: clean::Type::Generic(name), .. }] = &bare_fn.decl.inputs.values[..] &&
|
||||||
|
(self.kind.is_fake_variadic() || self.kind.is_auto())
|
||||||
|
{
|
||||||
|
// Hardcoded anchor library/core/src/primitive_docs.rs
|
||||||
|
// Link should match `# Trait implementations`
|
||||||
|
|
||||||
|
let hrtb = bare_fn.print_hrtb_with_space(cx);
|
||||||
|
let unsafety = bare_fn.unsafety.print_with_space();
|
||||||
|
let abi = print_abi_with_space(bare_fn.abi);
|
||||||
|
if f.alternate() {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"{hrtb:#}{unsafety}{abi:#}",
|
||||||
|
)?;
|
||||||
|
} else {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"{hrtb}{unsafety}{abi}",
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
let ellipsis = if bare_fn.decl.c_variadic {
|
||||||
|
", ..."
|
||||||
|
} else {
|
||||||
|
""
|
||||||
|
};
|
||||||
|
primitive_link_fragment(f, PrimitiveType::Tuple, &format!("fn ({name}₁, {name}₂, …, {name}ₙ{ellipsis})"), "#trait-implementations-1", cx)?;
|
||||||
|
// Write output.
|
||||||
|
if let clean::FnRetTy::Return(ty) = &bare_fn.decl.output {
|
||||||
|
write!(f, " -> ")?;
|
||||||
|
fmt_type(ty, f, use_absolute, cx)?;
|
||||||
|
}
|
||||||
} else if let Some(ty) = self.kind.as_blanket_ty() {
|
} else if let Some(ty) = self.kind.as_blanket_ty() {
|
||||||
fmt_type(ty, f, use_absolute, cx)?;
|
fmt_type(ty, f, use_absolute, cx)?;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -574,7 +574,7 @@ impl FromWithTcx<clean::Impl> for Impl {
|
||||||
let trait_ = trait_.map(|path| clean::Type::Path { path }.into_tcx(tcx));
|
let trait_ = trait_.map(|path| clean::Type::Path { path }.into_tcx(tcx));
|
||||||
// FIXME: use something like ImplKind in JSON?
|
// FIXME: use something like ImplKind in JSON?
|
||||||
let (synthetic, blanket_impl) = match kind {
|
let (synthetic, blanket_impl) = match kind {
|
||||||
clean::ImplKind::Normal | clean::ImplKind::TupleVaradic => (false, None),
|
clean::ImplKind::Normal | clean::ImplKind::FakeVaradic => (false, None),
|
||||||
clean::ImplKind::Auto => (true, None),
|
clean::ImplKind::Auto => (true, None),
|
||||||
clean::ImplKind::Blanket(ty) => (false, Some(*ty)),
|
clean::ImplKind::Blanket(ty) => (false, Some(*ty)),
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,13 +3,13 @@
|
||||||
trait Mine {}
|
trait Mine {}
|
||||||
|
|
||||||
// This one is fine
|
// This one is fine
|
||||||
#[doc(tuple_variadic)]
|
#[doc(fake_variadic)]
|
||||||
impl<T> Mine for (T,) {}
|
impl<T> Mine for (T,) {}
|
||||||
|
|
||||||
trait Mine2 {}
|
trait Mine2 {}
|
||||||
|
|
||||||
// This one is not
|
// This one is not
|
||||||
#[doc(tuple_variadic)] //~ ERROR
|
#[doc(fake_variadic)] //~ ERROR
|
||||||
impl<T, U> Mine for (T,U) {}
|
impl<T, U> Mine for (T,U) {}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
error: `#[doc(tuple_variadic)]` must be used on the first of a set of tuple trait impls with varying arity
|
error: `#[doc(fake_variadic)]` must be used on the first of a set of tuple or fn pointer trait impls with varying arity
|
||||||
--> $DIR/tuple-variadic-check.rs:12:7
|
--> $DIR/tuple-variadic-check.rs:12:7
|
||||||
|
|
|
|
||||||
LL | #[doc(tuple_variadic)]
|
LL | #[doc(fake_variadic)]
|
||||||
| ^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
// @has - '//h2[@id="trait-implementations-1"]' 'Trait implementations'
|
// @has - '//h2[@id="trait-implementations-1"]' 'Trait implementations'
|
||||||
/// # Trait implementations
|
/// # Trait implementations
|
||||||
///
|
///
|
||||||
/// This header is hard-coded in the HTML format linking for `#[doc(tuple_variadics)]`.
|
/// This header is hard-coded in the HTML format linking for `#[doc(fake_variadics)]`.
|
||||||
/// To make sure it gets linked correctly, we need to make sure the hardcoded anchor
|
/// To make sure it gets linked correctly, we need to make sure the hardcoded anchor
|
||||||
/// in the code matches what rustdoc generates for the header.
|
/// in the code matches what rustdoc generates for the header.
|
||||||
mod tuple_prim {}
|
mod tuple_prim {}
|
||||||
|
|
|
@ -7,12 +7,12 @@ pub trait Foo {}
|
||||||
|
|
||||||
// @has foo/trait.Foo.html
|
// @has foo/trait.Foo.html
|
||||||
// @has - '//section[@id="impl-Foo-for-(T%2C)"]/h3' 'impl<T> Foo for (T₁, T₂, …, Tₙ)'
|
// @has - '//section[@id="impl-Foo-for-(T%2C)"]/h3' 'impl<T> Foo for (T₁, T₂, …, Tₙ)'
|
||||||
#[doc(tuple_variadic)]
|
#[doc(fake_variadic)]
|
||||||
impl<T> Foo for (T,) {}
|
impl<T> Foo for (T,) {}
|
||||||
|
|
||||||
pub trait Bar {}
|
pub trait Bar {}
|
||||||
|
|
||||||
// @has foo/trait.Bar.html
|
// @has foo/trait.Bar.html
|
||||||
// @has - '//section[@id="impl-Bar-for-(U%2C)"]/h3' 'impl<U: Foo> Bar for (U₁, U₂, …, Uₙ)'
|
// @has - '//section[@id="impl-Bar-for-(U%2C)"]/h3' 'impl<U: Foo> Bar for (U₁, U₂, …, Uₙ)'
|
||||||
#[doc(tuple_variadic)]
|
#[doc(fake_variadic)]
|
||||||
impl<U: Foo> Bar for (U,) {}
|
impl<U: Foo> Bar for (U,) {}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
impl fn(u8) { //~ ERROR E0118
|
impl<T> T { //~ ERROR E0118
|
||||||
fn get_state(&self) -> String {
|
fn get_state(&self) -> String {
|
||||||
String::new()
|
String::new()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
error[E0118]: no nominal type found for inherent implementation
|
error[E0118]: no nominal type found for inherent implementation
|
||||||
--> $DIR/E0118.rs:1:6
|
--> $DIR/E0118.rs:1:9
|
||||||
|
|
|
|
||||||
LL | impl fn(u8) {
|
LL | impl<T> T {
|
||||||
| ^^^^^^ impl requires a nominal type
|
| ^ impl requires a nominal type
|
||||||
|
|
|
|
||||||
= note: either implement a trait on it or create a newtype to wrap it instead
|
= note: either implement a trait on it or create a newtype to wrap it instead
|
||||||
|
|
||||||
|
|
|
@ -4,5 +4,7 @@ struct Foo {
|
||||||
|
|
||||||
impl *mut Foo {} //~ ERROR E0390
|
impl *mut Foo {} //~ ERROR E0390
|
||||||
|
|
||||||
|
impl fn(Foo) {} //~ ERROR E0390
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,14 @@ LL | impl *mut Foo {}
|
||||||
|
|
|
|
||||||
= help: consider using an extension trait instead
|
= help: consider using an extension trait instead
|
||||||
|
|
||||||
error: aborting due to previous error
|
error[E0390]: cannot define inherent `impl` for primitive types
|
||||||
|
--> $DIR/E0390.rs:7:6
|
||||||
|
|
|
||||||
|
LL | impl fn(Foo) {}
|
||||||
|
| ^^^^^^^
|
||||||
|
|
|
||||||
|
= help: consider using an extension trait instead
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0390`.
|
For more information about this error, try `rustc --explain E0390`.
|
||||||
|
|
|
@ -4,7 +4,7 @@ mod foo {}
|
||||||
|
|
||||||
trait Mine {}
|
trait Mine {}
|
||||||
|
|
||||||
#[doc(tuple_variadic)] //~ ERROR: `#[doc(tuple_variadic)]` is meant for internal use only
|
#[doc(fake_variadic)] //~ ERROR: `#[doc(fake_variadic)]` is meant for internal use only
|
||||||
impl<T> Mine for (T,) {}
|
impl<T> Mine for (T,) {}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -7,11 +7,11 @@ LL | #[doc(keyword = "match")]
|
||||||
= note: see issue #90418 <https://github.com/rust-lang/rust/issues/90418> for more information
|
= note: see issue #90418 <https://github.com/rust-lang/rust/issues/90418> for more information
|
||||||
= help: add `#![feature(rustdoc_internals)]` to the crate attributes to enable
|
= help: add `#![feature(rustdoc_internals)]` to the crate attributes to enable
|
||||||
|
|
||||||
error[E0658]: `#[doc(tuple_variadic)]` is meant for internal use only
|
error[E0658]: `#[doc(fake_variadic)]` is meant for internal use only
|
||||||
--> $DIR/feature-gate-rustdoc_internals.rs:7:1
|
--> $DIR/feature-gate-rustdoc_internals.rs:7:1
|
||||||
|
|
|
|
||||||
LL | #[doc(tuple_variadic)]
|
LL | #[doc(fake_variadic)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: see issue #90418 <https://github.com/rust-lang/rust/issues/90418> for more information
|
= note: see issue #90418 <https://github.com/rust-lang/rust/issues/90418> for more information
|
||||||
= help: add `#![feature(rustdoc_internals)]` to the crate attributes to enable
|
= help: add `#![feature(rustdoc_internals)]` to the crate attributes to enable
|
||||||
|
|
|
@ -96,13 +96,13 @@ LL | assert_eq!(Foo::Bar, i);
|
||||||
= help: the trait `Debug` is not implemented for `fn(usize) -> Foo {Foo::Bar}`
|
= help: the trait `Debug` is not implemented for `fn(usize) -> Foo {Foo::Bar}`
|
||||||
= help: the following other types implement trait `Debug`:
|
= help: the following other types implement trait `Debug`:
|
||||||
extern "C" fn() -> Ret
|
extern "C" fn() -> Ret
|
||||||
extern "C" fn(A) -> Ret
|
|
||||||
extern "C" fn(A, ...) -> Ret
|
|
||||||
extern "C" fn(A, B) -> Ret
|
extern "C" fn(A, B) -> Ret
|
||||||
extern "C" fn(A, B, ...) -> Ret
|
extern "C" fn(A, B, ...) -> Ret
|
||||||
extern "C" fn(A, B, C) -> Ret
|
extern "C" fn(A, B, C) -> Ret
|
||||||
extern "C" fn(A, B, C, ...) -> Ret
|
extern "C" fn(A, B, C, ...) -> Ret
|
||||||
extern "C" fn(A, B, C, D) -> Ret
|
extern "C" fn(A, B, C, D) -> Ret
|
||||||
|
extern "C" fn(A, B, C, D, ...) -> Ret
|
||||||
|
extern "C" fn(A, B, C, D, E) -> Ret
|
||||||
and 68 others
|
and 68 others
|
||||||
= note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue