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