1
1
use std:: any:: { type_name, Any } ;
2
2
use std:: cell:: { Cell , RefCell } ;
3
- use std:: collections:: BTreeSet ;
3
+ use std:: collections:: { BTreeSet , HashSet } ;
4
4
use std:: env;
5
5
use std:: ffi:: { OsStr , OsString } ;
6
6
use std:: fmt:: { Debug , Write } ;
@@ -197,28 +197,29 @@ impl PathSet {
197
197
}
198
198
}
199
199
200
- /// Return all `TaskPath`s in `Self` that contain any of the `needles`, removing the
201
- /// matched needles.
200
+ /// Return all `TaskPath`s in `Self` that contain any of the `needles`, as well as the matched
201
+ /// needles.
202
202
///
203
203
/// This is used for `StepDescription::krate`, which passes all matching crates at once to
204
204
/// `Step::make_run`, rather than calling it many times with a single crate.
205
205
/// See `tests.rs` for examples.
206
- fn intersection_removing_matches (
206
+ fn intersection_with_matches < ' p > (
207
207
& self ,
208
- needles : & mut Vec < & Path > ,
208
+ needles : & [ & ' p Path ] ,
209
209
module : Option < Kind > ,
210
- ) -> PathSet {
210
+ ) -> ( PathSet , Vec < & ' p Path > ) {
211
+ let mut matched_paths = vec ! [ ] ;
211
212
let mut check = |p| {
212
- for ( i , n ) in needles. iter ( ) . enumerate ( ) {
213
+ for n in needles {
213
214
let matched = Self :: check ( p, n, module) ;
214
215
if matched {
215
- needles . remove ( i ) ;
216
+ matched_paths . push ( * n ) ;
216
217
return true ;
217
218
}
218
219
}
219
220
false
220
221
} ;
221
- match self {
222
+ let pathset = match self {
222
223
PathSet :: Set ( set) => PathSet :: Set ( set. iter ( ) . filter ( |& p| check ( p) ) . cloned ( ) . collect ( ) ) ,
223
224
PathSet :: Suite ( suite) => {
224
225
if check ( suite) {
@@ -227,7 +228,8 @@ impl PathSet {
227
228
PathSet :: empty ( )
228
229
}
229
230
}
230
- }
231
+ } ;
232
+ ( pathset, matched_paths)
231
233
}
232
234
233
235
/// A convenience wrapper for Steps which know they have no aliases and all their sets contain only a single path.
@@ -315,6 +317,7 @@ impl StepDescription {
315
317
316
318
// Handle all test suite paths.
317
319
// (This is separate from the loop below to avoid having to handle multiple paths in `is_suite_path` somehow.)
320
+ // Note that unlike below, we don't allow multiple suite paths to share the same path.
318
321
paths. retain ( |path| {
319
322
for ( desc, should_run) in v. iter ( ) . zip ( & should_runs) {
320
323
if let Some ( suite) = should_run. is_suite_path ( & path) {
@@ -330,15 +333,19 @@ impl StepDescription {
330
333
}
331
334
332
335
// Handle all PathSets.
336
+ let mut seen_paths = HashSet :: new ( ) ;
333
337
for ( desc, should_run) in v. iter ( ) . zip ( & should_runs) {
334
- let pathsets = should_run. pathset_for_paths_removing_matches ( & mut paths, desc. kind ) ;
338
+ let ( pathsets, matched ) = should_run. pathset_for_paths_with_matches ( & paths, desc. kind ) ;
335
339
if !pathsets. is_empty ( ) {
340
+ seen_paths. extend ( matched) ;
336
341
desc. maybe_run ( builder, pathsets) ;
337
342
}
338
343
}
339
344
340
- if !paths. is_empty ( ) {
341
- eprintln ! ( "error: no `{}` rules matched {:?}" , builder. kind. as_str( ) , paths, ) ;
345
+ let cli_paths: HashSet < _ > = paths. into_iter ( ) . collect ( ) ;
346
+ let missing_paths: Vec < _ > = cli_paths. difference ( & seen_paths) . collect ( ) ;
347
+ if !missing_paths. is_empty ( ) {
348
+ eprintln ! ( "error: no `{}` rules matched {:?}" , builder. kind. as_str( ) , missing_paths) ;
342
349
eprintln ! (
343
350
"help: run `x.py {} --help --verbose` to show a list of available paths" ,
344
351
builder. kind. as_str( )
@@ -500,19 +507,21 @@ impl<'a> ShouldRun<'a> {
500
507
///
501
508
/// The reason we return PathSet instead of PathBuf is to allow for aliases that mean the same thing
502
509
/// (for now, just `all_krates` and `paths`, but we may want to add an `aliases` function in the future?)
503
- fn pathset_for_paths_removing_matches (
510
+ fn pathset_for_paths_with_matches < ' p > (
504
511
& self ,
505
- paths : & mut Vec < & Path > ,
512
+ paths : & [ & ' p Path ] ,
506
513
kind : Kind ,
507
- ) -> Vec < PathSet > {
514
+ ) -> ( Vec < PathSet > , HashSet < & ' p Path > ) {
515
+ let mut all_matched_paths = HashSet :: new ( ) ;
508
516
let mut sets = vec ! [ ] ;
509
517
for pathset in & self . paths {
510
- let subset = pathset. intersection_removing_matches ( paths, Some ( kind) ) ;
518
+ let ( subset, matched_paths ) = pathset. intersection_with_matches ( paths, Some ( kind) ) ;
511
519
if subset != PathSet :: empty ( ) {
512
520
sets. push ( subset) ;
521
+ all_matched_paths. extend ( matched_paths) ;
513
522
}
514
523
}
515
- sets
524
+ ( sets, all_matched_paths )
516
525
}
517
526
}
518
527
0 commit comments