Skip to content

[EXPERIMENT] Ban generics in variadic args #127401

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

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

workingjubilee
Copy link
Member

pnkfelix mentioned doing this but it looks like I'm beating him to it.

r? @ghost

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Jul 6, 2024
Copy link
Member

@compiler-errors compiler-errors left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These comments are likely premature given that this is a draft but I'm gonna comment them anyways so I don't forget lmao

What exactly are the rules for what types are allowed in variadic args? If that set of rules doesn't exist, we may want to figure those out first. If they do, do they apply structurally?

It seems like we should be walking through types using something like a type folder rather than just matching on the outermost type constructor here.

Similarly, there are a lot of types that probably should be banned if we're banning ty::Param, things like ty::Alias and then structural types that contain ty::Param recursively.

@@ -428,6 +428,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let ptr_ty = self.resolve_vars_if_possible(ptr_ty);
variadic_error(tcx.sess, arg.span, arg_ty, &ptr_ty.to_string());
}
// generics? in C variadic? naaah
ty::Adt(_def, gen_args) if gen_args.len() > 0 => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems weird to ban Adt<i32> (fully monomorphic type) here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure what that looks like in Rust source?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fn variadic_fn(...) {}

struct Adt<T>(T);

fn call() {
  let x: Adt<i32> = Adt(0);
  variadic_fn(x);
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh yeah, I am in fact kinda hoping no one's relying on that lmao.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well, was at the time. clearly some people have made exciting choices.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm how does one tell apart Box<T> then?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well I don't know yet if we care to tell apart T from Box<T>, you still haven't told me what the rules for a valid c_variadic arg is 😆

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, it should probably have a trivial destructor (by which I mean does not contain Drop) for one, but setting that aside, it must be:

  • c_int
  • c_uint
  • and their longer friends
  • c_double
  • a thin pointer
  • something repr(transparent) with the above
  • a repr(C) struct that recursively contains only "repr(C) or FFI compatible" types, but it is fine if this result is smaller than an integer or contains only types that don't necessarily fit the above qualifications except for being repr(C), for instance it is acceptable for it to be
#[repr(C)]
struct TwoBytes {
    a_byte: c_char,
    byte_byte: c_char,
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Oh, and function pointers yes (pretending they're thin pointers, I guess).
  • repr(C) union with the same qualifications as repr(C) struct
  • a "unit" repr(C) enum should also be fine.
  • a "unit" repr(u8) enum is right out.

ty::Adt(_def, gen_args) if gen_args.len() > 0 => {
bug!("what the ferris are you doing")
}
ty::Param(_) => bug!("what the ferris are you doing"),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we ok w/ [T; N] 🤔

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me be clear here that I mean this for example. This also applies to all the other built-in types that allow other types inside of them, like tuples, refs, slices, etc.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we probably aren't!

@workingjubilee
Copy link
Member Author

What exactly are the rules for what types are allowed in variadic args? If that set of rules doesn't exist, we may want to figure those out first. If they do, do they apply structurally?

  1. They do exist.
  2. I don't know what you mean by "structurally", but there are types that are "illegal" when passed as "bare" types but may be "smuggled" inside a #[repr(C)] struct. I am drafting a proposal on how we should handle this as we speak, basically.

@workingjubilee
Copy link
Member Author

Note that this implies that a repr(transparent) struct should probably fail to permit the same smuggling.

@rust-log-analyzer
Copy link
Collaborator

The job x86_64-gnu-tools failed! Check out the build log: (web) (plain)

Click to see the possible cause of the failure (guessed by this bot)

thread 'rustc' panicked at compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs:435:37:
Box<dyn Any>
stack backtrace:
   0:     0x7fbb88715eef - <std[1e810906d2fadf8]::sys::backtrace::_print::DisplayBacktrace as core[839ef12c70fa2509]::fmt::Display>::fmt
   1:     0x7fbb88772430 - core[839ef12c70fa2509]::fmt::write
   2:     0x7fbb8870a8e9 - <std[1e810906d2fadf8]::sys::pal::unix::stdio::Stderr as std[1e810906d2fadf8]::io::Write>::write_fmt
   3:     0x7fbb88715cbe - std[1e810906d2fadf8]::sys::backtrace::print
   4:     0x7fbb8871899a - std[1e810906d2fadf8]::panicking::default_hook::{closure#1}
   5:     0x7fbb88718624 - std[1e810906d2fadf8]::panicking::default_hook
   6:     0x7fbb8a472c87 - <alloc[8501d074461e147f]::boxed::Box<rustc_driver_impl[31e15de76bbb1bb4]::install_ice_hook::{closure#0}> as core[839ef12c70fa2509]::ops::function::Fn<(&dyn for<'a, 'b> core[839ef12c70fa2509]::ops::function::Fn<(&'a std[1e810906d2fadf8]::panic::PanicHookInfo<'b>,), Output = ()> + core[839ef12c70fa2509]::marker::Send + core[839ef12c70fa2509]::marker::Sync, &std[1e810906d2fadf8]::panic::PanicHookInfo)>>::call
   7:     0x7fbb88719388 - std[1e810906d2fadf8]::panicking::rust_panic_with_hook
   8:     0x7fbb8e693b83 - std[1e810906d2fadf8]::panicking::begin_panic::<rustc_errors[95ecc2b6c4539d8]::ExplicitBug>::{closure#0}
   9:     0x7fbb8e693a56 - std[1e810906d2fadf8]::sys::backtrace::__rust_end_short_backtrace::<std[1e810906d2fadf8]::panicking::begin_panic<rustc_errors[95ecc2b6c4539d8]::ExplicitBug>::{closure#0}, !>
  10:     0x7fbb8e68a666 - std[1e810906d2fadf8]::panicking::begin_panic::<rustc_errors[95ecc2b6c4539d8]::ExplicitBug>
  11:     0x7fbb8e66a651 - <rustc_errors[95ecc2b6c4539d8]::diagnostic::BugAbort as rustc_errors[95ecc2b6c4539d8]::diagnostic::EmissionGuarantee>::emit_producing_guarantee
  12:     0x7fbb8e2029bd - rustc_middle[181fecaaf64f9719]::util::bug::opt_span_bug_fmt::<rustc_span[802050f372e962ba]::span_encoding::Span>::{closure#0}
  13:     0x7fbb8e201e2a - rustc_middle[181fecaaf64f9719]::ty::context::tls::with_opt::<rustc_middle[181fecaaf64f9719]::util::bug::opt_span_bug_fmt<rustc_span[802050f372e962ba]::span_encoding::Span>::{closure#0}, !>::{closure#0}
  14:     0x7fbb8e201ddb - rustc_middle[181fecaaf64f9719]::ty::context::tls::with_context_opt::<rustc_middle[181fecaaf64f9719]::ty::context::tls::with_opt<rustc_middle[181fecaaf64f9719]::util::bug::opt_span_bug_fmt<rustc_span[802050f372e962ba]::span_encoding::Span>::{closure#0}, !>::{closure#0}, !>
  15:     0x7fbb8e2028a2 - rustc_middle[181fecaaf64f9719]::util::bug::bug_fmt
  16:     0x7fbb8abb2671 - <rustc_hir_typeck[69d7bb0c82109318]::fn_ctxt::FnCtxt>::check_argument_types
  17:     0x7fbb8ab6deab - <rustc_hir_typeck[69d7bb0c82109318]::fn_ctxt::FnCtxt>::confirm_builtin_call
  18:     0x7fbb8ac168a0 - <rustc_hir_typeck[69d7bb0c82109318]::fn_ctxt::FnCtxt>::check_expr_kind
  19:     0x7fbb8ab8d605 - <rustc_hir_typeck[69d7bb0c82109318]::fn_ctxt::FnCtxt>::check_expr_with_expectation_and_args
  20:     0x7fbb8ac1191f - <rustc_hir_typeck[69d7bb0c82109318]::fn_ctxt::FnCtxt>::check_expr_with_expectation
  21:     0x7fbb8abbb6b8 - <rustc_hir_typeck[69d7bb0c82109318]::fn_ctxt::FnCtxt>::check_block_with_expected
  22:     0x7fbb8ac12a35 - <rustc_hir_typeck[69d7bb0c82109318]::fn_ctxt::FnCtxt>::check_expr_kind
  23:     0x7fbb8ab8d605 - <rustc_hir_typeck[69d7bb0c82109318]::fn_ctxt::FnCtxt>::check_expr_with_expectation_and_args
  24:     0x7fbb8ac1191f - <rustc_hir_typeck[69d7bb0c82109318]::fn_ctxt::FnCtxt>::check_expr_with_expectation
  25:     0x7fbb8ab8e82f - <rustc_hir_typeck[69d7bb0c82109318]::fn_ctxt::FnCtxt>::check_return_expr
  26:     0x7fbb8add235e - rustc_hir_typeck[69d7bb0c82109318]::check::check_fn
  27:     0x7fbb8adcc35c - rustc_hir_typeck[69d7bb0c82109318]::typeck
  28:     0x7fbb8c6f6525 - rustc_query_impl[bd46294947b1e958]::plumbing::__rust_begin_short_backtrace::<rustc_query_impl[bd46294947b1e958]::query_impl::typeck::dynamic_query::{closure#2}::{closure#0}, rustc_middle[181fecaaf64f9719]::query::erase::Erased<[u8; 8usize]>>
  29:     0x7fbb8c97f7e5 - <rustc_query_impl[bd46294947b1e958]::query_impl::typeck::dynamic_query::{closure#2} as core[839ef12c70fa2509]::ops::function::FnOnce<(rustc_middle[181fecaaf64f9719]::ty::context::TyCtxt, rustc_span[802050f372e962ba]::def_id::LocalDefId)>>::call_once
  30:     0x7fbb8c80c80c - rustc_query_system[41a8177b433cd17]::query::plumbing::try_execute_query::<rustc_query_impl[bd46294947b1e958]::DynamicConfig<rustc_query_system[41a8177b433cd17]::query::caches::VecCache<rustc_span[802050f372e962ba]::def_id::LocalDefId, rustc_middle[181fecaaf64f9719]::query::erase::Erased<[u8; 8usize]>>, false, false, false>, rustc_query_impl[bd46294947b1e958]::plumbing::QueryCtxt, false>
  31:     0x7fbb8c988c84 - rustc_query_impl[bd46294947b1e958]::query_impl::typeck::get_query_non_incr::__rust_end_short_backtrace
  32:     0x7fbb8afa8bae - <rustc_middle[181fecaaf64f9719]::hir::map::Map>::par_body_owners::<rustc_hir_analysis[6f4fc52d75a270e]::check_crate::{closure#4}>::{closure#0}
  33:     0x7fbb8b23f82b - <rustc_data_structures[73ab114716744ac8]::sync::parallel::ParallelGuard>::run::<(), rustc_data_structures[73ab114716744ac8]::sync::parallel::enabled::par_for_each_in<&rustc_span[802050f372e962ba]::def_id::LocalDefId, &[rustc_span[802050f372e962ba]::def_id::LocalDefId], <rustc_middle[181fecaaf64f9719]::hir::map::Map>::par_body_owners<rustc_hir_analysis[6f4fc52d75a270e]::check_crate::{closure#4}>::{closure#0}>::{closure#0}::{closure#0}::{closure#0}>
  34:     0x7fbb8b0547de - rustc_hir_analysis[6f4fc52d75a270e]::check_crate
  35:     0x7fbb8a840121 - rustc_interface[f069cc1ae5c72be5]::passes::analysis
  36:     0x7fbb8c6f6b43 - rustc_query_impl[bd46294947b1e958]::plumbing::__rust_begin_short_backtrace::<rustc_query_impl[bd46294947b1e958]::query_impl::analysis::dynamic_query::{closure#2}::{closure#0}, rustc_middle[181fecaaf64f9719]::query::erase::Erased<[u8; 1usize]>>
  37:     0x7fbb8caa55d1 - <rustc_query_impl[bd46294947b1e958]::query_impl::analysis::dynamic_query::{closure#2} as core[839ef12c70fa2509]::ops::function::FnOnce<(rustc_middle[181fecaaf64f9719]::ty::context::TyCtxt, ())>>::call_once
  38:     0x7fbb8c75a94d - rustc_query_system[41a8177b433cd17]::query::plumbing::try_execute_query::<rustc_query_impl[bd46294947b1e958]::DynamicConfig<rustc_query_system[41a8177b433cd17]::query::caches::SingleCache<rustc_middle[181fecaaf64f9719]::query::erase::Erased<[u8; 1usize]>>, false, false, false>, rustc_query_impl[bd46294947b1e958]::plumbing::QueryCtxt, false>
  39:     0x7fbb8c93fa21 - rustc_query_impl[bd46294947b1e958]::query_impl::analysis::get_query_non_incr::__rust_end_short_backtrace
  40:     0x7fbb8a4b6c05 - <rustc_middle[181fecaaf64f9719]::ty::context::GlobalCtxt>::enter::<rustc_driver_impl[31e15de76bbb1bb4]::run_compiler::{closure#0}::{closure#1}::{closure#5}, core[839ef12c70fa2509]::result::Result<(), rustc_span[802050f372e962ba]::ErrorGuaranteed>>
  41:     0x7fbb8a3f0fbc - <rustc_interface[f069cc1ae5c72be5]::interface::Compiler>::enter::<rustc_driver_impl[31e15de76bbb1bb4]::run_compiler::{closure#0}::{closure#1}, core[839ef12c70fa2509]::result::Result<core[839ef12c70fa2509]::option::Option<rustc_interface[f069cc1ae5c72be5]::queries::Linker>, rustc_span[802050f372e962ba]::ErrorGuaranteed>>
  42:     0x7fbb8a45e0c8 - rustc_span[802050f372e962ba]::create_session_globals_then::<core[839ef12c70fa2509]::result::Result<(), rustc_span[802050f372e962ba]::ErrorGuaranteed>, rustc_interface[f069cc1ae5c72be5]::util::run_in_thread_with_globals<rustc_interface[f069cc1ae5c72be5]::util::run_in_thread_pool_with_globals<rustc_interface[f069cc1ae5c72be5]::interface::run_compiler<core[839ef12c70fa2509]::result::Result<(), rustc_span[802050f372e962ba]::ErrorGuaranteed>, rustc_driver_impl[31e15de76bbb1bb4]::run_compiler::{closure#0}>::{closure#1}, core[839ef12c70fa2509]::result::Result<(), rustc_span[802050f372e962ba]::ErrorGuaranteed>>::{closure#0}, core[839ef12c70fa2509]::result::Result<(), rustc_span[802050f372e962ba]::ErrorGuaranteed>>::{closure#0}::{closure#0}::{closure#0}>
  43:     0x7fbb8a4b9032 - std[1e810906d2fadf8]::sys::backtrace::__rust_begin_short_backtrace::<rustc_interface[f069cc1ae5c72be5]::util::run_in_thread_with_globals<rustc_interface[f069cc1ae5c72be5]::util::run_in_thread_pool_with_globals<rustc_interface[f069cc1ae5c72be5]::interface::run_compiler<core[839ef12c70fa2509]::result::Result<(), rustc_span[802050f372e962ba]::ErrorGuaranteed>, rustc_driver_impl[31e15de76bbb1bb4]::run_compiler::{closure#0}>::{closure#1}, core[839ef12c70fa2509]::result::Result<(), rustc_span[802050f372e962ba]::ErrorGuaranteed>>::{closure#0}, core[839ef12c70fa2509]::result::Result<(), rustc_span[802050f372e962ba]::ErrorGuaranteed>>::{closure#0}::{closure#0}, core[839ef12c70fa2509]::result::Result<(), rustc_span[802050f372e962ba]::ErrorGuaranteed>>
  44:     0x7fbb8a4a89ef - <<std[1e810906d2fadf8]::thread::Builder>::spawn_unchecked_<rustc_interface[f069cc1ae5c72be5]::util::run_in_thread_with_globals<rustc_interface[f069cc1ae5c72be5]::util::run_in_thread_pool_with_globals<rustc_interface[f069cc1ae5c72be5]::interface::run_compiler<core[839ef12c70fa2509]::result::Result<(), rustc_span[802050f372e962ba]::ErrorGuaranteed>, rustc_driver_impl[31e15de76bbb1bb4]::run_compiler::{closure#0}>::{closure#1}, core[839ef12c70fa2509]::result::Result<(), rustc_span[802050f372e962ba]::ErrorGuaranteed>>::{closure#0}, core[839ef12c70fa2509]::result::Result<(), rustc_span[802050f372e962ba]::ErrorGuaranteed>>::{closure#0}::{closure#0}, core[839ef12c70fa2509]::result::Result<(), rustc_span[802050f372e962ba]::ErrorGuaranteed>>::{closure#2} as core[839ef12c70fa2509]::ops::function::FnOnce<()>>::call_once::{shim:vtable#0}
  45:     0x7fbb88724b14 - <std[1e810906d2fadf8]::sys::pal::unix::thread::Thread>::new::thread_start
  47:     0x7fbb8853c850 - <unknown>
  48:                0x0 - <unknown>

note: we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new?labels=C-bug%2C+I-ICE%2C+T-compiler&template=ice.md
note: we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new?labels=C-bug%2C+I-ICE%2C+T-compiler&template=ice.md

note: please make sure that you have updated to the latest nightly

note: please attach the file at `/cargo/registry/src/index.crates.io-6f17d22bba15001f/perf-event-open-sys-3.0.0/rustc-ice-2024-07-06T00_39_54-14171.txt` to your bug report

note: compiler flags: --crate-type lib -C opt-level=3 -C embed-bitcode=no -C debug-assertions=on -C symbol-mangling-version=v0 -Z unstable-options -Z macro-backtrace -C split-debuginfo=off -Z unstable-options -C prefer-dynamic -C link-args=-Wl,-z,origin -C link-args=-Wl,-rpath,$ORIGIN/../lib -Z on-broken-pipe=kill -Z binary-dep-depinfo -Z tls-model=initial-exec -Z force-unstable-if-unmarked
note: some of the compiler flags provided by cargo are hidden

query stack during panic:
query stack during panic:
#0 [typeck] type-checking `ioctls::untyped_ioctl`
end of query stack
error: could not compile `perf-event-open-sys` (lib)
warning: build failed, waiting for other jobs to finish...
Build completed unsuccessfully in 0:05:10
Build completed unsuccessfully in 0:05:10
+ set -e
+ cat /tmp/toolstate/toolstates.json
{"lld-wrapper":"test-fail"}
+ python3 ../x.py test --stage 2 check-tools
##[group]Building bootstrap
    Finished `dev` profile [unoptimized] target(s) in 0.04s
##[endgroup]
ERROR: Tool `book` was not recorded in tool state.
ERROR: Tool `nomicon` was not recorded in tool state.
ERROR: Tool `reference` was not recorded in tool state.
ERROR: Tool `rust-by-example` was not recorded in tool state.
ERROR: Tool `edition-guide` was not recorded in tool state.
ERROR: Tool `embedded-book` was not recorded in tool state.
  local time: Sat Jul  6 00:40:01 UTC 2024
  network time: Sat, 06 Jul 2024 00:40:01 GMT
##[error]Process completed with exit code 1.
Post job cleanup.

@workingjubilee
Copy link
Member Author

that's an evil omen.

@compiler-errors
Copy link
Member

(if you're curious where the ICE is coming from: https://docs.rs/perf-event-open-sys/latest/src/perf_event_open_sys/functions.rs.html#99-105)

@workingjubilee
Copy link
Member Author

yeah, I spotted it.

@workingjubilee
Copy link
Member Author

workingjubilee commented Jul 6, 2024

@compiler-errors btw am I understanding the delegation test failure as being because delegation syntax for reuse from_original_path::whatever; desugars a call to self::whatever(a: Type1, b: Type2) as calling like this?

fn self::whatever(a: Type1, b: Type2) {
    from_original_path::whatever(a, b)
}

because that's not correct for varargs.

@compiler-errors
Copy link
Member

I don't actually know if delegation turns into a fn call or if it does some other kind of forwarding of the associated item. @petrochenkov would know.

@workingjubilee
Copy link
Member Author

The perf_event_open_sys usage is sound with respect to varargs (I have no idea if it's a correct usage of the ioctl API).

@workingjubilee
Copy link
Member Author

moving to instantiation time it is, then.

@petrochenkov
Copy link
Contributor

Not sure what delegation test failure you are talking about, I don't see anything delegation-related in the thread above or in CI logs.

Delegation is supposed to copy the wrapper function signature from the target function, and then just pass all the parameters to the target function in the body.
I assume that applies to VaListImpl or whatever is hiding under the ... in C-like variadics as well.
If passing ... through requires some additional actions, the delegation should do those actions (or report an error), but now it's not doing them.

@petrochenkov
Copy link
Contributor

petrochenkov commented Jul 6, 2024

If passing ... through requires some additional actions

That said, Rust should make passing ... through "just work" if it's technically possible, even if C requires some additional dance for that.

@workingjubilee
Copy link
Member Author

I will open an issue for the delegation bug and in it explain why that is likely impossible.

@Dylan-DPC Dylan-DPC added S-experimental Status: Ongoing experiment that does not require reviewing and won't be merged in its current state. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Aug 21, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-experimental Status: Ongoing experiment that does not require reviewing and won't be merged in its current state. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants