From d88cfe98f83db9500ebb64b179a9f63e4aaf4399 Mon Sep 17 00:00:00 2001 From: Simon Friis Vindum Date: Thu, 27 Nov 2025 09:35:31 +0100 Subject: [PATCH 1/2] Rust: Implement `toString` for struct fields and visibility --- rust/ql/.generated.list | 1 - rust/ql/.gitattributes | 1 - .../rust/elements/internal/StructFieldImpl.qll | 12 ++++++++++++ .../codeql/rust/elements/internal/VisibilityImpl.qll | 12 ++++++++++-- 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/rust/ql/.generated.list b/rust/ql/.generated.list index fc9e0d0f30c5..98cd6b01af4d 100644 --- a/rust/ql/.generated.list +++ b/rust/ql/.generated.list @@ -434,7 +434,6 @@ lib/codeql/rust/elements/internal/VariantConstructor.qll 0297d4a9a9b32448d6d6063 lib/codeql/rust/elements/internal/VariantListConstructor.qll c841fb345eb46ea3978a0ed7a689f8955efc9178044b140b74d98a6bcd0c926a c9e52d112abdba2b60013fa01a944c8770766bf7368f9878e6b13daaa4eed446 lib/codeql/rust/elements/internal/VariantListImpl.qll 4ceeda617696eb547c707589ba26103cf4c5c3d889955531be24cbf224e79dff 4258196c126fd2fad0e18068cb3d570a67034a8b26e2f13f8223d7f1a246d1a4 lib/codeql/rust/elements/internal/VisibilityConstructor.qll 1fd30663d87945f08d15cfaca54f586a658f26b7a98ea45ac73a35d36d4f65d0 6ddaf11742cc8fbbe03af2aa578394041ae077911e62d2fa6c885ae0543ba53a -lib/codeql/rust/elements/internal/VisibilityImpl.qll 85c1e75d6a7f9246cfef5c261e2aea40891c016724de49b3d6632623ccc30dcf 278be4648a8aefb0d926480c4d98e1605196ad64d1e4dbad42aa58499e6d485d lib/codeql/rust/elements/internal/WhereClauseConstructor.qll 6d6f0f0376cf45fac37ea0c7c4345d08718d2a3d6d913e591de1de9e640317c9 ff690f3d4391e5f1fae6e9014365810105e8befe9d6b52a82625994319af9ffd lib/codeql/rust/elements/internal/WhereClauseImpl.qll 006e330df395183d15896e5f81128e24b8274d849fe45afb5040444e4b764226 ed5e8317b5f33104e5c322588dc400755c8852bbb77ef835177b13af7480fd43 lib/codeql/rust/elements/internal/WherePredConstructor.qll f331c37085792a01159e8c218e9ef827e80e99b7c3d5978b6489808f05bd11f8 179cad3e4c5aaaf27755891694ef3569322fcf34c5290e6af49e5b5e3f8aa732 diff --git a/rust/ql/.gitattributes b/rust/ql/.gitattributes index 99728972ec7a..6afbf118f11c 100644 --- a/rust/ql/.gitattributes +++ b/rust/ql/.gitattributes @@ -436,7 +436,6 @@ /lib/codeql/rust/elements/internal/VariantListConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/VariantListImpl.qll linguist-generated /lib/codeql/rust/elements/internal/VisibilityConstructor.qll linguist-generated -/lib/codeql/rust/elements/internal/VisibilityImpl.qll linguist-generated /lib/codeql/rust/elements/internal/WhereClauseConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/WhereClauseImpl.qll linguist-generated /lib/codeql/rust/elements/internal/WherePredConstructor.qll linguist-generated diff --git a/rust/ql/lib/codeql/rust/elements/internal/StructFieldImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/StructFieldImpl.qll index 4ed4466c2d90..a8e8a0fcf876 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/StructFieldImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/StructFieldImpl.qll @@ -29,5 +29,17 @@ module Impl { /** Holds if this record field is named `name` and belongs to the struct `s`. */ predicate isStructField(Struct s, string name) { this = s.getStructField(name) } + + override string toStringImpl() { result = concat(int i | | this.toStringPart(i) order by i) } + + private string toStringPart(int index) { + index = 0 and result = this.getVisibility().toAbbreviatedString() + " " + or + index = 1 and result = this.getName().getText() + or + index = 2 and result = ": " + or + index = 3 and result = this.getTypeRepr().toAbbreviatedString() + } } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/VisibilityImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/VisibilityImpl.qll index 21de0c88ca8c..e2bc7140b59e 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/VisibilityImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/VisibilityImpl.qll @@ -1,4 +1,3 @@ -// generated by codegen, remove this comment if you wish to edit this file /** * This module provides a hand-modifiable wrapper around the generated class `Visibility`. * @@ -12,6 +11,7 @@ private import codeql.rust.elements.internal.generated.Visibility * be referenced directly. */ module Impl { + // the following QLdoc is generated: if you need to edit it, do it in the schema file /** * A visibility modifier. * @@ -21,5 +21,13 @@ module Impl { * //^^^ * ``` */ - class Visibility extends Generated::Visibility { } + class Visibility extends Generated::Visibility { + override string toStringImpl() { result = this.toAbbreviatedString() } + + override string toAbbreviatedString() { + result = "pub(" + this.getPath().toAbbreviatedString() + ")" + or + not this.hasPath() and result = "pub" + } + } } From 1e305851eebb7cdf89a75f7351dbca873e535ff7 Mon Sep 17 00:00:00 2001 From: Simon Friis Vindum Date: Thu, 27 Nov 2025 11:48:36 +0100 Subject: [PATCH 2/2] Rust: Accept changes to expected files --- .../generated/MacroDef/MacroDef.expected | 2 +- .../generated/Module/Module.expected | 2 +- .../StructField/StructField.expected | 6 +-- .../StructFieldList/StructFieldList.expected | 4 +- .../generated/Trait/Trait.expected | 2 +- .../generated/Visibility/Visibility.expected | 4 +- .../macro-expansion/PrintAst.expected | 42 +++++++++---------- .../macro-in-library/PrintAst.expected | 10 ++--- .../ql/test/extractor-tests/utf8/ast.expected | 6 +-- 9 files changed, 39 insertions(+), 39 deletions(-) diff --git a/rust/ql/test/extractor-tests/generated/MacroDef/MacroDef.expected b/rust/ql/test/extractor-tests/generated/MacroDef/MacroDef.expected index ba510853f06b..e35d59d6588d 100644 --- a/rust/ql/test/extractor-tests/generated/MacroDef/MacroDef.expected +++ b/rust/ql/test/extractor-tests/generated/MacroDef/MacroDef.expected @@ -9,4 +9,4 @@ getBody getName | gen_macro_def.rs:4:5:9:5 | MacroDef | gen_macro_def.rs:7:15:7:24 | vec_of_two | getVisibility -| gen_macro_def.rs:4:5:9:5 | MacroDef | gen_macro_def.rs:7:5:7:7 | Visibility | +| gen_macro_def.rs:4:5:9:5 | MacroDef | gen_macro_def.rs:7:5:7:7 | pub | diff --git a/rust/ql/test/extractor-tests/generated/Module/Module.expected b/rust/ql/test/extractor-tests/generated/Module/Module.expected index d0259df5ee81..a22ef831d9ff 100644 --- a/rust/ql/test/extractor-tests/generated/Module/Module.expected +++ b/rust/ql/test/extractor-tests/generated/Module/Module.expected @@ -11,4 +11,4 @@ getName | gen_module.rs:5:1:7:1 | mod bar | gen_module.rs:5:5:5:7 | bar | | lib.rs:1:1:1:19 | mod gen_module | lib.rs:1:9:1:18 | gen_module | getVisibility -| lib.rs:1:1:1:19 | mod gen_module | lib.rs:1:1:1:3 | Visibility | +| lib.rs:1:1:1:19 | mod gen_module | lib.rs:1:1:1:3 | pub | diff --git a/rust/ql/test/extractor-tests/generated/StructField/StructField.expected b/rust/ql/test/extractor-tests/generated/StructField/StructField.expected index 3b5d0d7b71ca..285d3530c66f 100644 --- a/rust/ql/test/extractor-tests/generated/StructField/StructField.expected +++ b/rust/ql/test/extractor-tests/generated/StructField/StructField.expected @@ -1,9 +1,9 @@ instances -| gen_struct_field.rs:7:16:7:21 | StructField | isUnsafe: | no | +| gen_struct_field.rs:7:16:7:21 | x: i32 | isUnsafe: | no | getAttr getDefault getName -| gen_struct_field.rs:7:16:7:21 | StructField | gen_struct_field.rs:7:16:7:16 | x | +| gen_struct_field.rs:7:16:7:21 | x: i32 | gen_struct_field.rs:7:16:7:16 | x | getTypeRepr -| gen_struct_field.rs:7:16:7:21 | StructField | gen_struct_field.rs:7:19:7:21 | i32 | +| gen_struct_field.rs:7:16:7:21 | x: i32 | gen_struct_field.rs:7:19:7:21 | i32 | getVisibility diff --git a/rust/ql/test/extractor-tests/generated/StructFieldList/StructFieldList.expected b/rust/ql/test/extractor-tests/generated/StructFieldList/StructFieldList.expected index 847bfd3c9371..3e9fe67dd29d 100644 --- a/rust/ql/test/extractor-tests/generated/StructFieldList/StructFieldList.expected +++ b/rust/ql/test/extractor-tests/generated/StructFieldList/StructFieldList.expected @@ -1,5 +1,5 @@ instances | gen_struct_field_list.rs:7:14:7:31 | StructFieldList | getField -| gen_struct_field_list.rs:7:14:7:31 | StructFieldList | 0 | gen_struct_field_list.rs:7:16:7:21 | StructField | -| gen_struct_field_list.rs:7:14:7:31 | StructFieldList | 1 | gen_struct_field_list.rs:7:24:7:29 | StructField | +| gen_struct_field_list.rs:7:14:7:31 | StructFieldList | 0 | gen_struct_field_list.rs:7:16:7:21 | x: i32 | +| gen_struct_field_list.rs:7:14:7:31 | StructFieldList | 1 | gen_struct_field_list.rs:7:24:7:29 | y: i32 | diff --git a/rust/ql/test/extractor-tests/generated/Trait/Trait.expected b/rust/ql/test/extractor-tests/generated/Trait/Trait.expected index e0f91737d5e9..9e8d41cb5ff5 100644 --- a/rust/ql/test/extractor-tests/generated/Trait/Trait.expected +++ b/rust/ql/test/extractor-tests/generated/Trait/Trait.expected @@ -13,6 +13,6 @@ getName | gen_trait.rs:10:1:10:57 | trait Foo | gen_trait.rs:10:11:10:13 | Foo | getTypeBoundList getVisibility -| gen_trait.rs:10:1:10:57 | trait Foo | gen_trait.rs:10:1:10:3 | Visibility | +| gen_trait.rs:10:1:10:57 | trait Foo | gen_trait.rs:10:1:10:3 | pub | getWhereClause | gen_trait.rs:10:1:10:57 | trait Foo | gen_trait.rs:10:32:10:54 | WhereClause | diff --git a/rust/ql/test/extractor-tests/generated/Visibility/Visibility.expected b/rust/ql/test/extractor-tests/generated/Visibility/Visibility.expected index 4bc7fefe4c13..2d032d6eee46 100644 --- a/rust/ql/test/extractor-tests/generated/Visibility/Visibility.expected +++ b/rust/ql/test/extractor-tests/generated/Visibility/Visibility.expected @@ -1,4 +1,4 @@ instances -| gen_visibility.rs:7:7:7:9 | Visibility | -| lib.rs:1:1:1:3 | Visibility | +| gen_visibility.rs:7:7:7:9 | pub | +| lib.rs:1:1:1:3 | pub | getPath diff --git a/rust/ql/test/extractor-tests/macro-expansion/PrintAst.expected b/rust/ql/test/extractor-tests/macro-expansion/PrintAst.expected index 5174e0bd6186..158ee877d455 100644 --- a/rust/ql/test/extractor-tests/macro-expansion/PrintAst.expected +++ b/rust/ql/test/extractor-tests/macro-expansion/PrintAst.expected @@ -146,10 +146,10 @@ lib.rs: # 1| [SourceFile] SourceFile # 1| getItem(0): [Module] mod call # 1| getName(): [Name] call -# 1| getVisibility(): [Visibility] Visibility +# 1| getVisibility(): [Visibility] pub # 2| getItem(1): [Module] mod macro_expansion # 2| getName(): [Name] macro_expansion -# 2| getVisibility(): [Visibility] Visibility +# 2| getVisibility(): [Visibility] pub macro_expansion.rs: # 1| [SourceFile] SourceFile # 1| getItem(0): [Use] use proc_macro::{...} @@ -223,7 +223,7 @@ macro_expansion.rs: # 11| getSegment(): [PathSegment] inner_1 # 11| getIdentifier(): [NameRef] inner_1 # 4| getName(): [Name] foo -# 4| getVisibility(): [Visibility] Visibility +# 4| getVisibility(): [Visibility] pub # 4| getItem(1): [Function] fn foo_new # 4| getParamList(): [ParamList] ParamList # 4| getFunctionBody(): [BlockExpr] { ... } @@ -271,7 +271,7 @@ macro_expansion.rs: # 11| getSegment(): [PathSegment] inner_1 # 11| getIdentifier(): [NameRef] inner_1 # 4| getName(): [Name] foo_new -# 4| getVisibility(): [Visibility] Visibility +# 4| getVisibility(): [Visibility] pub # 3| getAttr(0): [Attr] Attr # 3| getMeta(): [Meta] Meta # 3| getPath(): [Path] add_one @@ -286,13 +286,13 @@ macro_expansion.rs: # 16| getFunctionBody(): [BlockExpr] { ... } # 16| getStmtList(): [StmtList] StmtList # 16| getName(): [Name] bar_0 -# 16| getVisibility(): [Visibility] Visibility +# 16| getVisibility(): [Visibility] pub # 16| getItem(1): [Function] fn bar_0_new # 16| getParamList(): [ParamList] ParamList # 16| getFunctionBody(): [BlockExpr] { ... } # 16| getStmtList(): [StmtList] StmtList # 16| getName(): [Name] bar_0_new -# 16| getVisibility(): [Visibility] Visibility +# 16| getVisibility(): [Visibility] pub # 15| getAttr(0): [Attr] Attr # 15| getMeta(): [Meta] Meta # 15| getPath(): [Path] add_one @@ -305,13 +305,13 @@ macro_expansion.rs: # 16| getFunctionBody(): [BlockExpr] { ... } # 16| getStmtList(): [StmtList] StmtList # 16| getName(): [Name] bar_1 -# 16| getVisibility(): [Visibility] Visibility +# 16| getVisibility(): [Visibility] pub # 16| getItem(1): [Function] fn bar_1_new # 16| getParamList(): [ParamList] ParamList # 16| getFunctionBody(): [BlockExpr] { ... } # 16| getStmtList(): [StmtList] StmtList # 16| getName(): [Name] bar_1_new -# 16| getVisibility(): [Visibility] Visibility +# 16| getVisibility(): [Visibility] pub # 15| getAttr(0): [Attr] Attr # 15| getMeta(): [Meta] Meta # 15| getPath(): [Path] add_one @@ -340,7 +340,7 @@ macro_expansion.rs: # 22| getTokenTree(): [TokenTree] TokenTree # 28| getItem(5): [Struct] struct S # 28| getName(): [Name] S -# 28| getVisibility(): [Visibility] Visibility +# 28| getVisibility(): [Visibility] pub # 30| getItem(6): [Impl] impl S { ... } # 30| getAssocItemList(): [AssocItemList] AssocItemList # 31| getAssocItem(0): [Function] (item with attribute macro expansion) @@ -392,7 +392,7 @@ macro_expansion.rs: # 31| getSegment(): [PathSegment] _print # 31| getIdentifier(): [NameRef] _print # 32| getName(): [Name] bzz_0 -# 32| getVisibility(): [Visibility] Visibility +# 32| getVisibility(): [Visibility] pub # 32| getItem(1): [Function] fn bzz_1 # 32| getParamList(): [ParamList] ParamList # 32| getFunctionBody(): [BlockExpr] { ... } @@ -440,7 +440,7 @@ macro_expansion.rs: # 31| getSegment(): [PathSegment] _print # 31| getIdentifier(): [NameRef] _print # 32| getName(): [Name] bzz_1 -# 32| getVisibility(): [Visibility] Visibility +# 32| getVisibility(): [Visibility] pub # 32| getItem(2): [Function] fn bzz_2 # 32| getParamList(): [ParamList] ParamList # 32| getFunctionBody(): [BlockExpr] { ... } @@ -488,7 +488,7 @@ macro_expansion.rs: # 31| getSegment(): [PathSegment] _print # 31| getIdentifier(): [NameRef] _print # 32| getName(): [Name] bzz_2 -# 32| getVisibility(): [Visibility] Visibility +# 32| getVisibility(): [Visibility] pub # 31| getAttr(0): [Attr] Attr # 31| getMeta(): [Meta] Meta # 31| getPath(): [Path] repeat @@ -515,7 +515,7 @@ macro_expansion.rs: # 44| getFunctionBody(): [BlockExpr] { ... } # 44| getStmtList(): [StmtList] StmtList # 44| getName(): [Name] x -# 44| getVisibility(): [Visibility] Visibility +# 44| getVisibility(): [Visibility] pub # 43| getSelfTy(): [PathTypeRepr] S # 43| getPath(): [Path] S # 43| getSegment(): [PathSegment] S @@ -700,7 +700,7 @@ macro_expansion.rs: # 76| getIdentifier(): [NameRef] i32 # 78| getItem(16): [Struct] struct MyStruct # 78| getFieldList(): [StructFieldList] StructFieldList -# 79| getField(0): [StructField] StructField +# 79| getField(0): [StructField] field: ... # 79| getName(): [Name] field # 79| getTypeRepr(): [MacroTypeRepr] MacroTypeRepr # 79| getMacroCall(): [MacroCall] my_int!... @@ -809,7 +809,7 @@ macro_expansion.rs: # 83| getIdentifier(): [NameRef] derive # 83| getTokenTree(): [TokenTree] TokenTree # 84| getFieldList(): [StructFieldList] StructFieldList -# 85| getField(0): [StructField] StructField +# 85| getField(0): [StructField] field: usize # 85| getName(): [Name] field # 85| getTypeRepr(): [PathTypeRepr] usize # 85| getPath(): [Path] usize @@ -990,13 +990,13 @@ macro_expansion.rs: # 98| getTokenTree(): [TokenTree] TokenTree # 99| getName(): [Name] MyDeriveUnion # 99| getStructFieldList(): [StructFieldList] StructFieldList -# 100| getField(0): [StructField] StructField +# 100| getField(0): [StructField] field1: usize # 100| getName(): [Name] field1 # 100| getTypeRepr(): [PathTypeRepr] usize # 100| getPath(): [Path] usize # 100| getSegment(): [PathSegment] usize # 100| getIdentifier(): [NameRef] usize -# 101| getField(1): [StructField] StructField +# 101| getField(1): [StructField] field2: f64 # 101| getName(): [Name] field2 # 101| getTypeRepr(): [PathTypeRepr] f64 # 101| getPath(): [Path] f64 @@ -2003,7 +2003,7 @@ proc_macro.rs: # 5| getPath(): [Path] TokenStream # 5| getSegment(): [PathSegment] TokenStream # 5| getIdentifier(): [NameRef] TokenStream -# 5| getVisibility(): [Visibility] Visibility +# 5| getVisibility(): [Visibility] pub # 20| getItem(3): [Function] fn add_one # 21| getParamList(): [ParamList] ParamList # 21| getParam(0): [Param] ...: TokenStream @@ -2434,7 +2434,7 @@ proc_macro.rs: # 21| getPath(): [Path] TokenStream # 21| getSegment(): [PathSegment] TokenStream # 21| getIdentifier(): [NameRef] TokenStream -# 21| getVisibility(): [Visibility] Visibility +# 21| getVisibility(): [Visibility] pub # 31| getItem(4): [Function] fn erase # 32| getParamList(): [ParamList] ParamList # 32| getParam(0): [Param] ...: TokenStream @@ -2473,7 +2473,7 @@ proc_macro.rs: # 32| getPath(): [Path] TokenStream # 32| getSegment(): [PathSegment] TokenStream # 32| getIdentifier(): [NameRef] TokenStream -# 32| getVisibility(): [Visibility] Visibility +# 32| getVisibility(): [Visibility] pub # 36| getItem(5): [Function] fn my_trait_derive # 37| getParamList(): [ParamList] ParamList # 37| getParam(0): [Param] ...: TokenStream @@ -3808,4 +3808,4 @@ proc_macro.rs: # 37| getPath(): [Path] TokenStream # 37| getSegment(): [PathSegment] TokenStream # 37| getIdentifier(): [NameRef] TokenStream -# 37| getVisibility(): [Visibility] Visibility +# 37| getVisibility(): [Visibility] pub diff --git a/rust/ql/test/extractor-tests/macro-in-library/PrintAst.expected b/rust/ql/test/extractor-tests/macro-in-library/PrintAst.expected index 30dbc24103b9..aa0fc42f81d8 100644 --- a/rust/ql/test/extractor-tests/macro-in-library/PrintAst.expected +++ b/rust/ql/test/extractor-tests/macro-in-library/PrintAst.expected @@ -2,7 +2,7 @@ lib.rs: # 1| [SourceFile] SourceFile # 1| getItem(0): [Module] mod macro_in_library # 1| getName(): [Name] macro_in_library -# 1| getVisibility(): [Visibility] Visibility +# 1| getVisibility(): [Visibility] pub macro_in_library.rs: # 1| [SourceFile] SourceFile # 1| getItem(0): [MacroCall] (item with attribute macro expansion) @@ -10,15 +10,15 @@ macro_in_library.rs: # 2| getItem(0): [Function] fn foo # 2| getParamList(): [ParamList] ParamList # 2| getName(): [Name] foo -# 2| getVisibility(): [Visibility] Visibility +# 2| getVisibility(): [Visibility] pub # 2| getItem(1): [Function] fn foo_new # 2| getParamList(): [ParamList] ParamList # 2| getName(): [Name] foo_new -# 2| getVisibility(): [Visibility] Visibility +# 2| getVisibility(): [Visibility] pub # 4| getItem(1): [Function] fn bar # 4| getParamList(): [ParamList] ParamList # 4| getName(): [Name] bar -# 4| getVisibility(): [Visibility] Visibility +# 4| getVisibility(): [Visibility] pub proc_macro.rs: # 1| [SourceFile] SourceFile # 1| getItem(0): [Use] use ...::TokenStream @@ -60,4 +60,4 @@ proc_macro.rs: # 5| getPath(): [Path] TokenStream # 5| getSegment(): [PathSegment] TokenStream # 5| getIdentifier(): [NameRef] TokenStream -# 5| getVisibility(): [Visibility] Visibility +# 5| getVisibility(): [Visibility] pub diff --git a/rust/ql/test/extractor-tests/utf8/ast.expected b/rust/ql/test/extractor-tests/utf8/ast.expected index 7fe2a9bd4ee7..a5f91da61589 100644 --- a/rust/ql/test/extractor-tests/utf8/ast.expected +++ b/rust/ql/test/extractor-tests/utf8/ast.expected @@ -1,4 +1,4 @@ -| lib.rs:1:1:1:3 | Visibility | +| lib.rs:1:1:1:3 | pub | | lib.rs:1:1:1:25 | SourceFile | | lib.rs:1:1:1:25 | mod utf8_identifiers | | lib.rs:1:9:1:24 | utf8_identifiers | @@ -17,12 +17,12 @@ | utf8_identifiers.rs:6:8:6:8 | X | | utf8_identifiers.rs:6:10:8:1 | StructFieldList | | utf8_identifiers.rs:7:5:7:5 | \u03b4 | -| utf8_identifiers.rs:7:5:7:13 | StructField | +| utf8_identifiers.rs:7:5:7:13 | \u03b4: usize | | utf8_identifiers.rs:7:9:7:13 | usize | | utf8_identifiers.rs:7:9:7:13 | usize | | utf8_identifiers.rs:7:9:7:13 | usize | | utf8_identifiers.rs:7:9:7:13 | usize | -| utf8_identifiers.rs:10:1:10:3 | Visibility | +| utf8_identifiers.rs:10:1:10:3 | pub | | utf8_identifiers.rs:10:1:12:1 | fn main | | utf8_identifiers.rs:10:8:10:11 | main | | utf8_identifiers.rs:10:12:10:13 | ParamList |