-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Remove impl ScheduleLabel for Box<dyn ScheduleLabel>
#7556
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm very glad to see that this wasn't ultimately needed. Thanks for cleaning this up for me.
Is this really a problem? All the internal uses use |
Hmm, fair. I'm split on whether or not this is a better design or not, now that you mention it. Externally, being able to interact with boxed labels is very convenient. |
You are still able to use boxed schedule labels. This PR doesn't reduce its capabilities in any way. The main purpose of this PR is to prevent users from passing in a #[derive(ScheduleLabel, Clone, Debug, PartialEq, Eq, Hash)]
pub enum MySchedule {
MyLabel,
}
...
let label = MySchedule::MyLabel;
schedules.insert(label, my_schedule);
let boxed_label: Box<dyn ScheduleLabel> = Box::new(label);
// Correct, pass in a &dyn ScheduleLabel and remove the label.
schedules.remove(&*boxed_label);
// Incorrect, pass in a &Box<dyn ScheduleLabel>, this does not remove the label from the hashmap.
schedules.remove(&boxed_label); |
That makes sense. I'm just uncomfortable with needing both a Maybe it'd be better to make |
I understand your concerns. In my opinion, having two methods If you prefer I can amend the docs to clarify the need to box the label. This should also alleviate the potential surprise that |
One way to both remove the The insert method would then take |
To clarify my suggestion, I was saying to remove the ScheduleLabel on boxed labels still, but only have one insert method that takes a &dyn ScheduleLabel. So to insert you'd need to do |
Thanks for the clarification. I think this is a valid alternative to having two methods and definitely worth considering. I realize that I may need to have some more thoughts on this on what the best way to approach this problem. If it's alright with you and @alice-i-cecile, I will leave this PR open until when I make a patch with a better solution. |
Objective
Within stageless, schedule labels are stored in a HashMap as
Box<dyn ScheduleLabel>
in theSchedules
resource. In order to support inserting both concrete labels and boxed labels, theinsert
method ofSchedules
takes animpl ScheduleLabel
, and a global impl ofimpl ScheduleLabel for Box<dyn ScheduleLabel>
was added.However, this introduced a footgun where a user with a boxed label could accidently forget to dereference their label while working with it. Since the label always implements
ScheduleLabel
no matter how many pointers it is behind, this is not caught by the compiler and can lead to confusing errors at runtime.&dyn ScheduleLabel
as argument. If the user has amy_schedule_label: Box<dyn ScheduleLabel>
, they should pass it by&*my_schedule_label
. It is however easy to forget to dereference and pass in&my_schedule_label
instead. This compiles without warnings but means something entirely different.Solution
Remove
impl ScheduleLabel for Box<dyn ScheduleLabel>
. In order to continue to support inserting boxed labels, ainsert_boxed
method is added toSchedules
. Two places in the code now usesinsert_boxed
where they were usinginsert
before.Changelog
(Only relevant to bevy main users)
impl ScheduleLabel for Box<dyn ScheduleLabel>
insert_boxed
toSchedules
Schedules::insert
no longer accepts a boxed schedule label. Useinsert_boxed
instead.