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:
Mazdak Farrokhzad 2019-09-29 04:35:58 +02:00 committed by GitHub
commit 37333b5131
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
42 changed files with 322 additions and 432 deletions

View file

@ -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 => {}
}
}

View file

@ -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| {

View file

@ -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

View file

@ -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)]

View file

@ -361,9 +361,6 @@ impl<'a> State<'a> {
self.s.word("/*ERROR*/");
self.pclose();
}
hir::TyKind::CVarArgs(_) => {
self.s.word("...");
}
}
self.end()
}

View file

@ -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);
}

View file

@ -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;
}
}