Skip to content

Commit 59e9b18

Browse files
committed
A delayed path removal processing scheme. Fixes rust-lang#19.
1 parent 63377fc commit 59e9b18

File tree

3 files changed

+33
-19
lines changed

3 files changed

+33
-19
lines changed

src/semcheck/traverse.rs

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,10 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet,
7474
let mut visited = HashSet::new();
7575
let mut children = NameMapping::default();
7676
let mut mod_queue = VecDeque::new();
77+
// Removals are processed with a delay to avoid creating multiple path change entries.
78+
// This is necessary, since the order in which added or removed paths are found wrt each
79+
// other and their item's definition can't be relied upon.
80+
let mut removals = Vec::new();
7781

7882
mod_queue.push_back((old, new, Public, Public));
7983

@@ -222,10 +226,11 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet,
222226
continue;
223227
}
224228

225-
if old_vis == Public && cstore.visibility(o.def.def_id()) == Public {
226-
let o_did = o.def.def_id();
227-
changes.new_path(o_did, o.ident.name, tcx.def_span(o_did));
228-
changes.add_path_removal(o_did, o.span);
229+
let o_did = o.def.def_id();
230+
231+
if old_vis == Public && cstore.visibility(o_did) == Public {
232+
// delay the handling of removals until the id mapping is complete
233+
removals.push(o);
229234
}
230235
}
231236
(None, Some(n)) => {
@@ -234,8 +239,9 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet,
234239
continue;
235240
}
236241

237-
if new_vis == Public && cstore.visibility(n.def.def_id()) == Public {
238-
let n_did = n.def.def_id();
242+
let n_did = n.def.def_id();
243+
244+
if new_vis == Public && cstore.visibility(n_did) == Public {
239245
changes.new_path(n_did, n.ident.name, tcx.def_span(n_did));
240246
changes.add_path_addition(n_did, n.span);
241247
}
@@ -244,6 +250,21 @@ fn diff_structure<'a, 'tcx>(changes: &mut ChangeSet,
244250
}
245251
}
246252
}
253+
254+
// finally, process item removals
255+
for o in removals.drain(..) {
256+
let o_did = o.def.def_id();
257+
258+
// reuse an already existing path change entry, if possible
259+
if id_mapping.contains_id(o_did) {
260+
let n_did = id_mapping.get_new_id(o_did);
261+
changes.new_path(n_did, o.ident.name, tcx.def_span(n_did));
262+
changes.add_path_removal(n_did, o.span);
263+
} else {
264+
changes.new_path(o_did, o.ident.name, tcx.def_span(o_did));
265+
changes.add_path_removal(o_did, o.span);
266+
}
267+
}
247268
}
248269

249270
/// Given two fn items, perform structural checks.

tests/cases/mix/stdout

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,4 @@
11
version bump: 1.0.0 -> (breaking) -> 2.0.0
2-
warning: path changes to `Abc`
3-
--> $REPO_PATH/tests/cases/mix/old.rs:2:5
4-
|
5-
2 | pub struct Abc;
6-
| ^^^^^^^^^^^^^^^
7-
|
8-
warning: removed path (breaking)
9-
--> $REPO_PATH/tests/cases/mix/old.rs:10:9
10-
|
11-
10| pub use self::a::Abc;
12-
| ^^^^^^^^^^^^
13-
142
warning: breaking changes in `Abc`
153
--> $REPO_PATH/tests/cases/mix/new.rs:2:5
164
|
@@ -33,6 +21,11 @@ warning: path changes to `Abc`
3321
2 | pub enum Abc {}
3422
| ^^^^^^^^^^^^^^^
3523
|
24+
warning: removed path (breaking)
25+
--> $REPO_PATH/tests/cases/mix/old.rs:10:9
26+
|
27+
10| pub use self::a::Abc;
28+
| ^^^^^^^^^^^^
3629
note: added path (technically breaking)
3730
--> $REPO_PATH/tests/cases/mix/new.rs:7:13
3831
|

tests/cases/removal_path/stdout

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
version bump: 1.0.0 -> (breaking) -> 2.0.0
22
warning: path changes to `Abc`
3-
--> $REPO_PATH/tests/cases/removal_path/old.rs:2:5
3+
--> $REPO_PATH/tests/cases/removal_path/new.rs:2:5
44
|
55
2 | pub struct Abc;
66
| ^^^^^^^^^^^^^^^

0 commit comments

Comments
 (0)