1
Fork 0

Rollup merge of #136411 - dtolnay:fnptr, r=notriddle

Omit argument names from function pointers that do not have argument names

This matches the style used for the vast majority of function pointer types in real-world code, in my experience. Prefixing `_: ` to every argument does not improve clarity.

**Before:**

<img src="https://github.com/user-attachments/assets/f07efa8b-d57e-4897-aa97-40db7d207862">

**After:**

<img src="https://github.com/user-attachments/assets/8405e08b-d6d2-4904-bcc3-a3eb866cecf0">
This commit is contained in:
Matthias Krüger 2025-02-03 21:11:34 +01:00 committed by GitHub
commit 2c6c7f8ef2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 34 additions and 12 deletions

View file

@ -1104,17 +1104,29 @@ fn clean_args_from_types_and_names<'tcx>(
types: &[hir::Ty<'tcx>],
names: &[Ident],
) -> Arguments {
fn nonempty_name(ident: &Ident) -> Option<Symbol> {
if ident.name == kw::Underscore || ident.name == kw::Empty {
None
} else {
Some(ident.name)
}
}
// If at least one argument has a name, use `_` as the name of unnamed
// arguments. Otherwise omit argument names.
let default_name = if names.iter().any(|ident| nonempty_name(ident).is_some()) {
kw::Underscore
} else {
kw::Empty
};
Arguments {
values: types
.iter()
.enumerate()
.map(|(i, ty)| Argument {
type_: clean_ty(ty, cx),
name: names
.get(i)
.map(|ident| ident.name)
.filter(|ident| !ident.is_empty())
.unwrap_or(kw::Underscore),
name: names.get(i).and_then(nonempty_name).unwrap_or(default_name),
is_const: false,
})
.collect(),

View file

@ -1408,7 +1408,9 @@ impl clean::Arguments {
) -> impl Display + 'a + Captures<'tcx> {
fmt::from_fn(move |f| {
for (i, input) in self.values.iter().enumerate() {
if !input.name.is_empty() {
write!(f, "{}: ", input.name)?;
}
input.type_.print(cx).fmt(f)?;
if i + 1 < self.values.len() {
write!(f, ", ")?;

View file

@ -45,7 +45,7 @@ pub fn f(_: &(ToString + 'static)) {}
impl Bar {
//@ has assoc_consts/struct.Bar.html '//*[@id="associatedconstant.F"]' \
// "const F: fn(_: &(dyn ToString + 'static))"
// "const F: fn(&(dyn ToString + 'static))"
pub const F: fn(_: &(ToString + 'static)) = f;
}

View file

@ -3,3 +3,11 @@
//@ has foo/fn.f.html
//@ has - '//pre[@class="rust item-decl"]' 'pub fn f(callback: fn(len: usize, foo: u32))'
pub fn f(callback: fn(len: usize, foo: u32)) {}
//@ has foo/fn.g.html
//@ has - '//pre[@class="rust item-decl"]' 'pub fn g(_: fn(usize, u32))'
pub fn g(_: fn(usize, _: u32)) {}
//@ has foo/fn.mixed.html
//@ has - '//pre[@class="rust item-decl"]' 'pub fn mixed(_: fn(_: usize, foo: u32))'
pub fn mixed(_: fn(usize, foo: u32)) {}

View file

@ -13,7 +13,7 @@ impl Owner {
}
// Make sure we handle bound vars correctly.
//@ has 'inherent_projections/fn.user.html' '//pre[@class="rust item-decl"]' "user(_: for<'a> fn(_: Carrier<'a>::Focus))"
//@ has 'inherent_projections/fn.user.html' '//pre[@class="rust item-decl"]' "user(_: for<'a> fn(Carrier<'a>::Focus))"
pub fn user(_: for<'a> fn(Carrier<'a>::Focus)) {}
pub struct Carrier<'a>(&'a ());

View file

@ -11,10 +11,10 @@ macro_rules! gen {
}
//@ has 'foo/struct.Providers.html'
//@ has - '//*[@class="rust item-decl"]//code' "pub a: for<'tcx> fn(_: TyCtxt<'tcx>, _: u8) -> i8,"
//@ has - '//*[@class="rust item-decl"]//code' "pub b: for<'tcx> fn(_: TyCtxt<'tcx>, _: u16) -> i16,"
//@ has - '//*[@id="structfield.a"]/code' "a: for<'tcx> fn(_: TyCtxt<'tcx>, _: u8) -> i8"
//@ has - '//*[@id="structfield.b"]/code' "b: for<'tcx> fn(_: TyCtxt<'tcx>, _: u16) -> i16"
//@ has - '//*[@class="rust item-decl"]//code' "pub a: for<'tcx> fn(TyCtxt<'tcx>, u8) -> i8,"
//@ has - '//*[@class="rust item-decl"]//code' "pub b: for<'tcx> fn(TyCtxt<'tcx>, u16) -> i16,"
//@ has - '//*[@id="structfield.a"]/code' "a: for<'tcx> fn(TyCtxt<'tcx>, u8) -> i8"
//@ has - '//*[@id="structfield.b"]/code' "b: for<'tcx> fn(TyCtxt<'tcx>, u16) -> i16"
gen! {
(a, 'tcx, [u8], [i8])
(b, 'tcx, [u16], [i16])