@@ -156,13 +156,15 @@ fn build_feature_map(
156
156
dependencies : & [ Dependency ] ,
157
157
) -> CargoResult < FeatureMap > {
158
158
use self :: FeatureValue :: * ;
159
- let mut dep_map = HashMap :: new ( ) ;
159
+ // A map of dependency names to whether there are any that are optional.
160
+ let mut dep_map: HashMap < InternedString , bool > = HashMap :: new ( ) ;
160
161
for dep in dependencies. iter ( ) {
161
- dep_map
162
- . entry ( dep. name_in_toml ( ) )
163
- . or_insert_with ( Vec :: new )
164
- . push ( dep ) ;
162
+ let has_optional = dep_map. entry ( dep . name_in_toml ( ) ) . or_insert ( false ) ;
163
+ if dep. is_optional ( ) {
164
+ * has_optional = true ;
165
+ }
165
166
}
167
+ let dep_map = dep_map; // We are done mutating this variable
166
168
167
169
let mut map: FeatureMap = features
168
170
. iter ( )
@@ -180,117 +182,78 @@ fn build_feature_map(
180
182
let explicitly_listed: HashSet < _ > = map
181
183
. values ( )
182
184
. flatten ( )
183
- . filter_map ( |fv| match fv {
184
- Dep { dep_name } => Some ( * dep_name) ,
185
- _ => None ,
186
- } )
185
+ . filter_map ( |fv| fv. explicitly_name ( ) )
187
186
. collect ( ) ;
188
187
for dep in dependencies {
189
188
if !dep. is_optional ( ) {
190
189
continue ;
191
190
}
192
- let dep_name_in_toml = dep. name_in_toml ( ) ;
193
- if features. contains_key ( & dep_name_in_toml) || explicitly_listed. contains ( & dep_name_in_toml)
194
- {
191
+ let dep_name = dep. name_in_toml ( ) ;
192
+ if features. contains_key ( & dep_name) || explicitly_listed. contains ( & dep_name) {
195
193
continue ;
196
194
}
197
- let fv = Dep {
198
- dep_name : dep_name_in_toml,
199
- } ;
200
- map. insert ( dep_name_in_toml, vec ! [ fv] ) ;
195
+ map. insert ( dep_name, vec ! [ Dep { dep_name } ] ) ;
201
196
}
197
+ let map = map; // We are done mutating this variable
202
198
203
199
// Validate features are listed properly.
204
200
for ( feature, fvs) in & map {
205
201
FeatureName :: new ( feature) ?;
206
202
for fv in fvs {
207
203
// Find data for the referenced dependency...
208
- let dep_data = {
209
- match fv {
210
- Feature ( dep_name) | Dep { dep_name, .. } | DepFeature { dep_name, .. } => {
211
- dep_map. get ( dep_name)
212
- }
213
- }
214
- } ;
215
- let is_optional_dep = dep_data
216
- . iter ( )
217
- . flat_map ( |d| d. iter ( ) )
218
- . any ( |d| d. is_optional ( ) ) ;
204
+ let dep_data = dep_map. get ( & fv. dep_name ( ) ) ;
219
205
let is_any_dep = dep_data. is_some ( ) ;
206
+ let is_optional_dep = dep_data. is_some_and ( |& o| o) ;
220
207
match fv {
221
208
Feature ( f) => {
222
209
if !features. contains_key ( f) {
223
210
if !is_any_dep {
224
211
bail ! (
225
- "feature `{}` includes `{}` which is neither a dependency \
226
- nor another feature",
227
- feature,
228
- fv
229
- ) ;
212
+ "feature `{feature}` includes `{fv}` which is neither a dependency \
213
+ nor another feature"
214
+ ) ;
230
215
}
231
216
if is_optional_dep {
232
217
if !map. contains_key ( f) {
233
218
bail ! (
234
- "feature `{}` includes `{}`, but `{}` is an \
219
+ "feature `{feature }` includes `{fv }`, but `{f }` is an \
235
220
optional dependency without an implicit feature\n \
236
- Use `dep:{}` to enable the dependency.",
237
- feature,
238
- fv,
239
- f,
240
- f
221
+ Use `dep:{f}` to enable the dependency."
241
222
) ;
242
223
}
243
224
} else {
244
- bail ! ( "feature `{}` includes `{}`, but `{}` is not an optional dependency\n \
225
+ bail ! ( "feature `{feature }` includes `{fv }`, but `{f }` is not an optional dependency\n \
245
226
A non-optional dependency of the same name is defined; \
246
- consider adding `optional = true` to its definition.",
247
- feature, fv, f) ;
227
+ consider adding `optional = true` to its definition.") ;
248
228
}
249
229
}
250
230
}
251
231
Dep { dep_name } => {
252
232
if !is_any_dep {
253
- bail ! (
254
- "feature `{}` includes `{}`, but `{}` is not listed as a dependency" ,
255
- feature,
256
- fv,
257
- dep_name
258
- ) ;
233
+ bail ! ( "feature `{feature}` includes `{fv}`, but `{dep_name}` is not listed as a dependency" ) ;
259
234
}
260
235
if !is_optional_dep {
261
236
bail ! (
262
- "feature `{}` includes `{}`, but `{}` is not an optional dependency\n \
237
+ "feature `{feature }` includes `{fv }`, but `{dep_name }` is not an optional dependency\n \
263
238
A non-optional dependency of the same name is defined; \
264
- consider adding `optional = true` to its definition.",
265
- feature,
266
- fv,
267
- dep_name
239
+ consider adding `optional = true` to its definition."
268
240
) ;
269
241
}
270
242
}
271
243
DepFeature {
272
244
dep_name,
273
245
dep_feature,
274
246
weak,
275
- ..
276
247
} => {
277
248
// Early check for some unlikely syntax.
278
249
if dep_feature. contains ( '/' ) {
279
- bail ! (
280
- "multiple slashes in feature `{}` (included by feature `{}`) are not allowed" ,
281
- fv,
282
- feature
283
- ) ;
250
+ bail ! ( "multiple slashes in feature `{fv}` (included by feature `{feature}`) are not allowed" ) ;
284
251
}
285
252
286
253
// dep: cannot be combined with /
287
254
if let Some ( stripped_dep) = dep_name. strip_prefix ( "dep:" ) {
288
255
let has_other_dep = explicitly_listed. contains ( stripped_dep) ;
289
- let is_optional = dep_map
290
- . get ( stripped_dep)
291
- . iter ( )
292
- . flat_map ( |d| d. iter ( ) )
293
- . any ( |d| d. is_optional ( ) ) ;
256
+ let is_optional = dep_map. get ( stripped_dep) . is_some_and ( |& o| o) ;
294
257
let extra_help = if * weak || has_other_dep || !is_optional {
295
258
// In this case, the user should just remove dep:.
296
259
// Note that "hiding" an optional dependency
@@ -314,18 +277,14 @@ fn build_feature_map(
314
277
315
278
// Validation of the feature name will be performed in the resolver.
316
279
if !is_any_dep {
317
- bail ! (
318
- "feature `{}` includes `{}`, but `{}` is not a dependency" ,
319
- feature,
320
- fv,
321
- dep_name
322
- ) ;
280
+ bail ! ( "feature `{feature}` includes `{fv}`, but `{dep_name}` is not a dependency" ) ;
323
281
}
324
282
if * weak && !is_optional_dep {
325
- bail ! ( "feature `{}` includes `{}` with a `?`, but `{}` is not an optional dependency\n \
283
+ bail ! (
284
+ "feature `{feature}` includes `{fv}` with a `?`, but `{dep_name}` is not an optional dependency\n \
326
285
A non-optional dependency of the same name is defined; \
327
- consider removing the `?` or changing the dependency to be optional",
328
- feature , fv , dep_name ) ;
286
+ consider removing the `?` or changing the dependency to be optional"
287
+ ) ;
329
288
}
330
289
}
331
290
}
@@ -341,15 +300,13 @@ fn build_feature_map(
341
300
_ => None ,
342
301
} )
343
302
. collect ( ) ;
344
- if let Some ( dep) = dependencies
303
+ if let Some ( ( dep, _ ) ) = dep_map
345
304
. iter ( )
346
- . find ( |dep| dep . is_optional ( ) && !used. contains ( & dep. name_in_toml ( ) ) )
305
+ . find ( |& ( dep, & is_optional) | is_optional && !used. contains ( dep) )
347
306
{
348
307
bail ! (
349
- "optional dependency `{}` is not included in any feature\n \
350
- Make sure that `dep:{}` is included in one of features in the [features] table.",
351
- dep. name_in_toml( ) ,
352
- dep. name_in_toml( ) ,
308
+ "optional dependency `{dep}` is not included in any feature\n \
309
+ Make sure that `dep:{dep}` is included in one of features in the [features] table."
353
310
) ;
354
311
}
355
312
@@ -376,19 +333,13 @@ pub enum FeatureValue {
376
333
377
334
impl FeatureValue {
378
335
pub fn new ( feature : InternedString ) -> FeatureValue {
379
- match feature. find ( '/' ) {
380
- Some ( pos) => {
381
- let ( dep, dep_feat) = feature. split_at ( pos) ;
382
- let dep_feat = & dep_feat[ 1 ..] ;
383
- let ( dep, weak) = if let Some ( dep) = dep. strip_suffix ( '?' ) {
384
- ( dep, true )
385
- } else {
386
- ( dep, false )
387
- } ;
336
+ match feature. split_once ( '/' ) {
337
+ Some ( ( dep, dep_feat) ) => {
338
+ let dep_name = dep. strip_suffix ( '?' ) ;
388
339
FeatureValue :: DepFeature {
389
- dep_name : InternedString :: new ( dep) ,
340
+ dep_name : InternedString :: new ( dep_name . unwrap_or ( dep) ) ,
390
341
dep_feature : InternedString :: new ( dep_feat) ,
391
- weak,
342
+ weak : dep_name . is_some ( ) ,
392
343
}
393
344
}
394
345
None => {
@@ -403,25 +354,35 @@ impl FeatureValue {
403
354
}
404
355
}
405
356
406
- /// Returns `true` if this feature explicitly used `dep:` syntax.
407
- pub fn has_dep_prefix ( & self ) -> bool {
408
- matches ! ( self , FeatureValue :: Dep { .. } )
357
+ fn explicitly_name ( & self ) -> Option < InternedString > {
358
+ match self {
359
+ FeatureValue :: Dep { dep_name, .. } => Some ( * dep_name) ,
360
+ _ => None ,
361
+ }
362
+ }
363
+
364
+ fn dep_name ( & self ) -> InternedString {
365
+ match self {
366
+ FeatureValue :: Feature ( dep_name)
367
+ | FeatureValue :: Dep { dep_name, .. }
368
+ | FeatureValue :: DepFeature { dep_name, .. } => * dep_name,
369
+ }
409
370
}
410
371
}
411
372
412
373
impl fmt:: Display for FeatureValue {
413
374
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
414
375
use self :: FeatureValue :: * ;
415
376
match self {
416
- Feature ( feat) => write ! ( f, "{}" , feat ) ,
417
- Dep { dep_name } => write ! ( f, "dep:{}" , dep_name ) ,
377
+ Feature ( feat) => write ! ( f, "{feat}" ) ,
378
+ Dep { dep_name } => write ! ( f, "dep:{dep_name}" ) ,
418
379
DepFeature {
419
380
dep_name,
420
381
dep_feature,
421
382
weak,
422
383
} => {
423
384
let weak = if * weak { "?" } else { "" } ;
424
- write ! ( f, "{}{ }/{}" , dep_name , weak , dep_feature )
385
+ write ! ( f, "{dep_name}{weak }/{dep_feature}" )
425
386
}
426
387
}
427
388
}
0 commit comments