html-to-markdown 2.24.1 → 2.24.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (148) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +9 -6
  3. data/ext/html-to-markdown-rb/native/Cargo.lock +13 -13
  4. data/ext/html-to-markdown-rb/native/Cargo.toml +1 -1
  5. data/lib/html_to_markdown/version.rb +1 -1
  6. data/rust-vendor/bytemuck/.cargo-checksum.json +1 -1
  7. data/rust-vendor/bytemuck/.cargo_vcs_info.json +1 -1
  8. data/rust-vendor/bytemuck/.github/workflows/rust.yml +4 -4
  9. data/rust-vendor/bytemuck/Cargo.lock +16 -9
  10. data/rust-vendor/bytemuck/Cargo.toml +6 -2
  11. data/rust-vendor/bytemuck/Cargo.toml.orig +7 -6
  12. data/rust-vendor/bytemuck/changelog.md +5 -0
  13. data/rust-vendor/bytemuck/src/must.rs +1 -1
  14. data/rust-vendor/bytemuck/src/pod.rs +13 -0
  15. data/rust-vendor/bytemuck/src/zeroable.rs +13 -0
  16. data/rust-vendor/bytemuck/src/zeroable_in_option.rs +2 -2
  17. data/rust-vendor/bytemuck/tests/std_tests.rs +1 -1
  18. data/rust-vendor/cc/.cargo-checksum.json +1 -1
  19. data/rust-vendor/cc/.cargo_vcs_info.json +1 -1
  20. data/rust-vendor/cc/CHANGELOG.md +8 -0
  21. data/rust-vendor/cc/Cargo.lock +3 -3
  22. data/rust-vendor/cc/Cargo.toml +2 -2
  23. data/rust-vendor/cc/Cargo.toml.orig +2 -2
  24. data/rust-vendor/cc/src/lib.rs +1 -0
  25. data/rust-vendor/cc/src/target/generated.rs +10 -0
  26. data/rust-vendor/find-msvc-tools/.cargo-checksum.json +1 -1
  27. data/rust-vendor/find-msvc-tools/.cargo_vcs_info.json +1 -1
  28. data/rust-vendor/find-msvc-tools/CHANGELOG.md +6 -0
  29. data/rust-vendor/find-msvc-tools/Cargo.lock +1 -1
  30. data/rust-vendor/find-msvc-tools/Cargo.toml +1 -1
  31. data/rust-vendor/find-msvc-tools/Cargo.toml.orig +1 -1
  32. data/rust-vendor/find-msvc-tools/src/find_tools.rs +55 -20
  33. data/rust-vendor/html-to-markdown-rs/src/converter/handlers/link.rs +1 -9
  34. data/rust-vendor/html-to-markdown-rs/src/converter/inline/link.rs +2 -11
  35. data/rust-vendor/html-to-markdown-rs/src/converter/list/definition.rs +30 -7
  36. data/rust-vendor/html-to-markdown-rs/src/converter/semantic/definition_list.rs +30 -7
  37. data/rust-vendor/html-to-markdown-rs/tests/issue_199_regressions.rs +15 -0
  38. data/rust-vendor/html-to-markdown-rs/tests/issue_200_regressions.rs +36 -0
  39. data/rust-vendor/zerocopy/.cargo-checksum.json +1 -1
  40. data/rust-vendor/zerocopy/.cargo_vcs_info.json +2 -1
  41. data/rust-vendor/zerocopy/Cargo.lock +3 -3
  42. data/rust-vendor/zerocopy/Cargo.toml +4 -4
  43. data/rust-vendor/zerocopy/Cargo.toml.orig +4 -4
  44. data/rust-vendor/zerocopy/src/doctests.rs +27 -0
  45. data/rust-vendor/zerocopy/src/error.rs +30 -0
  46. data/rust-vendor/zerocopy/src/layout.rs +239 -135
  47. data/rust-vendor/zerocopy/src/lib.rs +16 -0
  48. data/rust-vendor/zerocopy/src/macros.rs +255 -125
  49. data/rust-vendor/zerocopy/src/pointer/mod.rs +1 -1
  50. data/rust-vendor/zerocopy/src/pointer/ptr.rs +109 -23
  51. data/rust-vendor/zerocopy/src/util/macro_util.rs +344 -383
  52. data/rust-vendor/zerocopy/src/util/mod.rs +38 -0
  53. data/rust-vendor/zerocopy/tests/ui-msrv/transmute-mut-const.stderr +8 -0
  54. data/rust-vendor/zerocopy/tests/ui-msrv/transmute-mut-dst-not-a-reference.stderr +10 -0
  55. data/rust-vendor/zerocopy/tests/ui-msrv/transmute-mut-src-unsized.stderr +11 -3
  56. data/rust-vendor/zerocopy/tests/ui-msrv/transmute-ref-dst-mutable.stderr +10 -0
  57. data/rust-vendor/zerocopy/tests/ui-msrv/transmute-ref-dst-not-a-reference.stderr +10 -0
  58. data/rust-vendor/zerocopy/tests/ui-msrv/transmute-ref-src-dst-not-references.stderr +10 -0
  59. data/rust-vendor/zerocopy/tests/ui-msrv/transmute-ref-src-unsized.stderr +11 -3
  60. data/rust-vendor/zerocopy/tests/ui-msrv/try_transmute_mut-dst-not-tryfrombytes.stderr +0 -10
  61. data/rust-vendor/zerocopy/tests/ui-msrv/try_transmute_ref-dst-mutable.stderr +1 -1
  62. data/rust-vendor/zerocopy/tests/ui-msrv/try_transmute_ref-dst-not-immutable-tryfrombytes.stderr +0 -10
  63. data/rust-vendor/zerocopy/tests/ui-msrv/try_transmute_ref-src-not-immutable-intobytes.stderr +1 -11
  64. data/rust-vendor/zerocopy/tests/ui-nightly/transmute-mut-const.stderr +9 -0
  65. data/rust-vendor/zerocopy/tests/ui-nightly/transmute-mut-dst-not-a-reference.stderr +10 -0
  66. data/rust-vendor/zerocopy/tests/ui-nightly/transmute-mut-src-unsized.stderr +16 -8
  67. data/rust-vendor/zerocopy/tests/ui-nightly/transmute-ref-dst-mutable.stderr +10 -0
  68. data/rust-vendor/zerocopy/tests/ui-nightly/transmute-ref-dst-not-a-reference.stderr +10 -0
  69. data/rust-vendor/zerocopy/tests/ui-nightly/transmute-ref-src-dst-not-references.stderr +10 -0
  70. data/rust-vendor/zerocopy/tests/ui-nightly/transmute-ref-src-unsized.stderr +16 -8
  71. data/rust-vendor/zerocopy/tests/ui-nightly/try_transmute_mut-dst-not-tryfrombytes.stderr +38 -38
  72. data/rust-vendor/zerocopy/tests/ui-nightly/try_transmute_ref-dst-not-immutable-tryfrombytes.stderr +33 -33
  73. data/rust-vendor/zerocopy/tests/ui-nightly/try_transmute_ref-src-not-immutable-intobytes.stderr +12 -12
  74. data/rust-vendor/zerocopy/tests/ui-stable/transmute-mut-const.stderr +9 -0
  75. data/rust-vendor/zerocopy/tests/ui-stable/transmute-mut-dst-not-a-reference.stderr +10 -0
  76. data/rust-vendor/zerocopy/tests/ui-stable/transmute-mut-src-unsized.stderr +16 -8
  77. data/rust-vendor/zerocopy/tests/ui-stable/transmute-ref-dst-mutable.stderr +10 -0
  78. data/rust-vendor/zerocopy/tests/ui-stable/transmute-ref-dst-not-a-reference.stderr +10 -0
  79. data/rust-vendor/zerocopy/tests/ui-stable/transmute-ref-src-dst-not-references.stderr +10 -0
  80. data/rust-vendor/zerocopy/tests/ui-stable/transmute-ref-src-unsized.stderr +16 -8
  81. data/rust-vendor/zerocopy/tests/ui-stable/try_transmute_mut-dst-not-tryfrombytes.stderr +38 -38
  82. data/rust-vendor/zerocopy/tests/ui-stable/try_transmute_ref-dst-not-immutable-tryfrombytes.stderr +33 -33
  83. data/rust-vendor/zerocopy/tests/ui-stable/try_transmute_ref-src-not-immutable-intobytes.stderr +12 -12
  84. data/rust-vendor/zerocopy-derive/.cargo-checksum.json +1 -1
  85. data/rust-vendor/zerocopy-derive/.cargo_vcs_info.json +1 -1
  86. data/rust-vendor/zerocopy-derive/Cargo.lock +1 -1
  87. data/rust-vendor/zerocopy-derive/Cargo.toml +1 -1
  88. data/rust-vendor/zerocopy-derive/Cargo.toml.orig +1 -1
  89. data/rust-vendor/zerocopy-derive/tests/ui-nightly/enum.stderr +3 -3
  90. data/rust-vendor/zerocopy-derive/tests/ui-nightly/struct.stderr +5 -5
  91. data/rust-vendor/zerocopy-derive/tests/ui-stable/enum.stderr +3 -3
  92. data/rust-vendor/zerocopy-derive/tests/ui-stable/struct.stderr +5 -5
  93. data/rust-vendor/zmij/.cargo-checksum.json +1 -1
  94. data/rust-vendor/zmij/.cargo_vcs_info.json +1 -1
  95. data/rust-vendor/zmij/Cargo.lock +16 -16
  96. data/rust-vendor/zmij/Cargo.toml +1 -1
  97. data/rust-vendor/zmij/Cargo.toml.orig +1 -1
  98. data/rust-vendor/zmij/README.md +1 -1
  99. data/rust-vendor/zmij/src/lib.rs +54 -93
  100. metadata +4 -50
  101. data/rust-vendor/zerocopy/tests/ui-msrv/transmute-mut-dst-unsized.rs +0 -15
  102. data/rust-vendor/zerocopy/tests/ui-msrv/transmute-mut-dst-unsized.stderr +0 -8
  103. data/rust-vendor/zerocopy/tests/ui-msrv/transmute-ref-dst-unsized.rs +0 -15
  104. data/rust-vendor/zerocopy/tests/ui-msrv/transmute-ref-dst-unsized.stderr +0 -8
  105. data/rust-vendor/zerocopy/tests/ui-msrv/try_transmute_mut-alignment-increase.rs +0 -19
  106. data/rust-vendor/zerocopy/tests/ui-msrv/try_transmute_mut-alignment-increase.stderr +0 -9
  107. data/rust-vendor/zerocopy/tests/ui-msrv/try_transmute_mut-size-decrease.rs +0 -19
  108. data/rust-vendor/zerocopy/tests/ui-msrv/try_transmute_mut-size-decrease.stderr +0 -9
  109. data/rust-vendor/zerocopy/tests/ui-msrv/try_transmute_mut-size-increase.rs +0 -19
  110. data/rust-vendor/zerocopy/tests/ui-msrv/try_transmute_mut-size-increase.stderr +0 -17
  111. data/rust-vendor/zerocopy/tests/ui-msrv/try_transmute_ref-alignment-increase.rs +0 -18
  112. data/rust-vendor/zerocopy/tests/ui-msrv/try_transmute_ref-alignment-increase.stderr +0 -9
  113. data/rust-vendor/zerocopy/tests/ui-msrv/try_transmute_ref-size-decrease.rs +0 -18
  114. data/rust-vendor/zerocopy/tests/ui-msrv/try_transmute_ref-size-decrease.stderr +0 -9
  115. data/rust-vendor/zerocopy/tests/ui-msrv/try_transmute_ref-size-increase.rs +0 -18
  116. data/rust-vendor/zerocopy/tests/ui-msrv/try_transmute_ref-size-increase.stderr +0 -9
  117. data/rust-vendor/zerocopy/tests/ui-nightly/transmute-mut-dst-unsized.rs +0 -15
  118. data/rust-vendor/zerocopy/tests/ui-nightly/transmute-mut-dst-unsized.stderr +0 -16
  119. data/rust-vendor/zerocopy/tests/ui-nightly/transmute-ref-dst-unsized.rs +0 -15
  120. data/rust-vendor/zerocopy/tests/ui-nightly/transmute-ref-dst-unsized.stderr +0 -16
  121. data/rust-vendor/zerocopy/tests/ui-nightly/try_transmute_mut-alignment-increase.rs +0 -19
  122. data/rust-vendor/zerocopy/tests/ui-nightly/try_transmute_mut-alignment-increase.stderr +0 -9
  123. data/rust-vendor/zerocopy/tests/ui-nightly/try_transmute_mut-size-decrease.rs +0 -19
  124. data/rust-vendor/zerocopy/tests/ui-nightly/try_transmute_mut-size-decrease.stderr +0 -9
  125. data/rust-vendor/zerocopy/tests/ui-nightly/try_transmute_mut-size-increase.rs +0 -19
  126. data/rust-vendor/zerocopy/tests/ui-nightly/try_transmute_mut-size-increase.stderr +0 -17
  127. data/rust-vendor/zerocopy/tests/ui-nightly/try_transmute_ref-alignment-increase.rs +0 -18
  128. data/rust-vendor/zerocopy/tests/ui-nightly/try_transmute_ref-alignment-increase.stderr +0 -9
  129. data/rust-vendor/zerocopy/tests/ui-nightly/try_transmute_ref-size-decrease.rs +0 -18
  130. data/rust-vendor/zerocopy/tests/ui-nightly/try_transmute_ref-size-decrease.stderr +0 -9
  131. data/rust-vendor/zerocopy/tests/ui-nightly/try_transmute_ref-size-increase.rs +0 -18
  132. data/rust-vendor/zerocopy/tests/ui-nightly/try_transmute_ref-size-increase.stderr +0 -9
  133. data/rust-vendor/zerocopy/tests/ui-stable/transmute-mut-dst-unsized.rs +0 -15
  134. data/rust-vendor/zerocopy/tests/ui-stable/transmute-mut-dst-unsized.stderr +0 -16
  135. data/rust-vendor/zerocopy/tests/ui-stable/transmute-ref-dst-unsized.rs +0 -15
  136. data/rust-vendor/zerocopy/tests/ui-stable/transmute-ref-dst-unsized.stderr +0 -16
  137. data/rust-vendor/zerocopy/tests/ui-stable/try_transmute_mut-alignment-increase.rs +0 -19
  138. data/rust-vendor/zerocopy/tests/ui-stable/try_transmute_mut-alignment-increase.stderr +0 -9
  139. data/rust-vendor/zerocopy/tests/ui-stable/try_transmute_mut-size-decrease.rs +0 -19
  140. data/rust-vendor/zerocopy/tests/ui-stable/try_transmute_mut-size-decrease.stderr +0 -9
  141. data/rust-vendor/zerocopy/tests/ui-stable/try_transmute_mut-size-increase.rs +0 -19
  142. data/rust-vendor/zerocopy/tests/ui-stable/try_transmute_mut-size-increase.stderr +0 -17
  143. data/rust-vendor/zerocopy/tests/ui-stable/try_transmute_ref-alignment-increase.rs +0 -18
  144. data/rust-vendor/zerocopy/tests/ui-stable/try_transmute_ref-alignment-increase.stderr +0 -9
  145. data/rust-vendor/zerocopy/tests/ui-stable/try_transmute_ref-size-decrease.rs +0 -18
  146. data/rust-vendor/zerocopy/tests/ui-stable/try_transmute_ref-size-decrease.stderr +0 -9
  147. data/rust-vendor/zerocopy/tests/ui-stable/try_transmute_ref-size-increase.rs +0 -18
  148. data/rust-vendor/zerocopy/tests/ui-stable/try_transmute_ref-size-increase.stderr +0 -9
@@ -210,10 +210,11 @@ macro_rules! transmute {
210
210
  ///
211
211
  /// # Size compatibility
212
212
  ///
213
- /// `transmute_ref!` supports transmuting between `Sized` types or between
214
- /// unsized (i.e., `?Sized`) types. It supports any transmutation that preserves
215
- /// the number of bytes of the referent, even if doing so requires updating the
216
- /// metadata stored in an unsized "fat" reference:
213
+ /// `transmute_ref!` supports transmuting between `Sized` types, between unsized
214
+ /// (i.e., `?Sized`) types, and from a `Sized` type to an unsized type. It
215
+ /// supports any transmutation that preserves the number of bytes of the
216
+ /// referent, even if doing so requires updating the metadata stored in an
217
+ /// unsized "fat" reference:
217
218
  ///
218
219
  /// ```
219
220
  /// # use zerocopy::transmute_ref;
@@ -348,11 +349,32 @@ macro_rules! transmute_ref {
348
349
  } else {
349
350
  use $crate::util::macro_util::TransmuteRefDst;
350
351
  let t = $crate::util::macro_util::Wrap::new(e);
351
- // SAFETY: The `if false` branch ensures that:
352
- // - `Src: IntoBytes + Immutable`
353
- // - `Dst: FromBytes + Immutable`
354
- unsafe {
355
- t.transmute_ref()
352
+
353
+ if false {
354
+ // This branch exists solely to force the compiler to infer the
355
+ // type of `Dst` *before* it attempts to resolve the method call
356
+ // to `transmute_ref` in the `else` branch.
357
+ //
358
+ // Without this, if `Src` is `Sized` but `Dst` is `!Sized`, the
359
+ // compiler will eagerly select the inherent impl of
360
+ // `transmute_ref` (which requires `Dst: Sized`) because inherent
361
+ // methods take priority over trait methods. It does this before
362
+ // it realizes `Dst` is `!Sized`, leading to a compile error when
363
+ // it checks the bounds later.
364
+ //
365
+ // By calling this helper (which returns `&Dst`), we force `Dst`
366
+ // to be fully resolved. By the time it gets to the `else`
367
+ // branch, the compiler knows `Dst` is `!Sized`, properly
368
+ // disqualifies the inherent method, and falls back to the trait
369
+ // implementation.
370
+ t.transmute_ref_inference_helper()
371
+ } else {
372
+ // SAFETY: The outer `if false` branch ensures that:
373
+ // - `Src: IntoBytes + Immutable`
374
+ // - `Dst: FromBytes + Immutable`
375
+ unsafe {
376
+ t.transmute_ref()
377
+ }
356
378
  }
357
379
  }
358
380
  }}
@@ -367,8 +389,8 @@ macro_rules! transmute_ref {
367
389
  /// const fn transmute_mut<'src, 'dst, Src, Dst>(src: &'src mut Src) -> &'dst mut Dst
368
390
  /// where
369
391
  /// 'src: 'dst,
370
- /// Src: FromBytes + IntoBytes,
371
- /// Dst: FromBytes + IntoBytes,
392
+ /// Src: FromBytes + IntoBytes + ?Sized,
393
+ /// Dst: FromBytes + IntoBytes + ?Sized,
372
394
  /// align_of::<Src>() >= align_of::<Dst>(),
373
395
  /// size_compatible::<Src, Dst>(),
374
396
  /// {
@@ -383,10 +405,11 @@ macro_rules! transmute_ref {
383
405
  ///
384
406
  /// # Size compatibility
385
407
  ///
386
- /// `transmute_mut!` supports transmuting between `Sized` types or between
387
- /// unsized (i.e., `?Sized`) types. It supports any transmutation that preserves
388
- /// the number of bytes of the referent, even if doing so requires updating the
389
- /// metadata stored in an unsized "fat" reference:
408
+ /// `transmute_mut!` supports transmuting between `Sized` types, between unsized
409
+ /// (i.e., `?Sized`) types, and from a `Sized` type to an unsized type. It
410
+ /// supports any transmutation that preserves the number of bytes of the
411
+ /// referent, even if doing so requires updating the metadata stored in an
412
+ /// unsized "fat" reference:
390
413
  ///
391
414
  /// ```
392
415
  /// # use zerocopy::transmute_mut;
@@ -503,7 +526,26 @@ macro_rules! transmute_mut {
503
526
  #[allow(unused)]
504
527
  use $crate::util::macro_util::TransmuteMutDst as _;
505
528
  let t = $crate::util::macro_util::Wrap::new(e);
506
- t.transmute_mut()
529
+ if false {
530
+ // This branch exists solely to force the compiler to infer the type
531
+ // of `Dst` *before* it attempts to resolve the method call to
532
+ // `transmute_mut` in the `else` branch.
533
+ //
534
+ // Without this, if `Src` is `Sized` but `Dst` is `!Sized`, the
535
+ // compiler will eagerly select the inherent impl of `transmute_mut`
536
+ // (which requires `Dst: Sized`) because inherent methods take
537
+ // priority over trait methods. It does this before it realizes
538
+ // `Dst` is `!Sized`, leading to a compile error when it checks the
539
+ // bounds later.
540
+ //
541
+ // By calling this helper (which returns `&mut Dst`), we force `Dst`
542
+ // to be fully resolved. By the time it gets to the `else` branch,
543
+ // the compiler knows `Dst` is `!Sized`, properly disqualifies the
544
+ // inherent method, and falls back to the trait implementation.
545
+ t.transmute_mut_inference_helper()
546
+ } else {
547
+ t.transmute_mut()
548
+ }
507
549
  }}
508
550
  }
509
551
 
@@ -586,10 +628,10 @@ macro_rules! try_transmute {
586
628
  /// ```ignore
587
629
  /// fn try_transmute_ref<Src, Dst>(src: &Src) -> Result<&Dst, ValidityError<&Src, Dst>>
588
630
  /// where
589
- /// Src: IntoBytes + Immutable,
590
- /// Dst: TryFromBytes + Immutable,
591
- /// size_of::<Src>() == size_of::<Dst>(),
631
+ /// Src: IntoBytes + Immutable + ?Sized,
632
+ /// Dst: TryFromBytes + Immutable + ?Sized,
592
633
  /// align_of::<Src>() >= align_of::<Dst>(),
634
+ /// size_compatible::<Src, Dst>(),
593
635
  /// {
594
636
  /// # /*
595
637
  /// ...
@@ -597,13 +639,33 @@ macro_rules! try_transmute {
597
639
  /// }
598
640
  /// ```
599
641
  ///
600
- /// However, unlike a function, this macro can only be invoked when the types of
601
- /// `Src` and `Dst` are completely concrete. The types `Src` and `Dst` are
602
- /// inferred from the calling context; they cannot be explicitly specified in
603
- /// the macro invocation.
642
+ /// The types `Src` and `Dst` are inferred from the calling context; they cannot
643
+ /// be explicitly specified in the macro invocation.
644
+ ///
645
+ /// # Size compatibility
646
+ ///
647
+ /// `try_transmute_ref!` supports transmuting between `Sized` types, between
648
+ /// unsized (i.e., `?Sized`) types, and from a `Sized` type to an unsized type.
649
+ /// It supports any transmutation that preserves the number of bytes of the
650
+ /// referent, even if doing so requires updating the metadata stored in an
651
+ /// unsized "fat" reference:
652
+ ///
653
+ /// ```
654
+ /// # use zerocopy::try_transmute_ref;
655
+ /// # use core::mem::size_of_val; // Not in the prelude on our MSRV
656
+ /// let src: &[[u8; 2]] = &[[0, 1], [2, 3]][..];
657
+ /// let dst: &[u8] = try_transmute_ref!(src).unwrap();
658
+ ///
659
+ /// assert_eq!(src.len(), 2);
660
+ /// assert_eq!(dst.len(), 4);
661
+ /// assert_eq!(dst, [0, 1, 2, 3]);
662
+ /// assert_eq!(size_of_val(src), size_of_val(dst));
663
+ /// ```
604
664
  ///
605
665
  /// # Examples
606
666
  ///
667
+ /// Transmuting between `Sized` types:
668
+ ///
607
669
  /// ```
608
670
  /// # use zerocopy::*;
609
671
  /// // 0u8 → bool = false
@@ -619,67 +681,62 @@ macro_rules! try_transmute {
619
681
  /// ));
620
682
  /// ```
621
683
  ///
622
- /// # Alignment increase error message
623
- ///
624
- /// Because of limitations on macros, the error message generated when
625
- /// `try_transmute_ref!` is used to transmute from a type of lower alignment to
626
- /// a type of higher alignment is somewhat confusing. For example, the following
627
- /// code:
684
+ /// Transmuting between unsized types:
628
685
  ///
629
- /// ```compile_fail
630
- /// let increase_alignment: Result<&u16, _> = zerocopy::try_transmute_ref!(&[0u8; 2]);
631
686
  /// ```
687
+ /// # use {zerocopy::*, zerocopy_derive::*};
688
+ /// # type u16 = zerocopy::byteorder::native_endian::U16;
689
+ /// # type u32 = zerocopy::byteorder::native_endian::U32;
690
+ /// #[derive(KnownLayout, FromBytes, IntoBytes, Immutable)]
691
+ /// #[repr(C)]
692
+ /// struct SliceDst<T, U> {
693
+ /// t: T,
694
+ /// u: [U],
695
+ /// }
632
696
  ///
633
- /// ...generates the following error:
697
+ /// type Src = SliceDst<u32, u16>;
698
+ /// type Dst = SliceDst<u16, bool>;
634
699
  ///
635
- /// ```text
636
- /// error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
637
- /// --> example.rs:1:47
638
- /// |
639
- /// 1 | let increase_alignment: Result<&u16, _> = zerocopy::try_transmute_ref!(&[0u8; 2]);
640
- /// | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
641
- /// |
642
- /// = note: source type: `AlignOf<[u8; 2]>` (8 bits)
643
- /// = note: target type: `MaxAlignsOf<[u8; 2], u16>` (16 bits)
644
- /// = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `zerocopy::try_transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)/// ```
645
- /// ```
700
+ /// let src = Src::ref_from_bytes(&[0, 1, 0, 1, 0, 1, 0, 1]).unwrap();
701
+ /// let dst: &Dst = try_transmute_ref!(src).unwrap();
646
702
  ///
647
- /// This is saying that `max(align_of::<T>(), align_of::<U>()) !=
648
- /// align_of::<T>()`, which is equivalent to `align_of::<T>() <
649
- /// align_of::<U>()`.
703
+ /// assert_eq!(src.t.as_bytes(), [0, 1, 0, 1]);
704
+ /// assert_eq!(src.u.len(), 2);
705
+ /// assert_eq!(src.u.as_bytes(), [0, 1, 0, 1]);
706
+ ///
707
+ /// assert_eq!(dst.t.as_bytes(), [0, 1]);
708
+ /// assert_eq!(dst.u, [false, true, false, true, false, true]);
709
+ /// ```
650
710
  #[macro_export]
651
711
  macro_rules! try_transmute_ref {
652
712
  ($e:expr) => {{
653
- // NOTE: This must be a macro (rather than a function with trait bounds)
654
- // because there's no way, in a generic context, to enforce that two
655
- // types have the same size. `core::mem::transmute` uses compiler magic
656
- // to enforce this so long as the types are concrete.
657
-
658
713
  // Ensure that the source type is a reference or a mutable reference
659
714
  // (note that mutable references are implicitly reborrowed here).
660
715
  let e: &_ = $e;
661
716
 
662
- #[allow(unreachable_code, unused, clippy::diverging_sub_expression)]
717
+ #[allow(unused_imports)]
718
+ use $crate::util::macro_util::TryTransmuteRefDst as _;
719
+ let t = $crate::util::macro_util::Wrap::new(e);
663
720
  if false {
664
- // This branch, though never taken, ensures that `size_of::<T>() ==
665
- // size_of::<U>()` and that that `align_of::<T>() >=
666
- // align_of::<U>()`.
667
-
668
- // `t` is inferred to have type `T` because it's assigned to `e` (of
669
- // type `&T`) as `&t`.
670
- let mut t = loop {};
671
- e = &t;
672
-
673
- // `u` is inferred to have type `U` because it's used as `Ok(&u)` as
674
- // the value returned from this branch.
675
- let u;
676
-
677
- $crate::assert_size_eq!(t, u);
678
- $crate::assert_align_gt_eq!(t, u);
679
-
680
- Ok(&u)
721
+ // This branch exists solely to force the compiler to infer the type
722
+ // of `Dst` *before* it attempts to resolve the method call to
723
+ // `try_transmute_ref` in the `else` branch.
724
+ //
725
+ // Without this, if `Src` is `Sized` but `Dst` is `!Sized`, the
726
+ // compiler will eagerly select the inherent impl of
727
+ // `try_transmute_ref` (which requires `Dst: Sized`) because
728
+ // inherent methods take priority over trait methods. It does this
729
+ // before it realizes `Dst` is `!Sized`, leading to a compile error
730
+ // when it checks the bounds later.
731
+ //
732
+ // By calling this helper (which returns `&Dst`), we force `Dst`
733
+ // to be fully resolved. By the time it gets to the `else`
734
+ // branch, the compiler knows `Dst` is `!Sized`, properly
735
+ // disqualifies the inherent method, and falls back to the trait
736
+ // implementation.
737
+ Ok(t.transmute_ref_inference_helper())
681
738
  } else {
682
- $crate::util::macro_util::try_transmute_ref::<_, _>(e)
739
+ t.try_transmute_ref()
683
740
  }
684
741
  }}
685
742
  }
@@ -692,10 +749,10 @@ macro_rules! try_transmute_ref {
692
749
  /// ```ignore
693
750
  /// fn try_transmute_mut<Src, Dst>(src: &mut Src) -> Result<&mut Dst, ValidityError<&mut Src, Dst>>
694
751
  /// where
695
- /// Src: FromBytes + IntoBytes,
696
- /// Dst: TryFromBytes + IntoBytes,
697
- /// size_of::<Src>() == size_of::<Dst>(),
752
+ /// Src: FromBytes + IntoBytes + ?Sized,
753
+ /// Dst: TryFromBytes + IntoBytes + ?Sized,
698
754
  /// align_of::<Src>() >= align_of::<Dst>(),
755
+ /// size_compatible::<Src, Dst>(),
699
756
  /// {
700
757
  /// # /*
701
758
  /// ...
@@ -703,13 +760,34 @@ macro_rules! try_transmute_ref {
703
760
  /// }
704
761
  /// ```
705
762
  ///
706
- /// However, unlike a function, this macro can only be invoked when the types of
707
- /// `Src` and `Dst` are completely concrete. The types `Src` and `Dst` are
708
- /// inferred from the calling context; they cannot be explicitly specified in
709
- /// the macro invocation.
763
+ /// The types `Src` and `Dst` are inferred from the calling context; they cannot
764
+ /// be explicitly specified in the macro invocation.
765
+ ///
766
+ /// # Size compatibility
767
+ ///
768
+ /// `try_transmute_mut!` supports transmuting between `Sized` types, between
769
+ /// unsized (i.e., `?Sized`) types, and from a `Sized` type to an unsized type.
770
+ /// It supports any transmutation that preserves the number of bytes of the
771
+ /// referent, even if doing so requires updating the metadata stored in an
772
+ /// unsized "fat" reference:
773
+ ///
774
+ /// ```
775
+ /// # use zerocopy::try_transmute_mut;
776
+ /// # use core::mem::size_of_val; // Not in the prelude on our MSRV
777
+ /// let src: &mut [[u8; 2]] = &mut [[0, 1], [2, 3]][..];
778
+ /// let dst: &mut [u8] = try_transmute_mut!(src).unwrap();
779
+ ///
780
+ /// assert_eq!(dst.len(), 4);
781
+ /// assert_eq!(dst, [0, 1, 2, 3]);
782
+ /// let dst_size = size_of_val(dst);
783
+ /// assert_eq!(src.len(), 2);
784
+ /// assert_eq!(size_of_val(src), dst_size);
785
+ /// ```
710
786
  ///
711
787
  /// # Examples
712
788
  ///
789
+ /// Transmuting between `Sized` types:
790
+ ///
713
791
  /// ```
714
792
  /// # use zerocopy::*;
715
793
  /// // 0u8 → bool = false
@@ -728,67 +806,63 @@ macro_rules! try_transmute_ref {
728
806
  /// ));
729
807
  /// ```
730
808
  ///
731
- /// # Alignment increase error message
732
- ///
733
- /// Because of limitations on macros, the error message generated when
734
- /// `try_transmute_ref!` is used to transmute from a type of lower alignment to
735
- /// a type of higher alignment is somewhat confusing. For example, the following
736
- /// code:
809
+ /// Transmuting between unsized types:
737
810
  ///
738
- /// ```compile_fail
739
- /// let src = &mut [0u8; 2];
740
- /// let increase_alignment: Result<&mut u16, _> = zerocopy::try_transmute_mut!(src);
741
811
  /// ```
812
+ /// # use {zerocopy::*, zerocopy_derive::*};
813
+ /// # type u16 = zerocopy::byteorder::native_endian::U16;
814
+ /// # type u32 = zerocopy::byteorder::native_endian::U32;
815
+ /// #[derive(KnownLayout, FromBytes, IntoBytes, Immutable)]
816
+ /// #[repr(C)]
817
+ /// struct SliceDst<T, U> {
818
+ /// t: T,
819
+ /// u: [U],
820
+ /// }
742
821
  ///
743
- /// ...generates the following error:
822
+ /// type Src = SliceDst<u32, u16>;
823
+ /// type Dst = SliceDst<u16, bool>;
744
824
  ///
745
- /// ```text
746
- /// error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
747
- /// --> example.rs:2:51
748
- /// |
749
- /// 2 | let increase_alignment: Result<&mut u16, _> = zerocopy::try_transmute_mut!(src);
750
- /// | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
751
- /// |
752
- /// = note: source type: `AlignOf<[u8; 2]>` (8 bits)
753
- /// = note: target type: `MaxAlignsOf<[u8; 2], u16>` (16 bits)
754
- /// = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `zerocopy::try_transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
755
- /// ```
825
+ /// let mut bytes = [0, 1, 0, 1, 0, 1, 0, 1];
826
+ /// let src = Src::mut_from_bytes(&mut bytes).unwrap();
756
827
  ///
757
- /// This is saying that `max(align_of::<T>(), align_of::<U>()) !=
758
- /// align_of::<T>()`, which is equivalent to `align_of::<T>() <
759
- /// align_of::<U>()`.
828
+ /// assert_eq!(src.t.as_bytes(), [0, 1, 0, 1]);
829
+ /// assert_eq!(src.u.len(), 2);
830
+ /// assert_eq!(src.u.as_bytes(), [0, 1, 0, 1]);
831
+ ///
832
+ /// let dst: &Dst = try_transmute_mut!(src).unwrap();
833
+ ///
834
+ /// assert_eq!(dst.t.as_bytes(), [0, 1]);
835
+ /// assert_eq!(dst.u, [false, true, false, true, false, true]);
836
+ /// ```
760
837
  #[macro_export]
761
838
  macro_rules! try_transmute_mut {
762
839
  ($e:expr) => {{
763
- // NOTE: This must be a macro (rather than a function with trait bounds)
764
- // because there's no way, in a generic context, to enforce that two
765
- // types have the same size. `core::mem::transmute` uses compiler magic
766
- // to enforce this so long as the types are concrete.
767
-
768
840
  // Ensure that the source type is a mutable reference.
769
841
  let e: &mut _ = $e;
770
842
 
771
- #[allow(unreachable_code, unused, clippy::diverging_sub_expression)]
843
+ #[allow(unused_imports)]
844
+ use $crate::util::macro_util::TryTransmuteMutDst as _;
845
+ let t = $crate::util::macro_util::Wrap::new(e);
772
846
  if false {
773
- // This branch, though never taken, ensures that `size_of::<T>() ==
774
- // size_of::<U>()` and that that `align_of::<T>() >=
775
- // align_of::<U>()`.
776
-
777
- // `t` is inferred to have type `T` because it's assigned to `e` (of
778
- // type `&mut T`) as `&mut t`.
779
- let mut t = loop {};
780
- e = &mut t;
781
-
782
- // `u` is inferred to have type `U` because it's used as `Ok(&mut
783
- // u)` as the value returned from this branch.
784
- let u;
785
-
786
- $crate::assert_size_eq!(t, u);
787
- $crate::assert_align_gt_eq!(t, u);
788
-
789
- Ok(&mut u)
847
+ // This branch exists solely to force the compiler to infer the type
848
+ // of `Dst` *before* it attempts to resolve the method call to
849
+ // `try_transmute_mut` in the `else` branch.
850
+ //
851
+ // Without this, if `Src` is `Sized` but `Dst` is `!Sized`, the
852
+ // compiler will eagerly select the inherent impl of
853
+ // `try_transmute_mut` (which requires `Dst: Sized`) because
854
+ // inherent methods take priority over trait methods. It does this
855
+ // before it realizes `Dst` is `!Sized`, leading to a compile error
856
+ // when it checks the bounds later.
857
+ //
858
+ // By calling this helper (which returns `&Dst`), we force `Dst`
859
+ // to be fully resolved. By the time it gets to the `else`
860
+ // branch, the compiler knows `Dst` is `!Sized`, properly
861
+ // disqualifies the inherent method, and falls back to the trait
862
+ // implementation.
863
+ Ok(t.transmute_mut_inference_helper())
790
864
  } else {
791
- $crate::util::macro_util::try_transmute_mut::<_, _>(e)
865
+ t.try_transmute_mut()
792
866
  }
793
867
  }}
794
868
  }
@@ -1196,6 +1270,13 @@ mod tests {
1196
1270
  const X: &'static [[u8; 2]; 4] = transmute_ref!(&ARRAY_OF_U8S);
1197
1271
  assert_eq!(*X, ARRAY_OF_ARRAYS);
1198
1272
 
1273
+ // Test sized -> unsized transmutation.
1274
+ let array_of_u8s = [0u8, 1, 2, 3, 4, 5, 6, 7];
1275
+ let array_of_arrays = [[0, 1], [2, 3], [4, 5], [6, 7]];
1276
+ let slice_of_arrays = &array_of_arrays[..];
1277
+ let x: &[[u8; 2]] = transmute_ref!(&array_of_u8s);
1278
+ assert_eq!(x, slice_of_arrays);
1279
+
1199
1280
  // Before 1.61.0, we can't define the `const fn transmute_ref` function
1200
1281
  // that we do on and after 1.61.0.
1201
1282
  #[cfg(no_zerocopy_generic_bounds_in_const_fn_1_61_0)]
@@ -1347,6 +1428,27 @@ mod tests {
1347
1428
  #[allow(clippy::useless_transmute)]
1348
1429
  let y: Result<&u8, _> = try_transmute_ref!(&mut x);
1349
1430
  assert_eq!(y, Ok(&0));
1431
+
1432
+ // Test that sized types work which don't implement `KnownLayout`.
1433
+ let array_of_nkl_u8s = Nkl([0u8, 1, 2, 3, 4, 5, 6, 7]);
1434
+ let array_of_nkl_arrays = Nkl([[0, 1], [2, 3], [4, 5], [6, 7]]);
1435
+ let x: Result<&Nkl<[[u8; 2]; 4]>, _> = try_transmute_ref!(&array_of_nkl_u8s);
1436
+ assert_eq!(x, Ok(&array_of_nkl_arrays));
1437
+
1438
+ // Test sized -> unsized transmutation.
1439
+ let array_of_u8s = [0u8, 1, 2, 3, 4, 5, 6, 7];
1440
+ let array_of_arrays = [[0, 1], [2, 3], [4, 5], [6, 7]];
1441
+ let slice_of_arrays = &array_of_arrays[..];
1442
+ let x: Result<&[[u8; 2]], _> = try_transmute_ref!(&array_of_u8s);
1443
+ assert_eq!(x, Ok(slice_of_arrays));
1444
+
1445
+ // Test unsized -> unsized transmutation.
1446
+ let slice_dst_of_u8s =
1447
+ SliceDst::<U16, [u8; 2]>::ref_from_bytes(&[0, 1, 2, 3, 4, 5][..]).unwrap();
1448
+ let slice_dst_of_u16s =
1449
+ SliceDst::<U16, U16>::ref_from_bytes(&[0, 1, 2, 3, 4, 5][..]).unwrap();
1450
+ let x: Result<&SliceDst<U16, U16>, _> = try_transmute_ref!(slice_dst_of_u8s);
1451
+ assert_eq!(x, Ok(slice_dst_of_u16s));
1350
1452
  }
1351
1453
 
1352
1454
  #[test]
@@ -1382,6 +1484,27 @@ mod tests {
1382
1484
  #[allow(clippy::useless_transmute)]
1383
1485
  let y: Result<&mut u8, _> = try_transmute_mut!(&mut x);
1384
1486
  assert_eq!(y, Ok(&mut 0));
1487
+
1488
+ // Test that sized types work which don't implement `KnownLayout`.
1489
+ let mut array_of_nkl_u8s = Nkl([0u8, 1, 2, 3, 4, 5, 6, 7]);
1490
+ let mut array_of_nkl_arrays = Nkl([[0, 1], [2, 3], [4, 5], [6, 7]]);
1491
+ let x: Result<&mut Nkl<[[u8; 2]; 4]>, _> = try_transmute_mut!(&mut array_of_nkl_u8s);
1492
+ assert_eq!(x, Ok(&mut array_of_nkl_arrays));
1493
+
1494
+ // Test sized -> unsized transmutation.
1495
+ let mut array_of_u8s = [0u8, 1, 2, 3, 4, 5, 6, 7];
1496
+ let mut array_of_arrays = [[0, 1], [2, 3], [4, 5], [6, 7]];
1497
+ let slice_of_arrays = &mut array_of_arrays[..];
1498
+ let x: Result<&mut [[u8; 2]], _> = try_transmute_mut!(&mut array_of_u8s);
1499
+ assert_eq!(x, Ok(slice_of_arrays));
1500
+
1501
+ // Test unsized -> unsized transmutation.
1502
+ let mut bytes = [0, 1, 2, 3, 4, 5, 6];
1503
+ let slice_dst_of_u8s = SliceDst::<u8, [u8; 2]>::mut_from_bytes(&mut bytes[..]).unwrap();
1504
+ let mut bytes = [0, 1, 2, 3, 4, 5, 6];
1505
+ let slice_dst_of_u16s = SliceDst::<u8, U16>::mut_from_bytes(&mut bytes[..]).unwrap();
1506
+ let x: Result<&mut SliceDst<u8, U16>, _> = try_transmute_mut!(slice_dst_of_u8s);
1507
+ assert_eq!(x, Ok(slice_dst_of_u16s));
1385
1508
  }
1386
1509
 
1387
1510
  #[test]
@@ -1445,6 +1568,13 @@ mod tests {
1445
1568
  let slice_dst_small = SliceDst::<U16, u8>::mut_from_bytes(&mut bytes[..]).unwrap();
1446
1569
  let x: &mut SliceDst<U16, u8> = transmute_mut!(slice_dst_big);
1447
1570
  assert_eq!(x, slice_dst_small);
1571
+
1572
+ // Test sized -> unsized transmutation.
1573
+ let mut array_of_u8s = [0u8, 1, 2, 3, 4, 5, 6, 7];
1574
+ let mut array_of_arrays = [[0, 1], [2, 3], [4, 5], [6, 7]];
1575
+ let slice_of_arrays = &mut array_of_arrays[..];
1576
+ let x: &mut [[u8; 2]] = transmute_mut!(&mut array_of_u8s);
1577
+ assert_eq!(x, slice_of_arrays);
1448
1578
  }
1449
1579
 
1450
1580
  #[test]
@@ -19,7 +19,7 @@ pub use {inner::PtrInner, transmute::*};
19
19
  #[doc(hidden)]
20
20
  pub use {
21
21
  invariant::{BecauseExclusive, BecauseImmutable, Read},
22
- ptr::Ptr,
22
+ ptr::*,
23
23
  };
24
24
 
25
25
  use crate::wrappers::ReadOnly;