1414
1515HIDDEN_NAMESPACE_BEGIN (torch, stable, detail)
1616
17+ // Helper variable templates to detect 2.10+ types for better compile-time error
18+ // messages
19+ template <typename T>
20+ inline constexpr bool is_header_only_array_ref_v = false;
21+
22+ template <typename T>
23+ inline constexpr bool
24+ is_header_only_array_ref_v<torch::headeronly::HeaderOnlyArrayRef<T>> = true ;
25+
26+ template <typename T>
27+ inline constexpr bool is_std_vector_v = false ;
28+
29+ template <typename T>
30+ inline constexpr bool is_std_vector_v<std::vector<T>> = true ;
31+
1732// forward declare so that the from/to() implementations in the detail
1833// namespace of library.h where the real work is done can compile.
1934template <typename T>
@@ -35,6 +50,17 @@ struct FromImpl {
3550 T val,
3651 [[maybe_unused]] uint64_t extension_build_version,
3752 [[maybe_unused]] bool is_internal) {
53+ // Ensure 2.10+ types don't accidentally use the base case - provide clear
54+ // compile-time errors.
55+ static_assert (
56+ !std::is_same_v<T, torch::stable::Device>,
57+ " torch::stable::Device requires TORCH_FEATURE_VERSION >= TORCH_VERSION_2_10_0" );
58+ static_assert (
59+ !is_header_only_array_ref_v<T>,
60+ " HeaderOnlyArrayRef<T> requires TORCH_FEATURE_VERSION >= TORCH_VERSION_2_10_0" );
61+ static_assert (
62+ !is_std_vector_v<T>,
63+ " std::vector<T> requires TORCH_FEATURE_VERSION >= TORCH_VERSION_2_10_0" );
3864 static_assert (
3965 sizeof (T) <= sizeof (StableIValue),
4066 " StableLibrary stack does not support parameter types larger than 64 bits." );
@@ -126,6 +152,18 @@ struct FromImpl<ScalarType> {
126152 }
127153};
128154
155+ // [Note DeviceType version guard]
156+ // This conversion was introduced in 2.10. However, we do not gate it
157+ // with TORCH_FEATURE_VERSION >= TORCH_VERSION_2_10_0 because this
158+ // conversion is not actually used to pass DeviceType between user
159+ // extensions and libtorch (i.e. there is no c10::TypeKind::DeviceType).
160+ // The purpose of gating other conversions is to ensure that user
161+ // extensions do not try to pass a StableIValue that libtorch is
162+ // unable to interpret.
163+ // This conversion is only used
164+ // (1) In the conversion for torch::stable::Device (already gated)
165+ // (2) Within the user extension to translate between libtorch/extension's
166+ // DeviceType (no gating needed)
129167// Specialization for torch::headeronly::DeviceType => StableIValue
130168// Note that we call into the shim to translate between the user's
131169// DeviceType and libtorch's DeviceType, which can be different!
@@ -225,6 +263,11 @@ struct FromImpl<torch::stable::Tensor> {
225263 }
226264};
227265
266+ // =============================================================================
267+ // FROM CONVERSIONS requiring TORCH_FEATURE_VERSION >= TORCH_VERSION_2_10_0
268+ // =============================================================================
269+ #if TORCH_FEATURE_VERSION >= TORCH_VERSION_2_10_0
270+
228271// Specialization for torch::headeronly::HeaderOnlyArrayRef<T> => StableIValue
229272// Returns a new owning reference of the underlying list.
230273template <typename T>
@@ -287,6 +330,8 @@ struct FromImpl<torch::stable::Device> {
287330 }
288331};
289332
333+ #endif // TORCH_FEATURE_VERSION >= TORCH_VERSION_2_10_0
334+
290335// =============================================================================
291336// TO CONVERSIONS (StableIValue -> T)
292337// =============================================================================
@@ -299,6 +344,17 @@ struct ToImpl {
299344 [[maybe_unused]] uint64_t extension_build_version,
300345 [[maybe_unused]] bool is_internal) {
301346 static_assert (std::is_trivially_copyable_v<T>);
347+ // Ensure 2.10+ types don't accidentally use the base case - provide clear
348+ // compile-time errors.
349+ static_assert (
350+ !std::is_same_v<T, torch::stable::Device>,
351+ " torch::stable::Device requires TORCH_FEATURE_VERSION >= TORCH_VERSION_2_10_0" );
352+ static_assert (
353+ !is_header_only_array_ref_v<T>,
354+ " HeaderOnlyArrayRef<T> requires TORCH_FEATURE_VERSION >= TORCH_VERSION_2_10_0" );
355+ static_assert (
356+ !is_std_vector_v<T>,
357+ " std::vector<T> requires TORCH_FEATURE_VERSION >= TORCH_VERSION_2_10_0" );
302358 // T may not have a default constructor. (For example, it might be
303359 // c10::Device.) However, std::memcpy implicitly creates a T at the
304360 // destination. So, we can use a union to work around this lack of
@@ -387,6 +443,7 @@ struct ToImpl<ScalarType> {
387443 }
388444};
389445
446+ // See [Note DeviceType version guard]
390447// Specialization for StableIValue => torch::headeronly::DeviceType
391448template <>
392449struct ToImpl <DeviceType> {
@@ -467,6 +524,11 @@ struct ToImpl<torch::stable::Tensor> {
467524 }
468525};
469526
527+ // =============================================================================
528+ // TO CONVERSIONS requiring TORCH_FEATURE_VERSION >= TORCH_VERSION_2_10_0
529+ // =============================================================================
530+ #if TORCH_FEATURE_VERSION >= TORCH_VERSION_2_10_0
531+
470532// Specialization for StableIValue => std::vector<T>
471533// std::vector<T> should be represented as a StableListHandle
472534// filled with StableIValues
@@ -517,6 +579,8 @@ struct ToImpl<torch::stable::Device> {
517579 }
518580};
519581
582+ #endif // TORCH_FEATURE_VERSION >= TORCH_VERSION_2_10_0
583+
520584// =============================================================================
521585// end to helpers for converting between StableIValue and T
522586// =============================================================================
0 commit comments