@@ -396,17 +396,9 @@ determination about how to set up the standard library.
396
396
The "mainstream platform" will be expressed via a new primitive ` cfg ` pattern
397
397
called ` std ` . This is the ** default portability of all crates** , unless
398
398
opted-out (see below on "subsetting ` std ` "). Likewise, most items in ` std ` will
399
- initially be exported at ` std ` portability level. These two facts together mean
400
- that existing uses of ` std ` will continue to work without issuing any warnings.
401
-
402
- The ` std ` portability will include several implications, e.g.:
403
-
404
- - ` std ` implies ` any(windows, macos, linux) `
405
- - ` std ` implies ` any(target_pointer_width = "32", target_pointer_width = "64") `
406
-
407
- and so on. That means, in particular, that a ` match_cfg ` expression that covers
408
- * all* of Windows, macOS and Linux will be considered to have "mainstream
409
- portability" automatically.
399
+ * initially* be exported at ` std ` portability level (but see subsets
400
+ below). These two facts together mean that existing uses of ` std ` will continue
401
+ to work without issuing any warnings.
410
402
411
403
### Expanding ` std `
412
404
@@ -424,7 +416,7 @@ impl File {
424
416
```
425
417
426
418
and the portability of ` as_raw_fd ` will be ` all(std, unix) ` . Thus, any code
427
- using ` as_raw_fd ` will need to be in a ` unix ` context.
419
+ using ` as_raw_fd ` will need to be in a ` unix ` context in particular .
428
420
429
421
We can thus deprecate the ` std::os ` module in favor of these in-place
430
422
APIs. Doing so leverages the fact that we're using a portability * lint* : these
@@ -433,42 +425,75 @@ generate new warnings, but this is considered an acceptable change. After all,
433
425
lints on dependencies are automatically capped, and the lint will not prevent
434
426
code from compiling--and can be silenced.
435
427
436
- Expanding to include new atomics, SIMD, and other desired extensions should
437
- amount to a straightforward use of ` cfg ` .
428
+ For hardware features like additional atomics or SIMD, we can use the
429
+ ` target_feature ` cfg key to label the APIs -- which has to be done anyway, but
430
+ will also do the right thing for the lint.
431
+
432
+ In short, for expansions there's basically nothing to do. You just add the API
433
+ in its natural location, with its natural ` cfg ` , and everything works out.
438
434
439
435
### Subsetting ` std `
440
436
441
- What about subsets of ` std ` (or ` core ` )? First of all, if you apply ` cfg ` to
442
- your * crate* definition, you opt out of the default ` std ` portability level in
443
- favor of the ` cfg ` you write. Doing so will deny access to many APIs in ` std ` .
444
-
445
- Over time, APIs within ` std ` and ` core ` will be labeled with new, more narrow
446
- portabilities. Let's take, for example, threading--which we wish to not provide
447
- on platforms like Emscripten. The ` std ` threading APIs might be revised to use
448
- ` cfg(threads) ` , rather than ` cfg(std) ` ; at the same time, ` std ` would be set up
449
- to imply ` threads ` , so that no new warnings would be generated. To check for
450
- compatibility with Emscripten, you can opt out of the ` std ` scenario, and avoid
451
- opting into ` threads ` (or use ` match_cfg ` if you want to do so only optionally,
452
- for example to use optional parallelism).
453
-
454
- Similarly, ` libcore ` can be annotated with new ` cfg ` s, like ` cfg(float) ` for
455
- floating point support.
456
-
457
- Thus, library authors shooting for maximal portability should opt out of
458
- ` cfg(std) ` , and use ` cfg ` as little as possible. And over time, we can allow
459
- increasingly fine-grained subsets of ` std ` by introducing new ` cfg ` flags.
460
-
461
- ## Backwards compatibility and lint evolution
462
-
463
- The fact that the portability lint is a * lint* gives us a lot of
464
- flexibility. Take, for example, the assumption that ` std ` implies `any(windows,
465
- macos, linux)`. Conceivably, we may want to add more mainstream platforms in the
466
- future. Doing so may generate new warnings--particularly for people who had used
467
- ` match_cfg ` previously to exhaustively match against these cases. But (1) it's
468
- merely a new * warning* , which is fine to introduce, and can be silenced; (2)
469
- this is actually a highly desirable outcome if we ever did add a new mainstream
470
- platform, since existing code would get a heads-up that it may not longer be
471
- compatible with all mainstream platforms.
437
+ What about subsets of ` std ` ?
438
+
439
+ ** What use case do we want to address?** Going back to the Portability Goals
440
+ discussed earlier, the goal of subsetting ` std ` is mostly about helping people
441
+ who want * maximum portability* . For this use case, you should opt out of the
442
+ mainstream platform, and then * whitelist* the various features you need, thus
443
+ giving you assistance in using the minimal set of assumptions needed.
444
+
445
+ ** Opting out of the mainstream platform** . To opt out of the ` std ` platform, you
446
+ can just apply a ` cfg ` to your * crate* definition. The assumptions of that ` cfg `
447
+ will form the baseline for the crate.
448
+
449
+ ** Carving up ` std ` into whitelistable features** . When we want to provide
450
+ subsets of ` std ` , we can introduce a new set of target features, along the
451
+ following lines:
452
+
453
+ - each integer size
454
+ - each float size
455
+ - each atomics size
456
+ - allocation
457
+ - OS facilities
458
+ - env
459
+ - fs
460
+ - net
461
+ - process
462
+ - thread
463
+ - rng
464
+
465
+ ** To introduce these features, we would change APIs in ` std ` from being marked as
466
+ ` #[cfg(std)] ` to instead being labeled with the particular feature** , e.g.:
467
+
468
+ ``` rust
469
+ // previously: #[cfg(std)]
470
+ #[cfg(target_feature = " thread" )]
471
+ mod thread ;
472
+
473
+ // previously: #[cfg(std)]
474
+ #[cfg(target_feature = " fs" )]
475
+ mod fs ;
476
+ ```
477
+
478
+ and so on. We can then set up axioms such that ` std ` * implies* all of these
479
+ features. That way existing code written at the default portability level will
480
+ not produce warnings when using the standard library. And in general, we can
481
+ carve out increasingly fine-grained subsets, setting up implications between the
482
+ previous coarse-grained features and the new subsets.
483
+
484
+ On the other side, library authors shooting for maximal portability should opt
485
+ out of ` cfg(std) ` , and use ` cfg ` as little as possible, adding features to their
486
+ whitelist only after deciding they're truly needed, or abstracting over them
487
+ (such as using threading for parallelism only when it was available).
488
+
489
+ ## Proposed rollout
490
+
491
+ The most pressing problem in ` std ` is the desire for expansion, rather than
492
+ subsetting, so we should start there. The ` cfg ` needed for expansion is totally
493
+ straightforward, and will allow us to gain experience with the lint.
494
+
495
+ Later, we can start exploring subsets of ` std ` , which will likely require some
496
+ more thoughtful design to find the right granularity.
472
497
473
498
# Drawbacks
474
499
[ drawbacks ] : #drawbacks
@@ -527,6 +552,14 @@ the scenarios that arise in practice.
527
552
# Unresolved questions
528
553
[ unresolved ] : #unresolved-questions
529
554
555
+ ### Extensions to ` cfg ` itself
556
+
557
+ If we allow ` cfg ` to go beyond simple key-value pairs, for example to talk about
558
+ ranges, we will need to accommodate that somehow in the lint. One plausible
559
+ approach would be to use something more like SMT solving, which incorporates
560
+ reasoning about things like ordering constraints in addition to basic SAT
561
+ questions.
562
+
530
563
### External libraries
531
564
532
565
It's not clear what the story should be for a library like ` libc ` , which
@@ -538,8 +571,30 @@ approach such cases before landing the RFC.
538
571
To what extent does this proposal obviate the need for the ` std ` facade? Might
539
572
it be possible to deprecate ` libcore ` in favor of the "subsetting ` std ` " approach?
540
573
574
+ ### Cargo features
575
+
576
+ It's unclear whether, or how, to extend this approach to deal with Cargo
577
+ features. In particular, features are namespaced per crate, so there's no way to
578
+ use the ` cfg ` system today to talk about upstream features.
579
+
541
580
# Appendix: possible extensions
542
581
582
+ ## Subsetting ` std `
583
+
584
+
585
+ cfgs:
586
+
587
+ - each integer size
588
+ - each float size
589
+ - each atomics size
590
+ - allocation
591
+ - env
592
+ - fs
593
+ - net
594
+ - process
595
+ - thread
596
+ - OS rng
597
+
543
598
## ` match_cfg `
544
599
545
600
The original version of this RFC was more expansive, and proposed a ` match_cfg `
0 commit comments