Enforce that extern shared structs are declared unsafe
diff --git a/syntax/check.rs b/syntax/check.rs
index 5980f75..f823964 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -167,16 +167,22 @@
}
fn check_api_struct(cx: &mut Check, strct: &Struct) {
- check_reserved_name(cx, &strct.ident);
+ let ident = &strct.ident;
+ check_reserved_name(cx, ident);
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(&strct.ident) {
- let span = span_for_struct_error(strct);
- cx.error(span, "extern C++ structs are not implemented yet");
+ if cx.types.cxx.contains(ident) {
+ if let Some(ety) = cx.types.untrusted.get(ident) {
+ let msg = "extern shared struct must be declared in an `unsafe extern` block";
+ cx.error(ety, msg);
+ } else {
+ let span = span_for_struct_error(strct);
+ cx.error(span, "extern C++ structs are not implemented yet");
+ }
}
for field in &strct.fields {
diff --git a/syntax/types.rs b/syntax/types.rs
index 533ea48..8a86a46 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -1,7 +1,7 @@
use crate::syntax::atom::Atom::{self, *};
use crate::syntax::report::Errors;
use crate::syntax::set::OrderedSet as Set;
-use crate::syntax::{Api, Derive, Enum, Struct, Type, TypeAlias};
+use crate::syntax::{Api, Derive, Enum, ExternType, Struct, Type, TypeAlias};
use proc_macro2::Ident;
use quote::ToTokens;
use std::collections::{BTreeMap as Map, HashSet as UnorderedSet};
@@ -13,7 +13,7 @@
pub cxx: Set<&'a Ident>,
pub rust: Set<&'a Ident>,
pub aliases: Map<&'a Ident, &'a TypeAlias>,
- pub trusted: Set<&'a Ident>,
+ pub untrusted: Map<&'a Ident, &'a ExternType>,
}
impl<'a> Types<'a> {
@@ -24,7 +24,7 @@
let mut cxx = Set::new();
let mut rust = Set::new();
let mut aliases = Map::new();
- let mut trusted = Set::new();
+ let mut untrusted = Map::new();
fn visit<'a>(all: &mut Set<&'a Type>, ty: &'a Type) {
all.insert(ty);
@@ -101,8 +101,8 @@
duplicate_name(cx, ety, ident);
}
cxx.insert(ident);
- if ety.trusted {
- trusted.insert(ident);
+ if !ety.trusted {
+ untrusted.insert(ident, ety);
}
}
Api::RustType(ety) => {
@@ -142,7 +142,7 @@
cxx,
rust,
aliases,
- trusted,
+ untrusted,
}
}