Skip to content

Commit c28334c

Browse files
sunshowersepage
authored andcommitted
fix: Treat nil parents as empty tables
Encountered this regression via nextest's test suite (nextest-rs/nextest#2001). If a table is empty, it would be treated as a unit value. If attempted to be deserialized via a `Default` impl, it would lead to deserialization failing with an error like ```console profile.default-miri: invalid type: unit value, expected struct CustomProfileImpl ``` A bisect appears to indicate that ec36bff is responsible. For empty tables where the Default impl is supposed to work, it no longer would. I've attempted to restore the old behavior of putting in an empty table, specifically this section: ec36bff#diff-c5423e2d2d6c87501239c0304c0f496742e00440defdd20368cf548ba42ab184L175-L178 I'm happy to make changes if there's a better approach.
1 parent ecba2e1 commit c28334c

File tree

2 files changed

+38
-9
lines changed

2 files changed

+38
-9
lines changed

src/path/mod.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,12 +150,16 @@ impl Expression {
150150
let parent = self.get_mut_forcibly(root);
151151
match value.kind {
152152
ValueKind::Table(ref incoming_map) => {
153+
// If the parent is nil, treat it as an empty table
154+
if matches!(parent.kind, ValueKind::Nil) {
155+
*parent = Map::<String, Value>::new().into();
156+
}
157+
153158
// Continue the deep merge
154159
for (key, val) in incoming_map {
155160
Self::root(key.clone()).set(parent, val.clone());
156161
}
157162
}
158-
159163
_ => {
160164
*parent = value;
161165
}

tests/testsuite/merge.rs

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -112,10 +112,17 @@ fn test_merge_empty_maps() {
112112
.unwrap();
113113
let res = cfg.try_deserialize::<Settings>();
114114
assert_data_eq!(
115-
res.unwrap_err().to_string(),
116-
str![
117-
"invalid type: unit value, expected struct Profile for key `profile.missing_to_empty`"
118-
]
115+
res.unwrap().to_debug(),
116+
str![[r#"
117+
Settings {
118+
profile: {
119+
"missing_to_empty": Profile {
120+
name: None,
121+
},
122+
},
123+
}
124+
125+
"#]]
119126
);
120127

121128
// * missing_to_non_empty: no key -> map with k/v
@@ -158,8 +165,17 @@ Settings {
158165
.unwrap();
159166
let res = cfg.try_deserialize::<Settings>();
160167
assert_data_eq!(
161-
res.unwrap_err().to_string(),
162-
str!["invalid type: unit value, expected struct Profile for key `profile.empty_to_empty`"]
168+
res.unwrap().to_debug(),
169+
str![[r#"
170+
Settings {
171+
profile: {
172+
"empty_to_empty": Profile {
173+
name: None,
174+
},
175+
},
176+
}
177+
178+
"#]]
163179
);
164180

165181
// * empty_to_non_empty: empty map -> map with k/v
@@ -266,8 +282,17 @@ Settings {
266282
.unwrap();
267283
let res = cfg.try_deserialize::<Settings>();
268284
assert_data_eq!(
269-
res.unwrap_err().to_string(),
270-
str!["invalid type: unit value, expected struct Profile for key `profile.null_to_empty`"]
285+
res.unwrap().to_debug(),
286+
str![[r#"
287+
Settings {
288+
profile: {
289+
"null_to_empty": Profile {
290+
name: None,
291+
},
292+
},
293+
}
294+
295+
"#]]
271296
);
272297

273298
// * null_to_non_empty: null -> map with k/v

0 commit comments

Comments
 (0)