Skip to content

Commit

Permalink
Update v0.10 release notes (add breaking changes)
Browse files Browse the repository at this point in the history
  • Loading branch information
khvzak committed Oct 30, 2024
1 parent 76b896e commit d27d136
Showing 1 changed file with 61 additions and 0 deletions.
61 changes: 61 additions & 0 deletions docs/release_notes/v0.10.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,3 +132,64 @@ let f = lua.create_function(|_, ()| {
Ok(())
})?;
```

### Breaking changes

#### Scope changes

The following `Scope` methods were changed:
- Removed `Scope::create_any_userdata`
- `Scope::create_nonstatic_userdata` is renamed to `Scope::create_userdata`

Instead, scope has comprehensive support for borrowed userdata: `create_any_userdata_ref`, `create_any_userdata_ref_mut`, `create_userdata_ref`, `create_userdata_ref_mut`.

`UserDataRef` and `UserDataRefMut` are no longer acceptable for scoped userdata access as they require owned underlying data.
In mlua v0.9 this can cause read-after-free bug in some edge cases.

To temporarily borrow underlying data, the `AnyUserData::borrow_scoped` and `AnyUserData::borrow_mut_scoped` methods were introduced:

```rust
let data = "hello".to_string();
lua.scope(|scope| {
let ud = scope.create_any_userdata_ref(&data)?;

// We can only borrow scoped userdata using this method
ud.borrow_scoped::<String, ()>(|s| {
assert_eq!(s, "hello");
})?;

Ok(())
})?;
```

Those methods work for scoped and regular userdata objects (but still require `T: 'static`).

#### String changes

Since `mlua::String` holds a weak reference to Lua without any guarantees about the lifetime of the underlying data, getting a `&str` or `&[u8]` from it is no longer safe.
Lua instance can be destroyed while reference to the data is still alive:

```rust
let lua = Lua::new();
let s: mlua::String = lua.create_string("hello, world")?; // only weak reference to Lua!
let s_ref: &str = s.to_str()?; // this is not safe!
drop(lua);
println!("{s_ref}"); // use after free!
```

To solve this issue, return types of `mlua::String::to_str` and `mlua::String::as_bytes` methods changed to `BorrowedStr` and `BorrowedBytes` respectively.

These new types hold a strong reference to the Lua instance and can be safely converted to `&str` or `&[u8]`:

```rust
let lua = Lua::new();
let s: mlua::String = lua.create_string("hello, world")?;
let s_ref: mlua::BorrowedStr = s.to_str()?; // The strong reference to Lua is held here
drop(lua);
println!("{s_ref}"); // ok
```

The good news is that `BorrowedStr` implements `Deref<Target = str>`/`AsRef<str>` as well as `Display`, `Debug`, `Eq`, `PartialEq` and other traits for easy usage.
The same applies to `BorrowedBytes`.

Unfortunately, `mlua::String::to_string_lossy` cannot return `Cow<'a, str>` anymore, because it requires a strong reference to Lua. It now returns Rust `String` instead.

0 comments on commit d27d136

Please sign in to comment.