rune/module/module.rs
1use core::marker::PhantomData;
2
3use ::rust_alloc::sync::Arc;
4
5use crate as rune;
6use crate::alloc::prelude::*;
7use crate::alloc::{self, HashMap, HashSet};
8use crate::compile::context::{AttributeMacroHandler, MacroHandler};
9use crate::compile::{self, meta, ContextError, Docs, Named};
10use crate::function::{Async, Function, FunctionKind, InstanceFunction, Plain};
11use crate::function_meta::{
12 Associated, AssociatedFunctionData, AssociatedName, FunctionArgs, FunctionBuilder,
13 FunctionData, FunctionMeta, FunctionMetaKind, MacroMeta, MacroMetaKind, ToFieldFunction,
14 ToInstance,
15};
16use crate::item::IntoComponent;
17use crate::macros::{MacroContext, TokenStream};
18use crate::module::DocFunction;
19use crate::runtime::{
20 AnyTypeInfo, ConstConstruct, InstAddress, MaybeTypeOf, Memory, Output, Protocol, ToConstValue,
21 TypeHash, TypeOf, VmResult,
22};
23use crate::{Hash, Item, ItemBuf};
24
25use super::{
26 AssociatedKey, EnumMut, InstallWith, ItemFnMut, ItemMut, ModuleAssociated,
27 ModuleAssociatedKind, ModuleAttributeMacro, ModuleConstantBuilder, ModuleFunction,
28 ModuleFunctionBuilder, ModuleItem, ModuleItemCommon, ModuleItemKind, ModuleMacro, ModuleMeta,
29 ModuleRawFunctionBuilder, ModuleReexport, ModuleTrait, ModuleTraitImpl, ModuleType, TraitMut,
30 TypeMut, TypeSpecification, VariantMut,
31};
32
33#[derive(Debug, TryClone, PartialEq, Eq, Hash)]
34enum Name {
35 /// An associated key.
36 Associated(AssociatedKey),
37 /// A regular item.
38 Item(Hash),
39 /// A macro.
40 Macro(Hash),
41 /// An attribute macro.
42 AttributeMacro(Hash),
43 /// A conflicting trait implementation.
44 TraitImpl(Hash, Hash),
45}
46
47/// A [Module] that is a collection of native functions and types.
48///
49/// Needs to be installed into a [Context][crate::compile::Context] using
50/// [Context::install][crate::compile::Context::install].
51#[derive(Default)]
52pub struct Module {
53 /// Uniqueness checks.
54 names: HashSet<Name>,
55 /// A special identifier for this module, which will cause it to not conflict if installed multiple times.
56 pub(crate) unique: Option<&'static str>,
57 /// The name of the module.
58 pub(crate) item: ItemBuf,
59 /// Functions.
60 pub(crate) items: Vec<ModuleItem>,
61 /// Associated items.
62 pub(crate) associated: Vec<ModuleAssociated>,
63 /// Registered types.
64 pub(crate) types: Vec<ModuleType>,
65 /// Type hash to types mapping.
66 pub(crate) types_hash: HashMap<Hash, usize>,
67 /// A trait registered in the current module.
68 pub(crate) traits: Vec<ModuleTrait>,
69 /// A trait implementation registered in the current module.
70 pub(crate) trait_impls: Vec<ModuleTraitImpl>,
71 /// A re-export in the current module.
72 pub(crate) reexports: Vec<ModuleReexport>,
73 /// Constant constructors.
74 pub(crate) construct: Vec<(Hash, AnyTypeInfo, Arc<dyn ConstConstruct>)>,
75 /// Defines construct hashes.
76 pub(crate) construct_hash: HashSet<Hash>,
77 /// Module level metadata.
78 pub(crate) common: ModuleItemCommon,
79}
80
81impl Module {
82 /// Create an empty module for the root path.
83 pub fn new() -> Self {
84 Self::default()
85 }
86
87 /// Modify the current module to utilise a special identifier.
88 ///
89 /// TODO: Deprecate after next major release.
90 #[doc(hidden)]
91 pub fn with_unique(self, id: &'static str) -> Self {
92 Self {
93 unique: Some(id),
94 ..self
95 }
96 }
97
98 /// Construct a new module for the given item.
99 pub fn with_item(iter: impl IntoIterator<Item: IntoComponent>) -> Result<Self, ContextError> {
100 Ok(Self::inner_new(ItemBuf::with_item(iter)?))
101 }
102
103 /// Construct a new module for the given crate.
104 pub fn with_crate(name: &str) -> Result<Self, ContextError> {
105 Ok(Self::inner_new(ItemBuf::with_crate(name)?))
106 }
107
108 /// Construct a new module for the given crate.
109 pub fn with_crate_item(
110 name: &str,
111 iter: impl IntoIterator<Item: IntoComponent>,
112 ) -> Result<Self, ContextError> {
113 Ok(Self::inner_new(ItemBuf::with_crate_item(name, iter)?))
114 }
115
116 /// Construct a new module from the given module meta.
117 pub fn from_meta(module_meta: ModuleMeta) -> Result<Self, ContextError> {
118 let meta = module_meta()?;
119 let mut m = Self::inner_new(meta.item);
120 m.item_mut().static_docs(meta.docs)?;
121 Ok(m)
122 }
123
124 fn inner_new(item: ItemBuf) -> Self {
125 Self {
126 names: HashSet::new(),
127 unique: None,
128 item,
129 items: Vec::new(),
130 associated: Vec::new(),
131 types: Vec::new(),
132 traits: Vec::new(),
133 trait_impls: Vec::new(),
134 types_hash: HashMap::new(),
135 reexports: Vec::new(),
136 construct: Vec::new(),
137 construct_hash: HashSet::new(),
138 common: ModuleItemCommon {
139 docs: Docs::EMPTY,
140 deprecated: None,
141 },
142 }
143 }
144
145 /// Mutate item-level properties for this module.
146 pub fn item_mut(&mut self) -> ItemMut<'_> {
147 ItemMut {
148 docs: &mut self.common.docs,
149 #[cfg(feature = "doc")]
150 deprecated: &mut self.common.deprecated,
151 }
152 }
153
154 /// Register a type. Registering a type is mandatory in order to register
155 /// instance functions using that type.
156 ///
157 /// This will allow the type to be used within scripts, using the item named
158 /// here.
159 ///
160 /// # Examples
161 ///
162 /// ```
163 /// use rune::{Any, Context, Module};
164 ///
165 /// #[derive(Any)]
166 /// struct MyBytes {
167 /// queue: Vec<String>,
168 /// }
169 ///
170 /// impl MyBytes {
171 /// #[rune::function]
172 /// fn len(&self) -> usize {
173 /// self.queue.len()
174 /// }
175 /// }
176 ///
177 /// // Register `len` without registering a type.
178 /// let mut m = Module::default();
179 /// // Note: cannot do this until we have registered a type.
180 /// m.function_meta(MyBytes::len)?;
181 ///
182 /// let mut context = rune::Context::new();
183 /// assert!(context.install(m).is_err());
184 ///
185 /// // Register `len` properly.
186 /// let mut m = Module::default();
187 ///
188 /// m.ty::<MyBytes>()?;
189 /// m.function_meta(MyBytes::len)?;
190 ///
191 /// let mut context = Context::new();
192 /// assert!(context.install(m).is_ok());
193 /// # Ok::<_, rune::support::Error>(())
194 /// ```
195 pub fn ty<T>(&mut self) -> Result<TypeMut<'_, T>, ContextError>
196 where
197 T: ?Sized + TypeOf + Named + InstallWith,
198 {
199 if !self.names.try_insert(Name::Item(T::HASH))? {
200 return Err(ContextError::ConflictingType {
201 item: T::ITEM.try_to_owned()?,
202 type_info: T::type_info(),
203 hash: T::HASH,
204 });
205 }
206
207 let index = self.types.len();
208 self.types_hash.try_insert(T::HASH, index)?;
209
210 self.types.try_push(ModuleType {
211 item: T::ITEM.try_to_owned()?,
212 hash: T::HASH,
213 common: ModuleItemCommon {
214 docs: Docs::EMPTY,
215 deprecated: None,
216 },
217 type_parameters: T::PARAMETERS,
218 type_info: T::type_info(),
219 spec: None,
220 constructor: None,
221 })?;
222
223 T::install_with(self)?;
224
225 let ty = self.types.last_mut().unwrap();
226
227 Ok(TypeMut {
228 docs: &mut ty.common.docs,
229 #[cfg(feature = "doc")]
230 deprecated: &mut ty.common.deprecated,
231 spec: &mut ty.spec,
232 constructor: &mut ty.constructor,
233 item: &ty.item,
234 _marker: PhantomData,
235 })
236 }
237
238 /// Accessor to modify type metadata such as documentaiton, fields, variants.
239 pub fn type_meta<T>(&mut self) -> Result<TypeMut<'_, T>, ContextError>
240 where
241 T: ?Sized + TypeOf + Named,
242 {
243 let type_hash = T::HASH;
244
245 let Some(ty) = self.types_hash.get(&type_hash).map(|&i| &mut self.types[i]) else {
246 let full_name = T::display().try_to_string()?;
247
248 return Err(ContextError::MissingType {
249 item: ItemBuf::with_item(&[full_name])?,
250 type_info: T::type_info(),
251 });
252 };
253
254 Ok(TypeMut {
255 docs: &mut ty.common.docs,
256 #[cfg(feature = "doc")]
257 deprecated: &mut ty.common.deprecated,
258 spec: &mut ty.spec,
259 constructor: &mut ty.constructor,
260 item: &ty.item,
261 _marker: PhantomData,
262 })
263 }
264
265 /// Register that the given type is a struct, and that it has the given
266 /// compile-time metadata. This implies that each field has a
267 /// [Protocol::GET] field function.
268 ///
269 /// This is typically not used directly, but is used automatically with the
270 /// [Any][crate::Any] derive.
271 #[deprecated = "Use type_meta::<T>().make_struct(fields) instead"]
272 pub fn struct_meta<T>(&mut self, fields: &'static [&'static str]) -> Result<(), ContextError>
273 where
274 T: ?Sized + TypeOf + Named,
275 {
276 self.type_meta::<T>()?.make_named_struct(fields)?;
277 Ok(())
278 }
279
280 /// Register enum metadata for the given type `T`. This allows an enum to be
281 /// used in limited ways in Rune.
282 #[deprecated = "Use type_meta::<T>().make_enum(variants) instead"]
283 #[doc(hidden)]
284 pub fn enum_meta<T>(
285 &mut self,
286 variants: &'static [&'static str],
287 ) -> Result<EnumMut<'_, T>, ContextError>
288 where
289 T: ?Sized + TypeOf + Named,
290 {
291 self.type_meta::<T>()?.make_enum(variants)
292 }
293
294 /// Access variant metadata for the given type and the index of its variant.
295 pub fn variant_meta<T>(&mut self, index: usize) -> Result<VariantMut<'_, T>, ContextError>
296 where
297 T: ?Sized + TypeOf + Named,
298 {
299 let type_hash = T::HASH;
300
301 let Some(ty) = self.types_hash.get(&type_hash).map(|&i| &mut self.types[i]) else {
302 let full_name = T::display().try_to_string()?;
303
304 return Err(ContextError::MissingType {
305 item: ItemBuf::with_item(&[full_name])?,
306 type_info: T::type_info(),
307 });
308 };
309
310 let Some(TypeSpecification::Enum(en)) = &mut ty.spec else {
311 let full_name = T::display().try_to_string()?;
312
313 return Err(ContextError::MissingEnum {
314 item: ItemBuf::with_item(&[full_name])?,
315 type_info: T::type_info(),
316 });
317 };
318
319 let Some(variant) = en.variants.get_mut(index) else {
320 return Err(ContextError::MissingVariant {
321 type_info: T::type_info(),
322 index,
323 });
324 };
325
326 Ok(VariantMut {
327 name: variant.name,
328 docs: &mut variant.docs,
329 fields: &mut variant.fields,
330 constructor: &mut variant.constructor,
331 _marker: PhantomData,
332 })
333 }
334
335 /// Register a variant constructor for type `T`.
336 #[deprecated = "Use variant_meta() instead"]
337 pub fn variant_constructor<F, A>(
338 &mut self,
339 index: usize,
340 constructor: F,
341 ) -> Result<(), ContextError>
342 where
343 F: Function<A, Plain, Return: TypeOf + Named>,
344 {
345 self.variant_meta::<F::Return>(index)?
346 .constructor(constructor)?;
347 Ok(())
348 }
349
350 /// Register a constant value, at a crate, module or associated level.
351 ///
352 /// # Examples
353 ///
354 /// ```
355 /// use rune::{docstring, Any, Module};
356 ///
357 /// let mut module = Module::default();
358 ///
359 /// #[derive(Any)]
360 /// struct MyType;
361 ///
362 /// module.constant("TEN", 10)
363 /// .build()?
364 /// .docs(docstring! {
365 /// /// A global ten value.
366 /// });
367 ///
368 /// module.constant("TEN", 10)
369 /// .build_associated::<MyType>()?
370 /// .docs(docstring! {
371 /// /// Ten which looks like an associated constant.
372 /// });
373 /// # Ok::<_, rune::support::Error>(())
374 /// ```
375 pub fn constant<N, V>(&mut self, name: N, value: V) -> ModuleConstantBuilder<'_, N, V>
376 where
377 V: TypeHash + TypeOf + ToConstValue,
378 {
379 ModuleConstantBuilder {
380 module: self,
381 name,
382 value,
383 }
384 }
385
386 pub(super) fn insert_constant<N, V>(
387 &mut self,
388 name: N,
389 value: V,
390 ) -> Result<ItemMut<'_>, ContextError>
391 where
392 N: IntoComponent,
393 V: TypeHash + TypeOf + ToConstValue,
394 {
395 let item = self.item.join([name])?;
396 let hash = Hash::type_hash(&item);
397
398 let value = match value.to_const_value() {
399 Ok(value) => value,
400 Err(error) => {
401 return Err(ContextError::InvalidConstValue {
402 item,
403 error: Box::try_new(error)?,
404 })
405 }
406 };
407
408 if !self.names.try_insert(Name::Item(hash))? {
409 return Err(ContextError::ConflictingConstantName { item, hash });
410 }
411
412 self.items.try_push(ModuleItem {
413 item,
414 hash,
415 common: ModuleItemCommon {
416 docs: Docs::EMPTY,
417 deprecated: None,
418 },
419 kind: ModuleItemKind::Constant(value),
420 })?;
421
422 self.insert_const_construct::<V>()?;
423
424 let c = self.items.last_mut().unwrap();
425
426 Ok(ItemMut {
427 docs: &mut c.common.docs,
428 #[cfg(feature = "doc")]
429 deprecated: &mut c.common.deprecated,
430 })
431 }
432
433 pub(super) fn insert_associated_constant<V>(
434 &mut self,
435 associated: Associated,
436 value: V,
437 ) -> Result<ItemMut<'_>, ContextError>
438 where
439 V: TypeHash + TypeOf + ToConstValue,
440 {
441 let value = match value.to_const_value() {
442 Ok(value) => value,
443 Err(error) => {
444 return Err(ContextError::InvalidAssociatedConstValue {
445 container: associated.container_type_info,
446 kind: Box::try_new(associated.name.kind)?,
447 error: Box::try_new(error)?,
448 });
449 }
450 };
451
452 self.insert_associated_name(&associated)?;
453
454 self.associated.try_push(ModuleAssociated {
455 container: associated.container,
456 container_type_info: associated.container_type_info,
457 name: associated.name,
458 common: ModuleItemCommon {
459 docs: Docs::EMPTY,
460 deprecated: None,
461 },
462 kind: ModuleAssociatedKind::Constant(value),
463 })?;
464
465 self.insert_const_construct::<V>()?;
466
467 let last = self.associated.last_mut().unwrap();
468
469 Ok(ItemMut {
470 docs: &mut last.common.docs,
471 #[cfg(feature = "doc")]
472 deprecated: &mut last.common.deprecated,
473 })
474 }
475
476 fn insert_const_construct<V>(&mut self) -> alloc::Result<()>
477 where
478 V: TypeHash + TypeOf + ToConstValue,
479 {
480 if self.construct_hash.try_insert(V::HASH)? {
481 if let Some(construct) = V::construct() {
482 self.construct
483 .try_push((V::HASH, V::STATIC_TYPE_INFO, construct))?;
484 }
485 }
486
487 Ok(())
488 }
489
490 /// Register a native macro handler through its meta.
491 ///
492 /// The metadata must be provided by annotating the function with
493 /// [`#[rune::macro_]`][crate::macro_].
494 ///
495 /// This has the benefit that it captures documentation comments which can
496 /// be used when generating documentation or referencing the function
497 /// through code sense systems.
498 ///
499 /// # Examples
500 ///
501 /// ```
502 /// use rune::Module;
503 /// use rune::ast;
504 /// use rune::compile;
505 /// use rune::macros::{quote, MacroContext, TokenStream};
506 /// use rune::parse::Parser;
507 /// use rune::alloc::prelude::*;
508 ///
509 /// /// Takes an identifier and converts it into a string.
510 /// ///
511 /// /// # Examples
512 /// ///
513 /// /// ```rune
514 /// /// assert_eq!(ident_to_string!(Hello), "Hello");
515 /// /// ```
516 /// #[rune::macro_]
517 /// fn ident_to_string(cx: &mut MacroContext<'_, '_, '_>, stream: &TokenStream) -> compile::Result<TokenStream> {
518 /// let mut p = Parser::from_token_stream(stream, cx.input_span());
519 /// let ident = p.parse_all::<ast::Ident>()?;
520 /// let ident = cx.resolve(ident)?.try_to_owned()?;
521 /// let string = cx.lit(&ident)?;
522 /// Ok(quote!(#string).into_token_stream(cx)?)
523 /// }
524 ///
525 /// let mut m = Module::new();
526 /// m.macro_meta(ident_to_string)?;
527 ///
528 /// Ok::<_, rune::support::Error>(())
529 /// ```
530 #[inline]
531 pub fn macro_meta(&mut self, meta: MacroMeta) -> Result<ItemMut<'_>, ContextError> {
532 let meta = meta()?;
533
534 let item = match meta.kind {
535 MacroMetaKind::Function(data) => {
536 let item = self.item.join(&data.item)?;
537 let hash = Hash::type_hash(&item);
538
539 if !self.names.try_insert(Name::Macro(hash))? {
540 return Err(ContextError::ConflictingMacroName { item, hash });
541 }
542
543 let mut docs = Docs::EMPTY;
544 docs.set_docs(meta.docs)?;
545
546 self.items.try_push(ModuleItem {
547 item,
548 hash,
549 common: ModuleItemCommon {
550 docs,
551 deprecated: None,
552 },
553 kind: ModuleItemKind::Macro(ModuleMacro {
554 handler: data.handler,
555 }),
556 })?;
557
558 self.items.last_mut().unwrap()
559 }
560 MacroMetaKind::Attribute(data) => {
561 let item = self.item.join(&data.item)?;
562 let hash = Hash::type_hash(&item);
563
564 if !self.names.try_insert(Name::AttributeMacro(hash))? {
565 return Err(ContextError::ConflictingMacroName { item, hash });
566 }
567
568 let mut docs = Docs::EMPTY;
569 docs.set_docs(meta.docs)?;
570
571 self.items.try_push(ModuleItem {
572 item,
573 hash,
574 common: ModuleItemCommon {
575 docs,
576 deprecated: None,
577 },
578 kind: ModuleItemKind::AttributeMacro(ModuleAttributeMacro {
579 handler: data.handler,
580 }),
581 })?;
582
583 self.items.last_mut().unwrap()
584 }
585 };
586
587 Ok(ItemMut {
588 docs: &mut item.common.docs,
589 #[cfg(feature = "doc")]
590 deprecated: &mut item.common.deprecated,
591 })
592 }
593
594 /// Register a native macro handler.
595 ///
596 /// If possible, [`Module::macro_meta`] should be used since it includes more
597 /// useful information about the macro.
598 ///
599 /// # Examples
600 ///
601 /// ```
602 /// use rune::Module;
603 /// use rune::ast;
604 /// use rune::compile;
605 /// use rune::macros::{quote, MacroContext, TokenStream};
606 /// use rune::parse::Parser;
607 /// use rune::alloc::prelude::*;
608 ///
609 /// fn ident_to_string(cx: &mut MacroContext<'_, '_, '_>, stream: &TokenStream) -> compile::Result<TokenStream> {
610 /// let mut p = Parser::from_token_stream(stream, cx.input_span());
611 /// let ident = p.parse_all::<ast::Ident>()?;
612 /// let ident = cx.resolve(ident)?.try_to_owned()?;
613 /// let string = cx.lit(&ident)?;
614 /// Ok(quote!(#string).into_token_stream(cx)?)
615 /// }
616 ///
617 /// let mut m = Module::new();
618 /// m.macro_(["ident_to_string"], ident_to_string)?;
619 ///
620 /// Ok::<_, rune::support::Error>(())
621 /// ```
622 pub fn macro_<N, M>(&mut self, name: N, f: M) -> Result<ItemMut<'_>, ContextError>
623 where
624 M: 'static
625 + Send
626 + Sync
627 + Fn(&mut MacroContext<'_, '_, '_>, &TokenStream) -> compile::Result<TokenStream>,
628 N: IntoComponent,
629 {
630 let item = self.item.join([name])?;
631 let hash = Hash::type_hash(&item);
632
633 if !self.names.try_insert(Name::Macro(hash))? {
634 return Err(ContextError::ConflictingMacroName { item, hash });
635 }
636
637 let handler: Arc<MacroHandler> = Arc::new(f);
638
639 self.items.try_push(ModuleItem {
640 item,
641 hash,
642 common: ModuleItemCommon::default(),
643 kind: ModuleItemKind::Macro(ModuleMacro { handler }),
644 })?;
645
646 let m = self.items.last_mut().unwrap();
647
648 Ok(ItemMut {
649 docs: &mut m.common.docs,
650 #[cfg(feature = "doc")]
651 deprecated: &mut m.common.deprecated,
652 })
653 }
654
655 /// Register a native attribute macro handler.
656 ///
657 /// If possible, [`Module::macro_meta`] should be used since it includes more
658 /// useful information about the function.
659 ///
660 /// # Examples
661 ///
662 /// ```
663 /// use rune::Module;
664 /// use rune::ast;
665 /// use rune::compile;
666 /// use rune::macros::{quote, MacroContext, TokenStream, ToTokens};
667 /// use rune::parse::Parser;
668 ///
669 /// fn rename_fn(cx: &mut MacroContext<'_, '_, '_>, input: &TokenStream, item: &TokenStream) -> compile::Result<TokenStream> {
670 /// let mut item = Parser::from_token_stream(item, cx.macro_span());
671 /// let mut fun = item.parse_all::<ast::ItemFn>()?;
672 ///
673 /// let mut input = Parser::from_token_stream(input, cx.input_span());
674 /// fun.name = input.parse_all::<ast::EqValue<_>>()?.value;
675 /// Ok(quote!(#fun).into_token_stream(cx)?)
676 /// }
677 ///
678 /// let mut m = Module::new();
679 /// m.attribute_macro(["rename_fn"], rename_fn)?;
680 ///
681 /// Ok::<_, rune::support::Error>(())
682 /// ```
683 pub fn attribute_macro<N, M>(&mut self, name: N, f: M) -> Result<ItemMut<'_>, ContextError>
684 where
685 M: 'static
686 + Send
687 + Sync
688 + Fn(
689 &mut MacroContext<'_, '_, '_>,
690 &TokenStream,
691 &TokenStream,
692 ) -> compile::Result<TokenStream>,
693 N: IntoComponent,
694 {
695 let item = self.item.join([name])?;
696 let hash = Hash::type_hash(&item);
697
698 if !self.names.try_insert(Name::AttributeMacro(hash))? {
699 return Err(ContextError::ConflictingMacroName { item, hash });
700 }
701
702 let handler: Arc<AttributeMacroHandler> = Arc::new(f);
703
704 self.items.try_push(ModuleItem {
705 item,
706 hash,
707 common: ModuleItemCommon {
708 docs: Docs::EMPTY,
709 deprecated: None,
710 },
711 kind: ModuleItemKind::AttributeMacro(ModuleAttributeMacro { handler }),
712 })?;
713
714 let m = self.items.last_mut().unwrap();
715
716 Ok(ItemMut {
717 docs: &mut m.common.docs,
718 #[cfg(feature = "doc")]
719 deprecated: &mut m.common.deprecated,
720 })
721 }
722
723 /// Register a function handler through its meta.
724 ///
725 /// The metadata must be provided by annotating the function with
726 /// [`#[rune::function]`][macro@crate::function].
727 ///
728 /// This has the benefit that it captures documentation comments which can
729 /// be used when generating documentation or referencing the function
730 /// through code sense systems.
731 ///
732 /// # Examples
733 ///
734 /// ```
735 /// use rune::{ContextError, Module, Ref};
736 ///
737 /// /// This is a pretty neat function.
738 /// #[rune::function]
739 /// fn to_string(string: &str) -> String {
740 /// string.to_string()
741 /// }
742 ///
743 /// /// This is a pretty neat download function
744 /// #[rune::function]
745 /// async fn download(url: Ref<str>) -> rune::support::Result<String> {
746 /// # todo!()
747 /// }
748 ///
749 /// fn module() -> Result<Module, ContextError> {
750 /// let mut m = Module::new();
751 /// m.function_meta(to_string)?;
752 /// m.function_meta(download)?;
753 /// Ok(m)
754 /// }
755 /// ```
756 ///
757 /// Registering instance functions:
758 ///
759 /// ```
760 /// use rune::{Any, Module, Ref};
761 ///
762 /// #[derive(Any)]
763 /// struct MyBytes {
764 /// queue: Vec<String>,
765 /// }
766 ///
767 /// impl MyBytes {
768 /// fn new() -> Self {
769 /// Self {
770 /// queue: Vec::new(),
771 /// }
772 /// }
773 ///
774 /// #[rune::function]
775 /// fn len(&self) -> usize {
776 /// self.queue.len()
777 /// }
778 ///
779 /// #[rune::function(instance, path = Self::download)]
780 /// async fn download(this: Ref<Self>, url: Ref<str>) -> rune::support::Result<()> {
781 /// # todo!()
782 /// }
783 /// }
784 ///
785 /// let mut m = Module::default();
786 ///
787 /// m.ty::<MyBytes>()?;
788 /// m.function_meta(MyBytes::len)?;
789 /// m.function_meta(MyBytes::download)?;
790 /// # Ok::<_, rune::support::Error>(())
791 /// ```
792 #[inline]
793 pub fn function_meta(&mut self, meta: FunctionMeta) -> Result<ItemFnMut<'_>, ContextError> {
794 let meta = meta()?;
795
796 let mut docs = Docs::EMPTY;
797 docs.set_docs(meta.statics.docs)?;
798 docs.set_arguments(meta.statics.arguments)?;
799 let deprecated = meta.statics.deprecated.map(TryInto::try_into).transpose()?;
800
801 match meta.kind {
802 FunctionMetaKind::Function(data) => self.function_inner(data, docs, deprecated),
803 FunctionMetaKind::AssociatedFunction(data) => {
804 self.insert_associated_function(data, docs, deprecated)
805 }
806 }
807 }
808
809 pub(super) fn function_from_meta_kind(
810 &mut self,
811 kind: FunctionMetaKind,
812 ) -> Result<ItemFnMut<'_>, ContextError> {
813 match kind {
814 FunctionMetaKind::Function(data) => self.function_inner(data, Docs::EMPTY, None),
815 FunctionMetaKind::AssociatedFunction(data) => {
816 self.insert_associated_function(data, Docs::EMPTY, None)
817 }
818 }
819 }
820
821 /// Register a function.
822 ///
823 /// If possible, [`Module::function_meta`] should be used since it includes more
824 /// useful information about the function.
825 ///
826 /// # Examples
827 ///
828 /// ```
829 /// use rune::{docstring, Module};
830 ///
831 /// fn add_ten(value: i64) -> i64 {
832 /// value + 10
833 /// }
834 ///
835 /// let mut module = Module::default();
836 ///
837 /// module.function("add_ten", add_ten)
838 /// .build()?
839 /// .docs(docstring! {
840 /// /// Adds 10 to any integer passed in.
841 /// });
842 /// # Ok::<_, rune::support::Error>(())
843 /// ```
844 ///
845 /// Asynchronous function:
846 ///
847 /// ```
848 /// use rune::{docstring, Any, Module};
849 /// # async fn download(url: &str) -> Result<String, DownloadError> { Ok(String::new()) }
850 ///
851 /// #[derive(Any)]
852 /// struct DownloadError {
853 /// /* .. */
854 /// }
855 ///
856 /// async fn download_quote() -> Result<String, DownloadError> {
857 /// download("https://api.quotable.io/random").await
858 /// }
859 ///
860 /// let mut module = Module::default();
861 ///
862 /// module.function("download_quote", download_quote)
863 /// .build()?
864 /// .docs(docstring! {
865 /// /// Download a random quote from the internet.
866 /// });
867 /// # Ok::<_, rune::support::Error>(())
868 /// ```
869 pub fn function<F, A, N, K>(&mut self, name: N, f: F) -> ModuleFunctionBuilder<'_, F, A, N, K>
870 where
871 F: Function<A, K, Return: MaybeTypeOf>,
872 A: FunctionArgs,
873 K: FunctionKind,
874 {
875 ModuleFunctionBuilder {
876 module: self,
877 inner: FunctionBuilder::new(name, f),
878 }
879 }
880
881 /// See [`Module::function`].
882 #[deprecated = "Use `Module::function`"]
883 pub fn function2<F, A, N, K>(
884 &mut self,
885 name: N,
886 f: F,
887 ) -> Result<ModuleFunctionBuilder<'_, F, A, N, K>, ContextError>
888 where
889 F: Function<A, K, Return: MaybeTypeOf>,
890 A: FunctionArgs,
891 K: FunctionKind,
892 {
893 Ok(ModuleFunctionBuilder {
894 module: self,
895 inner: FunctionBuilder::new(name, f),
896 })
897 }
898
899 /// See [`Module::function`].
900 #[deprecated = "Use Module::function() instead"]
901 pub fn async_function<F, A, N>(&mut self, name: N, f: F) -> Result<ItemFnMut<'_>, ContextError>
902 where
903 F: Function<A, Async, Return: MaybeTypeOf>,
904 N: IntoComponent,
905 A: FunctionArgs,
906 {
907 self.function_inner(FunctionData::new(name, f)?, Docs::EMPTY, None)
908 }
909
910 /// Register an instance function.
911 ///
912 /// If possible, [`Module::function_meta`] should be used since it includes
913 /// more useful information about the function.
914 ///
915 /// This returns a [`ItemMut`], which is a handle that can be used to
916 /// associate more metadata with the inserted item.
917 ///
918 /// # Replacing this with `function_meta` and `#[rune::function]`
919 ///
920 /// This is how you declare an instance function which takes `&self` or
921 /// `&mut self`:
922 ///
923 /// ```rust
924 /// # use rune::Any;
925 /// #[derive(Any)]
926 /// struct Struct {
927 /// /* .. */
928 /// }
929 ///
930 /// impl Struct {
931 /// /// Get the length of the `Struct`.
932 /// #[rune::function]
933 /// fn len(&self) -> usize {
934 /// /* .. */
935 /// # todo!()
936 /// }
937 /// }
938 /// ```
939 ///
940 /// If a function does not take `&self` or `&mut self`, you must specify that
941 /// it's an instance function using `#[rune::function(instance)]`. The first
942 /// argument is then considered the instance the function gets associated with:
943 ///
944 /// ```rust
945 /// # use rune::Any;
946 /// #[derive(Any)]
947 /// struct Struct {
948 /// /* .. */
949 /// }
950 ///
951 /// /// Get the length of the `Struct`.
952 /// #[rune::function(instance)]
953 /// fn len(this: &Struct) -> usize {
954 /// /* .. */
955 /// # todo!()
956 /// }
957 /// ```
958 ///
959 /// To declare an associated function which does not receive the type we
960 /// must specify the path to the function using `#[rune::function(path =
961 /// Self::<name>)]`:
962 ///
963 /// ```rust
964 /// # use rune::Any;
965 /// #[derive(Any)]
966 /// struct Struct {
967 /// /* .. */
968 /// }
969 ///
970 /// impl Struct {
971 /// /// Construct a new [`Struct`].
972 /// #[rune::function(path = Self::new)]
973 /// fn new() -> Struct {
974 /// Struct {
975 /// /* .. */
976 /// }
977 /// }
978 /// }
979 /// ```
980 ///
981 /// Or externally like this:
982 ///
983 /// ```rust
984 /// # use rune::Any;
985 /// #[derive(Any)]
986 /// struct Struct {
987 /// /* .. */
988 /// }
989 ///
990 /// /// Construct a new [`Struct`].
991 /// #[rune::function(free, path = Struct::new)]
992 /// fn new() -> Struct {
993 /// Struct {
994 /// /* .. */
995 /// }
996 /// }
997 /// ```
998 ///
999 /// The first part `Struct` in `Struct::new` is used to determine the type
1000 /// the function is associated with.
1001 ///
1002 /// Protocol functions can either be defined in an impl block or externally.
1003 /// To define a protocol externally, you can simply do this:
1004 ///
1005 /// ```rust
1006 /// # use rune::Any;
1007 /// # use rune::runtime::Formatter;
1008 /// #[derive(Any)]
1009 /// struct Struct {
1010 /// /* .. */
1011 /// }
1012 ///
1013 /// #[rune::function(instance, protocol = DISPLAY_FMT)]
1014 /// fn display_fmt(this: &Struct, f: &mut Formatter) -> std::fmt::Result {
1015 /// /* .. */
1016 /// # todo!()
1017 /// }
1018 /// ```
1019 ///
1020 /// # Examples
1021 ///
1022 /// ```
1023 /// use rune::{Any, Module};
1024 ///
1025 /// #[derive(Any)]
1026 /// struct MyBytes {
1027 /// queue: Vec<String>,
1028 /// }
1029 ///
1030 /// impl MyBytes {
1031 /// /// Construct a new empty bytes container.
1032 /// #[rune::function(path = Self::new)]
1033 /// fn new() -> Self {
1034 /// Self {
1035 /// queue: Vec::new(),
1036 /// }
1037 /// }
1038 ///
1039 /// /// Get the number of bytes.
1040 /// #[rune::function]
1041 /// fn len(&self) -> usize {
1042 /// self.queue.len()
1043 /// }
1044 /// }
1045 ///
1046 /// let mut m = Module::default();
1047 ///
1048 /// m.ty::<MyBytes>()?;
1049 /// m.function_meta(MyBytes::new)?;
1050 /// m.function_meta(MyBytes::len)?;
1051 /// # Ok::<_, rune::support::Error>(())
1052 /// ```
1053 ///
1054 /// Asynchronous function:
1055 ///
1056 /// ```
1057 /// use std::sync::atomic::AtomicU32;
1058 /// use std::sync::Arc;
1059 ///
1060 /// use rune::{Any, Module, Ref};
1061 ///
1062 /// #[derive(Clone, Debug, Any)]
1063 /// struct Client {
1064 /// value: Arc<AtomicU32>,
1065 /// }
1066 ///
1067 /// #[derive(Any)]
1068 /// struct DownloadError {
1069 /// /* .. */
1070 /// }
1071 ///
1072 /// impl Client {
1073 /// /// Download a thing.
1074 /// #[rune::function(instance, path = Self::download)]
1075 /// async fn download(this: Ref<Self>) -> Result<(), DownloadError> {
1076 /// /* .. */
1077 /// # Ok(())
1078 /// }
1079 /// }
1080 ///
1081 /// let mut module = Module::default();
1082 ///
1083 /// module.ty::<Client>()?;
1084 /// module.function_meta(Client::download)?;
1085 /// # Ok::<_, rune::support::Error>(())
1086 /// ```
1087 pub fn associated_function<N, F, A, K>(
1088 &mut self,
1089 name: N,
1090 f: F,
1091 ) -> Result<ItemFnMut<'_>, ContextError>
1092 where
1093 N: ToInstance,
1094 F: InstanceFunction<A, K, Return: MaybeTypeOf>,
1095 A: FunctionArgs,
1096 K: FunctionKind,
1097 {
1098 self.insert_associated_function(
1099 AssociatedFunctionData::from_instance_function(name.to_instance()?, f)?,
1100 Docs::EMPTY,
1101 None,
1102 )
1103 }
1104
1105 /// See [`Module::associated_function`].
1106 #[deprecated = "Use Module::associated_function() instead"]
1107 #[inline]
1108 pub fn inst_fn<N, F, A, K>(&mut self, name: N, f: F) -> Result<ItemFnMut<'_>, ContextError>
1109 where
1110 N: ToInstance,
1111 F: InstanceFunction<A, K, Return: MaybeTypeOf>,
1112 A: FunctionArgs,
1113 K: FunctionKind,
1114 {
1115 self.associated_function(name, f)
1116 }
1117
1118 /// See [`Module::associated_function`].
1119 #[deprecated = "Use Module::associated_function() instead"]
1120 pub fn async_inst_fn<N, F, A>(&mut self, name: N, f: F) -> Result<ItemFnMut<'_>, ContextError>
1121 where
1122 N: ToInstance,
1123 F: InstanceFunction<A, Async, Return: MaybeTypeOf>,
1124 A: FunctionArgs,
1125 {
1126 self.associated_function(name, f)
1127 }
1128
1129 /// Install a protocol function that interacts with the given field.
1130 ///
1131 /// This returns a [`ItemMut`], which is a handle that can be used to
1132 /// associate more metadata with the inserted item.
1133 pub fn field_function<N, F, A>(
1134 &mut self,
1135 protocol: &'static Protocol,
1136 name: N,
1137 f: F,
1138 ) -> Result<ItemFnMut<'_>, ContextError>
1139 where
1140 N: ToFieldFunction,
1141 F: InstanceFunction<A, Plain, Return: MaybeTypeOf>,
1142 A: FunctionArgs,
1143 {
1144 self.insert_associated_function(
1145 AssociatedFunctionData::from_instance_function(name.to_field_function(protocol)?, f)?,
1146 Docs::EMPTY,
1147 None,
1148 )
1149 }
1150
1151 /// See [`Module::field_function`].
1152 #[deprecated = "Use Module::field_function() instead"]
1153 #[inline]
1154 pub fn field_fn<N, F, A>(
1155 &mut self,
1156 protocol: &'static Protocol,
1157 name: N,
1158 f: F,
1159 ) -> Result<ItemFnMut<'_>, ContextError>
1160 where
1161 N: ToFieldFunction,
1162 F: InstanceFunction<A, Plain, Return: MaybeTypeOf>,
1163 A: FunctionArgs,
1164 {
1165 self.field_function(protocol, name, f)
1166 }
1167
1168 /// Install a protocol function that interacts with the given index.
1169 ///
1170 /// An index can either be a field inside a tuple, or a variant inside of an
1171 /// enum as configured with [Module::enum_meta].
1172 pub fn index_function<F, A>(
1173 &mut self,
1174 protocol: &'static Protocol,
1175 index: usize,
1176 f: F,
1177 ) -> Result<ItemFnMut<'_>, ContextError>
1178 where
1179 F: InstanceFunction<A, Plain, Return: MaybeTypeOf>,
1180 A: FunctionArgs,
1181 {
1182 let name = AssociatedName::index(protocol, index);
1183 self.insert_associated_function(
1184 AssociatedFunctionData::from_instance_function(name, f)?,
1185 Docs::EMPTY,
1186 None,
1187 )
1188 }
1189
1190 /// See [`Module::index_function`].
1191 #[deprecated = "Use Module::index_function() instead"]
1192 #[inline]
1193 pub fn index_fn<F, A>(
1194 &mut self,
1195 protocol: &'static Protocol,
1196 index: usize,
1197 f: F,
1198 ) -> Result<ItemFnMut<'_>, ContextError>
1199 where
1200 F: InstanceFunction<A, Plain, Return: MaybeTypeOf>,
1201 A: FunctionArgs,
1202 {
1203 self.index_function(protocol, index, f)
1204 }
1205
1206 /// Register a raw function which interacts directly with the virtual
1207 /// machine.
1208 ///
1209 /// This returns a [`ItemMut`], which is a handle that can be used to
1210 /// associate more metadata with the inserted item.
1211 ///
1212 /// # Examples
1213 ///
1214 /// ```
1215 /// use rune::Module;
1216 /// use rune::runtime::{Output, Memory, ToValue, VmResult, InstAddress};
1217 /// use rune::{docstring, vm_try};
1218 ///
1219 /// fn sum(stack: &mut dyn Memory, addr: InstAddress, args: usize, out: Output) -> VmResult<()> {
1220 /// let mut number = 0;
1221 ///
1222 /// for value in vm_try!(stack.slice_at(addr, args)) {
1223 /// number += vm_try!(value.as_integer::<i64>());
1224 /// }
1225 ///
1226 /// out.store(stack, number);
1227 /// VmResult::Ok(())
1228 /// }
1229 ///
1230 /// let mut module = Module::default();
1231 ///
1232 /// module.raw_function("sum", sum)
1233 /// .build()?
1234 /// .docs(docstring! {
1235 /// /// Sum all numbers provided to the function.
1236 /// })?;
1237 ///
1238 /// # Ok::<_, rune::support::Error>(())
1239 /// ```
1240 pub fn raw_function<F, N>(&mut self, name: N, f: F) -> ModuleRawFunctionBuilder<'_, N>
1241 where
1242 F: 'static + Fn(&mut dyn Memory, InstAddress, usize, Output) -> VmResult<()> + Send + Sync,
1243 {
1244 ModuleRawFunctionBuilder {
1245 module: self,
1246 name,
1247 handler: Arc::new(move |stack, addr, args, output| f(stack, addr, args, output)),
1248 }
1249 }
1250
1251 /// See [`Module::raw_function`].
1252 #[deprecated = "Use `raw_function` builder instead"]
1253 pub fn raw_fn<F, N>(&mut self, name: N, f: F) -> Result<ItemFnMut<'_>, ContextError>
1254 where
1255 F: 'static + Fn(&mut dyn Memory, InstAddress, usize, Output) -> VmResult<()> + Send + Sync,
1256 N: IntoComponent,
1257 {
1258 self.raw_function(name, f).build()
1259 }
1260
1261 fn function_inner(
1262 &mut self,
1263 data: FunctionData,
1264 docs: Docs,
1265 #[allow(unused)] deprecated: Option<Box<str>>,
1266 ) -> Result<ItemFnMut<'_>, ContextError> {
1267 let item = self.item.join(&data.item)?;
1268 let hash = Hash::type_hash(&item);
1269
1270 if !self.names.try_insert(Name::Item(hash))? {
1271 return Err(ContextError::ConflictingFunctionName { item, hash });
1272 }
1273
1274 self.items.try_push(ModuleItem {
1275 item,
1276 hash,
1277 common: ModuleItemCommon { docs, deprecated },
1278 kind: ModuleItemKind::Function(ModuleFunction {
1279 handler: data.handler,
1280 trait_hash: None,
1281 doc: DocFunction {
1282 #[cfg(feature = "doc")]
1283 is_async: data.is_async,
1284 #[cfg(feature = "doc")]
1285 args: data.args,
1286 #[cfg(feature = "doc")]
1287 return_type: data.return_type,
1288 #[cfg(feature = "doc")]
1289 argument_types: data.argument_types,
1290 },
1291 }),
1292 })?;
1293
1294 let last = self.items.last_mut().unwrap();
1295
1296 #[cfg(feature = "doc")]
1297 let last_fn = match &mut last.kind {
1298 ModuleItemKind::Function(f) => f,
1299 _ => unreachable!(),
1300 };
1301
1302 Ok(ItemFnMut {
1303 docs: &mut last.common.docs,
1304 #[cfg(feature = "doc")]
1305 deprecated: &mut last.common.deprecated,
1306 #[cfg(feature = "doc")]
1307 is_async: &mut last_fn.doc.is_async,
1308 #[cfg(feature = "doc")]
1309 args: &mut last_fn.doc.args,
1310 #[cfg(feature = "doc")]
1311 return_type: &mut last_fn.doc.return_type,
1312 #[cfg(feature = "doc")]
1313 argument_types: &mut last_fn.doc.argument_types,
1314 })
1315 }
1316
1317 /// Install an associated function.
1318 fn insert_associated_function(
1319 &mut self,
1320 data: AssociatedFunctionData,
1321 docs: Docs,
1322 #[allow(unused)] deprecated: Option<Box<str>>,
1323 ) -> Result<ItemFnMut<'_>, ContextError> {
1324 self.insert_associated_name(&data.associated)?;
1325
1326 self.associated.try_push(ModuleAssociated {
1327 container: data.associated.container,
1328 container_type_info: data.associated.container_type_info,
1329 name: data.associated.name,
1330 common: ModuleItemCommon { docs, deprecated },
1331 kind: ModuleAssociatedKind::Function(ModuleFunction {
1332 handler: data.handler,
1333 trait_hash: None,
1334 doc: DocFunction {
1335 #[cfg(feature = "doc")]
1336 is_async: data.is_async,
1337 #[cfg(feature = "doc")]
1338 args: data.args,
1339 #[cfg(feature = "doc")]
1340 return_type: data.return_type,
1341 #[cfg(feature = "doc")]
1342 argument_types: data.argument_types,
1343 },
1344 }),
1345 })?;
1346
1347 let last = self.associated.last_mut().unwrap();
1348
1349 #[cfg(feature = "doc")]
1350 let last_fn = match &mut last.kind {
1351 ModuleAssociatedKind::Function(f) => f,
1352 _ => unreachable!(),
1353 };
1354
1355 Ok(ItemFnMut {
1356 docs: &mut last.common.docs,
1357 #[cfg(feature = "doc")]
1358 deprecated: &mut last.common.deprecated,
1359 #[cfg(feature = "doc")]
1360 is_async: &mut last_fn.doc.is_async,
1361 #[cfg(feature = "doc")]
1362 args: &mut last_fn.doc.args,
1363 #[cfg(feature = "doc")]
1364 return_type: &mut last_fn.doc.return_type,
1365 #[cfg(feature = "doc")]
1366 argument_types: &mut last_fn.doc.argument_types,
1367 })
1368 }
1369
1370 fn insert_associated_name(&mut self, associated: &Associated) -> Result<(), ContextError> {
1371 if !self
1372 .names
1373 .try_insert(Name::Associated(associated.as_key()?))?
1374 {
1375 return Err(match &associated.name.kind {
1376 meta::AssociatedKind::Protocol(protocol) => {
1377 ContextError::ConflictingProtocolFunction {
1378 type_info: associated.container_type_info.try_clone()?,
1379 name: protocol.name.try_into()?,
1380 }
1381 }
1382 meta::AssociatedKind::FieldFn(protocol, field) => {
1383 ContextError::ConflictingFieldFunction {
1384 type_info: associated.container_type_info.try_clone()?,
1385 name: protocol.name.try_into()?,
1386 field: field.as_ref().try_into()?,
1387 }
1388 }
1389 meta::AssociatedKind::IndexFn(protocol, index) => {
1390 ContextError::ConflictingIndexFunction {
1391 type_info: associated.container_type_info.try_clone()?,
1392 name: protocol.name.try_into()?,
1393 index: *index,
1394 }
1395 }
1396 meta::AssociatedKind::Instance(name) => ContextError::ConflictingInstanceFunction {
1397 type_info: associated.container_type_info.try_clone()?,
1398 name: name.as_ref().try_into()?,
1399 },
1400 });
1401 }
1402
1403 Ok(())
1404 }
1405
1406 /// Define a new trait.
1407 pub fn define_trait(
1408 &mut self,
1409 item: impl IntoIterator<Item: IntoComponent>,
1410 ) -> Result<TraitMut<'_>, ContextError> {
1411 let item = self.item.join(item)?;
1412 let hash = Hash::type_hash(&item);
1413
1414 if !self.names.try_insert(Name::Item(hash))? {
1415 return Err(ContextError::ConflictingTrait { item, hash });
1416 }
1417
1418 self.traits.try_push(ModuleTrait {
1419 item,
1420 hash,
1421 common: ModuleItemCommon::default(),
1422 handler: None,
1423 functions: Vec::new(),
1424 })?;
1425
1426 let t = self.traits.last_mut().unwrap();
1427
1428 Ok(TraitMut {
1429 docs: &mut t.common.docs,
1430 #[cfg(feature = "doc")]
1431 deprecated: &mut t.common.deprecated,
1432 handler: &mut t.handler,
1433 functions: &mut t.functions,
1434 })
1435 }
1436
1437 /// Implement the trait `trait_item` for the type `T`.
1438 pub fn implement_trait<T>(&mut self, trait_item: &Item) -> Result<(), ContextError>
1439 where
1440 T: ?Sized + TypeOf + Named,
1441 {
1442 let hash = T::HASH;
1443 let type_info = T::type_info();
1444 let trait_hash = Hash::type_hash(trait_item);
1445
1446 if !self.names.try_insert(Name::TraitImpl(hash, trait_hash))? {
1447 return Err(ContextError::ConflictingTraitImpl {
1448 trait_item: trait_item.try_to_owned()?,
1449 trait_hash,
1450 item: T::ITEM.try_to_owned()?,
1451 hash,
1452 });
1453 }
1454
1455 self.trait_impls.try_push(ModuleTraitImpl {
1456 item: T::ITEM.try_to_owned()?,
1457 hash,
1458 type_info,
1459 trait_item: trait_item.try_to_owned()?,
1460 trait_hash,
1461 })?;
1462
1463 Ok(())
1464 }
1465
1466 /// Define a re-export.
1467 pub fn reexport(
1468 &mut self,
1469 item: impl IntoIterator<Item: IntoComponent>,
1470 to: &Item,
1471 ) -> Result<(), ContextError> {
1472 let item = self.item.join(item)?;
1473 let hash = Hash::type_hash(&item);
1474
1475 if !self.names.try_insert(Name::Item(hash))? {
1476 return Err(ContextError::ConflictingReexport {
1477 item,
1478 hash,
1479 to: to.try_to_owned()?,
1480 });
1481 }
1482
1483 self.reexports.try_push(ModuleReexport {
1484 item,
1485 hash,
1486 to: to.try_to_owned()?,
1487 })?;
1488
1489 Ok(())
1490 }
1491}
1492
1493impl AsRef<Module> for Module {
1494 #[inline]
1495 fn as_ref(&self) -> &Module {
1496 self
1497 }
1498}