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}