mirror of
https://github.com/clockworklabs/SpacetimeDB.git
synced 2026-06-27 00:13:33 -04:00
Fix name collision with const index or const name colocated with #[table]
This is an old bug that isn't actually related to HTTP handlers at all, except that I encountered it while testing an HTTP handler named `index` or `name`. It's a simple enough fix that I'm slipping it in to this PR.
This commit is contained in:
@@ -1,3 +1,7 @@
|
||||
//! When editing generated code in this module, use `__`-prefixed reserved names
|
||||
//! for macro-emitted local bindings and helper items to avoid collisions with
|
||||
//! user-defined items at the expansion site.
|
||||
|
||||
extern crate core;
|
||||
extern crate proc_macro;
|
||||
|
||||
@@ -252,11 +256,13 @@ pub(crate) fn derive_satstype(ty: &SatsType<'_>) -> TokenStream {
|
||||
|
||||
#[automatically_derived]
|
||||
impl #impl_generics #krate::SpacetimeType for #name #ty_generics #where_clause {
|
||||
// __ reserved name for binding to prevent name conflicts. See module-level doc comment.
|
||||
fn make_type<S: #krate::sats::typespace::TypespaceBuilder>(__typespace: &mut S) -> #krate::sats::AlgebraicType {
|
||||
#krate::sats::typespace::TypespaceBuilder::add(
|
||||
__typespace,
|
||||
core::any::TypeId::of::<#name #typeid_ty_generics>(),
|
||||
Some(#ty_name),
|
||||
// __ reserved name for binding to prevent name conflicts. See module-level doc comment.
|
||||
|__typespace| #typ,
|
||||
)
|
||||
}
|
||||
@@ -407,6 +413,7 @@ pub(crate) fn derive_deserialize(ty: &SatsType<'_>) -> TokenStream {
|
||||
}
|
||||
}
|
||||
|
||||
// __ reserved name for binding to prevent name conflicts. See module-level doc comment.
|
||||
struct __ProductVisitor #impl_generics #where_clause {
|
||||
_marker: std::marker::PhantomData<fn() -> #name #ty_generics>,
|
||||
}
|
||||
@@ -435,8 +442,10 @@ pub(crate) fn derive_deserialize(ty: &SatsType<'_>) -> TokenStream {
|
||||
)*
|
||||
Ok(())
|
||||
}
|
||||
// __ reserved name for binding to prevent name conflicts. See module-level doc comment.
|
||||
fn visit_named_product<A: #spacetimedb_lib::de::NamedProductAccess<'de>>(self, mut __prod: A) -> Result<Self::Output, A::Error> {
|
||||
#(let mut #field_names = None;)*
|
||||
// __ reserved name for binding to prevent name conflicts. See module-level doc comment.
|
||||
while let Some(__field) = #spacetimedb_lib::de::NamedProductAccess::get_field_ident(&mut __prod, Self {
|
||||
_marker: std::marker::PhantomData,
|
||||
})? {
|
||||
@@ -454,8 +463,10 @@ pub(crate) fn derive_deserialize(ty: &SatsType<'_>) -> TokenStream {
|
||||
#field_names.ok_or_else(|| #spacetimedb_lib::de::Error::missing_field(#iter_n4, Some(#field_strings), &self))?,)*
|
||||
})
|
||||
}
|
||||
// __ reserved name for binding to prevent name conflicts. See module-level doc comment.
|
||||
fn validate_named_product<A: #spacetimedb_lib::de::NamedProductAccess<'de>>(self, mut __prod: A) -> Result<(), A::Error> {
|
||||
#(let mut #field_names = false;)*
|
||||
// __ reserved name for binding to prevent name conflicts. See module-level doc comment.
|
||||
while let Some(__field) = #spacetimedb_lib::de::NamedProductAccess::get_field_ident(&mut __prod, Self {
|
||||
_marker: std::marker::PhantomData,
|
||||
})? {
|
||||
@@ -485,15 +496,18 @@ pub(crate) fn derive_deserialize(ty: &SatsType<'_>) -> TokenStream {
|
||||
[#(#field_strings),*].into_iter().map(Some)
|
||||
}
|
||||
|
||||
fn visit<__E: #spacetimedb_lib::de::Error>(self, name: &str) -> Result<Self::Output, __E> {
|
||||
match name {
|
||||
// __ reserved name for binding to prevent name conflicts. See module-level doc comment.
|
||||
// __ reserved name for binding to prevent name conflicts. See module-level doc comment.
|
||||
fn visit<__E: #spacetimedb_lib::de::Error>(self, __name: &str) -> Result<Self::Output, __E> {
|
||||
match __name {
|
||||
#(#field_strings => Ok(__ProductFieldIdent::#field_names),)*
|
||||
_ => Err(#spacetimedb_lib::de::Error::unknown_field_name(name, &self)),
|
||||
_ => Err(#spacetimedb_lib::de::Error::unknown_field_name(__name, &self)),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_seq(self, index: usize) -> Self::Output {
|
||||
match index {
|
||||
// __ reserved name for binding to prevent name conflicts. See module-level doc comment.
|
||||
fn visit_seq(self, __index: usize) -> Self::Output {
|
||||
match __index {
|
||||
#(#iter_n7 => __ProductFieldIdent::#field_names,)*
|
||||
_ => core::unreachable!(),
|
||||
}
|
||||
@@ -501,6 +515,7 @@ pub(crate) fn derive_deserialize(ty: &SatsType<'_>) -> TokenStream {
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
// __ reserved name for binding to prevent name conflicts. See module-level doc comment.
|
||||
enum __ProductFieldIdent {
|
||||
#(#field_names,)*
|
||||
}
|
||||
@@ -555,6 +570,7 @@ pub(crate) fn derive_deserialize(ty: &SatsType<'_>) -> TokenStream {
|
||||
}
|
||||
}
|
||||
|
||||
// __ reserved name for binding to prevent name conflicts. See module-level doc comment.
|
||||
struct __SumVisitor #impl_generics #where_clause {
|
||||
_marker: std::marker::PhantomData<fn() -> #name #ty_generics>,
|
||||
}
|
||||
@@ -566,14 +582,18 @@ pub(crate) fn derive_deserialize(ty: &SatsType<'_>) -> TokenStream {
|
||||
Some(#tuple_name)
|
||||
}
|
||||
|
||||
// __ reserved name for binding to prevent name conflicts. See module-level doc comment.
|
||||
fn visit_sum<A: #spacetimedb_lib::de::SumAccess<'de>>(self, __data: A) -> Result<Self::Output, A::Error> {
|
||||
// __ reserved name for binding to prevent name conflicts. See module-level doc comment.
|
||||
let (__variant, __access) = __data.variant(self)?;
|
||||
match __variant {
|
||||
#(#arms)*
|
||||
}
|
||||
}
|
||||
|
||||
// __ reserved name for binding to prevent name conflicts. See module-level doc comment.
|
||||
fn validate_sum<A: #spacetimedb_lib::de::SumAccess<'de>>(self, __data: A) -> Result<(), A::Error> {
|
||||
// __ reserved name for binding to prevent name conflicts. See module-level doc comment.
|
||||
let (__variant, __access) = __data.variant(self)?;
|
||||
match __variant {
|
||||
#(#arms_validate)*
|
||||
@@ -583,6 +603,7 @@ pub(crate) fn derive_deserialize(ty: &SatsType<'_>) -> TokenStream {
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
// __ reserved name for binding to prevent name conflicts. See module-level doc comment.
|
||||
enum __Variant {
|
||||
#(#variant_idents,)*
|
||||
}
|
||||
@@ -594,12 +615,14 @@ pub(crate) fn derive_deserialize(ty: &SatsType<'_>) -> TokenStream {
|
||||
[#(#variant_names,)*].into_iter()
|
||||
}
|
||||
|
||||
// __ reserved name for binding to prevent name conflicts. See module-level doc comment.
|
||||
fn visit_tag<E: #spacetimedb_lib::de::Error>(self, __tag: u8) -> Result<Self::Output, E> {
|
||||
match __tag {
|
||||
#(#tags => Ok(__Variant::#variant_idents),)*
|
||||
_ => Err(#spacetimedb_lib::de::Error::unknown_variant_tag(__tag, &self)),
|
||||
}
|
||||
}
|
||||
// __ reserved name for binding to prevent name conflicts. See module-level doc comment.
|
||||
fn visit_name<E: #spacetimedb_lib::de::Error>(self, __name: &str) -> Result<Self::Output, E> {
|
||||
match __name {
|
||||
#(#variant_names => Ok(__Variant::#variant_idents),)*
|
||||
@@ -664,6 +687,7 @@ pub(crate) fn derive_serialize(ty: &SatsType) -> TokenStream {
|
||||
let fieldnamestrings = fields.iter().map(|field| field.name.as_ref().unwrap());
|
||||
let nfields = fields.len();
|
||||
quote! {
|
||||
// __ reserved name for binding to prevent name conflicts. See module-level doc comment.
|
||||
let mut __prod = __serializer.serialize_named_product(#nfields)?;
|
||||
#(#spacetimedb_lib::ser::SerializeNamedProduct::serialize_element::<#tys>(&mut __prod, Some(#fieldnamestrings), &self.#fieldnames)?;)*
|
||||
#spacetimedb_lib::ser::SerializeNamedProduct::end(__prod)
|
||||
@@ -675,6 +699,7 @@ pub(crate) fn derive_serialize(ty: &SatsType) -> TokenStream {
|
||||
let tag = i as u8;
|
||||
if let (Some(member), Some(ty)) = (&var.member, var.ty) {
|
||||
quote_spanned! {ty.span()=>
|
||||
// __ reserved name for binding to prevent name conflicts. See module-level doc comment.
|
||||
Self::#name { #member: __variant } => __serializer.serialize_variant::<#ty>(#tag, Some(#name_str), __variant),
|
||||
}
|
||||
} else {
|
||||
@@ -692,6 +717,7 @@ pub(crate) fn derive_serialize(ty: &SatsType) -> TokenStream {
|
||||
quote! {
|
||||
impl #impl_generics #spacetimedb_lib::ser::Serialize for #name #ty_generics #where_clause {
|
||||
#fast_body
|
||||
// __ reserved name for binding to prevent name conflicts. See module-level doc comment.
|
||||
fn serialize<S: #spacetimedb_lib::ser::Serializer>(&self, __serializer: S) -> Result<S::Ok, S::Error> {
|
||||
#body
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
// This file tests that it's possible to have a value item (`fn`, `const`, or `static`) named `index`
|
||||
// without introducing a name conflict due to a binding introduced by the `#[table]` macro.
|
||||
// Prior to a fix, the SATS derive macros (which were invoked by `table`) introduced some bindings
|
||||
// which were not in the `__` reserved namespace and had common names,
|
||||
// resulting in name collisions with user code.
|
||||
|
||||
use spacetimedb::http::{Request, Response};
|
||||
|
||||
#[spacetimedb::http::handler]
|
||||
fn index(_ctx: &mut spacetimedb::HandlerContext, _req: Request) -> Response {
|
||||
Response::new(().into())
|
||||
}
|
||||
|
||||
#[spacetimedb::table(accessor = things)]
|
||||
struct Thing {
|
||||
#[index(btree)]
|
||||
value: u32,
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,19 @@
|
||||
// This file tests that it's possible to have a value item (`fn`, `const`, or `static`) named `name`
|
||||
// without introducing a name conflict due to a binding introduced by the `#[table]` macro.
|
||||
// Prior to a fix, the SATS derive macros (which were invoked by `table`) introduced some bindings
|
||||
// which were not in the `__` reserved namespace and had common names,
|
||||
// resulting in name collisions with user code.
|
||||
|
||||
use spacetimedb::http::{Request, Response};
|
||||
|
||||
#[spacetimedb::http::handler]
|
||||
fn name(_ctx: &mut spacetimedb::HandlerContext, _req: Request) -> Response {
|
||||
Response::new(().into())
|
||||
}
|
||||
|
||||
#[spacetimedb::table(accessor = things)]
|
||||
struct Thing {
|
||||
value: u32,
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -2,4 +2,5 @@
|
||||
fn ui() {
|
||||
let t = trybuild::TestCases::new();
|
||||
t.compile_fail("tests/ui/*.rs");
|
||||
t.pass("tests/pass/*.rs");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user