Remove Type::Slice from syntax tree
Slices were considered illegal in most positions except as the target of
a reference, which led to confusing code in the code generators. This
commit replaces their syntax tree representation from
Type::Ref(Type::Slice(...)) to Type::SliceRef(...).
diff --git a/syntax/check.rs b/syntax/check.rs
index fcce5d4..968f28b 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -3,7 +3,7 @@
use crate::syntax::types::TrivialReason;
use crate::syntax::{
error, ident, Api, Array, Enum, ExternFn, ExternType, Impl, Lang, Receiver, Ref, Signature,
- Slice, Struct, Ty1, Type, Types,
+ Struct, Ty1, Type, Types,
};
use proc_macro2::{Delimiter, Group, Ident, TokenStream};
use quote::{quote, ToTokens};
@@ -34,7 +34,6 @@
Type::UniquePtr(ptr) => check_type_unique_ptr(cx, ptr),
Type::CxxVector(ptr) => check_type_cxx_vector(cx, ptr),
Type::Ref(ty) => check_type_ref(cx, ty),
- Type::Slice(ty) => check_type_slice(cx, ty),
Type::Array(array) => check_type_array(cx, array),
Type::Fn(ty) => check_type_fn(cx, ty),
Type::Str(_) | Type::Void(_) | Type::SliceRefU8(_) => {}
@@ -178,13 +177,6 @@
cx.error(ty, "unsupported reference type");
}
-fn check_type_slice(cx: &mut Check, ty: &Slice) {
- cx.error(
- ty,
- "only &[u8] and &mut [u8] are supported so far, not other slice types",
- );
-}
-
fn check_type_array(cx: &mut Check, ty: &Array) {
let supported = match &ty.inner {
Type::Str(_) | Type::SliceRefU8(_) => false,
@@ -424,7 +416,7 @@
ident == CxxString || is_opaque_cxx(cx, ident) || cx.types.rust.contains(ident)
}
Type::Array(array) => is_unsized(cx, &array.inner),
- Type::CxxVector(_) | Type::Slice(_) | Type::Fn(_) | Type::Void(_) => true,
+ Type::CxxVector(_) | Type::Fn(_) | Type::Void(_) => true,
Type::RustBox(_)
| Type::RustVec(_)
| Type::UniquePtr(_)
@@ -500,7 +492,6 @@
Type::Ref(_) => "reference".to_owned(),
Type::Str(_) => "&str".to_owned(),
Type::CxxVector(_) => "C++ vector".to_owned(),
- Type::Slice(_) => "slice".to_owned(),
Type::SliceRefU8(ty) => match ty.mutable {
false => "&[u8]".to_owned(),
true => "&mut [u8]".to_owned(),
diff --git a/syntax/impls.rs b/syntax/impls.rs
index f533093..36cf3cd 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -1,4 +1,6 @@
-use crate::syntax::{Array, ExternFn, Impl, Include, Receiver, Ref, Signature, Slice, Ty1, Type};
+use crate::syntax::{
+ Array, ExternFn, Impl, Include, Receiver, Ref, Signature, SliceRef, Ty1, Type,
+};
use std::borrow::Borrow;
use std::hash::{Hash, Hasher};
use std::mem;
@@ -48,7 +50,6 @@
Type::RustVec(t) => t.hash(state),
Type::CxxVector(t) => t.hash(state),
Type::Fn(t) => t.hash(state),
- Type::Slice(t) => t.hash(state),
Type::SliceRefU8(t) => t.hash(state),
Type::Array(t) => t.hash(state),
Type::Void(_) => {}
@@ -69,7 +70,6 @@
(Type::RustVec(lhs), Type::RustVec(rhs)) => lhs == rhs,
(Type::CxxVector(lhs), Type::CxxVector(rhs)) => lhs == rhs,
(Type::Fn(lhs), Type::Fn(rhs)) => lhs == rhs,
- (Type::Slice(lhs), Type::Slice(rhs)) => lhs == rhs,
(Type::SliceRefU8(lhs), Type::SliceRefU8(rhs)) => lhs == rhs,
(Type::Void(_), Type::Void(_)) => true,
(_, _) => false,
@@ -154,22 +154,42 @@
}
}
-impl Eq for Slice {}
+impl Eq for SliceRef {}
-impl PartialEq for Slice {
- fn eq(&self, other: &Slice) -> bool {
- let Slice { bracket: _, inner } = self;
- let Slice {
+impl PartialEq for SliceRef {
+ fn eq(&self, other: &SliceRef) -> bool {
+ let SliceRef {
+ ampersand: _,
+ lifetime,
+ mutable,
+ bracket: _,
+ inner,
+ mutability: _,
+ } = self;
+ let SliceRef {
+ ampersand: _,
+ lifetime: lifetime2,
+ mutable: mutable2,
bracket: _,
inner: inner2,
+ mutability: _,
} = other;
- inner == inner2
+ lifetime == lifetime2 && mutable == mutable2 && inner == inner2
}
}
-impl Hash for Slice {
+impl Hash for SliceRef {
fn hash<H: Hasher>(&self, state: &mut H) {
- let Slice { bracket: _, inner } = self;
+ let SliceRef {
+ ampersand: _,
+ lifetime,
+ mutable,
+ bracket: _,
+ inner,
+ mutability: _,
+ } = self;
+ lifetime.hash(state);
+ mutable.hash(state);
inner.hash(state);
}
}
diff --git a/syntax/improper.rs b/syntax/improper.rs
index e016884..95cf4af 100644
--- a/syntax/improper.rs
+++ b/syntax/improper.rs
@@ -27,7 +27,6 @@
| Type::Str(_)
| Type::Fn(_)
| Type::Void(_)
- | Type::Slice(_)
| Type::SliceRefU8(_) => Definite(true),
Type::UniquePtr(_) | Type::CxxVector(_) => Definite(false),
Type::Ref(ty) => self.determine_improper_ctype(&ty.inner),
diff --git a/syntax/mod.rs b/syntax/mod.rs
index e61e384..c3c24ff 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -164,8 +164,7 @@
CxxVector(Box<Ty1>),
Fn(Box<Signature>),
Void(Span),
- Slice(Box<Slice>),
- SliceRefU8(Box<Ref>),
+ SliceRefU8(Box<SliceRef>),
Array(Box<Array>),
}
@@ -186,9 +185,13 @@
pub mutability: Option<Token![mut]>,
}
-pub struct Slice {
+pub struct SliceRef {
+ pub ampersand: Token![&],
+ pub lifetime: Option<Lifetime>,
+ pub mutable: bool,
pub bracket: Bracket,
pub inner: Type,
+ pub mutability: Option<Token![mut]>,
}
pub struct Array {
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 018e71a..71da158 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -4,8 +4,8 @@
use crate::syntax::Atom::*;
use crate::syntax::{
attrs, error, Api, Array, Doc, Enum, ExternFn, ExternType, Impl, Include, IncludeKind, Lang,
- Namespace, Pair, Receiver, Ref, ResolvableName, Signature, Slice, Struct, Ty1, Type, TypeAlias,
- Var, Variant,
+ Namespace, Pair, Receiver, Ref, ResolvableName, Signature, SliceRef, Struct, Ty1, Type,
+ TypeAlias, Var, Variant,
};
use proc_macro2::{Delimiter, Group, Span, TokenStream, TokenTree};
use quote::{format_ident, quote, quote_spanned};
@@ -15,7 +15,7 @@
Abi, Attribute, Error, Expr, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType,
GenericArgument, GenericParam, Generics, Ident, ItemEnum, ItemImpl, ItemStruct, Lit, LitStr,
Pat, PathArguments, Result, ReturnType, Token, Type as RustType, TypeArray, TypeBareFn,
- TypePath, TypeReference, TypeSlice,
+ TypePath, TypeReference,
};
pub mod kw {
@@ -640,7 +640,6 @@
match ty {
RustType::Reference(ty) => parse_type_reference(ty),
RustType::Path(ty) => parse_type_path(ty),
- RustType::Slice(ty) => parse_type_slice(ty),
RustType::Array(ty) => parse_type_array(ty),
RustType::BareFn(ty) => parse_type_fn(ty),
RustType::Tuple(ty) if ty.elems.is_empty() => Ok(Type::Void(ty.paren_token.span)),
@@ -649,6 +648,24 @@
}
fn parse_type_reference(ty: &TypeReference) -> Result<Type> {
+ if let RustType::Slice(slice) = ty.elem.as_ref() {
+ let inner = parse_type(&slice.elem)?;
+ return match &inner {
+ Type::Ident(ident) if ident.rust == U8 => Ok(Type::SliceRefU8(Box::new(SliceRef {
+ ampersand: ty.and_token,
+ lifetime: ty.lifetime.clone(),
+ mutable: ty.mutability.is_some(),
+ bracket: slice.bracket_token,
+ inner,
+ mutability: ty.mutability,
+ }))),
+ _ => Err(Error::new_spanned(
+ ty,
+ "only &[u8] and &mut [u8] are supported so far, not other slice types",
+ )),
+ };
+ }
+
let inner = parse_type(&ty.elem)?;
let which = match &inner {
Type::Ident(ident) if ident.rust == "str" => {
@@ -658,10 +675,6 @@
Type::Str
}
}
- Type::Slice(slice) => match &slice.inner {
- Type::Ident(ident) if ident.rust == U8 => Type::SliceRefU8,
- _ => Type::Ref,
- },
_ => Type::Ref,
};
Ok(which(Box::new(Ref {
@@ -742,14 +755,6 @@
Err(Error::new_spanned(ty, "unsupported type"))
}
-fn parse_type_slice(ty: &TypeSlice) -> Result<Type> {
- let inner = parse_type(&ty.elem)?;
- Ok(Type::Slice(Box::new(Slice {
- bracket: ty.bracket_token,
- inner,
- })))
-}
-
fn parse_type_array(ty: &TypeArray) -> Result<Type> {
let inner = parse_type(&ty.elem)?;
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 30a63d8..7b64a2d 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -1,7 +1,7 @@
use crate::syntax::atom::Atom::*;
use crate::syntax::{
Array, Atom, Derive, Enum, ExternFn, ExternType, Impl, Receiver, Ref, ResolvableName,
- Signature, Slice, Struct, Ty1, Type, TypeAlias, Var,
+ Signature, SliceRef, Struct, Ty1, Type, TypeAlias, Var,
};
use proc_macro2::{Ident, Span, TokenStream};
use quote::{quote_spanned, ToTokens};
@@ -20,11 +20,11 @@
Type::RustBox(ty) | Type::UniquePtr(ty) | Type::CxxVector(ty) | Type::RustVec(ty) => {
ty.to_tokens(tokens)
}
- Type::Ref(r) | Type::Str(r) | Type::SliceRefU8(r) => r.to_tokens(tokens),
- Type::Slice(s) => s.to_tokens(tokens),
+ Type::Ref(r) | Type::Str(r) => r.to_tokens(tokens),
Type::Array(a) => a.to_tokens(tokens),
Type::Fn(f) => f.to_tokens(tokens),
Type::Void(span) => tokens.extend(quote_spanned!(*span=> ())),
+ Type::SliceRefU8(r) => r.to_tokens(tokens),
}
}
}
@@ -69,6 +69,17 @@
}
}
+impl ToTokens for SliceRef {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ self.ampersand.to_tokens(tokens);
+ self.lifetime.to_tokens(tokens);
+ self.mutability.to_tokens(tokens);
+ self.bracket.surround(tokens, |tokens| {
+ self.inner.to_tokens(tokens);
+ });
+ }
+}
+
impl ToTokens for Array {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.bracket.surround(tokens, |tokens| {
@@ -79,14 +90,6 @@
}
}
-impl ToTokens for Slice {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- self.bracket.surround(tokens, |tokens| {
- self.inner.to_tokens(tokens);
- });
- }
-}
-
impl ToTokens for Derive {
fn to_tokens(&self, tokens: &mut TokenStream) {
Ident::new(self.as_ref(), Span::call_site()).to_tokens(tokens);
diff --git a/syntax/types.rs b/syntax/types.rs
index d59bce0..746370c 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -48,7 +48,6 @@
| Type::CxxVector(ty)
| Type::RustVec(ty) => visit(all, &ty.inner),
Type::Ref(r) => visit(all, &r.inner),
- Type::Slice(s) => visit(all, &s.inner),
Type::Array(a) => visit(all, &a.inner),
Type::Fn(f) => {
if let Some(ret) = &f.ret {