Skip to content

Commit 4bc1336

Browse files
author
bors-servo
authored
Auto merge of #581 - fitzgen:issue-573-even-more-spidermonkey-layout-test-failures, r=emilio
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. r? @emilio
2 parents 08230b7 + 92c1a25 commit 4bc1336

File tree

6 files changed

+418
-150
lines changed

6 files changed

+418
-150
lines changed

build.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ mod codegen {
1010

1111
quasi_codegen::expand(&src, &dst).unwrap();
1212
println!("cargo:rerun-if-changed=src/codegen/mod.rs");
13+
println!("cargo:rerun-if-changed=src/codegen/error.rs");
1314
println!("cargo:rerun-if-changed=src/codegen/helpers.rs");
1415
println!("cargo:rerun-if-changed=src/codegen/struct_layout.rs");
1516
}

src/codegen/error.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
use std::error;
2+
use std::fmt;
3+
4+
/// Errors that can occur during code generation.
5+
#[derive(Clone, Debug, PartialEq, Eq)]
6+
pub enum Error {
7+
/// Tried to generate an opaque blob for a type that did not have a layout.
8+
NoLayoutForOpaqueBlob,
9+
10+
/// Tried to instantiate an opaque template definition, or a template
11+
/// definition that is too difficult for us to understand (like a partial
12+
/// template specialization).
13+
InstantiationOfOpaqueType,
14+
}
15+
16+
impl fmt::Display for Error {
17+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
18+
write!(f, "{}", error::Error::description(self))
19+
}
20+
}
21+
22+
impl error::Error for Error {
23+
fn cause(&self) -> Option<&error::Error> {
24+
None
25+
}
26+
27+
fn description(&self) -> &'static str {
28+
match *self {
29+
Error::NoLayoutForOpaqueBlob => {
30+
"Tried to generate an opaque blob, but had no layout"
31+
}
32+
Error::InstantiationOfOpaqueType => {
33+
"Instantiation of opaque template type or partial template \
34+
specialization"
35+
}
36+
}
37+
}
38+
}
39+
40+
/// A `Result` of `T` or an error of `bindgen::codegen::error::Error`.
41+
pub type Result<T> = ::std::result::Result<T, Error>;

0 commit comments

Comments
 (0)