ir: Be less strict when instantiating opaque types.
There are two situations where we can legitimately end up with a different number of template params. Fixes #532. Fixes #527.
This commit is contained in:
@@ -27,6 +27,32 @@ impl GenericParams {
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
|
||||
fn write_internal<F: Write>(
|
||||
&self,
|
||||
config: &Config,
|
||||
out: &mut SourceWriter<F>,
|
||||
with_default: bool,
|
||||
) {
|
||||
if !self.0.is_empty() && config.language == Language::Cxx {
|
||||
out.write("template<");
|
||||
for (i, item) in self.0.iter().enumerate() {
|
||||
if i != 0 {
|
||||
out.write(", ");
|
||||
}
|
||||
write!(out, "typename {}", item);
|
||||
if with_default {
|
||||
write!(out, " = void");
|
||||
}
|
||||
}
|
||||
out.write(">");
|
||||
out.new_line();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_with_default<F: Write>(&self, config: &Config, out: &mut SourceWriter<F>) {
|
||||
self.write_internal(config, out, true);
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for GenericParams {
|
||||
@@ -39,17 +65,7 @@ impl Deref for GenericParams {
|
||||
|
||||
impl Source for GenericParams {
|
||||
fn write<F: Write>(&self, config: &Config, out: &mut SourceWriter<F>) {
|
||||
if !self.0.is_empty() && config.language == Language::Cxx {
|
||||
out.write("template<");
|
||||
for (i, item) in self.0.iter().enumerate() {
|
||||
if i != 0 {
|
||||
out.write(", ");
|
||||
}
|
||||
write!(out, "typename {}", item);
|
||||
}
|
||||
out.write(">");
|
||||
out.new_line();
|
||||
}
|
||||
self.write_internal(config, out, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -105,12 +105,16 @@ impl Item for OpaqueItem {
|
||||
out: &mut Monomorphs,
|
||||
) {
|
||||
assert!(
|
||||
self.generic_params.len() > 0,
|
||||
!self.generic_params.is_empty(),
|
||||
"{} is not generic",
|
||||
self.path
|
||||
);
|
||||
|
||||
// We can be instantiated with less generic params because of default
|
||||
// template parameters, or because of empty types that we remove during
|
||||
// parsing (`()`).
|
||||
assert!(
|
||||
self.generic_params.len() == generic_values.len(),
|
||||
self.generic_params.len() >= generic_values.len(),
|
||||
"{} has {} params but is being instantiated with {} values",
|
||||
self.path,
|
||||
self.generic_params.len(),
|
||||
@@ -137,7 +141,7 @@ impl Source for OpaqueItem {
|
||||
|
||||
self.documentation.write(config, out);
|
||||
|
||||
self.generic_params.write(config, out);
|
||||
self.generic_params.write_with_default(config, out);
|
||||
|
||||
if config.style.generate_typedef() && config.language == Language::C {
|
||||
write!(
|
||||
|
||||
@@ -391,7 +391,7 @@ impl Parse {
|
||||
add_opaque("Option", vec!["T"]);
|
||||
add_opaque("NonNull", vec!["T"]);
|
||||
add_opaque("Vec", vec!["T"]);
|
||||
add_opaque("HashMap", vec!["K", "V"]);
|
||||
add_opaque("HashMap", vec!["K", "V", "Hasher"]);
|
||||
add_opaque("BTreeMap", vec!["K", "V"]);
|
||||
add_opaque("HashSet", vec!["T"]);
|
||||
add_opaque("BTreeSet", vec!["T"]);
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
#ifdef __cplusplus
|
||||
// These could be added as opaque types I guess.
|
||||
template <typename T>
|
||||
struct BuildHasherDefault;
|
||||
|
||||
struct DefaultHasher;
|
||||
#endif
|
||||
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef struct HashMap_i32__i32__BuildHasherDefault_DefaultHasher HashMap_i32__i32__BuildHasherDefault_DefaultHasher;
|
||||
|
||||
typedef struct Result_Foo Result_Foo;
|
||||
|
||||
/**
|
||||
* Fast hash map used internally.
|
||||
*/
|
||||
typedef HashMap_i32__i32__BuildHasherDefault_DefaultHasher FastHashMap_i32__i32;
|
||||
|
||||
typedef FastHashMap_i32__i32 Foo;
|
||||
|
||||
typedef Result_Foo Bar;
|
||||
|
||||
void root(const Foo *a, const Bar *b);
|
||||
@@ -0,0 +1,36 @@
|
||||
#ifdef __cplusplus
|
||||
// These could be added as opaque types I guess.
|
||||
template <typename T>
|
||||
struct BuildHasherDefault;
|
||||
|
||||
struct DefaultHasher;
|
||||
#endif
|
||||
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef struct HashMap_i32__i32__BuildHasherDefault_DefaultHasher HashMap_i32__i32__BuildHasherDefault_DefaultHasher;
|
||||
|
||||
typedef struct Result_Foo Result_Foo;
|
||||
|
||||
/**
|
||||
* Fast hash map used internally.
|
||||
*/
|
||||
typedef HashMap_i32__i32__BuildHasherDefault_DefaultHasher FastHashMap_i32__i32;
|
||||
|
||||
typedef FastHashMap_i32__i32 Foo;
|
||||
|
||||
typedef Result_Foo Bar;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
void root(const Foo *a, const Bar *b);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif // __cplusplus
|
||||
@@ -3,10 +3,10 @@
|
||||
#include <cstdlib>
|
||||
#include <new>
|
||||
|
||||
template<typename T>
|
||||
template<typename T = void>
|
||||
struct NotReprC;
|
||||
|
||||
template<typename T>
|
||||
template<typename T = void>
|
||||
struct RefCell;
|
||||
|
||||
using Foo = NotReprC<RefCell<int32_t>>;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include <cstdlib>
|
||||
#include <new>
|
||||
|
||||
template<typename T>
|
||||
template<typename T = void>
|
||||
struct Bar;
|
||||
|
||||
template<typename T>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include <cstdlib>
|
||||
#include <new>
|
||||
|
||||
template<typename T>
|
||||
template<typename T = void>
|
||||
struct Bar;
|
||||
|
||||
template<typename T>
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
#ifdef __cplusplus
|
||||
// These could be added as opaque types I guess.
|
||||
template <typename T>
|
||||
struct BuildHasherDefault;
|
||||
|
||||
struct DefaultHasher;
|
||||
#endif
|
||||
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef struct HashMap_i32__i32__BuildHasherDefault_DefaultHasher HashMap_i32__i32__BuildHasherDefault_DefaultHasher;
|
||||
|
||||
typedef struct Result_Foo Result_Foo;
|
||||
|
||||
/**
|
||||
* Fast hash map used internally.
|
||||
*/
|
||||
typedef HashMap_i32__i32__BuildHasherDefault_DefaultHasher FastHashMap_i32__i32;
|
||||
|
||||
typedef FastHashMap_i32__i32 Foo;
|
||||
|
||||
typedef Result_Foo Bar;
|
||||
|
||||
void root(const Foo *a, const Bar *b);
|
||||
@@ -0,0 +1,36 @@
|
||||
#ifdef __cplusplus
|
||||
// These could be added as opaque types I guess.
|
||||
template <typename T>
|
||||
struct BuildHasherDefault;
|
||||
|
||||
struct DefaultHasher;
|
||||
#endif
|
||||
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef struct HashMap_i32__i32__BuildHasherDefault_DefaultHasher HashMap_i32__i32__BuildHasherDefault_DefaultHasher;
|
||||
|
||||
typedef struct Result_Foo Result_Foo;
|
||||
|
||||
/**
|
||||
* Fast hash map used internally.
|
||||
*/
|
||||
typedef HashMap_i32__i32__BuildHasherDefault_DefaultHasher FastHashMap_i32__i32;
|
||||
|
||||
typedef FastHashMap_i32__i32 Foo;
|
||||
|
||||
typedef Result_Foo Bar;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
void root(const Foo *a, const Bar *b);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif // __cplusplus
|
||||
@@ -0,0 +1,33 @@
|
||||
#ifdef __cplusplus
|
||||
// These could be added as opaque types I guess.
|
||||
template <typename T>
|
||||
struct BuildHasherDefault;
|
||||
|
||||
struct DefaultHasher;
|
||||
#endif
|
||||
|
||||
|
||||
#include <cstdarg>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <new>
|
||||
|
||||
template<typename K = void, typename V = void, typename Hasher = void>
|
||||
struct HashMap;
|
||||
|
||||
template<typename T = void, typename E = void>
|
||||
struct Result;
|
||||
|
||||
/// Fast hash map used internally.
|
||||
template<typename K, typename V>
|
||||
using FastHashMap = HashMap<K, V, BuildHasherDefault<DefaultHasher>>;
|
||||
|
||||
using Foo = FastHashMap<int32_t, int32_t>;
|
||||
|
||||
using Bar = Result<Foo>;
|
||||
|
||||
extern "C" {
|
||||
|
||||
void root(const Foo *a, const Bar *b);
|
||||
|
||||
} // extern "C"
|
||||
@@ -3,15 +3,15 @@
|
||||
#include <cstdlib>
|
||||
#include <new>
|
||||
|
||||
template<typename T>
|
||||
template<typename T = void>
|
||||
struct Option;
|
||||
|
||||
template<typename T, typename E>
|
||||
template<typename T = void, typename E = void>
|
||||
struct Result;
|
||||
|
||||
struct String;
|
||||
|
||||
template<typename T>
|
||||
template<typename T = void>
|
||||
struct Vec;
|
||||
|
||||
extern "C" {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include <cstdlib>
|
||||
#include <new>
|
||||
|
||||
template<typename T>
|
||||
template<typename T = void>
|
||||
struct Box;
|
||||
|
||||
struct Opaque;
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
#ifdef __cplusplus
|
||||
// These could be added as opaque types I guess.
|
||||
template <typename T>
|
||||
struct BuildHasherDefault;
|
||||
|
||||
struct DefaultHasher;
|
||||
#endif
|
||||
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
struct HashMap_i32__i32__BuildHasherDefault_DefaultHasher;
|
||||
|
||||
struct Result_Foo;
|
||||
|
||||
/**
|
||||
* Fast hash map used internally.
|
||||
*/
|
||||
typedef struct HashMap_i32__i32__BuildHasherDefault_DefaultHasher FastHashMap_i32__i32;
|
||||
|
||||
typedef FastHashMap_i32__i32 Foo;
|
||||
|
||||
typedef struct Result_Foo Bar;
|
||||
|
||||
void root(const Foo *a, const Bar *b);
|
||||
@@ -0,0 +1,36 @@
|
||||
#ifdef __cplusplus
|
||||
// These could be added as opaque types I guess.
|
||||
template <typename T>
|
||||
struct BuildHasherDefault;
|
||||
|
||||
struct DefaultHasher;
|
||||
#endif
|
||||
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
struct HashMap_i32__i32__BuildHasherDefault_DefaultHasher;
|
||||
|
||||
struct Result_Foo;
|
||||
|
||||
/**
|
||||
* Fast hash map used internally.
|
||||
*/
|
||||
typedef struct HashMap_i32__i32__BuildHasherDefault_DefaultHasher FastHashMap_i32__i32;
|
||||
|
||||
typedef FastHashMap_i32__i32 Foo;
|
||||
|
||||
typedef struct Result_Foo Bar;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
void root(const Foo *a, const Bar *b);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif // __cplusplus
|
||||
@@ -0,0 +1,10 @@
|
||||
/// Fast hash map used internally.
|
||||
type FastHashMap<K, V> =
|
||||
std::collections::HashMap<K, V, std::hash::BuildHasherDefault<std::collections::hash_map::DefaultHasher>>;
|
||||
|
||||
pub type Foo = FastHashMap<i32, i32>;
|
||||
|
||||
pub type Bar = Result<Foo, ()>;
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn root(a: &Foo, b: &Bar) {}
|
||||
@@ -0,0 +1,9 @@
|
||||
header = """
|
||||
#ifdef __cplusplus
|
||||
// These could be added as opaque types I guess.
|
||||
template <typename T>
|
||||
struct BuildHasherDefault;
|
||||
|
||||
struct DefaultHasher;
|
||||
#endif
|
||||
"""
|
||||
Reference in New Issue
Block a user