Allow namespace override.
This change allows a
#[namespace (namespace = A::B)]
attribute for each item in a cxx::bridge.
We now have a fair number of different types of name floating
around:
* C++ identifiers
* C++ fully-qualified names
* Rust identifiers
* Rust fully-qualified names (future, when we support sub-modules)
* Items with both a Rust and C++ name (a 'Pair')
* Types with only a known Rust name, which can be resolved to a
C++ name.
This change attempts to put some sensible names for all these
things in syntax/mod.rs, and so that would be a good place to start
review.
At the moment, the Namespace (included in each CppName)
is ruthlessly cloned all over the place. As a given namespace is
likely to be applicable to many types and functions, it may
save significant memory in future to use Rc<> here. But let's not
optimise too early.
diff --git a/syntax/check.rs b/syntax/check.rs
index ced1570..9aba9ac 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -1,5 +1,4 @@
use crate::syntax::atom::Atom::{self, *};
-use crate::syntax::namespace::Namespace;
use crate::syntax::report::Errors;
use crate::syntax::types::TrivialReason;
use crate::syntax::{
@@ -11,15 +10,13 @@
use std::fmt::Display;
pub(crate) struct Check<'a> {
- namespace: &'a Namespace,
apis: &'a [Api],
types: &'a Types<'a>,
errors: &'a mut Errors,
}
-pub(crate) fn typecheck(cx: &mut Errors, namespace: &Namespace, apis: &[Api], types: &Types) {
+pub(crate) fn typecheck(cx: &mut Errors, apis: &[Api], types: &Types) {
do_typecheck(&mut Check {
- namespace,
apis,
types,
errors: cx,
@@ -27,11 +24,11 @@
}
fn do_typecheck(cx: &mut Check) {
- ident::check_all(cx, cx.namespace, cx.apis);
+ ident::check_all(cx, cx.apis);
for ty in cx.types {
match ty {
- Type::Ident(ident) => check_type_ident(cx, ident),
+ Type::Ident(ident) => check_type_ident(cx, &ident.rust),
Type::RustBox(ptr) => check_type_box(cx, ptr),
Type::RustVec(ty) => check_type_rust_vec(cx, ty),
Type::UniquePtr(ptr) => check_type_unique_ptr(cx, ptr),
@@ -67,20 +64,20 @@
&& !cx.types.cxx.contains(ident)
&& !cx.types.rust.contains(ident)
{
- cx.error(ident, &format!("unsupported type: {}", ident));
+ cx.error(ident, &format!("unsupported type: {}", ident.to_string()));
}
}
fn check_type_box(cx: &mut Check, ptr: &Ty1) {
if let Type::Ident(ident) = &ptr.inner {
- if cx.types.cxx.contains(ident)
- && !cx.types.structs.contains_key(ident)
- && !cx.types.enums.contains_key(ident)
+ if cx.types.cxx.contains(&ident.rust)
+ && !cx.types.structs.contains_key(&ident.rust)
+ && !cx.types.enums.contains_key(&ident.rust)
{
cx.error(ptr, error::BOX_CXX_TYPE.msg);
}
- if Atom::from(ident).is_none() {
+ if Atom::from(&ident.rust).is_none() {
return;
}
}
@@ -90,15 +87,15 @@
fn check_type_rust_vec(cx: &mut Check, ty: &Ty1) {
if let Type::Ident(ident) = &ty.inner {
- if cx.types.cxx.contains(ident)
- && !cx.types.structs.contains_key(ident)
- && !cx.types.enums.contains_key(ident)
+ if cx.types.cxx.contains(&ident.rust)
+ && !cx.types.structs.contains_key(&ident.rust)
+ && !cx.types.enums.contains_key(&ident.rust)
{
cx.error(ty, "Rust Vec containing C++ type is not supported yet");
return;
}
- match Atom::from(ident) {
+ match Atom::from(&ident.rust) {
None | Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(Usize) | Some(I8)
| Some(I16) | Some(I32) | Some(I64) | Some(Isize) | Some(F32) | Some(F64)
| Some(RustString) => return,
@@ -112,11 +109,11 @@
fn check_type_unique_ptr(cx: &mut Check, ptr: &Ty1) {
if let Type::Ident(ident) = &ptr.inner {
- if cx.types.rust.contains(ident) {
+ if cx.types.rust.contains(&ident.rust) {
cx.error(ptr, "unique_ptr of a Rust type is not supported yet");
}
- match Atom::from(ident) {
+ match Atom::from(&ident.rust) {
None | Some(CxxString) => return,
_ => {}
}
@@ -129,14 +126,14 @@
fn check_type_cxx_vector(cx: &mut Check, ptr: &Ty1) {
if let Type::Ident(ident) = &ptr.inner {
- if cx.types.rust.contains(ident) {
+ if cx.types.rust.contains(&ident.rust) {
cx.error(
ptr,
"C++ vector containing a Rust type is not supported yet",
);
}
- match Atom::from(ident) {
+ match Atom::from(&ident.rust) {
None | Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(Usize) | Some(I8)
| Some(I16) | Some(I32) | Some(I64) | Some(Isize) | Some(F32) | Some(F64)
| Some(CxxString) => return,
@@ -170,15 +167,15 @@
fn check_api_struct(cx: &mut Check, strct: &Struct) {
let ident = &strct.ident;
- check_reserved_name(cx, ident);
+ check_reserved_name(cx, &ident.rust);
if strct.fields.is_empty() {
let span = span_for_struct_error(strct);
cx.error(span, "structs without any fields are not supported");
}
- if cx.types.cxx.contains(ident) {
- if let Some(ety) = cx.types.untrusted.get(ident) {
+ if cx.types.cxx.contains(&ident.rust) {
+ if let Some(ety) = cx.types.untrusted.get(&ident.rust) {
let msg = "extern shared struct must be declared in an `unsafe extern` block";
cx.error(ety, msg);
}
@@ -200,7 +197,7 @@
}
fn check_api_enum(cx: &mut Check, enm: &Enum) {
- check_reserved_name(cx, &enm.ident);
+ check_reserved_name(cx, &enm.ident.rust);
if enm.variants.is_empty() {
let span = span_for_enum_error(enm);
@@ -209,11 +206,13 @@
}
fn check_api_type(cx: &mut Check, ety: &ExternType) {
- check_reserved_name(cx, &ety.ident);
+ check_reserved_name(cx, &ety.ident.rust);
- if let Some(reason) = cx.types.required_trivial.get(&ety.ident) {
+ if let Some(reason) = cx.types.required_trivial.get(&ety.ident.rust) {
let what = match reason {
- TrivialReason::StructField(strct) => format!("a field of `{}`", strct.ident),
+ TrivialReason::StructField(strct) => {
+ format!("a field of `{}`", strct.ident.cxx.to_fully_qualified())
+ }
TrivialReason::FunctionArgument(efn) => format!("an argument of `{}`", efn.ident.rust),
TrivialReason::FunctionReturn(efn) => format!("a return value of `{}`", efn.ident.rust),
};
@@ -229,7 +228,7 @@
if let Some(receiver) = &efn.receiver {
let ref span = span_for_receiver_error(receiver);
- if receiver.ty == "Self" {
+ if receiver.ty.is_self() {
let mutability = match receiver.mutability {
Some(_) => "mut ",
None => "",
@@ -241,9 +240,9 @@
mutability = mutability,
);
cx.error(span, msg);
- } else if !cx.types.structs.contains_key(&receiver.ty)
- && !cx.types.cxx.contains(&receiver.ty)
- && !cx.types.rust.contains(&receiver.ty)
+ } else if !cx.types.structs.contains_key(&receiver.ty.rust)
+ && !cx.types.cxx.contains(&receiver.ty.rust)
+ && !cx.types.rust.contains(&receiver.ty.rust)
{
cx.error(span, "unrecognized receiver type");
}
@@ -290,7 +289,7 @@
fn check_api_impl(cx: &mut Check, imp: &Impl) {
if let Type::UniquePtr(ty) | Type::CxxVector(ty) = &imp.ty {
if let Type::Ident(inner) = &ty.inner {
- if Atom::from(inner).is_none() {
+ if Atom::from(&inner.rust).is_none() {
return;
}
}
@@ -357,7 +356,7 @@
fn is_unsized(cx: &mut Check, ty: &Type) -> bool {
let ident = match ty {
- Type::Ident(ident) => ident,
+ Type::Ident(ident) => &ident.rust,
Type::CxxVector(_) | Type::Slice(_) | Type::Void(_) => return true,
_ => return false,
};
@@ -400,20 +399,20 @@
fn describe(cx: &mut Check, ty: &Type) -> String {
match ty {
Type::Ident(ident) => {
- if cx.types.structs.contains_key(ident) {
+ if cx.types.structs.contains_key(&ident.rust) {
"struct".to_owned()
- } else if cx.types.enums.contains_key(ident) {
+ } else if cx.types.enums.contains_key(&ident.rust) {
"enum".to_owned()
- } else if cx.types.aliases.contains_key(ident) {
+ } else if cx.types.aliases.contains_key(&ident.rust) {
"C++ type".to_owned()
- } else if cx.types.cxx.contains(ident) {
+ } else if cx.types.cxx.contains(&ident.rust) {
"opaque C++ type".to_owned()
- } else if cx.types.rust.contains(ident) {
+ } else if cx.types.rust.contains(&ident.rust) {
"opaque Rust type".to_owned()
- } else if Atom::from(ident) == Some(CxxString) {
+ } else if Atom::from(&ident.rust) == Some(CxxString) {
"C++ string".to_owned()
} else {
- ident.to_string()
+ ident.rust.to_string()
}
}
Type::RustBox(_) => "Box".to_owned(),