diff --git a/compiler/pavexc/src/compiler/analyses/application_state/mod.rs b/compiler/pavexc/src/compiler/analyses/application_state/mod.rs index bf31cffa7..287be8435 100644 --- a/compiler/pavexc/src/compiler/analyses/application_state/mod.rs +++ b/compiler/pavexc/src/compiler/analyses/application_state/mod.rs @@ -311,7 +311,7 @@ fn _field_name_candidate(ty_: &Type, strategy: NamingStrategy, candidate: &mut S if i > 0 { candidate.push('_'); } - _field_name_candidate(input, strategy, candidate); + _field_name_candidate(&input.type_, strategy, candidate); } if let Some(output) = &fp.output { candidate.push_str("_ret_"); diff --git a/compiler/pavexc/src/compiler/codegen/mod.rs b/compiler/pavexc/src/compiler/codegen/mod.rs index 6a1613538..20bb9ed08 100644 --- a/compiler/pavexc/src/compiler/codegen/mod.rs +++ b/compiler/pavexc/src/compiler/codegen/mod.rs @@ -485,7 +485,7 @@ fn collect_type_package_ids(package_ids: &mut IndexSet, t: &Type) { } Type::FunctionPointer(fp) => { for input in &fp.inputs { - collect_type_package_ids(package_ids, input); + collect_type_package_ids(package_ids, &input.type_); } if let Some(output) = &fp.output { collect_type_package_ids(package_ids, output); diff --git a/rustdoc/rustdoc_ir/src/function_pointer.rs b/rustdoc/rustdoc_ir/src/function_pointer.rs index 4340391bf..87654e2e1 100644 --- a/rustdoc/rustdoc_ir/src/function_pointer.rs +++ b/rustdoc/rustdoc_ir/src/function_pointer.rs @@ -4,11 +4,23 @@ use rustdoc_types::Abi; use crate::Type; +/// A single input parameter for a function pointer type. +#[derive(serde::Serialize, serde::Deserialize, Eq, PartialEq, Hash, Clone)] +pub struct FunctionPointerInput { + /// The name of the parameter, if any. + /// + /// `None` for unnamed parameters (e.g. `fn(usize)`), + /// `Some` for named parameters (e.g. `fn(a: usize)`). + pub name: Option, + /// The type of the parameter. + pub type_: Type, +} + /// A Rust function pointer type—e.g. `fn(u32) -> u8` or `unsafe extern "C" fn()`. #[derive(serde::Serialize, serde::Deserialize, Eq, PartialEq, Hash, Clone)] pub struct FunctionPointer { - /// The input parameter types. - pub inputs: Vec, + /// The input parameters, including optional names and types. + pub inputs: Vec, /// The return type. `None` means the unit type `()`. pub output: Option>, /// The ABI of the function pointer (e.g. `Abi::Rust`, `Abi::C { unwind: false }`). @@ -65,7 +77,10 @@ impl Debug for FunctionPointer { if i > 0 { write!(f, ", ")?; } - write!(f, "{:?}", input)?; + if let Some(name) = &input.name { + write!(f, "{name}: ")?; + } + write!(f, "{:?}", input.type_)?; } write!(f, ")")?; if let Some(output) = &self.output { diff --git a/rustdoc/rustdoc_ir/src/lib.rs b/rustdoc/rustdoc_ir/src/lib.rs index 70ce01bb0..1a31eb1f0 100644 --- a/rustdoc/rustdoc_ir/src/lib.rs +++ b/rustdoc/rustdoc_ir/src/lib.rs @@ -25,7 +25,7 @@ pub use callable_path::{ EnumVariantConstructorPath, FreeFunctionPath, InherentMethodPath, StructLiteralPath, TraitMethodPath, }; -pub use function_pointer::FunctionPointer; +pub use function_pointer::{FunctionPointer, FunctionPointerInput}; pub use generic::Generic; pub use generic_argument::{GenericArgument, GenericLifetimeParameter}; pub use lifetime::Lifetime; diff --git a/rustdoc/rustdoc_ir/src/render.rs b/rustdoc/rustdoc_ir/src/render.rs index 487bb4e09..8e2149833 100644 --- a/rustdoc/rustdoc_ir/src/render.rs +++ b/rustdoc/rustdoc_ir/src/render.rs @@ -226,7 +226,10 @@ impl Type { write!(buffer, "fn(").unwrap(); let mut inputs = fp.inputs.iter().peekable(); while let Some(input) = inputs.next() { - input.render_into(config, buffer); + if let Some(name) = &input.name { + write!(buffer, "{name}: ").unwrap(); + } + input.type_.render_into(config, buffer); if inputs.peek().is_some() { write!(buffer, ", ").unwrap(); } diff --git a/rustdoc/rustdoc_ir/src/type_.rs b/rustdoc/rustdoc_ir/src/type_.rs index c23f01a60..cc3b34483 100644 --- a/rustdoc/rustdoc_ir/src/type_.rs +++ b/rustdoc/rustdoc_ir/src/type_.rs @@ -5,8 +5,9 @@ use indexmap::{IndexMap, IndexSet}; use crate::generics_equivalence::UnassignedIdGenerator; use crate::{ - Array, FunctionPointer, Generic, GenericArgument, GenericLifetimeParameter, Lifetime, - NamedLifetime, PathType, RawPointer, Slice, Tuple, Type, TypeReference, + Array, FunctionPointer, FunctionPointerInput, Generic, GenericArgument, + GenericLifetimeParameter, Lifetime, NamedLifetime, PathType, RawPointer, Slice, Tuple, Type, + TypeReference, }; /// A `Type` with canonicalized names for lifetimes and unassigned generic type parameters. @@ -115,7 +116,10 @@ impl Type { inputs: fp .inputs .iter() - .map(|t| t.bind_generic_type_parameters(bindings)) + .map(|input| FunctionPointerInput { + name: input.name.clone(), + type_: input.type_.bind_generic_type_parameters(bindings), + }) .collect(), output: fp .output @@ -154,7 +158,7 @@ impl Type { Type::Array(a) => a.element_type.is_a_template(), Type::RawPointer(r) => r.inner.is_a_template(), Type::FunctionPointer(fp) => { - fp.inputs.iter().any(|t| t.is_a_template()) + fp.inputs.iter().any(|input| input.type_.is_a_template()) || fp.output.as_ref().is_some_and(|t| t.is_a_template()) } Type::Generic(_) => true, @@ -194,7 +198,7 @@ impl Type { Type::RawPointer(r) => r.inner._unassigned_generic_type_parameters(set), Type::FunctionPointer(fp) => { for input in &fp.inputs { - input._unassigned_generic_type_parameters(set); + input.type_._unassigned_generic_type_parameters(set); } if let Some(output) = &fp.output { output._unassigned_generic_type_parameters(set); @@ -283,7 +287,11 @@ impl Type { .inputs .iter() .zip(templated_fp.inputs.iter()) - .all(|(concrete, templated)| templated._is_a_template_for(concrete, bindings)); + .all(|(concrete, templated)| { + templated + .type_ + ._is_a_template_for(&concrete.type_, bindings) + }); if !inputs_match { return false; } @@ -385,11 +393,15 @@ impl Type { if self_fp.inputs.len() != other_fp.inputs.len() { return false; } - let inputs_match = self_fp - .inputs - .iter() - .zip(other_fp.inputs.iter()) - .all(|(s, o)| s._is_equivalent_to(o, self_id_gen, other_id_gen)); + let inputs_match = + self_fp + .inputs + .iter() + .zip(other_fp.inputs.iter()) + .all(|(s, o)| { + s.type_ + ._is_equivalent_to(&o.type_, self_id_gen, other_id_gen) + }); if !inputs_match { return false; } @@ -445,7 +457,7 @@ impl Type { Type::FunctionPointer(fp) => { fp.inputs .iter() - .any(|t| t.has_implicit_lifetime_parameters()) + .any(|input| input.type_.has_implicit_lifetime_parameters()) || fp .output .as_ref() @@ -495,7 +507,9 @@ impl Type { Type::RawPointer(r) => r.inner.set_implicit_lifetimes(inferred_lifetime), Type::FunctionPointer(fp) => { for input in fp.inputs.iter_mut() { - input.set_implicit_lifetimes(inferred_lifetime.clone()); + input + .type_ + .set_implicit_lifetimes(inferred_lifetime.clone()); } if let Some(output) = fp.output.as_mut() { output.set_implicit_lifetimes(inferred_lifetime); @@ -553,7 +567,7 @@ impl Type { } Type::FunctionPointer(fp) => { for input in fp.inputs.iter_mut() { - input.rename_lifetime_parameters(original2renamed); + input.type_.rename_lifetime_parameters(original2renamed); } if let Some(output) = fp.output.as_mut() { output.rename_lifetime_parameters(original2renamed); @@ -598,7 +612,7 @@ impl Type { Type::RawPointer(r) => r.inner._lifetime_parameters(set), Type::FunctionPointer(fp) => { for input in &fp.inputs { - input._lifetime_parameters(set); + input.type_._lifetime_parameters(set); } if let Some(output) = &fp.output { output._lifetime_parameters(set); @@ -651,7 +665,7 @@ impl Type { Type::RawPointer(r) => r.inner._named_lifetime_parameters(set), Type::FunctionPointer(fp) => { for input in &fp.inputs { - input._named_lifetime_parameters(set); + input.type_._named_lifetime_parameters(set); } if let Some(output) = &fp.output { output._named_lifetime_parameters(set); @@ -810,7 +824,14 @@ impl Type { inputs: fp .inputs .iter() - .map(|t| t._canonicalize(lifetime_counter, generic_counter, generic_name_map)) + .map(|input| FunctionPointerInput { + name: None, + type_: input.type_._canonicalize( + lifetime_counter, + generic_counter, + generic_name_map, + ), + }) .collect(), output: fp.output.as_ref().map(|t| { Box::new(t._canonicalize(lifetime_counter, generic_counter, generic_name_map)) diff --git a/rustdoc/rustdoc_resolver/src/resolve_type.rs b/rustdoc/rustdoc_resolver/src/resolve_type.rs index 702025764..13796f8b6 100644 --- a/rustdoc/rustdoc_resolver/src/resolve_type.rs +++ b/rustdoc/rustdoc_resolver/src/resolve_type.rs @@ -7,8 +7,8 @@ use once_cell::sync::OnceCell; use rustdoc_types::{GenericArg, GenericArgs, GenericParamDefKind, ItemEnum, Type as RustdocType}; use rustdoc_ir::{ - Array, FunctionPointer, Generic, GenericArgument, GenericLifetimeParameter, PathType, - RawPointer, Slice, Tuple, Type, TypeReference, + Array, FunctionPointer, FunctionPointerInput, Generic, GenericArgument, + GenericLifetimeParameter, PathType, RawPointer, Slice, Tuple, Type, TypeReference, }; use rustdoc_processor::CrateCollection; use rustdoc_processor::indexing::CrateIndexer; @@ -516,8 +516,8 @@ fn _resolve_type( .inputs .iter() .enumerate() - .map(|(i, (_, ty))| { - resolve_type( + .map(|(i, (name, ty))| { + let resolved_ty = resolve_type( ty, used_by_package_id, krate_collection, @@ -531,6 +531,14 @@ fn _resolve_type( source, }, )) + })?; + let name = match name.as_str() { + "" | "_" => None, + s => Some(s.to_owned()), + }; + Ok(FunctionPointerInput { + name, + type_: resolved_ty, }) }) .collect::, _>>()?;