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:
Emilio Cobos Álvarez
2020-08-14 22:13:28 +02:00
parent 6b4181540c
commit d652d29ae2
17 changed files with 287 additions and 23 deletions
+27 -11
View File
@@ -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);
}
}
+7 -3
View File
@@ -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!(
+1 -1
View File
@@ -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"]);
+28
View File
@@ -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);
+36
View File
@@ -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
+2 -2
View File
@@ -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>>;
+1 -1
View File
@@ -3,7 +3,7 @@
#include <cstdlib>
#include <new>
template<typename T>
template<typename T = void>
struct Bar;
template<typename T>
+1 -1
View File
@@ -3,7 +3,7 @@
#include <cstdlib>
#include <new>
template<typename T>
template<typename T = void>
struct Bar;
template<typename T>
+28
View File
@@ -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);
+36
View File
@@ -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
+33
View File
@@ -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 -3
View File
@@ -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" {
+1 -1
View File
@@ -5,7 +5,7 @@
#include <cstdlib>
#include <new>
template<typename T>
template<typename T = void>
struct Box;
struct Opaque;
+28
View File
@@ -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);
+36
View File
@@ -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
+10
View File
@@ -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) {}
+9
View File
@@ -0,0 +1,9 @@
header = """
#ifdef __cplusplus
// These could be added as opaque types I guess.
template <typename T>
struct BuildHasherDefault;
struct DefaultHasher;
#endif
"""