Rust: Model String -> str implicit conversion in type inference

This commit is contained in:
Tom Hvitved
2025-06-11 21:28:18 +02:00
parent 5b5074e922
commit 66c0ff61bb
10 changed files with 207 additions and 13 deletions

View File

@@ -65,3 +65,12 @@ class FutureTrait extends Trait {
result.getName().getText() = "Output"
}
}
/**
* The [`String` struct][1].
*
* [1]: https://doc.rust-lang.org/std/string/struct.String.html
*/
class StringStruct extends Struct {
StringStruct() { this.getCanonicalPath() = "alloc::string::String" }
}

View File

@@ -780,12 +780,18 @@ private Type inferCallExprBaseType(AstNode n, TypePath path) {
not (path0.isEmpty() and result = TRefType()) and
path = TypePath::cons(TRefTypeParameter(), path0)
else (
not path0.isCons(TRefTypeParameter(), _) and
not (path0.isEmpty() and result = TRefType()) and
path = path0
or
// adjust for implicit borrow
path0.isCons(TRefTypeParameter(), path)
not (
receiverType.(StructType).asItemNode() instanceof StringStruct and
result.(StructType).asItemNode() instanceof Builtins::Str
) and
(
not path0.isCons(TRefTypeParameter(), _) and
not (path0.isEmpty() and result = TRefType()) and
path = path0
or
// adjust for implicit borrow
path0.isCons(TRefTypeParameter(), path)
)
)
)
else path = path0
@@ -1130,12 +1136,27 @@ final class MethodCall extends Call {
Type getTypeAt(TypePath path) {
if this.receiverImplicitlyBorrowed()
then
exists(TypePath path0 | result = inferType(super.getReceiver(), path0) |
path0.isCons(TRefTypeParameter(), path)
exists(TypePath path0, Type t0 |
t0 = inferType(super.getReceiver(), path0) and
(
path0.isCons(TRefTypeParameter(), path)
or
not path0.isCons(TRefTypeParameter(), _) and
not (path0.isEmpty() and result = TRefType()) and
path = path0
)
|
result = t0
or
not path0.isCons(TRefTypeParameter(), _) and
not (path0.isEmpty() and result = TRefType()) and
path = path0
// We do not yet model the `Deref` trait, so we hard-code the fact that
// `String` dereferences to `str` here. This allows us e.g. to resolve
// `x.parse::<usize>()` to the function `<core::str>::parse` when `x` has
// type `String`.
//
// See also https://doc.rust-lang.org/reference/expressions/method-call-expr.html#r-expr.method.autoref-deref
path.isEmpty() and
t0.(StructType).asItemNode() instanceof StringStruct and
result.(StructType).asItemNode() instanceof Builtins::Str
)
else result = inferType(super.getReceiver(), path)
}

View File

@@ -962,6 +962,8 @@ readStep
| main.rs:442:25:442:29 | names | file://:0:0:0:0 | element | main.rs:442:9:442:20 | TuplePat |
| main.rs:444:41:444:67 | [post] \|...\| ... | main.rs:441:9:441:20 | captured default_name | main.rs:444:41:444:67 | [post] default_name |
| main.rs:444:44:444:55 | this | main.rs:441:9:441:20 | captured default_name | main.rs:444:44:444:55 | default_name |
| main.rs:469:13:469:13 | [post] receiver for b | file://:0:0:0:0 | &ref | main.rs:469:13:469:13 | [post] b |
| main.rs:470:19:470:19 | [post] receiver for b | file://:0:0:0:0 | &ref | main.rs:470:19:470:19 | [post] b |
| main.rs:481:10:481:11 | vs | file://:0:0:0:0 | element | main.rs:481:10:481:14 | vs[0] |
| main.rs:482:11:482:35 | ... .unwrap() | file://:0:0:0:0 | &ref | main.rs:482:10:482:35 | * ... |
| main.rs:483:11:483:35 | ... .unwrap() | file://:0:0:0:0 | &ref | main.rs:483:10:483:35 | * ... |
@@ -1058,6 +1060,8 @@ storeStep
| main.rs:429:30:429:30 | 3 | file://:0:0:0:0 | element | main.rs:429:23:429:31 | [...] |
| main.rs:432:18:432:27 | source(...) | file://:0:0:0:0 | element | main.rs:432:5:432:11 | [post] mut_arr |
| main.rs:444:41:444:67 | default_name | main.rs:441:9:441:20 | captured default_name | main.rs:444:41:444:67 | \|...\| ... |
| main.rs:469:13:469:13 | b | file://:0:0:0:0 | &ref | main.rs:469:13:469:13 | receiver for b |
| main.rs:470:19:470:19 | b | file://:0:0:0:0 | &ref | main.rs:470:19:470:19 | receiver for b |
| main.rs:479:15:479:24 | source(...) | file://:0:0:0:0 | element | main.rs:479:14:479:34 | [...] |
| main.rs:479:27:479:27 | 2 | file://:0:0:0:0 | element | main.rs:479:14:479:34 | [...] |
| main.rs:479:30:479:30 | 3 | file://:0:0:0:0 | element | main.rs:479:14:479:34 | [...] |

View File

@@ -13,6 +13,10 @@ multipleMethodCallTargets
| test_futures_io.rs:92:26:92:63 | pinned.poll_read(...) | file://:0:0:0:0 | fn poll_read |
| test_futures_io.rs:115:22:115:50 | pinned.poll_fill_buf(...) | file://:0:0:0:0 | fn poll_fill_buf |
| test_futures_io.rs:115:22:115:50 | pinned.poll_fill_buf(...) | file://:0:0:0:0 | fn poll_fill_buf |
| web_frameworks.rs:88:14:88:23 | a.as_str() | file://:0:0:0:0 | fn as_str |
| web_frameworks.rs:88:14:88:23 | a.as_str() | file://:0:0:0:0 | fn as_str |
| web_frameworks.rs:89:14:89:25 | a.as_bytes() | file://:0:0:0:0 | fn as_bytes |
| web_frameworks.rs:89:14:89:25 | a.as_bytes() | file://:0:0:0:0 | fn as_bytes |
multiplePathResolutions
| test.rs:112:62:112:73 | ...::from | file://:0:0:0:0 | fn from |
| test.rs:112:62:112:73 | ...::from | file://:0:0:0:0 | fn from |

View File

@@ -1,3 +1,6 @@
multipleMethodCallTargets
| main.rs:64:16:64:25 | s.as_str() | file://:0:0:0:0 | fn as_str |
| main.rs:64:16:64:25 | s.as_str() | file://:0:0:0:0 | fn as_str |
multiplePathResolutions
| main.rs:52:11:52:22 | ...::from | file://:0:0:0:0 | fn from |
| main.rs:52:11:52:22 | ...::from | file://:0:0:0:0 | fn from |

View File

@@ -0,0 +1,53 @@
multipleMethodCallTargets
| test.rs:55:7:55:26 | ... .as_str() | file://:0:0:0:0 | fn as_str |
| test.rs:55:7:55:26 | ... .as_str() | file://:0:0:0:0 | fn as_str |
| test.rs:56:7:56:21 | ... .as_str() | file://:0:0:0:0 | fn as_str |
| test.rs:56:7:56:21 | ... .as_str() | file://:0:0:0:0 | fn as_str |
| test.rs:72:7:72:26 | ... .as_str() | file://:0:0:0:0 | fn as_str |
| test.rs:72:7:72:26 | ... .as_str() | file://:0:0:0:0 | fn as_str |
| test.rs:73:7:73:36 | ... .as_str() | file://:0:0:0:0 | fn as_str |
| test.rs:73:7:73:36 | ... .as_str() | file://:0:0:0:0 | fn as_str |
| test.rs:74:7:74:34 | ... .as_str() | file://:0:0:0:0 | fn as_str |
| test.rs:74:7:74:34 | ... .as_str() | file://:0:0:0:0 | fn as_str |
| test.rs:75:7:75:27 | ... .as_str() | file://:0:0:0:0 | fn as_str |
| test.rs:75:7:75:27 | ... .as_str() | file://:0:0:0:0 | fn as_str |
| test.rs:254:7:254:36 | ... .as_str() | file://:0:0:0:0 | fn as_str |
| test.rs:254:7:254:36 | ... .as_str() | file://:0:0:0:0 | fn as_str |
| test.rs:256:7:256:33 | ... .as_str() | file://:0:0:0:0 | fn as_str |
| test.rs:256:7:256:33 | ... .as_str() | file://:0:0:0:0 | fn as_str |
| test.rs:257:7:257:36 | ... .as_str() | file://:0:0:0:0 | fn as_str |
| test.rs:257:7:257:36 | ... .as_str() | file://:0:0:0:0 | fn as_str |
| test.rs:258:7:258:26 | ... .as_str() | file://:0:0:0:0 | fn as_str |
| test.rs:258:7:258:26 | ... .as_str() | file://:0:0:0:0 | fn as_str |
| test.rs:262:7:262:28 | ... .as_str() | file://:0:0:0:0 | fn as_str |
| test.rs:262:7:262:28 | ... .as_str() | file://:0:0:0:0 | fn as_str |
| test.rs:263:7:263:37 | ... .as_str() | file://:0:0:0:0 | fn as_str |
| test.rs:263:7:263:37 | ... .as_str() | file://:0:0:0:0 | fn as_str |
| test.rs:264:7:264:36 | ... .as_str() | file://:0:0:0:0 | fn as_str |
| test.rs:264:7:264:36 | ... .as_str() | file://:0:0:0:0 | fn as_str |
| test.rs:267:7:267:32 | ... .as_str() | file://:0:0:0:0 | fn as_str |
| test.rs:267:7:267:32 | ... .as_str() | file://:0:0:0:0 | fn as_str |
| test.rs:277:7:277:34 | ... .as_str() | file://:0:0:0:0 | fn as_str |
| test.rs:277:7:277:34 | ... .as_str() | file://:0:0:0:0 | fn as_str |
| test.rs:280:7:280:36 | ... .as_str() | file://:0:0:0:0 | fn as_str |
| test.rs:280:7:280:36 | ... .as_str() | file://:0:0:0:0 | fn as_str |
| test.rs:284:7:284:39 | ... .as_str() | file://:0:0:0:0 | fn as_str |
| test.rs:284:7:284:39 | ... .as_str() | file://:0:0:0:0 | fn as_str |
| test.rs:291:7:291:53 | ... .as_str() | file://:0:0:0:0 | fn as_str |
| test.rs:291:7:291:53 | ... .as_str() | file://:0:0:0:0 | fn as_str |
| test.rs:292:7:292:45 | ... .as_str() | file://:0:0:0:0 | fn as_str |
| test.rs:292:7:292:45 | ... .as_str() | file://:0:0:0:0 | fn as_str |
| test.rs:294:7:294:39 | ... .as_str() | file://:0:0:0:0 | fn as_str |
| test.rs:294:7:294:39 | ... .as_str() | file://:0:0:0:0 | fn as_str |
| test.rs:295:7:295:34 | ... .as_str() | file://:0:0:0:0 | fn as_str |
| test.rs:295:7:295:34 | ... .as_str() | file://:0:0:0:0 | fn as_str |
| test.rs:296:7:296:42 | ... .as_str() | file://:0:0:0:0 | fn as_str |
| test.rs:296:7:296:42 | ... .as_str() | file://:0:0:0:0 | fn as_str |
| test.rs:298:7:298:48 | ... .as_str() | file://:0:0:0:0 | fn as_str |
| test.rs:298:7:298:48 | ... .as_str() | file://:0:0:0:0 | fn as_str |
| test.rs:299:7:299:35 | ... .as_str() | file://:0:0:0:0 | fn as_str |
| test.rs:299:7:299:35 | ... .as_str() | file://:0:0:0:0 | fn as_str |
| test.rs:300:7:300:35 | ... .as_str() | file://:0:0:0:0 | fn as_str |
| test.rs:300:7:300:35 | ... .as_str() | file://:0:0:0:0 | fn as_str |
| test.rs:339:7:339:39 | ... .as_str() | file://:0:0:0:0 | fn as_str |
| test.rs:339:7:339:39 | ... .as_str() | file://:0:0:0:0 | fn as_str |

View File

@@ -1109,9 +1109,9 @@ mod method_call_type_conversion {
println!("{:?}", x7);
let x9 : String = "Hello".to_string(); // $ type=x9:String
// Implicit `String` -> `str` conversion happense via the `Deref` trait:
// Implicit `String` -> `str` conversion happens via the `Deref` trait:
// https://doc.rust-lang.org/std/string/struct.String.html#deref.
let u = x9.parse::<u32>(); // $ MISSING: method=parse type=u:T.u32
let u = x9.parse::<u32>(); // $ method=parse type=u:T.u32
}
}

View File

@@ -1413,7 +1413,11 @@ inferType
| main.rs:1111:13:1111:14 | x9 | | {EXTERNAL LOCATION} | String |
| main.rs:1111:27:1111:33 | "Hello" | | {EXTERNAL LOCATION} | str |
| main.rs:1111:27:1111:45 | "Hello".to_string() | | {EXTERNAL LOCATION} | String |
| main.rs:1114:13:1114:13 | u | | {EXTERNAL LOCATION} | Result |
| main.rs:1114:13:1114:13 | u | T | {EXTERNAL LOCATION} | u32 |
| main.rs:1114:17:1114:18 | x9 | | {EXTERNAL LOCATION} | String |
| main.rs:1114:17:1114:33 | x9.parse() | | {EXTERNAL LOCATION} | Result |
| main.rs:1114:17:1114:33 | x9.parse() | T | {EXTERNAL LOCATION} | u32 |
| main.rs:1121:16:1121:20 | SelfParam | | file://:0:0:0:0 | & |
| main.rs:1121:16:1121:20 | SelfParam | &T | main.rs:1119:5:1127:5 | Self [trait MyTrait] |
| main.rs:1124:16:1124:20 | SelfParam | | file://:0:0:0:0 | & |

View File

@@ -1,3 +1,92 @@
multipleMethodCallTargets
| sqlx.rs:64:26:64:46 | safe_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:64:26:64:46 | safe_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:65:26:65:46 | safe_query_2.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:65:26:65:46 | safe_query_2.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:67:26:67:48 | unsafe_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:67:26:67:48 | unsafe_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:69:30:69:52 | unsafe_query_2.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:69:30:69:52 | unsafe_query_2.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:70:30:70:52 | unsafe_query_3.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:70:30:70:52 | unsafe_query_3.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:75:25:75:45 | safe_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:75:25:75:45 | safe_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:76:25:76:45 | safe_query_2.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:76:25:76:45 | safe_query_2.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:78:25:78:47 | unsafe_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:78:25:78:47 | unsafe_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:80:29:80:51 | unsafe_query_2.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:80:29:80:51 | unsafe_query_2.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:81:29:81:51 | unsafe_query_3.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:81:29:81:51 | unsafe_query_3.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:84:25:84:49 | prepared_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:84:25:84:49 | prepared_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:85:25:85:49 | prepared_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:85:25:85:49 | prepared_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:87:29:87:53 | prepared_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:87:29:87:53 | prepared_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:88:29:88:53 | prepared_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:88:29:88:53 | prepared_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:106:26:106:46 | safe_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:106:26:106:46 | safe_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:108:30:108:52 | unsafe_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:108:30:108:52 | unsafe_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:111:27:111:47 | safe_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:111:27:111:47 | safe_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:113:31:113:53 | unsafe_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:113:31:113:53 | unsafe_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:117:25:117:45 | safe_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:117:25:117:45 | safe_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:118:25:118:49 | prepared_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:118:25:118:49 | prepared_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:120:29:120:51 | unsafe_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:120:29:120:51 | unsafe_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:121:29:121:53 | prepared_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:121:29:121:53 | prepared_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:124:25:124:45 | safe_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:124:25:124:45 | safe_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:125:25:125:49 | prepared_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:125:25:125:49 | prepared_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:127:29:127:51 | unsafe_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:127:29:127:51 | unsafe_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:128:29:128:53 | prepared_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:128:29:128:53 | prepared_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:131:54:131:74 | safe_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:131:54:131:74 | safe_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:133:54:133:78 | prepared_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:133:54:133:78 | prepared_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:136:55:136:77 | unsafe_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:136:55:136:77 | unsafe_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:137:55:137:79 | prepared_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:137:55:137:79 | prepared_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:140:54:140:74 | safe_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:140:54:140:74 | safe_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:142:54:142:78 | prepared_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:142:54:142:78 | prepared_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:145:55:145:77 | unsafe_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:145:55:145:77 | unsafe_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:146:55:146:79 | prepared_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:146:55:146:79 | prepared_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:149:25:149:45 | safe_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:149:25:149:45 | safe_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:150:25:150:49 | prepared_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:150:25:150:49 | prepared_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:153:29:153:51 | unsafe_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:153:29:153:51 | unsafe_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:154:29:154:53 | prepared_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:154:29:154:53 | prepared_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:179:26:179:46 | safe_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:179:26:179:46 | safe_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:181:30:181:52 | unsafe_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:181:30:181:52 | unsafe_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:185:25:185:45 | safe_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:185:25:185:45 | safe_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:186:25:186:49 | prepared_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:186:25:186:49 | prepared_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:188:29:188:51 | unsafe_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:188:29:188:51 | unsafe_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:189:29:189:53 | prepared_query_1.as_str() | file://:0:0:0:0 | fn as_str |
| sqlx.rs:189:29:189:53 | prepared_query_1.as_str() | file://:0:0:0:0 | fn as_str |
multiplePathResolutions
| sqlx.rs:46:24:46:35 | ...::from | file://:0:0:0:0 | fn from |
| sqlx.rs:46:24:46:35 | ...::from | file://:0:0:0:0 | fn from |

View File

@@ -0,0 +1,7 @@
multipleMethodCallTargets
| test_logging.rs:77:20:77:36 | password.as_str() | file://:0:0:0:0 | fn as_str |
| test_logging.rs:77:20:77:36 | password.as_str() | file://:0:0:0:0 | fn as_str |
| test_logging.rs:78:22:78:38 | password.as_str() | file://:0:0:0:0 | fn as_str |
| test_logging.rs:78:22:78:38 | password.as_str() | file://:0:0:0:0 | fn as_str |
| test_logging.rs:88:18:88:34 | password.as_str() | file://:0:0:0:0 | fn as_str |
| test_logging.rs:88:18:88:34 | password.as_str() | file://:0:0:0:0 | fn as_str |