Skip to main content

teeny_cuda/
errors.rs

1/*
2 * Copyright (c) 2026 Teenygrad.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *   http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17use crate::cuda;
18
19/// `teeny-cuda`'s result alias.
20pub type Result<T> = anyhow::Result<T>;
21
22/// Errors produced by `teeny-cuda`.
23#[derive(thiserror::Error, Debug)]
24pub enum Error {
25    /// No CUDA-capable device/driver was found.
26    #[error("CUDA not available")]
27    CudaNotAvailable,
28
29    /// A CUDA runtime/driver API call failed.
30    #[error("CUDA error: {code} ({message})")]
31    CudaError {
32        /// The CUDA error code.
33        code: cuda::cudaError_enum,
34        /// The human-readable message from `cudaGetErrorString`.
35        message: String,
36    },
37
38    /// A capability string didn't match any known GPU architecture.
39    #[error("Unknown capability: {0}")]
40    UnknownCapability(String),
41
42    /// A Rust string contained an interior NUL byte and couldn't convert to a C string.
43    #[error("CString error: {0}")]
44    CStringError(std::ffi::NulError),
45
46    /// `nvptxcompiler` failed to compile PTX.
47    #[error("NVPTX Compile error {code}: {log}")]
48    NvptxCompileError {
49        /// The `nvptxcompiler` result code.
50        code: cuda::nvPTXCompileResult,
51        /// The compiler's error log.
52        log: String,
53    },
54
55    /// A source buffer had more elements than the destination buffer could hold.
56    #[error("buffer overflow: source has {src} elements but buffer holds {buf}")]
57    BufferOverflow {
58        /// Number of elements in the source.
59        src: usize,
60        /// Capacity of the destination buffer.
61        buf: usize,
62    },
63
64    /// A `--options`-style compiler options string ([`crate::compiler::options::Options::parse`])
65    /// was malformed.
66    #[error("invalid compiler options '{input}': {reason}")]
67    InvalidOptions {
68        /// The original, unparsed options string.
69        input: String,
70        /// Why parsing failed.
71        reason: String,
72    },
73}
74
75impl Error {
76    /// Builds a [`Error::CudaError`] from a raw CUDA error code, looking up its message via
77    /// `cudaGetErrorString`.
78    pub fn from_cuda_error(code: cuda::cudaError_enum) -> Self {
79        // SAFETY: cudaGetErrorString returns a valid C string for any cudaError_enum value.
80        let err_str = unsafe {
81            let ptr = cuda::cudaGetErrorString(code);
82            if ptr.is_null() {
83                "<unknown CUDA error>"
84            } else {
85                std::ffi::CStr::from_ptr(ptr)
86                    .to_str()
87                    .unwrap_or("<invalid utf8 CUDA error>")
88            }
89        }
90        .to_owned();
91
92        Error::CudaError {
93            code,
94            message: err_str,
95        }
96    }
97}