Skip to content

Commit 9c0e32b

Browse files
committed
rustdoc-json: Rename Path::name to path, and give it path (again).
Closes rust-lang#135600 Effectivly reverts rust-lang#134880
1 parent 9f4d9dc commit 9c0e32b

File tree

12 files changed

+125
-26
lines changed

12 files changed

+125
-26
lines changed

src/librustdoc/json/conversions.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -622,7 +622,7 @@ impl FromClean<clean::Type> for Type {
622622
impl FromClean<clean::Path> for Path {
623623
fn from_clean(path: clean::Path, renderer: &JsonRenderer<'_>) -> Path {
624624
Path {
625-
name: path.last_opt().map_or(String::from(""), |s| String::from(s.as_str())),
625+
path: path.whole_name(),
626626
id: renderer.id_from_item_default(path.def_id().into()),
627627
args: path.segments.last().map(|args| Box::new(args.clone().args.into_json(renderer))),
628628
}

src/rustdoc-json-types/lib.rs

+12-8
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ pub type FxHashMap<K, V> = HashMap<K, V>; // re-export for use in src/librustdoc
3030
/// This integer is incremented with every breaking change to the API,
3131
/// and is returned along with the JSON blob as [`Crate::format_version`].
3232
/// Consuming code should assert that this value matches the format version(s) that it supports.
33-
pub const FORMAT_VERSION: u32 = 38;
33+
pub const FORMAT_VERSION: u32 = 39;
3434

3535
/// The root of the emitted JSON blob.
3636
///
@@ -1036,16 +1036,20 @@ pub enum Type {
10361036
/// A type that has a simple path to it. This is the kind of type of structs, unions, enums, etc.
10371037
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
10381038
pub struct Path {
1039-
/// The name of the type as declared, e.g. in
1039+
/// The path of the type.
1040+
///
1041+
/// This will be the path that is *used* (not where it is defined), so
1042+
/// multiple `Path`s may have different values for this field even if
1043+
/// they all refer to the same item. e.g.
10401044
///
10411045
/// ```rust
1042-
/// mod foo {
1043-
/// struct Bar;
1044-
/// }
1046+
/// pub type Vec1 = std::vec::Vec<i32>; // path: "std::vec::Vec"
1047+
/// pub type Vec2 = Vec<i32>; // path: "Vec"
1048+
/// pub type Vec3 = std::prelude::v1::Vec<i32>; // path: "std::prelude::v1::Vec"
10451049
/// ```
1046-
///
1047-
/// for `foo::Bar`, this field will be `Bar`.
1048-
pub name: String,
1050+
//
1051+
// Example tested in ./tests/rustdoc-json/path_name.rs
1052+
pub path: String,
10491053
/// The ID of the type.
10501054
pub id: Id,
10511055
/// Generic arguments to the type.

src/tools/jsondoclint/src/validator/tests.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ fn errors_on_missing_path() {
163163
sig: FunctionSignature {
164164
inputs: vec![],
165165
output: Some(Type::ResolvedPath(Path {
166-
name: "Bar".to_owned(),
166+
path: "Bar".to_owned(),
167167
id: Id(1),
168168
args: None,
169169
})),
@@ -191,7 +191,7 @@ fn errors_on_missing_path() {
191191

192192
check(&krate, &[Error {
193193
kind: ErrorKind::Custom(
194-
r#"No entry in '$.paths' for Path { name: "Bar", id: Id(1), args: None }"#.to_owned(),
194+
r#"No entry in '$.paths' for Path { path: "Bar", id: Id(1), args: None }"#.to_owned(),
195195
),
196196
id: Id(1),
197197
}]);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
pub mod m1 {
2+
pub struct InPubMod;
3+
}
4+
5+
mod m2 {
6+
pub struct InPrivMod;
7+
}
8+
9+
pub use m1::{InPubMod, InPubMod as InPubMod2};
10+
pub use m2::{InPrivMod, InPrivMod as InPrivMod2};

tests/rustdoc-json/blanket_impls.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@
44

55
//@ has "$.index[*][?(@.name=='Error')].inner.assoc_type"
66
//@ has "$.index[*][?(@.name=='Error')].inner.assoc_type.type.resolved_path"
7-
//@ has "$.index[*][?(@.name=='Error')].inner.assoc_type.type.resolved_path.name" \"Infallible\"
7+
//@ has "$.index[*][?(@.name=='Error')].inner.assoc_type.type.resolved_path.path" \"Infallible\"
88
pub struct ForBlanketTryFromImpl;

tests/rustdoc-json/fns/async_return.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,15 @@ pub async fn get_int_async() -> i32 {
1717
42
1818
}
1919

20-
//@ is "$.index[*][?(@.name=='get_int_future')].inner.function.sig.output.impl_trait[0].trait_bound.trait.name" '"Future"'
20+
//@ is "$.index[*][?(@.name=='get_int_future')].inner.function.sig.output.impl_trait[0].trait_bound.trait.path" '"Future"'
2121
//@ is "$.index[*][?(@.name=='get_int_future')].inner.function.sig.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].name" '"Output"'
2222
//@ is "$.index[*][?(@.name=='get_int_future')].inner.function.sig.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].binding.equality.type.primitive" \"i32\"
2323
//@ is "$.index[*][?(@.name=='get_int_future')].inner.function.header.is_async" false
2424
pub fn get_int_future() -> impl Future<Output = i32> {
2525
async { 42 }
2626
}
2727

28-
//@ is "$.index[*][?(@.name=='get_int_future_async')].inner.function.sig.output.impl_trait[0].trait_bound.trait.name" '"Future"'
28+
//@ is "$.index[*][?(@.name=='get_int_future_async')].inner.function.sig.output.impl_trait[0].trait_bound.trait.path" '"Future"'
2929
//@ is "$.index[*][?(@.name=='get_int_future_async')].inner.function.sig.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].name" '"Output"'
3030
//@ is "$.index[*][?(@.name=='get_int_future_async')].inner.function.sig.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].binding.equality.type.primitive" \"i32\"
3131
//@ is "$.index[*][?(@.name=='get_int_future_async')].inner.function.header.is_async" true

tests/rustdoc-json/impl-trait-in-assoc-type.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ impl IntoIterator for AlwaysTrue {
1010
type Item = bool;
1111

1212
//@ count '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.type.impl_trait[*]' 1
13-
//@ is '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.type.impl_trait[0].trait_bound.trait.name' '"Iterator"'
13+
//@ is '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.type.impl_trait[0].trait_bound.trait.path' '"Iterator"'
1414
//@ count '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.type.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[*]' 1
1515
//@ is '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.type.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].name' '"Item"'
1616
//@ is '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.type.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].binding.equality.type.primitive' '"bool"'

tests/rustdoc-json/path_name.rs

+83
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
// Test for the Path::name field within a single crate.
2+
//
3+
// See https://github.com/rust-lang/rust/issues/135600
4+
// and https://github.com/rust-lang/rust/pull/134880#issuecomment-2596386111
5+
//
6+
// ignore-tidy-linelength
7+
//@ aux-build: defines_and_reexports.rs
8+
extern crate defines_and_reexports;
9+
10+
mod priv_mod {
11+
pub struct InPrivMod;
12+
}
13+
14+
pub mod pub_mod {
15+
pub struct InPubMod;
16+
}
17+
18+
use priv_mod::InPrivMod as InPrivMod3;
19+
pub use priv_mod::{InPrivMod, InPrivMod as InPrivMod2};
20+
use pub_mod::InPubMod as InPubMod3;
21+
pub use pub_mod::{InPubMod, InPubMod as InPubMod2};
22+
23+
//@ is "$.index[*][?(@.name=='T0')].inner.type_alias.type.resolved_path.path" '"priv_mod::InPrivMod"'
24+
pub type T0 = priv_mod::InPrivMod;
25+
//@ is "$.index[*][?(@.name=='T1')].inner.type_alias.type.resolved_path.path" '"InPrivMod"'
26+
pub type T1 = InPrivMod;
27+
//@ is "$.index[*][?(@.name=='T2')].inner.type_alias.type.resolved_path.path" '"InPrivMod2"'
28+
pub type T2 = InPrivMod2;
29+
//@ is "$.index[*][?(@.name=='T3')].inner.type_alias.type.resolved_path.path" '"priv_mod::InPrivMod"'
30+
pub type T3 = InPrivMod3;
31+
32+
//@ is "$.index[*][?(@.name=='U0')].inner.type_alias.type.resolved_path.path" '"pub_mod::InPubMod"'
33+
pub type U0 = pub_mod::InPubMod;
34+
//@ is "$.index[*][?(@.name=='U1')].inner.type_alias.type.resolved_path.path" '"InPubMod"'
35+
pub type U1 = InPubMod;
36+
//@ is "$.index[*][?(@.name=='U2')].inner.type_alias.type.resolved_path.path" '"InPubMod2"'
37+
pub type U2 = InPubMod2;
38+
//@ is "$.index[*][?(@.name=='U3')].inner.type_alias.type.resolved_path.path" '"pub_mod::InPubMod"'
39+
pub type U3 = InPubMod3;
40+
41+
// Check we only have paths for structs at their original path
42+
//@ ismany "$.paths[*][?(@.crate_id==0 && @.kind=='struct')].path" '["path_name", "priv_mod", "InPrivMod"]' '["path_name", "pub_mod", "InPubMod"]'
43+
44+
pub use defines_and_reexports::{InPrivMod as XPrivMod, InPubMod as XPubMod};
45+
use defines_and_reexports::{InPrivMod as XPrivMod2, InPubMod as XPubMod2};
46+
47+
//@ is "$.index[*][?(@.name=='X0')].inner.type_alias.type.resolved_path.path" '"defines_and_reexports::m1::InPubMod"'
48+
pub type X0 = defines_and_reexports::m1::InPubMod;
49+
//@ is "$.index[*][?(@.name=='X1')].inner.type_alias.type.resolved_path.path" '"defines_and_reexports::InPubMod"'
50+
pub type X1 = defines_and_reexports::InPubMod;
51+
//@ is "$.index[*][?(@.name=='X2')].inner.type_alias.type.resolved_path.path" '"defines_and_reexports::InPubMod2"'
52+
pub type X2 = defines_and_reexports::InPubMod2;
53+
//@ is "$.index[*][?(@.name=='X3')].inner.type_alias.type.resolved_path.path" '"XPubMod"'
54+
pub type X3 = XPubMod;
55+
// N.B. This isn't the path as used *or* the original path!
56+
//@ is "$.index[*][?(@.name=='X4')].inner.type_alias.type.resolved_path.path" '"defines_and_reexports::InPubMod"'
57+
pub type X4 = XPubMod2;
58+
59+
//@ is "$.index[*][?(@.name=='Y1')].inner.type_alias.type.resolved_path.path" '"defines_and_reexports::InPrivMod"'
60+
pub type Y1 = defines_and_reexports::InPrivMod;
61+
//@ is "$.index[*][?(@.name=='Y2')].inner.type_alias.type.resolved_path.path" '"defines_and_reexports::InPrivMod2"'
62+
pub type Y2 = defines_and_reexports::InPrivMod2;
63+
//@ is "$.index[*][?(@.name=='Y3')].inner.type_alias.type.resolved_path.path" '"XPrivMod"'
64+
pub type Y3 = XPrivMod;
65+
//@ is "$.index[*][?(@.name=='Y4')].inner.type_alias.type.resolved_path.path" '"defines_and_reexports::InPrivMod"'
66+
pub type Y4 = XPrivMod2;
67+
68+
// For foreign items, $.paths contains the *origional* path, even if it's not publicly
69+
// assessable. This should probably be changed.
70+
71+
//@ has "$.paths[*].path" '["defines_and_reexports", "m1", "InPubMod"]'
72+
//@ has "$.paths[*].path" '["defines_and_reexports", "m2", "InPrivMod"]'
73+
//@ !has "$.paths[*].path" '["defines_and_reexports", "InPubMod"]'
74+
//@ !has "$.paths[*].path" '["defines_and_reexports", "InPrivMod"]'
75+
76+
// Tests for the example in the docs of Path::name.
77+
// If these change, chage the docs.
78+
//@ is "$.index[*][?(@.name=='Vec1')].inner.type_alias.type.resolved_path.path" '"std::vec::Vec"'
79+
pub type Vec1 = std::vec::Vec<i32>;
80+
//@ is "$.index[*][?(@.name=='Vec2')].inner.type_alias.type.resolved_path.path" '"Vec"'
81+
pub type Vec2 = Vec<i32>;
82+
//@ is "$.index[*][?(@.name=='Vec3')].inner.type_alias.type.resolved_path.path" '"std::prelude::v1::Vec"'
83+
pub type Vec3 = std::prelude::v1::Vec<i32>;

tests/rustdoc-json/return_private.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@
22
// ignore-tidy-linelength
33

44
mod secret {
5+
//@ set struct_secret = "$.index[*][?(@.name == 'Secret' && @.inner.struct)].id"
56
pub struct Secret;
67
}
78

89
//@ has "$.index[*][?(@.name=='get_secret')].inner.function"
9-
//@ is "$.index[*][?(@.name=='get_secret')].inner.function.sig.output.resolved_path.name" \"Secret\"
10+
//@ is "$.index[*][?(@.name=='get_secret')].inner.function.sig.output.resolved_path.path" '"secret::Secret"'
11+
//@ is "$.index[*][?(@.name=='get_secret')].inner.function.sig.output.resolved_path.id" $struct_secret
1012
pub fn get_secret() -> secret::Secret {
1113
secret::Secret
1214
}

tests/rustdoc-json/type/dyn.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use std::fmt::Debug;
1010
//@ has "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias"
1111
//@ is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.generics" '{"params": [], "where_predicates": []}'
1212
//@ has "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path"
13-
//@ is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.name" \"Box\"
13+
//@ is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.path" \"Box\"
1414
//@ is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.constraints" []
1515
//@ count "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args" 1
1616
//@ has "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait"
@@ -19,9 +19,9 @@ use std::fmt::Debug;
1919
//@ is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[0].generic_params" []
2020
//@ is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[1].generic_params" []
2121
//@ is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[2].generic_params" []
22-
//@ is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[0].trait.name" '"Fn"'
23-
//@ is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[1].trait.name" '"Send"'
24-
//@ is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[2].trait.name" '"Sync"'
22+
//@ is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[0].trait.path" '"Fn"'
23+
//@ is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[1].trait.path" '"Send"'
24+
//@ is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[2].trait.path" '"Sync"'
2525
//@ is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[0].trait.args" '{"parenthesized": {"inputs": [],"output": {"primitive": "i32"}}}'
2626
pub type SyncIntGen = Box<dyn Fn() -> i32 + Send + Sync + 'static>;
2727

@@ -34,13 +34,13 @@ pub type SyncIntGen = Box<dyn Fn() -> i32 + Send + Sync + 'static>;
3434
//@ is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.lifetime" null
3535
//@ count "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.traits[*]" 1
3636
//@ is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.traits[0].generic_params" '[{"kind": {"lifetime": {"outlives": []}},"name": "'\''b"}]'
37-
//@ is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.traits[0].trait.name" '"Fn"'
37+
//@ is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.traits[0].trait.path" '"Fn"'
3838
//@ has "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.traits[0].trait.args.parenthesized.inputs[0].borrowed_ref"
3939
//@ is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.traits[0].trait.args.parenthesized.inputs[0].borrowed_ref.lifetime" "\"'b\""
4040
//@ has "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.traits[0].trait.args.parenthesized.output.borrowed_ref"
4141
//@ is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.traits[0].trait.args.parenthesized.output.borrowed_ref.lifetime" "\"'b\""
4242
pub type RefFn<'a> = &'a dyn for<'b> Fn(&'b i32) -> &'b i32;
4343

44-
//@ is "$.index[*][?(@.name=='WeirdOrder')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[0].trait.name" '"Send"'
45-
//@ is "$.index[*][?(@.name=='WeirdOrder')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[1].trait.name" '"Debug"'
44+
//@ is "$.index[*][?(@.name=='WeirdOrder')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[0].trait.path" '"Send"'
45+
//@ is "$.index[*][?(@.name=='WeirdOrder')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[1].trait.path" '"Debug"'
4646
pub type WeirdOrder = Box<dyn Send + Debug>;

tests/rustdoc-json/type/generic_default.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@ pub struct MyError {}
2121
//@ is "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.params[0].kind.type.default" null
2222
//@ has "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.params[1].kind.type.default.resolved_path"
2323
//@ is "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.params[1].kind.type.default.resolved_path.id" $my_error
24-
//@ is "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.params[1].kind.type.default.resolved_path.name" \"MyError\"
24+
//@ is "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.params[1].kind.type.default.resolved_path.path" \"MyError\"
2525
//@ has "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path"
2626
//@ is "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.id" $result
27-
//@ is "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.name" \"Result\"
27+
//@ is "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.path" \"Result\"
2828
//@ is "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.args.angle_bracketed.constraints" []
2929
//@ has "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.generic"
3030
//@ has "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[1].type.generic"

tests/rustdoc-json/type/hrtb.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ where
1515
//@ is "$.index[*][?(@.name=='dynfn')].inner.function.sig.inputs[0][1].borrowed_ref.type.dyn_trait.lifetime" null
1616
//@ count "$.index[*][?(@.name=='dynfn')].inner.function.sig.inputs[0][1].borrowed_ref.type.dyn_trait.traits[*]" 1
1717
//@ is "$.index[*][?(@.name=='dynfn')].inner.function.sig.inputs[0][1].borrowed_ref.type.dyn_trait.traits[0].generic_params" '[{"kind": {"lifetime": {"outlives": []}},"name": "'\''a"},{"kind": {"lifetime": {"outlives": []}},"name": "'\''b"}]'
18-
//@ is "$.index[*][?(@.name=='dynfn')].inner.function.sig.inputs[0][1].borrowed_ref.type.dyn_trait.traits[0].trait.name" '"Fn"'
18+
//@ is "$.index[*][?(@.name=='dynfn')].inner.function.sig.inputs[0][1].borrowed_ref.type.dyn_trait.traits[0].trait.path" '"Fn"'
1919
pub fn dynfn(f: &dyn for<'a, 'b> Fn(&'a i32, &'b i32)) {
2020
let zero = 0;
2121
f(&zero, &zero);

0 commit comments

Comments
 (0)