Skip to content

Commit

Permalink
bevy_reflect: Disambiguate type bounds in where clauses. (#8761)
Browse files Browse the repository at this point in the history
# Objective

It was accidentally found that rustc is unable to parse certain
constructs in `where` clauses properly. `bevy_reflect::Reflect`'s habit
of copying and pasting the field types in a type's definition to its
`where` clauses made it very easy to accidentally run into this
behaviour - particularly with the construct
```rust
where
    for<'a> fn(&'a T) -> &'a T: Trait1 + Trait2
```

which was incorrectly parsed as
```rust
where
    for<'a> (fn(&'a T) -> &'a T: Trait1 + Trait2)
            ^                                   ^ incorrect syntax grouping
```

instead of
```rust
where
    (for<'a> fn(&'a T) -> &'a T): Trait1 + Trait2
    ^                          ^ correct syntax grouping
```

Fixes #8759 

## Solution

This commit fixes the issue by inserting explicit parentheses to
disambiguate types from their bound lists.
  • Loading branch information
Themayu authored Jun 5, 2023
1 parent b72b154 commit 1e97c79
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 3 deletions.
11 changes: 8 additions & 3 deletions crates/bevy_reflect/bevy_reflect_derive/src/utility.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,11 +155,16 @@ pub(crate) fn extend_where_clause(
} else {
quote!()
};

// The nested parentheses here are required to properly scope HRTBs coming
// from field types to the type itself, as the compiler will scope them to
// the whole bound by default, resulting in a failure to prove trait
// adherence.
generic_where_clause.extend(quote! {
#(#active_types: #active_trait_bounds,)*
#(#ignored_types: #ignored_trait_bounds,)*
#((#active_types): #active_trait_bounds,)*
#((#ignored_types): #ignored_trait_bounds,)*
// Leave parameter bounds to the end for more sane error messages.
#(#parameter_types: #parameter_trait_bounds,)*
#((#parameter_types): #parameter_trait_bounds,)*
});
generic_where_clause
}
Expand Down
20 changes: 20 additions & 0 deletions crates/bevy_reflect/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1426,6 +1426,26 @@ mod tests {
assert!(info.is::<MyValue>());
}

#[test]
fn should_permit_higher_ranked_lifetimes() {
#[derive(Reflect)]
struct TestStruct {
#[reflect(ignore)]
_hrl: for<'a> fn(&'a str) -> &'a str,
}

impl Default for TestStruct {
fn default() -> Self {
TestStruct {
_hrl: |input| input,
}
}
}

fn get_type_registration<T: GetTypeRegistration>() {}
get_type_registration::<TestStruct>();
}

#[test]
fn should_permit_valid_represented_type_for_dynamic() {
let type_info = <[i32; 2] as Typed>::type_info();
Expand Down

0 comments on commit 1e97c79

Please sign in to comment.