Skip to content

Commit c8c590e

Browse files
committed
fixup! feat(core.utils): special-case include_path/pre_include in _option_is_set
1 parent 2d29e04 commit c8c590e

File tree

2 files changed

+31
-16
lines changed

2 files changed

+31
-16
lines changed

cuda_core/cuda/core/utils/_program_cache.py

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -304,31 +304,38 @@ def _cuda_core_version() -> str:
304304

305305

306306
# ProgramOptions fields gated by plain truthiness in ``_program.pyx`` (the
307-
# compiler writes the flag only when the value is truthy). For every other
308-
# field listed in the cache-guard sets, the compiler uses ``is not None``,
309-
# so even ``False`` / ``""`` must count as set.
307+
# compiler writes the flag only when the value is truthy).
310308
_BOOLEAN_OPTION_FIELDS = frozenset({"pch"})
311309

310+
# Fields whose compiler emission requires ``isinstance(value, str)`` or a
311+
# non-empty sequence; anything else (``False``, ``int``, ``None``, ``[]``)
312+
# is silently ignored at compile time.
313+
_STR_OR_SEQUENCE_OPTION_FIELDS = frozenset({"include_path", "pre_include"})
314+
312315

313316
def _option_is_set(options: ProgramOptions, name: str) -> bool:
314-
"""Match how ``_program.pyx`` gates option emission.
315-
316-
- For boolean flags (``pch``): value must be truthy.
317-
- For sequence-shaped fields (``include_path``, ``pre_include``): ``None``
318-
or an empty ``list``/``tuple`` counts as absent; any other value
319-
(including the empty string, which NVRTC still emits as ``--flag=``)
320-
is set.
321-
- For path/string-shaped fields (``create_pch``, ``time``,
317+
"""Match how ``_program.pyx`` gates option emission, per field shape.
318+
319+
- Boolean flags (``pch``): truthy only.
320+
- str-or-sequence fields (``include_path``, ``pre_include``): ``str``
321+
(including empty) or a non-empty ``list``/``tuple``; everything else
322+
(``False``, ``int``, empty sequence, ``None``) is ignored by the
323+
compiler and must not trigger a cache-time guard.
324+
- Path/string-shaped fields (``create_pch``, ``time``,
322325
``fdevice_time_trace``, ``use_pch``, ``pch_dir``): ``is not None`` --
323326
the compiler emits ``--flag=<value>`` for any non-None value, so
324-
``False``/``""``/``0`` must still count as set.
327+
``False`` / ``""`` / ``0`` must still count as set.
325328
"""
326329
value = getattr(options, name, None)
327330
if value is None:
328331
return False
329332
if name in _BOOLEAN_OPTION_FIELDS:
330333
return bool(value)
331-
return not (isinstance(value, (list, tuple)) and len(value) == 0)
334+
if name in _STR_OR_SEQUENCE_OPTION_FIELDS:
335+
if isinstance(value, str):
336+
return True
337+
return isinstance(value, (list, tuple)) and len(value) > 0
338+
return True
332339

333340

334341
def make_program_cache_key(

cuda_core/tests/test_program_cache.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -437,11 +437,14 @@ def _flaky_replace(src, dst):
437437
pytest.param({"use_pch": ""}, id="use_pch_empty_string"),
438438
pytest.param({"pch_dir": ""}, id="pch_dir_empty_string"),
439439
pytest.param({"pre_include": ""}, id="pre_include_empty_string"),
440-
# Same for ``False`` -- NVRTC's gate on these path-shaped fields is
441-
# ``is not None``, so even False emits a real flag.
440+
# For path-shaped fields (``use_pch``, ``pch_dir``), NVRTC's gate is
441+
# ``is not None``, so even False emits a real flag and must be caught.
442442
pytest.param({"use_pch": False}, id="use_pch_false"),
443443
pytest.param({"pch_dir": False}, id="pch_dir_false"),
444-
pytest.param({"pre_include": False}, id="pre_include_false"),
444+
# ``include_path`` / ``pre_include`` are NOT in that group: the
445+
# compiler only emits them for str or non-empty sequences, so
446+
# ``False`` is silently ignored at compile time -- test the accept
447+
# path below, not the reject path.
445448
],
446449
)
447450
def test_make_program_cache_key_rejects_external_content_without_extra_digest(option_kw):
@@ -458,6 +461,11 @@ def test_make_program_cache_key_rejects_external_content_without_extra_digest(op
458461
pytest.param({"include_path": []}, id="include_path_empty_list"),
459462
pytest.param({"include_path": ()}, id="include_path_empty_tuple"),
460463
pytest.param({"pre_include": []}, id="pre_include_empty_list"),
464+
# ``_prepare_nvrtc_options_impl`` only emits include_path / pre_include
465+
# for str or non-empty sequence, so False (or any non-str non-sequence)
466+
# is silently ignored at compile time and must not trip the guard.
467+
pytest.param({"include_path": False}, id="include_path_false"),
468+
pytest.param({"pre_include": False}, id="pre_include_false"),
461469
],
462470
)
463471
def test_make_program_cache_key_accepts_empty_external_content(option_kw):

0 commit comments

Comments
 (0)