diff options
author | Nick Fitzgerald <fitzgen@gmail.com> | 2017-03-10 13:59:10 -0800 |
---|---|---|
committer | Nick Fitzgerald <fitzgen@gmail.com> | 2017-03-15 10:50:26 -0700 |
commit | 92c1a254e84f5ebe233c5731258f14d2dd32fa6b (patch) | |
tree | 65cbd71659c1d704ffbe81dc96c10c737250fa44 /src/codegen/error.rs | |
parent | 08230b7f141ed74f3a1ed2519decb6963e88679f (diff) |
Refactor fallibility of conversions from IR to Rust types
The old ToRustTy and ItemToRustTy conversion traits were problematic
in that they assumed infallibity. That assumption is problematic
because we are often dealing with C++ constructs for which Rust has no
equivalent *and* we don't have a usable layout from which to generate
an opaque blob in its stead. But, a usable layout is often "up the
stack" if only we had a way to get up there.
For example, Rust does not currently have an equivalent of const value
template parameters, and libclang will not give us a layout for
template definitions with const value template parameters. However,
libclang will give us the layout for an instantiation of such a
template definition.
First, this commit separates the concepts of generating an equivalent
Rust type from generating an opaque blob of the same size and
alignment as an IR thing. This consolidates and DRYs up a *ton* of
code involved in falling back to an opaque blob (and doing our best to
get a Layout for the blob) when we can't generate an equivalent Rust
type for some IR thing.
Second, it separates fallible and infallible conversions, and provides
a nice little framework for when to choose which. This gives us one
single place where we do this whole dance:
if could not generate equivalent Rust type:
if we have a layout:
return opaque blob based on layout
else:
return opaque blob based on a wish and a prayer
The ToRustTy trait is replaced by the TryToOpaque, ToOpaque,
TryToRustTyOrOpaque, and ToRustTyOrOpaque traits. The ItemToRustTy
helper was just a way to avoid ToRustTy's Self::Extra parameter when
it was not needed, and is simply removed without a replacement. We
suck it up and pass `&()` at call sites now. We *could* introduce
ItemTryToOpaque, ItemToOpaque, etc... traits, but the cost of the
added boiler plate would outweigh the benefits of not passing `&()` at
call sites, IMHO.
In addition to being a nice code cleanup, this also fixes #573.
Diffstat (limited to 'src/codegen/error.rs')
-rw-r--r-- | src/codegen/error.rs | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/src/codegen/error.rs b/src/codegen/error.rs new file mode 100644 index 00000000..ccb76c5b --- /dev/null +++ b/src/codegen/error.rs @@ -0,0 +1,41 @@ +use std::error; +use std::fmt; + +/// Errors that can occur during code generation. +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum Error { + /// Tried to generate an opaque blob for a type that did not have a layout. + NoLayoutForOpaqueBlob, + + /// Tried to instantiate an opaque template definition, or a template + /// definition that is too difficult for us to understand (like a partial + /// template specialization). + InstantiationOfOpaqueType, +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", error::Error::description(self)) + } +} + +impl error::Error for Error { + fn cause(&self) -> Option<&error::Error> { + None + } + + fn description(&self) -> &'static str { + match *self { + Error::NoLayoutForOpaqueBlob => { + "Tried to generate an opaque blob, but had no layout" + } + Error::InstantiationOfOpaqueType => { + "Instantiation of opaque template type or partial template \ + specialization" + } + } + } +} + +/// A `Result` of `T` or an error of `bindgen::codegen::error::Error`. +pub type Result<T> = ::std::result::Result<T, Error>; |