mirror of
https://github.com/bevyengine/bevy
synced 2024-11-25 06:00:20 +00:00
bevy_reflect: Disambiguate type bounds in where clauses. (#8761)
# 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.
This commit is contained in:
parent
b72b15465d
commit
1e97c79ec1
2 changed files with 28 additions and 3 deletions
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in a new issue