-
-
Notifications
You must be signed in to change notification settings - Fork 15.6k
Add FCW for invalid C variadic arguments #162478
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
Open
theemathas
wants to merge
3
commits into
rust-lang:main
Choose a base branch
from
theemathas:variadic-fcw
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,169 @@ | ||
| //@ check-pass | ||
|
|
||
| use std::ffi::VaArgSafe; | ||
|
|
||
| unsafe extern "C" fn variadic(_: ...) {} | ||
|
|
||
| fn main() { | ||
| unsafe { | ||
| variadic(); | ||
| variadic(1_i32); | ||
| variadic(String::new()); | ||
| //~^ WARN type `String` does not implement `VaArgSafe` | ||
| //~| WARN this was previously accepted by the compiler but is being phased out | ||
| variadic(1_i32, String::new()); | ||
| //~^ WARN type `String` does not implement `VaArgSafe` | ||
| //~| WARN this was previously accepted by the compiler but is being phased out | ||
| variadic(String::new(), 1_i32); | ||
| //~^ WARN type `String` does not implement `VaArgSafe` | ||
| //~| WARN this was previously accepted by the compiler but is being phased out | ||
| variadic(String::new(), String::new()); | ||
| //~^ WARN type `String` does not implement `VaArgSafe` | ||
| //~| WARN this was previously accepted by the compiler but is being phased out | ||
| //~| WARN type `String` does not implement `VaArgSafe` | ||
| //~| WARN this was previously accepted by the compiler but is being phased out | ||
| } | ||
| } | ||
|
|
||
| fn generic<T>(x: T) { | ||
| unsafe { | ||
| variadic(x); | ||
| //~^ WARN type `T` does not implement `VaArgSafe` | ||
| //~| WARN this was previously accepted by the compiler but is being phased out | ||
| } | ||
| } | ||
|
|
||
| fn generic_with_bound<T: VaArgSafe>(x: T) { | ||
| unsafe { | ||
| variadic(x); | ||
| } | ||
| } | ||
|
|
||
| fn indirect() { | ||
| unsafe { | ||
| let f = variadic; | ||
| f(String::new()); | ||
| //~^ WARN type `String` does not implement `VaArgSafe` | ||
| //~| WARN this was previously accepted by the compiler but is being phased out | ||
| let f_ref = &f; | ||
| f_ref(String::new()); | ||
| //~^ WARN type `String` does not implement `VaArgSafe` | ||
| //~| WARN this was previously accepted by the compiler but is being phased out | ||
| let g = variadic as unsafe extern "C" fn(...); | ||
| g(String::new()); | ||
| //~^ WARN type `String` does not implement `VaArgSafe` | ||
| //~| WARN this was previously accepted by the compiler but is being phased out | ||
| let g_ref = &g; | ||
| g_ref(String::new()); | ||
| //~^ WARN type `String` does not implement `VaArgSafe` | ||
| //~| WARN this was previously accepted by the compiler but is being phased out | ||
| } | ||
| } | ||
|
|
||
| #[repr(C)] | ||
| #[derive(Clone, Copy)] | ||
| struct MyStruct { | ||
| x: i32, | ||
| y: i32, | ||
| } | ||
|
|
||
| unsafe extern "C" fn variadic_after_struct(_: MyStruct, _: ...) {} | ||
|
|
||
| fn simple_variadic_after_struct(my_struct: MyStruct) { | ||
| unsafe { | ||
| variadic_after_struct(my_struct); | ||
| variadic_after_struct(my_struct, 1_i32); | ||
| variadic_after_struct(my_struct, String::new()); | ||
| //~^ WARN type `String` does not implement `VaArgSafe` | ||
| //~| WARN this was previously accepted by the compiler but is being phased out | ||
| variadic_after_struct(my_struct, 1_i32, String::new()); | ||
| //~^ WARN type `String` does not implement `VaArgSafe` | ||
| //~| WARN this was previously accepted by the compiler but is being phased out | ||
| variadic_after_struct(my_struct, String::new(), 1_i32); | ||
| //~^ WARN type `String` does not implement `VaArgSafe` | ||
| //~| WARN this was previously accepted by the compiler but is being phased out | ||
| variadic_after_struct(my_struct, String::new(), String::new()); | ||
| //~^ WARN type `String` does not implement `VaArgSafe` | ||
| //~| WARN this was previously accepted by the compiler but is being phased out | ||
| //~| WARN type `String` does not implement `VaArgSafe` | ||
| //~| WARN this was previously accepted by the compiler but is being phased out | ||
| } | ||
| } | ||
|
|
||
| trait Trait { | ||
| type Assoc<'a>; | ||
| } | ||
|
|
||
| // Unlikely case which our lint doesn't catch. | ||
| fn lifetime_dependent<'a, 'b, T: Trait<Assoc<'a>: VaArgSafe>>(x: <T as Trait>::Assoc<'b>) { | ||
| unsafe { | ||
| variadic(x); | ||
| } | ||
| } | ||
|
|
||
| // We don't lint (thin) references even though they currently don't implement VaArgSafe | ||
| fn references<T, U: ?Sized>(tr: &T, tm: &mut T, ur: &U, um: &mut U) { | ||
| unsafe { | ||
| variadic(&String::new()); | ||
| variadic(&mut String::new()); | ||
| variadic(&String::new() as &dyn Send); | ||
| //~^ WARN type `&dyn Send` does not implement `VaArgSafe` | ||
| //~| WARN this was previously accepted by the compiler but is being phased out | ||
| variadic(&mut String::new() as &mut dyn Send); | ||
| //~^ WARN type `&mut dyn Send` does not implement `VaArgSafe` | ||
| //~| WARN this was previously accepted by the compiler but is being phased out | ||
| variadic(tr); | ||
| variadic(tm); | ||
| variadic(ur); | ||
| //~^ WARN type `&U` does not implement `VaArgSafe` | ||
| //~| WARN this was previously accepted by the compiler but is being phased out | ||
| variadic(um); | ||
| //~^ WARN type `&mut U` does not implement `VaArgSafe` | ||
| //~| WARN this was previously accepted by the compiler but is being phased out | ||
| } | ||
| } | ||
|
|
||
| // Quirk with our current hard error: It allows infer vars as varargs | ||
| // even if they wouldn't be allowed when the concrete type is known. | ||
| fn infer_var() { | ||
| unsafe { | ||
| let mut x = 1; | ||
| variadic(x); | ||
| //~^ WARN type `u8` does not implement `VaArgSafe` | ||
| //~| WARN this was previously accepted by the compiler but is being phased out | ||
| x = 1_u8; | ||
| } | ||
| } | ||
|
|
||
| fn integer_float_fallback() { | ||
| unsafe { | ||
| variadic(1); | ||
| variadic(1.0); | ||
| } | ||
| } | ||
|
|
||
| struct Thing; | ||
| impl Thing { | ||
| unsafe extern "C" fn variadic_method(&self, _: ...) {} | ||
| } | ||
|
|
||
| fn method_call_syntax() { | ||
| unsafe { | ||
| Thing.variadic_method(); | ||
| Thing.variadic_method(1_i32); | ||
| Thing.variadic_method(String::new()); | ||
| //~^ WARN type `String` does not implement `VaArgSafe` | ||
| //~| WARN this was previously accepted by the compiler but is being phased out | ||
| Thing.variadic_method(1_i32, String::new()); | ||
| //~^ WARN type `String` does not implement `VaArgSafe` | ||
| //~| WARN this was previously accepted by the compiler but is being phased out | ||
| Thing.variadic_method(String::new(), 1_i32); | ||
| //~^ WARN type `String` does not implement `VaArgSafe` | ||
| //~| WARN this was previously accepted by the compiler but is being phased out | ||
| Thing.variadic_method(String::new(), String::new()); | ||
| //~^ WARN type `String` does not implement `VaArgSafe` | ||
| //~| WARN this was previously accepted by the compiler but is being phased out | ||
| //~| WARN type `String` does not implement `VaArgSafe` | ||
| //~| WARN this was previously accepted by the compiler but is being phased out | ||
| } | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.
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.
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_depdsan optional field? The default is far from obvious. (When I introducedFutureReleaseErrorDontReportInDepsmany 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.)View changes since the review
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.
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
Uh oh!
There was an error while loading. Please reload this page.
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 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_depdsmandatory I guess... except I don't know how to make it mandatory just forFutureReleaseError; 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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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 atEditionAndFutureReleaseErrorwhich 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_depsinReleaseFcw. 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.
Uh oh!
There was an error while loading. Please reload this page.
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 was assuming you'd not want that since it seems to partially revert your PR #141936, by coupling
report_in_depswith the reason again. But it sounds great to me so if you can also live with it, all good. :)❤️
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.
Presumably we'd then add
ReleaseFcwtoEditionAndFutureReleaseErrorand toEditionAndFutureReleaseSemanticsChange? (Currently these only includeEditionFcw.)If helpful to factoring, note that lang has been following the policy of setting
report_in_deps = trueexactly when we make an FCWdeny-by-default(and otherwise settingreport_in_deps = false). Possibly, after cleaning up any lingering exceptions, it could be OK to lean on that.Uh oh!
There was an error while loading. Please reload this page.
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.
#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...