Skip to content

Commit

Permalink
Make generic container types InteriorMutable
Browse files Browse the repository at this point in the history
Affects NSEnumerator, NSArray, NSDictionary, NSSet and the mutable
variants.

This removes all `_mut` methods and `Mut` iterators, as these are now
both unsound and unnecessary.

Most methods are also converted to `_retained` variants, as returning
references is unsound if the collection is mutated. `_unchecked`
variants are provided as alternatives instead.

At the same time, we remove a bunch of helper methods that are now
unnecessary, including `from_vec`.

Finally, we add a fuzz target for ensuring that the safe methods do
catch mutation mistakes.
  • Loading branch information
madsmtm committed Sep 4, 2024
1 parent d6f570d commit 032b698
Show file tree
Hide file tree
Showing 45 changed files with 1,862 additions and 2,539 deletions.
4 changes: 4 additions & 0 deletions crates/header-translator/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,10 @@ specific API!
3. If the method can throw an exception if provided with invalid inputs, it is
not safe. Consider declaring a helper method that checks the preconditions
first!

Invalid indexes will throw `NSRangeException`, which is _technically_ still
unsafe, but everything in Objective-C can throw, so we won't really bother
with that in our evaluation.
4. Beware of `Mutable` classes; these usually need to be passed as `&mut T`, or
operate on `&mut self`.

Expand Down
44 changes: 34 additions & 10 deletions crates/header-translator/src/stmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use std::collections::BTreeMap;
use std::collections::BTreeSet;
use std::collections::HashSet;
use std::fmt;
use std::fmt::Display;
use std::iter;

use clang::{Entity, EntityKind, EntityVisitResult};
Expand Down Expand Up @@ -405,28 +406,46 @@ impl Mutability {
Mutability::Mutable | Mutability::MutableWithImmutableSuperclass(_)
)
}
}

impl fmt::Display for Mutability {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
fn display<'a>(&'a self, other_generics: impl Display + 'a) -> impl Display + 'a {
FormatterFn(move |f| match self {
Self::Immutable => write!(f, "Immutable"),
Self::Mutable => write!(f, "Mutable"),
Self::ImmutableWithMutableSubclass(subclass) => {
write!(f, "ImmutableWithMutableSubclass<{}>", subclass.path())
write!(
f,
"ImmutableWithMutableSubclass<{}{}>",
subclass.path(),
other_generics
)
}
Self::MutableWithImmutableSuperclass(superclass) => {
write!(f, "MutableWithImmutableSuperclass<{}>", superclass.path())
write!(
f,
"MutableWithImmutableSuperclass<{}{}>",
superclass.path(),
other_generics
)
}
Self::InteriorMutable => write!(f, "InteriorMutable"),
Self::InteriorMutableWithSubclass(subclass) => {
write!(f, "InteriorMutableWithSubclass<{}>", subclass.path())
write!(
f,
"InteriorMutableWithSubclass<{}{}>",
subclass.path(),
other_generics
)
}
Self::InteriorMutableWithSuperclass(superclass) => {
write!(f, "InteriorMutableWithSuperclass<{}>", superclass.path())
write!(
f,
"InteriorMutableWithSuperclass<{}{}>",
superclass.path(),
other_generics
)
}
Self::MainThreadOnly => write!(f, "MainThreadOnly"),
}
})
}
}

Expand Down Expand Up @@ -1779,7 +1798,12 @@ impl Stmt {
superclass.path_in_relation_to(id.location()),
GenericTyHelper(superclass_generics),
)?;
writeln!(f, " type Mutability = {mutability};")?;
writeln!(
f,
" type Mutability = {};",
// Counterpart classes are required to have the same generics.
mutability.display(GenericTyHelper(generics)),
)?;
if !generics.is_empty() {
writeln!(f)?;
writeln!(
Expand Down
5 changes: 5 additions & 0 deletions crates/objc2/src/topics/about_generated/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- `NSCharacterSet` and `NSMutableCharacterSet`.
- `NSURLRequest` and `NSMutableURLRequest`.
- `NSData` and `NSMutableData`.
- `NSEnumerator`.
- `NSArray` and `NSMutableArray`.
- `NSDictionary` and `NSMutableDictionary`.
- `NSSet`, `NSMutableSet`, `NSCountedSet`, `NSOrderedSet` and
`NSMutableOrderedSet`.

This means that these can now be `retain`-ed like you would expect, and you
no longer need to use `mut` to mutate them, but it also means that they are
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 032b698

Please sign in to comment.