-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Lint against &T
to &mut T
and &T
to &UnsafeCell<T>
transmutes
#118446
Lint against &T
to &mut T
and &T
to &UnsafeCell<T>
transmutes
#118446
Conversation
This adds the lint against `&T`->`&UnsafeCell<T>` transmutes, and also check in struct fields. The code is quite complex; I've tried my best to simplify and comment it. This is missing one parts: array transmutes. When transmuting an array, this only consider the first element. The reason for that is that the code is already quite complex, and I didn't want to complicate it more. This catches the most common pattern of transmuting an array into an array of the same length with type of the same size; more complex cases are likely not properly handled. We could take a bigger sample, for example the first and last elements to increase the chance that the lint will catch mistakes, but then the runtime complexity becomes exponential with the nesting of the arrays (`[[[[[T; 2]; 2]; 2]; 2]; 2]` has complexity of O(2**5), for instance).
r? @cjgillot (rustbot has picked a reviewer for you, use r? to override) |
The job Click to see the possible cause of the failure (guessed by this bot)
|
The CI failure is exactly the Tree Borrows problem I was talking about... Apparently it is checked in a test. What am I supposed to do? Downgrade it to warn by default? Allow the lint in the test? |
I see significant overlap with the |
@Nilstrieb Indeed; that is why I said
Do you prefer to fix this on this PR? |
I think it would be nice if this logic could be shared between mutable_transmutes and invalid_reference_casting so they both have this detection. |
@Nilstrieb It turns out there isn't much to share: Only one function is similar enough, and even it is different enough to make sharing not worth it. I'm already on it, though, so I'll push this addition to this PR soon. |
let mut breadcrumbs = self.0.as_slice(); | ||
while let &[current_breadcrumb, ref rest_breadcrumbs @ ..] = breadcrumbs { | ||
breadcrumbs = rest_breadcrumbs; |
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.
let mut breadcrumbs = self.0.as_slice(); | |
while let &[current_breadcrumb, ref rest_breadcrumbs @ ..] = breadcrumbs { | |
breadcrumbs = rest_breadcrumbs; | |
for ¤t_breadcrumb in &self.0 { |
?
while let &[current_breadcrumb, ref rest_breadcrumbs @ ..] = breadcrumbs { | ||
breadcrumbs = rest_breadcrumbs; | ||
|
||
match ty.kind() { |
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.
match ty.kind() { | |
ty = match ty.kind() { |
to make the code flow a bit clearer
CheckFields, | ||
DoNotCheckFields, |
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.
Yes/No should be enough.
CheckFields, | ||
DoNotCheckFields, |
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.
Yes/No should be enough here too.
☔ The latest upstream changes (presumably #120242) made this pull request unmergeable. Please resolve the merge conflicts. |
@ChayimFriedman2 any updates on the changes requested above? thanks |
Closing this as inactive. Feel free to reöpen this pr or create a new pr if you get the time to work on this. Thanks |
This adds the lint against
&T
->&UnsafeCell<T>
transmutes, and also check in struct fields.The code is quite complex; I've tried my best to simplify and comment it.
This is missing one parts: array transmutes. When transmuting an array, this only consider the first element. The reason for that is that the code is already quite complex, and I didn't want to complicate it more. This catches the most common pattern of transmuting an array into an array of the same length with type of the same size; more complex cases are likely not properly handled. We could take a bigger sample, for example the first and last elements to increase the chance that the lint will catch mistakes, but then the runtime complexity becomes exponential with the nesting of the arrays (
[[[[[T; 2]; 2]; 2]; 2]; 2]
has complexity of O(2**5), for instance).Fixes #111229.
I've made this a deny-by-default and the wording says it's immediate UB, but from what I understand, under Tree Borrows this is not UB? CC rust-lang/unsafe-code-guidelines#303. So maybe we should make this warn-by-default and make the wording less strong. But #111229 says it causes miscompilations... So I'm not sure what is really the situation.
This also doesn't handle other ways of doing the transmute, such as via pointer casts. A fix for that should be quite simple, but I left it out for future PR.