Add FCW for invalid C variadic arguments - #162478
Conversation
|
rustbot has assigned @dingxiangfei2009. Use Why was this reviewer chosen?The reviewer was selected based on:
|
| @future_incompatible = FutureIncompatibleInfo { | ||
| reason: fcw!(FutureReleaseError #61275), | ||
| }; |
There was a problem hiding this comment.
Ah, people changed the syntax of this macro again and now one cannot easily tell whether this will be reported in dependencies or not. :/
That's a side-effect of #141936. @WaffleLapkin why is report_in_depds an optional field? The default is far from obvious. (When I introduced FutureReleaseErrorDontReportInDeps many people were surprised that FCW do not report-in-deps by default. That's why I introduced this name that makes it so obvious. IMO it is a step backwards that now we again have syntax where this is not obvious.)
There was a problem hiding this comment.
Based on this, it seems that the field being optional is intentional:
rust/compiler/rustc_lint_defs/src/lib.rs
Lines 324 to 335 in 745de6e
There was a problem hiding this comment.
I think that's a bad choice. It certainly could have warranted a bit more discussion, given that this effectively reverted changes I made previously (#116049), in terms of what is and is not explicit in the API.
I guess people weren't aware of the prior discussion and didn't realize the downsides of the new API choice. Time to make another PR to make report_in_depds mandatory I guess... except I don't know how to make it mandatory just for FutureReleaseError; we don't need it mandatory for edition errors as those "obviously" are not reported in dependencies. That's the downside of the new structure...
There was a problem hiding this comment.
I was indeed not aware of the previous discussion, ugh =_=
I think the justification from #141936, "It gets especially unruly if you want to add non-FutureReleaseError* warnings which are included in the reports." was targeted at EditionAndFutureReleaseError which I was working with at the time, in the process of stabilizing never.
Looking at the current structure, I'd say we can put report_in_deps in ReleaseFcw. That adds the assumption that we only want to report warnings in dependencies if we plan to change something in a future release, but I guess that's fine (and is at the very least currently true).
I'll make a PR for this.
There was a problem hiding this comment.
Looking at the current structure, I'd say we can put report_in_deps in ReleaseFcw. That adds the assumption that we only want to report warnings in dependencies if we plan to change something in a future release, but I guess that's fine (and is at the very least currently true).
I was assuming you'd not want that since it seems to partially revert your PR #141936, by coupling report_in_deps with the reason again. But it sounds great to me so if you can also live with it, all good. :)
I'll make a PR for this.
❤️
There was a problem hiding this comment.
Presumably we'd then add ReleaseFcw to EditionAndFutureReleaseError and to EditionAndFutureReleaseSemanticsChange? (Currently these only include EditionFcw.)
If helpful to factoring, note that lang has been following the policy of setting report_in_deps = true exactly when we make an FCW deny-by-default (and otherwise setting report_in_deps = false). Possibly, after cleaning up any lingering exceptions, it could be OK to lean on that.
There was a problem hiding this comment.
#159700 is a recent example of a Warn + report_in_deps lint. It also shows up in a lot of dependency trees so maybe that was not a good call and it should have been Warn-only for a while like normal FCWs...
This comment has been minimized.
This comment has been minimized.
2ff9fb2 to
5cb13f7
Compare
|
It would be good to do a crater check run with the lint level set to deny to see if there are any commonly-used types that don't currently implement |
|
|
This comment has been minimized.
This comment has been minimized.
5cb13f7 to
4a0af16
Compare
|
cc @rust-lang/miri |
This comment was marked as outdated.
This comment was marked as outdated.
This comment has been minimized.
This comment has been minimized.
Add FCW for invalid C variadic arguments
This comment has been minimized.
This comment has been minimized.
|
@rust-lang/lang Nominating for team discussion. :) See the PR description for a summary. We ask for your feedback on which of these three options you would prefer (or whether you'd prefer something entirely different):
My personal preference is option 3. That standard library code looks entirely reasonable, there is no reason to change it. We define |
This comment has been minimized.
This comment has been minimized.
|
💔 Test for ec4987a failed: CI. Failed jobs:
|
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
|
Based on the failure in the first attempt at a crater run, the
|
This comment was marked as resolved.
This comment was marked as resolved.
|
The job Click to see the possible cause of the failure (guessed by this bot) |
|
Based on checking locally, it does seem that passing I've pushed a new commit for the crater run. It emits a hard error only if @craterbot abort @bors try |
This comment has been minimized.
This comment has been minimized.
Add FCW for invalid C variadic arguments
|
🗑️ Experiment ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more |
|
I have removed the t-lang nomination -- I suspect having an idea of just how bad this crater run will be, and which types we could allow to make it less bad, will be very useful for the discussion. |
|
@craterbot run start=eca445e5ae4a6679cc27d3a09106ce245e13a5a6 end=40527f3e444fde1deb361751bdef9b9e11d1b971+rustflags="--cfg crater_hack --force-warn invalid-c-variadic-arguments" mode=check-only |
|
👌 Experiment ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more |
|
I'm against making this a FCW; I think it should just be a normal warn-by-default lint (perhaps deny for certain cases). There are perfectly legitimate reasons to pass non- |
@Jules-Bertholet Is there a legitimate reason to then proceed to pass a value of that type as a variadic argument? |
|
If some weird C API you are linking against requires it, then that's what you have to do. (Sorry for typo, see edited message) |
|
@Jules-Bertholet I believe that passing a repr(C) struct (or a struct defined in C) as a variadic argument is UB both in C and in rust. Or if it's not UB when you pass it, it will be UB when you try to read it. |
In C, all types that can be passed as function arguments (except for types like
I think the solution there would be to allow such types to implement |
View all comments
Fixes #61275 by adding an FCW for invalid C-variadic arguments:
invalid_c_variadic_arguments.Tracking issue for the FCW: #162483
For the purposes of this FCW, a valid C-variadic argument must either implement
VaArgSafe, or be a thin reference.cc @RalfJung
Background
C-variadic functions are functions defined either in Rust or externally via FFI that can accept any number of arguments. However, due to C ABI weirdness, only certain types can be passed as C-variadic arguments.
Previously, we had a check that would cause us to attempt to emit a hard error on commonly mistakenly used C-variadic argument types. In particular, this affected types that are not "directly supported" as a variadic argument, but would be automatically coerced to a supported type in C/C++. For instance, when passing a
short, a C/C++ compiler will automatically promote this tointand so on the ABI level, anintgets passed. We do not do such coercions in Rust, so passing ani16can lead to fatal bugs due to the wrong ABI being used.In #61275, it was found that this hard error didn't prevent such footguns from occurring when the C-variadic function was called with generic arguments. It was then also later found that this error had a bug that caused it to depend on the details of the type inference algorithm.
The current behavior of this hard error is as follows:
f32,i8,i16,u8,u16, orbool, and the type doesn't implementVaArgSafein the current target, we emit an error.Stringdoesn't trigger this error.)In #155697, we stabilized the ability to define C-variadic functions in Rust. With it, we also stabilized the
VaArgSafetrait. This trait is implemented for types that are supported as variadic arguments. Thus, we now have the ability, in stable Rust, to describe the type requirements for being supported as a C-variadic argument.Therefore, this PR adds an FCW that would warn against C-variadic arguments that are not
VaArgSafe. In generic contexts, users can add aT: VaArgSafebound to satisfy this lint. This FCW runs after type inference is done, but before monomorphization.There's a caveat though: There's likely much code in the wild that passes a reference as a C-variadic argument. However, references do not implement
VaArgSafeyet. Thus, we don't yet lint when a thin reference is passed as a C-variadic argument.In the future, I expect that it would be possible to turn this into a hard error by, in the type inference/checking algorithm, adding a trait obligation that requires C-variadic arguments to implement
VaArgSafe. (This is similar to what happens when one calls afn<T: VaArgSafe>(T).) This can technically break code that wasn't previously linted, due to lifetime-dependent where bounds, and maybe due to the effect that the trait bound has on subsequent type inference. I expect this to be extremely unlikely though.