Rollup merge of #63492 - eddyb:cvarargs, r=nagisa,matthewjasper
Remove redundancy from the implementation of C variadics. This cleanup was first described in https://github.com/rust-lang/rust/issues/44930#issuecomment-497163539: * AST doesn't track `c_variadic: bool` anymore, relying solely on a trailing `CVarArgs` type in fn signatures * HIR doesn't have a `CVarArgs` anymore, relying solely on `c_variadic: bool` * same for `ty::FnSig` (see tests for diagnostics improvements from that) * `{hir,mir}::Body` have one extra argument than the signature when `c_variadic == true` * `rustc_typeck` and `rustc_mir::{build,borrowck}` need to give that argument the right type (which no longer uses a lifetime parameter, but a function-internal scope) * `rustc_target::abi::call` doesn't need special hacks anymore (since it never sees the `VaListImpl` now, it's all inside the body) r? @nagisa / @rkruppe cc @dlrobertson @oli-obk
This commit is contained in:
commit
37333b5131
42 changed files with 322 additions and 432 deletions
|
|
@ -633,9 +633,6 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
|
|||
TyKind::Typeof(ref expression) => {
|
||||
visitor.visit_anon_const(expression)
|
||||
}
|
||||
TyKind::CVarArgs(ref lt) => {
|
||||
visitor.visit_lifetime(lt)
|
||||
}
|
||||
TyKind::Infer | TyKind::Err => {}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1335,13 +1335,8 @@ impl<'a> LoweringContext<'a> {
|
|||
}
|
||||
}
|
||||
}
|
||||
TyKind::Mac(_) => bug!("`TyMac` should have been expanded by now"),
|
||||
TyKind::CVarArgs => {
|
||||
// Create the implicit lifetime of the "spoofed" `VaListImpl`.
|
||||
let span = self.sess.source_map().next_point(t.span.shrink_to_lo());
|
||||
let lt = self.new_implicit_lifetime(span);
|
||||
hir::TyKind::CVarArgs(lt)
|
||||
},
|
||||
TyKind::Mac(_) => bug!("`TyKind::Mac` should have been expanded by now"),
|
||||
TyKind::CVarArgs => bug!("`TyKind::CVarArgs` should have been handled elsewhere"),
|
||||
};
|
||||
|
||||
hir::Ty {
|
||||
|
|
@ -2093,7 +2088,14 @@ impl<'a> LoweringContext<'a> {
|
|||
}
|
||||
|
||||
fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> hir::HirVec<Ident> {
|
||||
decl.inputs
|
||||
// Skip the `...` (`CVarArgs`) trailing arguments from the AST,
|
||||
// as they are not explicit in HIR/Ty function signatures.
|
||||
// (instead, the `c_variadic` flag is set to `true`)
|
||||
let mut inputs = &decl.inputs[..];
|
||||
if decl.c_variadic() {
|
||||
inputs = &inputs[..inputs.len() - 1];
|
||||
}
|
||||
inputs
|
||||
.iter()
|
||||
.map(|param| match param.pat.kind {
|
||||
PatKind::Ident(_, ident, _) => ident,
|
||||
|
|
@ -2130,10 +2132,19 @@ impl<'a> LoweringContext<'a> {
|
|||
self.anonymous_lifetime_mode
|
||||
};
|
||||
|
||||
let c_variadic = decl.c_variadic();
|
||||
|
||||
// Remember how many lifetimes were already around so that we can
|
||||
// only look at the lifetime parameters introduced by the arguments.
|
||||
let inputs = self.with_anonymous_lifetime_mode(lt_mode, |this| {
|
||||
decl.inputs
|
||||
// Skip the `...` (`CVarArgs`) trailing arguments from the AST,
|
||||
// as they are not explicit in HIR/Ty function signatures.
|
||||
// (instead, the `c_variadic` flag is set to `true`)
|
||||
let mut inputs = &decl.inputs[..];
|
||||
if c_variadic {
|
||||
inputs = &inputs[..inputs.len() - 1];
|
||||
}
|
||||
inputs
|
||||
.iter()
|
||||
.map(|param| {
|
||||
if let Some((_, ibty)) = &mut in_band_ty_params {
|
||||
|
|
@ -2168,7 +2179,7 @@ impl<'a> LoweringContext<'a> {
|
|||
P(hir::FnDecl {
|
||||
inputs,
|
||||
output,
|
||||
c_variadic: decl.c_variadic,
|
||||
c_variadic,
|
||||
implicit_self: decl.inputs.get(0).map_or(
|
||||
hir::ImplicitSelfKind::None,
|
||||
|arg| {
|
||||
|
|
|
|||
|
|
@ -450,7 +450,6 @@ impl LoweringContext<'_> {
|
|||
let ast_decl = FnDecl {
|
||||
inputs: vec![],
|
||||
output,
|
||||
c_variadic: false
|
||||
};
|
||||
let decl = self.lower_fn_decl(&ast_decl, None, /* impl trait allowed */ false, None);
|
||||
let body_id = self.lower_fn_body(&ast_decl, |this| {
|
||||
|
|
@ -739,7 +738,6 @@ impl LoweringContext<'_> {
|
|||
let outer_decl = FnDecl {
|
||||
inputs: decl.inputs.clone(),
|
||||
output: FunctionRetTy::Default(fn_decl_span),
|
||||
c_variadic: false,
|
||||
};
|
||||
// We need to lower the declaration outside the new scope, because we
|
||||
// have to conserve the state of being inside a loop condition for the
|
||||
|
|
|
|||
|
|
@ -2016,9 +2016,6 @@ pub enum TyKind {
|
|||
Infer,
|
||||
/// Placeholder for a type that has failed to be defined.
|
||||
Err,
|
||||
/// Placeholder for C-variadic arguments. We "spoof" the `VaListImpl` created
|
||||
/// from the variadic arguments. This type is only valid up to typeck.
|
||||
CVarArgs(Lifetime),
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
|
||||
|
|
|
|||
|
|
@ -361,9 +361,6 @@ impl<'a> State<'a> {
|
|||
self.s.word("/*ERROR*/");
|
||||
self.pclose();
|
||||
}
|
||||
hir::TyKind::CVarArgs(_) => {
|
||||
self.s.word("...");
|
||||
}
|
||||
}
|
||||
self.end()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -764,13 +764,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
|||
});
|
||||
}
|
||||
}
|
||||
hir::TyKind::CVarArgs(ref lt) => {
|
||||
// Resolve the generated lifetime for the C-variadic arguments.
|
||||
// The lifetime is generated in AST -> HIR lowering.
|
||||
if lt.name.is_elided() {
|
||||
self.resolve_elided_lifetimes(vec![lt])
|
||||
}
|
||||
}
|
||||
_ => intravisit::walk_ty(self, ty),
|
||||
}
|
||||
}
|
||||
|
|
@ -2378,7 +2371,6 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
|||
self.visit_lifetime(lifetime);
|
||||
}
|
||||
}
|
||||
hir::TyKind::CVarArgs(_) => {}
|
||||
_ => {
|
||||
intravisit::walk_ty(self, ty);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
|
|||
pub use rustc_target::abi::*;
|
||||
use rustc_target::spec::{HasTargetSpec, abi::Abi as SpecAbi};
|
||||
use rustc_target::abi::call::{
|
||||
ArgAttribute, ArgAttributes, ArgType, Conv, FnType, IgnoreMode, PassMode, Reg, RegKind
|
||||
ArgAttribute, ArgAttributes, ArgType, Conv, FnType, PassMode, Reg, RegKind
|
||||
};
|
||||
|
||||
pub trait IntegerExt {
|
||||
|
|
@ -2722,14 +2722,6 @@ where
|
|||
}
|
||||
};
|
||||
|
||||
// Store the index of the last argument. This is useful for working with
|
||||
// C-compatible variadic arguments.
|
||||
let last_arg_idx = if sig.inputs().is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(sig.inputs().len() - 1)
|
||||
};
|
||||
|
||||
let arg_of = |ty: Ty<'tcx>, arg_idx: Option<usize>| {
|
||||
let is_return = arg_idx.is_none();
|
||||
let mut arg = mk_arg_type(ty, arg_idx);
|
||||
|
|
@ -2739,30 +2731,7 @@ where
|
|||
// The same is true for s390x-unknown-linux-gnu
|
||||
// and sparc64-unknown-linux-gnu.
|
||||
if is_return || rust_abi || (!win_x64_gnu && !linux_s390x && !linux_sparc64) {
|
||||
arg.mode = PassMode::Ignore(IgnoreMode::Zst);
|
||||
}
|
||||
}
|
||||
|
||||
// If this is a C-variadic function, this is not the return value,
|
||||
// and there is one or more fixed arguments; ensure that the `VaListImpl`
|
||||
// is ignored as an argument.
|
||||
if sig.c_variadic {
|
||||
match (last_arg_idx, arg_idx) {
|
||||
(Some(last_idx), Some(cur_idx)) if last_idx == cur_idx => {
|
||||
let va_list_did = match cx.tcx().lang_items().va_list() {
|
||||
Some(did) => did,
|
||||
None => bug!("`va_list` lang item required for C-variadic functions"),
|
||||
};
|
||||
match ty.kind {
|
||||
ty::Adt(def, _) if def.did == va_list_did => {
|
||||
// This is the "spoofed" `VaListImpl`. Set the arguments mode
|
||||
// so that it will be ignored.
|
||||
arg.mode = PassMode::Ignore(IgnoreMode::CVarArgs);
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
arg.mode = PassMode::Ignore;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue