diff --git a/README.md b/README.md index cc68898c..73ca1bb5 100644 --- a/README.md +++ b/README.md @@ -7,10 +7,13 @@ Rhai - Embedded Scripting for Rust [![crates.io](https://img.shields.io/crates/v/rhai.svg)](https://crates.io/crates/rhai/) [![crates.io](https://img.shields.io/crates/d/rhai)](https://crates.io/crates/rhai/) [![API Docs](https://docs.rs/rhai/badge.svg)](https://docs.rs/rhai/) +[![chat](https://img.shields.io/discord/767611025456889857.svg?logo=discord)](https://discord.gg/yZMKAQ) +[![Reddit](https://img.shields.io/reddit/subreddit-subscribers/Rhai)](https://www.reddit.com/r/Rhai) Rhai is an embedded scripting language and evaluation engine for Rust that gives a safe and easy way to add scripting to any application. + Supported targets and builds --------------------------- @@ -19,6 +22,7 @@ Supported targets and builds * `no-std` * Minimum Rust version 1.45 + Standard features ----------------- @@ -41,13 +45,15 @@ Standard features * Serialization/deserialization support via [serde](https://crates.io/crates/serde) (requires the `serde` feature). * Support for [minimal builds](https://schungx.github.io/rhai/start/builds/minimal.html) by excluding unneeded language [features](https://schungx.github.io/rhai/start/features.html). -Protection against attacks --------------------------- + +Protected against attacks +------------------------- * Sand-boxed - the scripting engine, if declared immutable, cannot mutate the containing environment unless [explicitly permitted](https://schungx.github.io/rhai/patterns/control.html). * Rugged - protected against malicious attacks (such as [stack-overflow](https://schungx.github.io/rhai/safety/max-call-stack.html), [over-sized data](https://schungx.github.io/rhai/safety/max-string-size.html), and [runaway scripts](https://schungx.github.io/rhai/safety/max-operations.html) etc.) that may come from untrusted third-party user-land scripts. * Track script evaluation [progress](https://schungx.github.io/rhai/safety/progress.html) and manually terminate a script run. + For those who actually want their own language --------------------------------------------- @@ -56,6 +62,7 @@ For those who actually want their own language * Define [custom operators](https://schungx.github.io/rhai/engine/custom-op.html). * Extend the language with [custom syntax](https://schungx.github.io/rhai/engine/custom-syntax.html). + Documentation ------------- @@ -65,12 +72,14 @@ To build _The Book_, first install [`mdbook`](https://github.com/rust-lang/mdBoo and [`mdbook-tera`](https://github.com/avitex/mdbook-tera) (for templating). Running `mdbook build` builds it. + Playground ---------- An [Online Playground](https://alvinhochun.github.io/rhai-demo/) is available with syntax-highlighting editor. Scripts can be evaluated directly from the editor. + License ------- diff --git a/doc/src/SUMMARY.md b/doc/src/SUMMARY.md index 1e59b3e7..962bdca1 100644 --- a/doc/src/SUMMARY.md +++ b/doc/src/SUMMARY.md @@ -36,8 +36,8 @@ The Rhai Scripting Language 4. [Register a Fallible Rust Function](rust/fallible.md) 6. [Override a Built-in Function](rust/override.md) 7. [Operator Overloading](rust/operators.md) - 8. [Register a Custom Type and its Methods](rust/custom.md) - 1. [Getters and Setters](rust/getters-setters.md) + 8. [Register any Rust Type and its Methods](rust/custom.md) + 1. [Property Getters and Setters](rust/getters-setters.md) 2. [Indexers](rust/indexers.md) 3. [Disable Custom Types](rust/disable-custom.md) 4. [Printing Custom Types](rust/print-custom.md) diff --git a/doc/src/about/related.md b/doc/src/about/related.md index 8174676b..a284c7f0 100644 --- a/doc/src/about/related.md +++ b/doc/src/about/related.md @@ -3,7 +3,9 @@ Related Resources {{#include ../links.md}} -Other online documentation resources for Rhai: + +Other Online Resources for Rhai +------------------------------ * [`crates.io`](https://crates.io/crates/rhai) - Rhai crate @@ -13,7 +15,13 @@ Other online documentation resources for Rhai: * [Online Playground][playground] - Run scripts directly from editor -Other cool projects to check out: +* [Discord Chat](https://discord.gg/yZMKAQ) - Rhai channel + +* [Reddit](https://www.reddit.com/r/Rhai) - Rhai community + + +Other Cool Projects +------------------- * [ChaiScript](http://chaiscript.com) - A strong inspiration for Rhai. An embedded scripting language for C++. diff --git a/doc/src/images/rhai.png b/doc/src/images/rhai.png new file mode 100644 index 00000000..73d16a99 Binary files /dev/null and b/doc/src/images/rhai.png differ diff --git a/doc/src/plugins/module.md b/doc/src/plugins/module.md index 81195d47..6d07abdc 100644 --- a/doc/src/plugins/module.md +++ b/doc/src/plugins/module.md @@ -8,7 +8,7 @@ Prelude ------- When using the plugins system, the entire `rhai::plugin` module must be imported as a prelude -because code generated will these imports. +because code generated will need these imports. ```rust use rhai::plugin::*; diff --git a/doc/src/rust/custom.md b/doc/src/rust/custom.md index eb548f69..59815079 100644 --- a/doc/src/rust/custom.md +++ b/doc/src/rust/custom.md @@ -1,124 +1,118 @@ -Register a Custom Type and its Methods +Register any Rust Type and its Methods ===================================== {{#include ../links.md}} -Rhai works seamlessly with _any_ complex Rust type. The type can be registered with the `Engine`, as below. + +Free Typing +----------- + +Rhai works seamlessly with _any_ Rust type. The type can be _anything_; it does not +have any prerequisites other than being `Clone`. It does not need to implement +any other trait or use any custom `#[derive]`. + +This allows Rhai to be integrated into an existing code base with as little plumbing +as possible, usually silently and seamlessly. External types that are not defined +within the same crate (and thus cannot implement special Rhai traits or +use special `#[derive]`) can also be used easily with Rhai. + +The reason why it is termed a _custom_ type throughout this documentation is that +Rhai natively supports a number of data types with fast, internal treatment (see +the list of [standard types]). Any type outside of this list is considered _custom_. + +Any type not supported natively by Rhai is stored as a Rust _trait object_, with no +restrictions other than being `Clone` (plus `Send + Sync` under the [`sync`] feature). +It runs slightly slower than natively-supported types as it does not have built-in, +optimized implementations for commonly-used functions, but for all other purposes has +no difference. Support for custom types can be turned off via the [`no_object`] feature. -```rust -use rhai::{Engine, EvalAltResult}; -use rhai::RegisterFn; // remember 'RegisterFn' is needed -#[derive(Clone)] -struct TestStruct { - field: i64 -} +Register a Custom Type and its Methods +------------------------------------- -impl TestStruct { - fn update(&mut self) { - self.field += 41; - } +Any custom type must implement the `Clone` trait as this allows the [`Engine`] to pass by value. - fn new() -> Self { - TestStruct { field: 1 } - } -} - -let mut engine = Engine::new(); - -engine - .register_type::() // most API's can be chained up - .register_fn("update", TestStruct::update) - .register_fn("new_ts", TestStruct::new); - -let result = engine.eval::("let x = new_ts(); x.update(); x")?; - -println!("result: {}", result.field); // prints 42 -``` - - -Register a Custom Type ---------------------- - -A custom type must implement `Clone` as this allows the [`Engine`] to pass by value. +If the [`sync`] feature is used, it must also be `Send + Sync`. Notice that the custom type needs to be _registered_ using `Engine::register_type` or `Engine::register_type_with_name`. +To use native methods on custom types in Rhai scripts, it is common to register an API +for the type using one of the `Engine::register_XXX` functions. + ```rust +use rhai::{Engine, EvalAltResult}; +use rhai::RegisterFn; // remember 'RegisterFn' is needed + #[derive(Clone)] struct TestStruct { field: i64 } impl TestStruct { - fn update(&mut self) { // methods take &mut as first parameter - self.field += 41; + fn new() -> Self { + Self { field: 1 } } - fn new() -> Self { - TestStruct { field: 1 } + fn update(&mut self, x: i64) { // methods take &mut as first parameter + self.field += x; } } let mut engine = Engine::new(); -engine.register_type::(); -``` - - -Methods on the Custom Type -------------------------- - -To use native custom types, methods and functions in Rhai scripts, simply register them -using one of the `Engine::register_XXX` API. - -Below, the `update` and `new` methods are registered using `Engine::register_fn`. - -```rust +// Most Engine API's can be chained up. engine - .register_fn("update", TestStruct::update) // registers 'update(&mut TestStruct)' - .register_fn("new_ts", TestStruct::new); // registers 'new()' + .register_type::() // register custom type + .register_fn("new_ts", TestStruct::new) + .register_fn("update", TestStruct::update); + +// Cast result back to custom type. +let result = engine.eval::( + r" + let x = new_ts(); // calls 'TestStruct::new' + x.update(41); // calls 'TestStruct::update' + x // 'x' holds a 'TestStruct' + " +)?; + +println!("result: {}", result.field); // prints 42 ``` -***Note**: Rhai follows the convention that methods of custom types take a `&mut` first parameter -so that invoking methods can update the types. All other parameters in Rhai are passed by value (i.e. clones).* +Rhai follows the convention that methods of custom types take a `&mut` first parameter +to that type, so that invoking methods can always update it. + +All other parameters in Rhai are passed by value (i.e. clones). **IMPORTANT: Rhai does NOT support normal references (i.e. `&T`) as parameters.** -Use the Custom Type in Scripts ------------------------------ - -The custom type is then ready for use in scripts. Scripts can see the functions and methods registered earlier. -Get the evaluation result back out just as before, this time casting to the custom type: - -```rust -let result = engine.eval::("let x = new_ts(); x.update(); x")?; - -println!("result: {}", result.field); // prints 42 -``` - - Method-Call Style vs. Function-Call Style ---------------------------------------- Any function with a first argument that is a `&mut` reference can be used as method calls because internally they are the same thing: methods on a type is implemented as a functions taking a `&mut` first argument. + This design is similar to Rust. ```rust -fn foo(ts: &mut TestStruct) -> i64 { - ts.field +impl TestStruct { + fn foo(&mut self) -> i64 { + self.field + } } -engine.register_fn("foo", foo); // register a Rust native function +engine.register_fn("foo", TestStruct::foo); let result = engine.eval::( - "let x = new_ts(); x.foo()" // 'foo' can be called like a method on 'x' + r" + let x = new_ts(); + foo(x); // normal call to 'foo' + x.foo() // 'foo' can also be called like a method on 'x' + " )?; println!("result: {}", result); // prints 1 @@ -128,8 +122,9 @@ Under [`no_object`], however, the _method_ style of function calls (i.e. calling a function as an object-method) is no longer supported. ```rust -// Below is a syntax error under 'no_object' because 'clear' cannot be called in method style. -let result = engine.eval::<()>("let x = [1, 2, 3]; x.clear()")?; +// Below is a syntax error under 'no_object'. +let result = engine.eval("let x = [1, 2, 3]; x.clear();")?; + // ^ cannot call in method style under 'no_object' ``` @@ -143,18 +138,16 @@ with a special "pretty-print" name, [`type_of()`] will return that name instead. ```rust engine - .register_type::() - .register_fn("new_ts", TestStruct::new); + .register_type::() + .register_fn("new_ts1", TestStruct1::new) + .register_type_with_name::("MyType") + .register_fn("new_ts2", TestStruct2::new); -let x = new_ts(); -x.type_of() == "path::to::module::TestStruct"; +let ts1_type = engine.eval::(r#"let x = new_ts1(); x.type_of()"#)?; +let ts2_type = engine.eval::(r#"let x = new_ts2(); x.type_of()"#)?; -engine - .register_type_with_name::("Hello") - .register_fn("new_ts", TestStruct::new); - -let x = new_ts(); -x.type_of() == "Hello"; +println!("{}", ts1_type); // prints 'path::to::TestStruct' +println!("{}", ts1_type); // prints 'MyType' ``` @@ -190,7 +183,9 @@ the `==` operator must be registered for the custom type: ```rust // Assume 'TestStruct' implements `PartialEq` -engine.register_fn("==", |item1: &mut TestStruct, item2: TestStruct| item1 == item2); +engine.register_fn("==", + |item1: &mut TestStruct, item2: TestStruct| item1 == &item2 +); // Then this works in Rhai: let item = new_ts(); // construct a new 'TestStruct' diff --git a/doc/src/rust/getters-setters.md b/doc/src/rust/getters-setters.md index 586070af..334c7438 100644 --- a/doc/src/rust/getters-setters.md +++ b/doc/src/rust/getters-setters.md @@ -1,29 +1,32 @@ -Custom Type Getters and Setters -============================== +Custom Type Property Getters and Setters +======================================= {{#include ../links.md}} -A custom type can also expose members by registering `get` and/or `set` functions. +A [custom type] can also expose properties by registering `get` and/or `set` functions. Getters and setters each take a `&mut` reference to the first parameter. Getters and setters are disabled when the [`no_object`] feature is used. -| `Engine` API | Description | Return Value of Function | -| --------------------- | ------------------------------------------------- | :-----------------------------------: | -| `register_get` | register a getter | _any_ `T: Clone` | -| `register_set` | register a setter | _none_ | -| `register_get_set` | short-hand to register both a getter and a setter | _none_ | -| `register_get_result` | register a getter | `Result>` | -| `register_set_result` | register a setter | `Result<(), Box>` | +| `Engine` API | Function signature(s)
(`T: Clone` = custom type,
`V: Clone` = data type) | Can mutate `T`? | +| --------------------- | -------------------------------------------------------------------------------- | :----------------------------: | +| `register_get` | `Fn(&mut T) -> V` | yes, but not advised | +| `register_set` | `Fn(&mut T, V)` | yes | +| `register_get_set` | getter: `Fn(&mut T) -> V`
setter: `Fn(&mut T, V)` | yes, but not advised in getter | +| `register_get_result` | `Fn(&mut T) -> Result>` | yes, but not advised | +| `register_set_result` | `Fn(&mut T, V) -> Result<(), Box>` | yes | + +By convention, property getters are not supposed to mutate the [custom type], although there is nothing +that prevents this mutation. Cannot Override Object Maps -------------------------- -Getters and setters are only intended for [custom types]. +Property getters and setters are mainly intended for [custom types]. -Any getter or setter function registered for [object maps] is simply ignored because +Any getter or setter function registered for [object maps] is simply _ignored_ because the get/set calls will be interpreted as properties on the [object maps]. @@ -47,7 +50,7 @@ impl TestStruct { } fn new() -> Self { - TestStruct { field: "hello" } + Self { field: "hello" } } } diff --git a/doc/src/rust/indexers.md b/doc/src/rust/indexers.md index 2f76277f..f7cff1af 100644 --- a/doc/src/rust/indexers.md +++ b/doc/src/rust/indexers.md @@ -3,23 +3,30 @@ Custom Type Indexers {{#include ../links.md}} -A custom type can also expose an _indexer_ by registering an indexer function. +A [custom type] can also expose an _indexer_ by registering an indexer function. -A custom type with an indexer function defined can use the bracket notation to get a property value: +A [custom type] with an indexer function defined can use the bracket notation to get a property value: > _object_ `[` _index_ `]` -Like getters and setters, indexers take a `&mut` reference to the first parameter. +Like property [getters/setters], indexers take a `&mut` reference to the first parameter. + +They also take an additional parameter of any type that serves as the _index_ within brackets. Indexers are disabled when the [`no_index`] feature is used. -| `Engine` API | Description | Return Value of Function | -| ----------------------------- | -------------------------------------------------------- | :-----------------------------------: | -| `register_indexer_get` | register an index getter | _any_ `T: Clone` | -| `register_indexer_set` | register an index setter | _none_ | -| `register_indexer_get_set` | short-hand to register both an index getter and a setter | _none_ | -| `register_indexer_get_result` | register an index getter | `Result>` | -| `register_indexer_set_result` | register an index setter | `Result<(), Box>` | +| `Engine` API | Function signature(s)
(`T: Clone` = custom type,
`X: Clone` = index type,
`V: Clone` = data type) | Can mutate `T`? | +| ----------------------------- | ------------------------------------------------------------------------------------------------------------- | :----------------------------: | +| `register_indexer_get` | `Fn(&mut T, X) -> V` | yes, but not advised | +| `register_indexer_set` | `Fn(&mut T, X, V)` | yes | +| `register_indexer_get_set` | getter: `Fn(&mut T, X) -> V`
setter: `Fn(&mut T, X, V)` | yes, but not advised in getter | +| `register_indexer_get_result` | `Fn(&mut T, X) -> Result>` | yes, but not advised | +| `register_indexer_set_result` | `Fn(&mut T, X, V) -> Result<(), Box>` | yes | + +By convention, index getters are not supposed to mutate the [custom type], although there is nothing +that prevents this mutation. + +**IMPORTANT: Rhai does NOT support normal references (i.e. `&T`) as parameters.** Cannot Override Arrays, Object Maps and Strings @@ -42,15 +49,15 @@ struct TestStruct { impl TestStruct { // Remember &mut must be used even for getters - fn get_field(&mut self, index: i64) -> i64 { - self.fields[index as usize] + fn get_field(&mut self, index: String) -> i64 { + self.fields[index.len()] } - fn set_field(&mut self, index: i64, value: i64) { - self.fields[index as usize] = value + fn set_field(&mut self, index: String, value: i64) { + self.fields[index.len()] = value } fn new() -> Self { - TestStruct { fields: vec![1, 2, 3, 4, 5] } + Self { fields: vec![1, 2, 3, 4, 5] } } } @@ -63,9 +70,13 @@ engine .register_indexer_get(TestStruct::get_field) .register_indexer_set(TestStruct::set_field); -let result = engine.eval::("let a = new_ts(); a[2] = 42; a[2]")?; +let result = engine.eval::( + r#" + let a = new_ts(); + a["xyz"] = 42; // these indexers use strings + a["xyz"] // as the index type + "# +)?; println!("Answer: {}", result); // prints 42 ``` - -**IMPORTANT: Rhai does NOT support normal references (i.e. `&T`) as parameters.** diff --git a/doc/src/rust/register-raw.md b/doc/src/rust/register-raw.md index dc4e3ca2..87854acc 100644 --- a/doc/src/rust/register-raw.md +++ b/doc/src/rust/register-raw.md @@ -65,7 +65,7 @@ The function signature passed to `Engine::register_raw_fn` takes the following f where: -* `T: Variant + Clone` - return type of the function. +* `T: Clone` - return type of the function. * `context: NativeCallContext` - the current _native call context_, which exposes the following: diff --git a/examples/arrays_and_structs.rs b/examples/arrays_and_structs.rs index 6aa9fafa..0ad34051 100644 --- a/examples/arrays_and_structs.rs +++ b/examples/arrays_and_structs.rs @@ -11,7 +11,7 @@ impl TestStruct { } fn new() -> Self { - TestStruct { x: 1 } + Self { x: 1 } } } diff --git a/examples/custom_types_and_methods.rs b/examples/custom_types_and_methods.rs index 4a8e260a..4b0118fa 100644 --- a/examples/custom_types_and_methods.rs +++ b/examples/custom_types_and_methods.rs @@ -11,7 +11,7 @@ impl TestStruct { } fn new() -> Self { - TestStruct { x: 1 } + Self { x: 1 } } } diff --git a/src/api.rs b/src/api.rs index 031e06b7..07f0cef1 100644 --- a/src/api.rs +++ b/src/api.rs @@ -88,7 +88,7 @@ impl Engine { /// } /// /// impl TestStruct { - /// fn new() -> Self { TestStruct { field: 1 } } + /// fn new() -> Self { Self { field: 1 } } /// fn update(&mut self, offset: i64) { self.field += offset; } /// } /// @@ -130,7 +130,7 @@ impl Engine { /// } /// /// impl TestStruct { - /// fn new() -> Self { TestStruct { field: 1 } } + /// fn new() -> Self { Self { field: 1 } } /// } /// /// # fn main() -> Result<(), Box> { @@ -200,7 +200,7 @@ impl Engine { /// } /// /// impl TestStruct { - /// fn new() -> Self { TestStruct { field: 1 } } + /// fn new() -> Self { Self { field: 1 } } /// // Even a getter must start with `&mut self` and not `&self`. /// fn get_field(&mut self) -> i64 { self.field } /// } @@ -252,7 +252,7 @@ impl Engine { /// } /// /// impl TestStruct { - /// fn new() -> Self { TestStruct { field: 1 } } + /// fn new() -> Self { Self { field: 1 } } /// // Even a getter must start with `&mut self` and not `&self`. /// fn get_field(&mut self) -> Result> { /// Ok(self.field.into()) @@ -295,7 +295,7 @@ impl Engine { /// } /// /// impl TestStruct { - /// fn new() -> Self { TestStruct { field: 1 } } + /// fn new() -> Self { Self { field: 1 } } /// fn set_field(&mut self, new_val: i64) { self.field = new_val; } /// } /// @@ -348,7 +348,7 @@ impl Engine { /// } /// /// impl TestStruct { - /// fn new() -> Self { TestStruct { field: 1 } } + /// fn new() -> Self { Self { field: 1 } } /// fn set_field(&mut self, new_val: i64) -> Result<(), Box> { /// self.field = new_val; /// Ok(()) @@ -386,8 +386,7 @@ impl Engine { U: Variant + Clone, { self.register_result_fn(&make_setter(name), move |obj: &mut T, value: U| { - callback(obj, value)?; - Ok(().into()) + callback(obj, value).map(Into::into) }) } @@ -405,7 +404,7 @@ impl Engine { /// } /// /// impl TestStruct { - /// fn new() -> Self { TestStruct { field: 1 } } + /// fn new() -> Self { Self { field: 1 } } /// // Even a getter must start with `&mut self` and not `&self`. /// fn get_field(&mut self) -> i64 { self.field } /// fn set_field(&mut self, new_val: i64) { self.field = new_val; } @@ -462,7 +461,7 @@ impl Engine { /// } /// /// impl TestStruct { - /// fn new() -> Self { TestStruct { fields: vec![1, 2, 3, 4, 5] } } + /// fn new() -> Self { Self { fields: vec![1, 2, 3, 4, 5] } } /// // Even a getter must start with `&mut self` and not `&self`. /// fn get_field(&mut self, index: i64) -> i64 { self.fields[index as usize] } /// } @@ -534,7 +533,7 @@ impl Engine { /// } /// /// impl TestStruct { - /// fn new() -> Self { TestStruct { fields: vec![1, 2, 3, 4, 5] } } + /// fn new() -> Self { Self { fields: vec![1, 2, 3, 4, 5] } } /// // Even a getter must start with `&mut self` and not `&self`. /// fn get_field(&mut self, index: i64) -> Result> { /// Ok(self.fields[index as usize].into()) @@ -600,7 +599,7 @@ impl Engine { /// } /// /// impl TestStruct { - /// fn new() -> Self { TestStruct { fields: vec![1, 2, 3, 4, 5] } } + /// fn new() -> Self { Self { fields: vec![1, 2, 3, 4, 5] } } /// fn set_field(&mut self, index: i64, value: i64) { self.fields[index as usize] = value; } /// } /// @@ -672,7 +671,7 @@ impl Engine { /// } /// /// impl TestStruct { - /// fn new() -> Self { TestStruct { fields: vec![1, 2, 3, 4, 5] } } + /// fn new() -> Self { Self { fields: vec![1, 2, 3, 4, 5] } } /// fn set_field(&mut self, index: i64, value: i64) -> Result<(), Box> { /// self.fields[index as usize] = value; /// Ok(()) @@ -724,8 +723,7 @@ impl Engine { } self.register_result_fn(FN_IDX_SET, move |obj: &mut T, index: X, value: U| { - callback(obj, index, value)?; - Ok(().into()) + callback(obj, index, value).map(Into::into) }) } @@ -745,7 +743,7 @@ impl Engine { /// } /// /// impl TestStruct { - /// fn new() -> Self { TestStruct { fields: vec![1, 2, 3, 4, 5] } } + /// fn new() -> Self { Self { fields: vec![1, 2, 3, 4, 5] } } /// // Even a getter must start with `&mut self` and not `&self`. /// fn get_field(&mut self, index: i64) -> i64 { self.fields[index as usize] } /// fn set_field(&mut self, index: i64, value: i64) { self.fields[index as usize] = value; } diff --git a/src/engine.rs b/src/engine.rs index bc7063dc..c526b561 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -934,7 +934,9 @@ impl Engine { level, ) .map_err(|err| match *err { - EvalAltResult::ErrorFunctionNotFound(_, _) => { + EvalAltResult::ErrorFunctionNotFound(fn_sig, _) + if fn_sig.ends_with("]=") => + { EvalAltResult::ErrorIndexingType( self.map_type_name(val_type_name).into(), Position::none(), @@ -1381,9 +1383,12 @@ impl Engine { ) .map(|(v, _)| v.into()) .map_err(|err| match *err { - EvalAltResult::ErrorFunctionNotFound(_, _) => Box::new( - EvalAltResult::ErrorIndexingType(type_name.into(), Position::none()), - ), + EvalAltResult::ErrorFunctionNotFound(fn_sig, _) if fn_sig.ends_with("]") => { + Box::new(EvalAltResult::ErrorIndexingType( + type_name.into(), + Position::none(), + )) + } _ => err, }) } diff --git a/tests/arrays.rs b/tests/arrays.rs index cbd4daf5..65811a23 100644 --- a/tests/arrays.rs +++ b/tests/arrays.rs @@ -84,7 +84,7 @@ fn test_array_with_structs() -> Result<(), Box> { } fn new() -> Self { - TestStruct { x: 1 } + Self { x: 1 } } } diff --git a/tests/float.rs b/tests/float.rs index ea87ece3..534115e3 100644 --- a/tests/float.rs +++ b/tests/float.rs @@ -51,7 +51,7 @@ fn test_struct_with_float() -> Result<(), Box> { } fn new() -> Self { - TestStruct { x: 1.0 } + Self { x: 1.0 } } } diff --git a/tests/get_set.rs b/tests/get_set.rs index ca5c0c47..b654348c 100644 --- a/tests/get_set.rs +++ b/tests/get_set.rs @@ -25,7 +25,7 @@ fn test_get_set() -> Result<(), Box> { } fn new() -> Self { - TestStruct { + Self { x: 1, y: 0, array: vec![1, 2, 3, 4, 5], diff --git a/tests/method_call.rs b/tests/method_call.rs index 20612146..e7b863e6 100644 --- a/tests/method_call.rs +++ b/tests/method_call.rs @@ -15,7 +15,7 @@ fn test_method_call() -> Result<(), Box> { } fn new() -> Self { - TestStruct { x: 1 } + Self { x: 1 } } } diff --git a/tests/mismatched_op.rs b/tests/mismatched_op.rs index 01373df2..5ef401f0 100644 --- a/tests/mismatched_op.rs +++ b/tests/mismatched_op.rs @@ -20,7 +20,7 @@ fn test_mismatched_op_custom_type() { impl TestStruct { fn new() -> Self { - TestStruct { x: 1 } + Self { x: 1 } } }