diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index d7b5462da27..05bdd0887f0 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -633,7 +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 | TyKind::Infer | TyKind::Err => {} } } diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index d9b444f5228..6f51e05881b 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -1335,8 +1335,8 @@ impl<'a> LoweringContext<'a> { } } } - TyKind::Mac(_) => bug!("`TyMac` should have been expanded by now"), - TyKind::CVarArgs => hir::TyKind::CVarArgs, + TyKind::Mac(_) => bug!("`TyKind::Mac` should have been expanded by now"), + TyKind::CVarArgs => bug!("`TyKind::CVarArgs` should have been handled elsewhere"), }; hir::Ty { @@ -2088,7 +2088,14 @@ impl<'a> LoweringContext<'a> { } fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> hir::HirVec { - 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, @@ -2125,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 { @@ -2163,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| { diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 0331d2be1a3..4e8b4337cc6 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -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, } #[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index 45cce24381b..6cffaa8a494 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -361,9 +361,6 @@ impl<'a> State<'a> { self.s.word("/*ERROR*/"); self.pclose(); } - hir::TyKind::CVarArgs => { - self.s.word("..."); - } } self.end() } diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 3accbdf9bcb..bd6b6006c1a 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -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| { 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; } } diff --git a/src/librustc_codegen_llvm/abi.rs b/src/librustc_codegen_llvm/abi.rs index 2ca517dc3b1..ae5cfc4d97b 100644 --- a/src/librustc_codegen_llvm/abi.rs +++ b/src/librustc_codegen_llvm/abi.rs @@ -264,7 +264,7 @@ impl ArgTypeExt<'ll, 'tcx> for ArgType<'tcx, Ty<'tcx>> { val }; match self.mode { - PassMode::Ignore(_) => {} + PassMode::Ignore => {} PassMode::Pair(..) => { OperandValue::Pair(next(), next()).store(bx, dst); } @@ -319,9 +319,7 @@ impl<'tcx> FnTypeLlvmExt<'tcx> for FnType<'tcx, Ty<'tcx>> { ); let llreturn_ty = match self.ret.mode { - PassMode::Ignore(IgnoreMode::Zst) => cx.type_void(), - PassMode::Ignore(IgnoreMode::CVarArgs) => - bug!("`va_list` should never be a return type"), + PassMode::Ignore => cx.type_void(), PassMode::Direct(_) | PassMode::Pair(..) => { self.ret.layout.immediate_llvm_type(cx) } @@ -339,7 +337,7 @@ impl<'tcx> FnTypeLlvmExt<'tcx> for FnType<'tcx, Ty<'tcx>> { } let llarg_ty = match arg.mode { - PassMode::Ignore(_) => continue, + PassMode::Ignore => continue, PassMode::Direct(_) => arg.layout.immediate_llvm_type(cx), PassMode::Pair(..) => { llargument_tys.push(arg.layout.scalar_pair_element_llvm_type(cx, 0, true)); @@ -408,7 +406,7 @@ impl<'tcx> FnTypeLlvmExt<'tcx> for FnType<'tcx, Ty<'tcx>> { apply(&ArgAttributes::new(), None); } match arg.mode { - PassMode::Ignore(_) => {} + PassMode::Ignore => {} PassMode::Direct(ref attrs) | PassMode::Indirect(ref attrs, None) => apply(attrs, Some(arg.layout.llvm_type(cx))), PassMode::Indirect(ref attrs, Some(ref extra_attrs)) => { @@ -455,7 +453,7 @@ impl<'tcx> FnTypeLlvmExt<'tcx> for FnType<'tcx, Ty<'tcx>> { apply(&ArgAttributes::new(), None); } match arg.mode { - PassMode::Ignore(_) => {} + PassMode::Ignore => {} PassMode::Direct(ref attrs) | PassMode::Indirect(ref attrs, None) => apply(attrs, Some(arg.layout.llvm_type(bx))), PassMode::Indirect(ref attrs, Some(ref extra_attrs)) => { diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index 3069199a212..0b9519f1c80 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -3,7 +3,7 @@ use rustc::ty::{self, Ty, TypeFoldable, Instance}; use rustc::ty::layout::{self, LayoutOf, HasTyCtxt, FnTypeExt}; use rustc::mir::{self, Place, PlaceBase, Static, StaticKind}; use rustc::mir::interpret::PanicInfo; -use rustc_target::abi::call::{ArgType, FnType, PassMode, IgnoreMode}; +use rustc_target::abi::call::{ArgType, FnType, PassMode}; use rustc_target::spec::abi::Abi; use crate::base; use crate::MemFlags; @@ -242,15 +242,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { return; } let llval = match self.fn_ty.ret.mode { - PassMode::Ignore(IgnoreMode::Zst) | PassMode::Indirect(..) => { + PassMode::Ignore | PassMode::Indirect(..) => { bx.ret_void(); return; } - PassMode::Ignore(IgnoreMode::CVarArgs) => { - bug!("C-variadic arguments should never be the return type"); - } - PassMode::Direct(_) | PassMode::Pair(..) => { let op = self.codegen_consume(&mut bx, &mir::Place::return_place().as_ref()); @@ -502,10 +498,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { return; } - // The "spoofed" `VaListImpl` added to a C-variadic functions signature - // should not be included in the `extra_args` calculation. - let extra_args_start_idx = sig.inputs().len() - if sig.c_variadic { 1 } else { 0 }; - let extra_args = &args[extra_args_start_idx..]; + let extra_args = &args[sig.inputs().len()..]; let extra_args = extra_args.iter().map(|op_arg| { let op_ty = op_arg.ty(self.mir, bx.tcx()); self.monomorphize(&op_ty) @@ -691,26 +684,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { (&args[..], None) }; - // Useful determining if the current argument is the "spoofed" `VaListImpl` - let last_arg_idx = if sig.inputs().is_empty() { - None - } else { - Some(sig.inputs().len() - 1) - }; 'make_args: for (i, arg) in first_args.iter().enumerate() { - // If this is a C-variadic function the function signature contains - // an "spoofed" `VaListImpl`. This argument is ignored, but we need to - // populate it with a dummy operand so that the users real arguments - // are not overwritten. - let i = if sig.c_variadic && last_arg_idx.map(|x| i >= x).unwrap_or(false) { - if i + 1 < fn_ty.args.len() { - i + 1 - } else { - break 'make_args - } - } else { - i - }; let mut op = self.codegen_operand(&mut bx, arg); if let (0, Some(ty::InstanceDef::Virtual(_, idx))) = (i, def) { diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs index c341c0685c6..5f8ffaad3d4 100644 --- a/src/librustc_codegen_ssa/mir/mod.rs +++ b/src/librustc_codegen_ssa/mir/mod.rs @@ -2,7 +2,7 @@ use rustc::ty::{self, Ty, TypeFoldable, UpvarSubsts, Instance}; use rustc::ty::layout::{TyLayout, HasTyCtxt, FnTypeExt}; use rustc::mir::{self, Body}; use rustc::session::config::DebugInfo; -use rustc_target::abi::call::{FnType, PassMode, IgnoreMode}; +use rustc_target::abi::call::{FnType, PassMode}; use rustc_target::abi::{Variants, VariantIdx}; use crate::base; use crate::debuginfo::{self, VariableAccess, VariableKind, FunctionDebugContext}; @@ -441,15 +441,6 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( None }; - // Store the index of the last argument. This is used to - // call va_start on the va_list instead of attempting - // to store_fn_arg. - let last_arg_idx = if fx.fn_ty.args.is_empty() { - None - } else { - Some(fx.fn_ty.args.len() - 1) - }; - mir.args_iter().enumerate().map(|(arg_index, local)| { let arg_decl = &mir.local_decls[local]; @@ -503,6 +494,33 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( return LocalRef::Place(place); } + if fx.fn_ty.c_variadic && arg_index == fx.fn_ty.args.len() { + let arg_ty = fx.monomorphize(&arg_decl.ty); + + let va_list = PlaceRef::alloca(bx, bx.layout_of(arg_ty)); + bx.set_var_name(va_list.llval, name); + bx.va_start(va_list.llval); + // FIXME(eddyb) remove `va_list_ref`. + *va_list_ref = Some(va_list); + + arg_scope.map(|scope| { + let variable_access = VariableAccess::DirectVariable { + alloca: va_list.llval + }; + bx.declare_local( + &fx.debug_context, + arg_decl.name.unwrap_or(kw::Invalid), + va_list.layout.ty, + scope, + variable_access, + VariableKind::ArgumentVariable(arg_index + 1), + DUMMY_SP + ); + }); + + return LocalRef::Place(va_list); + } + let arg = &fx.fn_ty.args[idx]; idx += 1; if arg.pad.is_some() { @@ -515,10 +533,9 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // of putting everything in allocas just so we can use llvm.dbg.declare. let local = |op| LocalRef::Operand(Some(op)); match arg.mode { - PassMode::Ignore(IgnoreMode::Zst) => { + PassMode::Ignore => { return local(OperandRef::new_zst(bx, arg.layout)); } - PassMode::Ignore(IgnoreMode::CVarArgs) => {} PassMode::Direct(_) => { let llarg = bx.get_param(llarg_idx); bx.set_var_name(llarg, &name); @@ -568,22 +585,7 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( } else { let tmp = PlaceRef::alloca(bx, arg.layout); bx.set_var_name(tmp.llval, name); - if fx.fn_ty.c_variadic && last_arg_idx.map(|idx| arg_index == idx).unwrap_or(false) { - let va_list_did = match tcx.lang_items().va_list() { - Some(did) => did, - None => bug!("`va_list` lang item required for C-variadic functions"), - }; - match arg_decl.ty.kind { - ty::Adt(def, _) if def.did == va_list_did => { - // Call `va_start` on the spoofed `VaListImpl`. - bx.va_start(tmp.llval); - *va_list_ref = Some(tmp); - }, - _ => bug!("last argument of variadic function is not a `va_list`") - } - } else { - bx.store_fn_arg(arg, &mut llarg_idx, tmp); - } + bx.store_fn_arg(arg, &mut llarg_idx, tmp); tmp }; let upvar_debuginfo = &mir.__upvar_debuginfo_codegen_only_do_not_use; diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index e4567dc8265..150719c1dbc 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -944,15 +944,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { let def_id = self.cx.tcx.hir().local_def_id(id); let sig = self.cx.tcx.fn_sig(def_id); let sig = self.cx.tcx.erase_late_bound_regions(&sig); - let inputs = if sig.c_variadic { - // Don't include the spoofed `VaListImpl` in the functions list - // of inputs. - &sig.inputs()[..sig.inputs().len() - 1] - } else { - &sig.inputs()[..] - }; - for (input_ty, input_hir) in inputs.iter().zip(&decl.inputs) { + for (input_ty, input_hir) in sig.inputs().iter().zip(&decl.inputs) { self.check_type_for_ffi_and_report_errors(input_hir.span, input_ty); } diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs index c4b508e030f..8b1ba59c6df 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs @@ -399,7 +399,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { self.universal_regions.unnormalized_input_tys[implicit_inputs + argument_index]; if let Some(region_name) = self.give_name_if_we_can_match_hir_ty_from_argument( infcx, - body, mir_def_id, fr, arg_ty, @@ -415,7 +414,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { fn give_name_if_we_can_match_hir_ty_from_argument( &self, infcx: &InferCtxt<'_, 'tcx>, - body: &Body<'tcx>, mir_def_id: DefId, needle_fr: RegionVid, argument_ty: Ty<'tcx>, @@ -424,18 +422,14 @@ impl<'tcx> RegionInferenceContext<'tcx> { ) -> Option { let mir_hir_id = infcx.tcx.hir().as_local_hir_id(mir_def_id)?; let fn_decl = infcx.tcx.hir().fn_decl_by_hir_id(mir_hir_id)?; - let argument_hir_ty: &hir::Ty = &fn_decl.inputs[argument_index]; + let argument_hir_ty: &hir::Ty = fn_decl.inputs.get(argument_index)?; match argument_hir_ty.kind { // This indicates a variable with no type annotation, like // `|x|`... in that case, we can't highlight the type but // must highlight the variable. - hir::TyKind::Infer => self.give_name_if_we_cannot_match_hir_ty( - infcx, - body, - needle_fr, - argument_ty, - renctx, - ), + // NOTE(eddyb) this is handled in/by the sole caller + // (`give_name_if_anonymous_region_appears_in_arguments`). + hir::TyKind::Infer => None, _ => self.give_name_if_we_can_match_hir_ty( infcx.tcx, diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index b981c76905c..fa326062fe2 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -1726,17 +1726,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { from_hir_call: bool, ) { debug!("check_call_inputs({:?}, {:?})", sig, args); - // Do not count the `VaListImpl` argument as a "true" argument to - // a C-variadic function. - let inputs = if sig.c_variadic { - &sig.inputs()[..sig.inputs().len() - 1] - } else { - &sig.inputs()[..] - }; - if args.len() < inputs.len() || (args.len() > inputs.len() && !sig.c_variadic) { + if args.len() < sig.inputs().len() || (args.len() > sig.inputs().len() && !sig.c_variadic) { span_mirbug!(self, term, "call to {:?} with wrong # of args", sig); } - for (n, (fn_arg, op_arg)) in inputs.iter().zip(args).enumerate() { + for (n, (fn_arg, op_arg)) in sig.inputs().iter().zip(args).enumerate() { let op_arg_ty = op_arg.ty(body, self.tcx()); let category = if from_hir_call { ConstraintCategory::CallArgument diff --git a/src/librustc_mir/borrow_check/nll/universal_regions.rs b/src/librustc_mir/borrow_check/nll/universal_regions.rs index 9f9450188fa..7053bdca259 100644 --- a/src/librustc_mir/borrow_check/nll/universal_regions.rs +++ b/src/librustc_mir/borrow_check/nll/universal_regions.rs @@ -16,8 +16,9 @@ use either::Either; use rustc::hir::def_id::DefId; use rustc::hir::{self, BodyOwnerKind, HirId}; use rustc::infer::{InferCtxt, NLLRegionVariableOrigin}; +use rustc::middle::lang_items; use rustc::ty::fold::TypeFoldable; -use rustc::ty::subst::{InternalSubsts, SubstsRef}; +use rustc::ty::subst::{InternalSubsts, SubstsRef, Subst}; use rustc::ty::{self, ClosureSubsts, GeneratorSubsts, RegionVid, Ty, TyCtxt}; use rustc::util::nodemap::FxHashMap; use rustc_data_structures::indexed_vec::{Idx, IndexVec}; @@ -425,12 +426,33 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { .replace_late_bound_regions_with_nll_infer_vars(self.mir_def_id, &mut indices); } + let (unnormalized_output_ty, mut unnormalized_input_tys) = + inputs_and_output.split_last().unwrap(); + + // C-variadic fns also have a `VaList` input that's not listed in the signature + // (as it's created inside the body itself, not passed in from outside). + if let DefiningTy::FnDef(def_id, _) = defining_ty { + if self.infcx.tcx.fn_sig(def_id).c_variadic() { + let va_list_did = self.infcx.tcx.require_lang_item( + lang_items::VaListTypeLangItem, + Some(self.infcx.tcx.def_span(self.mir_def_id),), + ); + let region = self.infcx.tcx.mk_region(ty::ReVar( + self.infcx.next_nll_region_var(FR).to_region_vid(), + )); + let va_list_ty = self.infcx.tcx.type_of(va_list_did) + .subst(self.infcx.tcx, &[region.into()]); + + unnormalized_input_tys = self.infcx.tcx.mk_type_list( + unnormalized_input_tys.iter().copied() + .chain(iter::once(va_list_ty)), + ); + } + } + let fr_fn_body = self.infcx.next_nll_region_var(FR).to_region_vid(); let num_universals = self.infcx.num_region_vars(); - let (unnormalized_output_ty, unnormalized_input_tys) = - inputs_and_output.split_last().unwrap(); - debug!( "build: global regions = {}..{}", FIRST_GLOBAL_INDEX, first_extern_index diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index f1e045302ec..17932ae8557 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -7,9 +7,11 @@ use crate::util as mir_util; use rustc::hir; use rustc::hir::Node; use rustc::hir::def_id::DefId; +use rustc::middle::lang_items; use rustc::middle::region; use rustc::mir::*; use rustc::ty::{self, Ty, TyCtxt}; +use rustc::ty::subst::Subst; use rustc::util::nodemap::HirIdMap; use rustc_target::spec::PanicStrategy; use rustc_data_structures::indexed_vec::{IndexVec, Idx}; @@ -102,9 +104,7 @@ pub fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> Body<'_> { let opt_ty_info; let self_arg; if let Some(ref fn_decl) = tcx.hir().fn_decl_by_hir_id(owner_id) { - let ty_hir_id = fn_decl.inputs[index].hir_id; - let ty_span = tcx.hir().span(ty_hir_id); - opt_ty_info = Some(ty_span); + opt_ty_info = fn_decl.inputs.get(index).map(|ty| ty.span); self_arg = if index == 0 && fn_decl.implicit_self.has_implicit_self() { match fn_decl.implicit_self { hir::ImplicitSelfKind::Imm => Some(ImplicitSelfKind::Imm), @@ -121,7 +121,24 @@ pub fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> Body<'_> { self_arg = None; } - ArgInfo(fn_sig.inputs()[index], opt_ty_info, Some(&arg), self_arg) + // C-variadic fns also have a `VaList` input that's not listed in `fn_sig` + // (as it's created inside the body itself, not passed in from outside). + let ty = if fn_sig.c_variadic && index == fn_sig.inputs().len() { + let va_list_did = tcx.require_lang_item( + lang_items::VaListTypeLangItem, + Some(arg.span), + ); + let region = tcx.mk_region(ty::ReScope(region::Scope { + id: body.value.hir_id.local_id, + data: region::ScopeData::CallSite + })); + + tcx.type_of(va_list_did).subst(tcx, &[region.into()]) + } else { + fn_sig.inputs()[index] + }; + + ArgInfo(ty, opt_ty_info, Some(&arg), self_arg) }); let arguments = implicit_argument.into_iter().chain(explicit_arguments); diff --git a/src/librustc_target/abi/call/mod.rs b/src/librustc_target/abi/call/mod.rs index fbbd120f934..bc21113527e 100644 --- a/src/librustc_target/abi/call/mod.rs +++ b/src/librustc_target/abi/call/mod.rs @@ -23,18 +23,10 @@ mod x86_64; mod x86_win64; mod wasm32; -#[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub enum IgnoreMode { - /// C-variadic arguments. - CVarArgs, - /// A zero-sized type. - Zst, -} - #[derive(Clone, Copy, PartialEq, Eq, Debug)] pub enum PassMode { - /// Ignore the argument (useful for empty structs and C-variadic args). - Ignore(IgnoreMode), + /// Ignore the argument. + Ignore, /// Pass the argument directly. Direct(ArgAttributes), /// Pass a pair's elements directly in two arguments. @@ -490,7 +482,7 @@ impl<'a, Ty> ArgType<'a, Ty> { pub fn is_ignore(&self) -> bool { match self.mode { - PassMode::Ignore(_) => true, + PassMode::Ignore => true, _ => false } } diff --git a/src/librustc_target/abi/call/x86.rs b/src/librustc_target/abi/call/x86.rs index 6ca3ce88bd6..2e809571ab1 100644 --- a/src/librustc_target/abi/call/x86.rs +++ b/src/librustc_target/abi/call/x86.rs @@ -88,7 +88,7 @@ pub fn compute_abi_info<'a, Ty, C>(cx: &C, fty: &mut FnType<'a, Ty>, flavor: Fla for arg in &mut fty.args { let attrs = match arg.mode { - PassMode::Ignore(_) | + PassMode::Ignore | PassMode::Indirect(_, None) => continue, PassMode::Direct(ref mut attrs) => attrs, PassMode::Pair(..) | diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 06f51e972c9..fd6744da060 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -2148,18 +2148,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // handled specially and will not descend into this routine. self.ty_infer(None, ast_ty.span) } - hir::TyKind::CVarArgs => { - let va_list_did = match tcx.lang_items().va_list() { - Some(did) => did, - None => span_bug!(ast_ty.span, - "`va_list` lang item required for variadics"), - }; - // FIXME(eddyb) compute this in the body and don't let it reach the signature. - // HACK(eddyb) the `123` anon index is only temporary, to keep tests passing. - // Ideally this would use `ReScope` or similar. - let region = tcx.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BrAnon(123))); - tcx.type_of(va_list_did).subst(tcx, &[region.into()]) - } hir::TyKind::Err => { tcx.types.err } diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index 7e0a3e78188..290b87388eb 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -397,27 +397,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .0; let fn_sig = self.normalize_associated_types_in(call_expr.span, &fn_sig); - let inputs = if fn_sig.c_variadic { - if fn_sig.inputs().len() > 1 { - &fn_sig.inputs()[..fn_sig.inputs().len() - 1] - } else { - span_bug!(call_expr.span, - "C-variadic functions are only valid with one or more fixed arguments"); - } - } else { - &fn_sig.inputs()[..] - }; // Call the generic checker. let expected_arg_tys = self.expected_inputs_for_expected_output( call_expr.span, expected, fn_sig.output(), - inputs, + fn_sig.inputs(), ); self.check_argument_types( call_expr.span, call_expr, - inputs, + fn_sig.inputs(), &expected_arg_tys[..], arg_exprs, fn_sig.c_variadic, diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 9f2c991fdd2..a7832b8c2cf 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1132,8 +1132,29 @@ fn check_fn<'a, 'tcx>( let outer_hir_id = fcx.tcx.hir().as_local_hir_id(outer_def_id).unwrap(); GatherLocalsVisitor { fcx: &fcx, parent_id: outer_hir_id, }.visit_body(body); + // C-variadic fns also have a `VaList` input that's not listed in `fn_sig` + // (as it's created inside the body itself, not passed in from outside). + let maybe_va_list = if fn_sig.c_variadic { + let va_list_did = fcx.tcx.require_lang_item( + lang_items::VaListTypeLangItem, + Some(body.params.last().unwrap().span), + ); + let region = fcx.tcx.mk_region(ty::ReScope(region::Scope { + id: body.value.hir_id.local_id, + data: region::ScopeData::CallSite + })); + + Some(fcx.tcx.type_of(va_list_did).subst(fcx.tcx, &[region.into()])) + } else { + None + }; + // Add formal parameters. - for (param_ty, param) in fn_sig.inputs().iter().zip(&body.params) { + for (param_ty, param) in + fn_sig.inputs().iter().copied() + .chain(maybe_va_list) + .zip(&body.params) + { // Check the pattern. fcx.check_pat_top(¶m.pat, param_ty, None); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 24d017147e4..b530851b80d 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2032,6 +2032,7 @@ impl Clean for doctree::Function<'_> { pub struct FnDecl { pub inputs: Arguments, pub output: FunctionRetTy, + pub c_variadic: bool, pub attrs: Attributes, } @@ -2110,6 +2111,7 @@ impl<'a, A: Copy> Clean for (&'a hir::FnDecl, A) FnDecl { inputs: (&self.0.inputs[..], self.1).clean(cx), output: self.0.output.clean(cx), + c_variadic: self.0.c_variadic, attrs: Attributes::default(), } } @@ -2127,6 +2129,7 @@ impl<'tcx> Clean for (DefId, ty::PolyFnSig<'tcx>) { FnDecl { output: Return(sig.skip_binder().output().clean(cx)), attrs: Attributes::default(), + c_variadic: sig.skip_binder().c_variadic, inputs: Arguments { values: sig.skip_binder().inputs().iter().map(|t| { Argument { @@ -2545,7 +2548,6 @@ pub enum Type { Slice(Box), Array(Box, String), Never, - CVarArgs, RawPointer(Mutability, Box), BorrowedRef { lifetime: Option, @@ -2583,7 +2585,6 @@ pub enum PrimitiveType { Reference, Fn, Never, - CVarArgs, } #[derive(Clone, Copy, Debug)] @@ -2787,7 +2788,6 @@ impl PrimitiveType { Reference => "reference", Fn => "fn", Never => "never", - CVarArgs => "...", } } @@ -3032,7 +3032,6 @@ impl Clean for hir::Ty { TyKind::BareFn(ref barefn) => BareFunction(box barefn.clean(cx)), TyKind::Infer | TyKind::Err => Infer, TyKind::Typeof(..) => panic!("unimplemented type {:?}", self.kind), - TyKind::CVarArgs => CVarArgs, } } } @@ -3980,7 +3979,6 @@ fn build_deref_target_impls(cx: &DocContext<'_>, Reference => None, Fn => None, Never => None, - CVarArgs => tcx.lang_items().va_list(), }; if let Some(did) = did { if !did.is_local() { diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index fafd43cb60b..4cde868201e 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -657,7 +657,6 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter<'_>, use_absolute: bool) -> primitive_link(f, PrimitiveType::Array, &format!("; {}]", n)) } clean::Never => primitive_link(f, PrimitiveType::Never, "!"), - clean::CVarArgs => primitive_link(f, PrimitiveType::CVarArgs, "..."), clean::RawPointer(m, ref t) => { let m = match m { clean::Immutable => "const", @@ -903,12 +902,15 @@ impl clean::BareFunctionDecl { impl clean::FnDecl { crate fn print(&self) -> impl fmt::Display + '_ { display_fn(move |f| { + let ellipsis = if self.c_variadic { ", ..." } else { "" }; if f.alternate() { write!(f, - "({args:#}){arrow:#}", args = self.inputs.print(), arrow = self.output.print()) + "({args:#}{ellipsis}){arrow:#}", + args = self.inputs.print(), ellipsis = ellipsis, arrow = self.output.print()) } else { write!(f, - "({args}){arrow}", args = self.inputs.print(), arrow = self.output.print()) + "({args}{ellipsis}){arrow}", + args = self.inputs.print(), ellipsis = ellipsis, arrow = self.output.print()) } }) } @@ -975,7 +977,12 @@ impl Function<'_> { } } - let args_plain = format!("({})", args_plain); + let mut args_plain = format!("({})", args_plain); + + if decl.c_variadic { + args.push_str(",
..."); + args_plain.push_str(", ..."); + } let output = if let hir::IsAsync::Async = asyncness { Cow::Owned(decl.sugared_async_return_type()) diff --git a/src/test/rustdoc/variadic.rs b/src/test/rustdoc/variadic.rs index 5af2aea21fc..bd8f1775b3d 100644 --- a/src/test/rustdoc/variadic.rs +++ b/src/test/rustdoc/variadic.rs @@ -1,4 +1,4 @@ extern "C" { - // @has variadic/fn.foo.html //pre 'pub unsafe extern "C" fn foo(x: i32, _: ...)' + // @has variadic/fn.foo.html //pre 'pub unsafe extern "C" fn foo(x: i32, ...)' pub fn foo(x: i32, ...); } diff --git a/src/test/ui/c-variadic/variadic-ffi-1.stderr b/src/test/ui/c-variadic/variadic-ffi-1.stderr index 695eba2a7ee..73f72a177bc 100644 --- a/src/test/ui/c-variadic/variadic-ffi-1.stderr +++ b/src/test/ui/c-variadic/variadic-ffi-1.stderr @@ -29,7 +29,7 @@ LL | let x: unsafe extern "C" fn(f: isize, x: u8) = foo; | ^^^ expected non-variadic fn, found variadic function | = note: expected type `unsafe extern "C" fn(isize, u8)` - found type `for<'r> unsafe extern "C" fn(isize, u8, std::ffi::VaListImpl<'r>, ...) {foo}` + found type `unsafe extern "C" fn(isize, u8, ...) {foo}` error[E0308]: mismatched types --> $DIR/variadic-ffi-1.rs:20:54 @@ -37,7 +37,7 @@ error[E0308]: mismatched types LL | let y: extern "C" fn(f: isize, x: u8, ...) = bar; | ^^^ expected variadic fn, found non-variadic function | - = note: expected type `for<'r> extern "C" fn(isize, u8, std::ffi::VaListImpl<'r>, ...)` + = note: expected type `extern "C" fn(isize, u8, ...)` found type `extern "C" fn(isize, u8) {bar}` error[E0617]: can't pass `f32` to variadic function diff --git a/src/test/ui/c-variadic/variadic-ffi-4.nll.stderr b/src/test/ui/c-variadic/variadic-ffi-4.nll.stderr index ab8398ec5e9..8b70b15fa6e 100644 --- a/src/test/ui/c-variadic/variadic-ffi-4.nll.stderr +++ b/src/test/ui/c-variadic/variadic-ffi-4.nll.stderr @@ -1,18 +1,30 @@ -error[E0621]: explicit lifetime required in the type of `ap` +error: lifetime may not live long enough --> $DIR/variadic-ffi-4.rs:8:5 | LL | pub unsafe extern "C" fn no_escape0<'f>(_: usize, ap: ...) -> VaListImpl<'f> { - | --- help: add explicit lifetime `'f` to the type of `ap`: `core::ffi::VaListImpl<'f>` + | -- -- has type `core::ffi::VaListImpl<'1>` + | | + | lifetime `'f` defined here LL | ap - | ^^ lifetime `'f` required + | ^^ function was supposed to return data with lifetime `'1` but it is returning data with lifetime `'f` -error[E0621]: explicit lifetime required in the type of `ap` +error: lifetime may not live long enough + --> $DIR/variadic-ffi-4.rs:8:5 + | +LL | pub unsafe extern "C" fn no_escape0<'f>(_: usize, ap: ...) -> VaListImpl<'f> { + | -- -- has type `core::ffi::VaListImpl<'1>` + | | + | lifetime `'f` defined here +LL | ap + | ^^ returning this value requires that `'1` must outlive `'f` + +error: lifetime may not live long enough --> $DIR/variadic-ffi-4.rs:12:5 | LL | pub unsafe extern "C" fn no_escape1(_: usize, ap: ...) -> VaListImpl<'static> { - | --- help: add explicit lifetime `'static` to the type of `ap`: `core::ffi::VaListImpl<'static>` + | -- has type `core::ffi::VaListImpl<'1>` LL | ap - | ^^ lifetime `'static` required + | ^^ returning this value requires that `'1` must outlive `'static` error: lifetime may not live long enough --> $DIR/variadic-ffi-4.rs:16:33 @@ -44,7 +56,7 @@ LL | *ap0 = ap1; | ^^^^ assignment requires that `'2` must outlive `'1` error: lifetime may not live long enough - --> $DIR/variadic-ffi-4.rs:25:5 + --> $DIR/variadic-ffi-4.rs:24:5 | LL | pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) { | --- ------- has type `core::ffi::VaListImpl<'2>` @@ -54,7 +66,7 @@ LL | ap0 = &mut ap1; | ^^^^^^^^^^^^^^ assignment requires that `'1` must outlive `'2` error: lifetime may not live long enough - --> $DIR/variadic-ffi-4.rs:25:5 + --> $DIR/variadic-ffi-4.rs:24:5 | LL | pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) { | --- ------- has type `core::ffi::VaListImpl<'2>` @@ -64,7 +76,7 @@ LL | ap0 = &mut ap1; | ^^^^^^^^^^^^^^ assignment requires that `'2` must outlive `'1` error[E0384]: cannot assign to immutable argument `ap0` - --> $DIR/variadic-ffi-4.rs:25:5 + --> $DIR/variadic-ffi-4.rs:24:5 | LL | pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) { | --- help: make this binding mutable: `mut ap0` @@ -72,7 +84,7 @@ LL | ap0 = &mut ap1; | ^^^^^^^^^^^^^^ cannot assign to immutable argument error[E0597]: `ap1` does not live long enough - --> $DIR/variadic-ffi-4.rs:25:11 + --> $DIR/variadic-ffi-4.rs:24:11 | LL | pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) { | - let's call the lifetime of this reference `'1` @@ -86,7 +98,7 @@ LL | } | - `ap1` dropped here while still borrowed error: lifetime may not live long enough - --> $DIR/variadic-ffi-4.rs:33:12 + --> $DIR/variadic-ffi-4.rs:31:12 | LL | pub unsafe extern "C" fn no_escape5(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) { | ------- ------- has type `core::ffi::VaListImpl<'2>` @@ -96,7 +108,7 @@ LL | *ap0 = ap1.clone(); | ^^^^^^^^^^^ argument requires that `'1` must outlive `'2` error: lifetime may not live long enough - --> $DIR/variadic-ffi-4.rs:33:12 + --> $DIR/variadic-ffi-4.rs:31:12 | LL | pub unsafe extern "C" fn no_escape5(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) { | ------- ------- has type `core::ffi::VaListImpl<'2>` @@ -105,7 +117,7 @@ LL | pub unsafe extern "C" fn no_escape5(_: usize, mut ap0: &mut VaListImpl, mut LL | *ap0 = ap1.clone(); | ^^^^^^^^^^^ argument requires that `'2` must outlive `'1` -error: aborting due to 11 previous errors +error: aborting due to 12 previous errors -Some errors have detailed explanations: E0384, E0597, E0621. +Some errors have detailed explanations: E0384, E0597. For more information about an error, try `rustc --explain E0384`. diff --git a/src/test/ui/c-variadic/variadic-ffi-4.rs b/src/test/ui/c-variadic/variadic-ffi-4.rs index 4a50d352a5b..a4d658cef16 100644 --- a/src/test/ui/c-variadic/variadic-ffi-4.rs +++ b/src/test/ui/c-variadic/variadic-ffi-4.rs @@ -5,11 +5,11 @@ use core::ffi::{VaList, VaListImpl}; pub unsafe extern "C" fn no_escape0<'f>(_: usize, ap: ...) -> VaListImpl<'f> { - ap //~ ERROR: explicit lifetime required + ap //~ ERROR: mismatched types } pub unsafe extern "C" fn no_escape1(_: usize, ap: ...) -> VaListImpl<'static> { - ap //~ ERROR: explicit lifetime required + ap //~ ERROR: mismatched types } pub unsafe extern "C" fn no_escape2(_: usize, ap: ...) { @@ -18,18 +18,15 @@ pub unsafe extern "C" fn no_escape2(_: usize, ap: ...) { pub unsafe extern "C" fn no_escape3(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) { *ap0 = ap1; //~ ERROR: mismatched types - //~^ ERROR: mismatched types } pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) { ap0 = &mut ap1; //~^ ERROR: a value of type `core::ffi::VaListImpl<'_>` is borrowed for too long - //~^^ ERROR: mismatched types - //~^^^ ERROR: mismatched types - //~^^^^ ERROR: cannot infer an appropriate lifetime + //~| ERROR: mismatched types + //~| ERROR: cannot infer an appropriate lifetime } pub unsafe extern "C" fn no_escape5(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) { *ap0 = ap1.clone(); //~ ERROR: mismatched types - //~^ ERROR: mismatched types } diff --git a/src/test/ui/c-variadic/variadic-ffi-4.stderr b/src/test/ui/c-variadic/variadic-ffi-4.stderr index 3b7eb26c073..b986d0c2435 100644 --- a/src/test/ui/c-variadic/variadic-ffi-4.stderr +++ b/src/test/ui/c-variadic/variadic-ffi-4.stderr @@ -1,18 +1,42 @@ -error[E0621]: explicit lifetime required in the type of `ap` +error[E0308]: mismatched types --> $DIR/variadic-ffi-4.rs:8:5 | -LL | pub unsafe extern "C" fn no_escape0<'f>(_: usize, ap: ...) -> VaListImpl<'f> { - | --- help: add explicit lifetime `'f` to the type of `ap`: `core::ffi::VaListImpl<'f>` LL | ap - | ^^ lifetime `'f` required + | ^^ lifetime mismatch + | + = note: expected type `core::ffi::VaListImpl<'f>` + found type `core::ffi::VaListImpl<'_>` +note: the scope of call-site for function at 7:78... + --> $DIR/variadic-ffi-4.rs:7:78 + | +LL | pub unsafe extern "C" fn no_escape0<'f>(_: usize, ap: ...) -> VaListImpl<'f> { + | ______________________________________________________________________________^ +LL | | ap +LL | | } + | |_^ +note: ...does not necessarily outlive the lifetime 'f as defined on the function body at 7:37 + --> $DIR/variadic-ffi-4.rs:7:37 + | +LL | pub unsafe extern "C" fn no_escape0<'f>(_: usize, ap: ...) -> VaListImpl<'f> { + | ^^ -error[E0621]: explicit lifetime required in the type of `ap` +error[E0308]: mismatched types --> $DIR/variadic-ffi-4.rs:12:5 | -LL | pub unsafe extern "C" fn no_escape1(_: usize, ap: ...) -> VaListImpl<'static> { - | --- help: add explicit lifetime `'static` to the type of `ap`: `core::ffi::VaListImpl<'static>` LL | ap - | ^^ lifetime `'static` required + | ^^ lifetime mismatch + | + = note: expected type `core::ffi::VaListImpl<'static>` + found type `core::ffi::VaListImpl<'_>` +note: the scope of call-site for function at 11:79... + --> $DIR/variadic-ffi-4.rs:11:79 + | +LL | pub unsafe extern "C" fn no_escape1(_: usize, ap: ...) -> VaListImpl<'static> { + | _______________________________________________________________________________^ +LL | | ap +LL | | } + | |_^ + = note: ...does not necessarily outlive the static lifetime error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements --> $DIR/variadic-ffi-4.rs:16:33 @@ -47,12 +71,12 @@ LL | *ap0 = ap1; | = note: expected type `core::ffi::VaListImpl<'_>` found type `core::ffi::VaListImpl<'_>` -note: the anonymous lifetime #124 defined on the function body at 19:1... - --> $DIR/variadic-ffi-4.rs:19:1 +note: the scope of call-site for function at 19:87... + --> $DIR/variadic-ffi-4.rs:19:87 | -LL | / pub unsafe extern "C" fn no_escape3(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) { +LL | pub unsafe extern "C" fn no_escape3(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) { + | _______________________________________________________________________________________^ LL | | *ap0 = ap1; -LL | | LL | | } | |_^ note: ...does not necessarily outlive the anonymous lifetime #2 defined on the function body at 19:1 @@ -60,216 +84,129 @@ note: ...does not necessarily outlive the anonymous lifetime #2 defined on the f | LL | / pub unsafe extern "C" fn no_escape3(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) { LL | | *ap0 = ap1; -LL | | -LL | | } - | |_^ - -error[E0308]: mismatched types - --> $DIR/variadic-ffi-4.rs:20:12 - | -LL | *ap0 = ap1; - | ^^^ lifetime mismatch - | - = note: expected type `core::ffi::VaListImpl<'_>` - found type `core::ffi::VaListImpl<'_>` -note: the anonymous lifetime #2 defined on the function body at 19:1... - --> $DIR/variadic-ffi-4.rs:19:1 - | -LL | / pub unsafe extern "C" fn no_escape3(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) { -LL | | *ap0 = ap1; -LL | | -LL | | } - | |_^ -note: ...does not necessarily outlive the anonymous lifetime #124 defined on the function body at 19:1 - --> $DIR/variadic-ffi-4.rs:19:1 - | -LL | / pub unsafe extern "C" fn no_escape3(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) { -LL | | *ap0 = ap1; -LL | | LL | | } | |_^ error[E0490]: a value of type `core::ffi::VaListImpl<'_>` is borrowed for too long - --> $DIR/variadic-ffi-4.rs:25:11 + --> $DIR/variadic-ffi-4.rs:24:11 | LL | ap0 = &mut ap1; | ^^^^^^^^ | -note: the type is valid for the anonymous lifetime #1 defined on the function body at 24:1 - --> $DIR/variadic-ffi-4.rs:24:1 +note: the type is valid for the anonymous lifetime #1 defined on the function body at 23:1 + --> $DIR/variadic-ffi-4.rs:23:1 | LL | / pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) { LL | | ap0 = &mut ap1; LL | | LL | | LL | | -LL | | LL | | } | |_^ -note: but the borrow lasts for the anonymous lifetime #124 defined on the function body at 24:1 - --> $DIR/variadic-ffi-4.rs:24:1 +note: but the borrow lasts for the scope of call-site for function at 23:83 + --> $DIR/variadic-ffi-4.rs:23:83 | -LL | / pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) { +LL | pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) { + | ___________________________________________________________________________________^ LL | | ap0 = &mut ap1; LL | | LL | | LL | | -LL | | LL | | } | |_^ error[E0308]: mismatched types - --> $DIR/variadic-ffi-4.rs:25:11 + --> $DIR/variadic-ffi-4.rs:24:11 | LL | ap0 = &mut ap1; | ^^^^^^^^ lifetime mismatch | = note: expected type `&mut core::ffi::VaListImpl<'_>` found type `&mut core::ffi::VaListImpl<'_>` -note: the anonymous lifetime #124 defined on the function body at 24:1... - --> $DIR/variadic-ffi-4.rs:24:1 +note: the scope of call-site for function at 23:83... + --> $DIR/variadic-ffi-4.rs:23:83 | -LL | / pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) { +LL | pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) { + | ___________________________________________________________________________________^ LL | | ap0 = &mut ap1; LL | | LL | | LL | | -LL | | LL | | } | |_^ -note: ...does not necessarily outlive the anonymous lifetime #2 defined on the function body at 24:1 - --> $DIR/variadic-ffi-4.rs:24:1 +note: ...does not necessarily outlive the anonymous lifetime #2 defined on the function body at 23:1 + --> $DIR/variadic-ffi-4.rs:23:1 | LL | / pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) { LL | | ap0 = &mut ap1; LL | | LL | | LL | | -LL | | -LL | | } - | |_^ - -error[E0308]: mismatched types - --> $DIR/variadic-ffi-4.rs:25:11 - | -LL | ap0 = &mut ap1; - | ^^^^^^^^ lifetime mismatch - | - = note: expected type `&mut core::ffi::VaListImpl<'_>` - found type `&mut core::ffi::VaListImpl<'_>` -note: the anonymous lifetime #2 defined on the function body at 24:1... - --> $DIR/variadic-ffi-4.rs:24:1 - | -LL | / pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) { -LL | | ap0 = &mut ap1; -LL | | -LL | | -LL | | -LL | | -LL | | } - | |_^ -note: ...does not necessarily outlive the anonymous lifetime #124 defined on the function body at 24:1 - --> $DIR/variadic-ffi-4.rs:24:1 - | -LL | / pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) { -LL | | ap0 = &mut ap1; -LL | | -LL | | -LL | | -LL | | LL | | } | |_^ error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements - --> $DIR/variadic-ffi-4.rs:25:11 + --> $DIR/variadic-ffi-4.rs:24:11 | LL | ap0 = &mut ap1; | ^^^^^^^^ | -note: first, the lifetime cannot outlive the anonymous lifetime #124 defined on the function body at 24:1... - --> $DIR/variadic-ffi-4.rs:24:1 +note: first, the lifetime cannot outlive the scope of call-site for function at 23:83... + --> $DIR/variadic-ffi-4.rs:23:83 | -LL | / pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) { +LL | pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) { + | ___________________________________________________________________________________^ LL | | ap0 = &mut ap1; LL | | LL | | LL | | -LL | | LL | | } | |_^ note: ...so that the type `core::ffi::VaListImpl<'_>` is not borrowed for too long - --> $DIR/variadic-ffi-4.rs:25:11 + --> $DIR/variadic-ffi-4.rs:24:11 | LL | ap0 = &mut ap1; | ^^^^^^^^ -note: but, the lifetime must be valid for the anonymous lifetime #1 defined on the function body at 24:1... - --> $DIR/variadic-ffi-4.rs:24:1 +note: but, the lifetime must be valid for the anonymous lifetime #1 defined on the function body at 23:1... + --> $DIR/variadic-ffi-4.rs:23:1 | LL | / pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) { LL | | ap0 = &mut ap1; LL | | LL | | LL | | -LL | | LL | | } | |_^ note: ...so that reference does not outlive borrowed content - --> $DIR/variadic-ffi-4.rs:25:11 + --> $DIR/variadic-ffi-4.rs:24:11 | LL | ap0 = &mut ap1; | ^^^^^^^^ error[E0308]: mismatched types - --> $DIR/variadic-ffi-4.rs:33:12 + --> $DIR/variadic-ffi-4.rs:31:12 | LL | *ap0 = ap1.clone(); | ^^^^^^^^^^^ lifetime mismatch | = note: expected type `core::ffi::VaListImpl<'_>` found type `core::ffi::VaListImpl<'_>` -note: the anonymous lifetime #124 defined on the function body at 32:1... - --> $DIR/variadic-ffi-4.rs:32:1 +note: the scope of call-site for function at 30:87... + --> $DIR/variadic-ffi-4.rs:30:87 | -LL | / pub unsafe extern "C" fn no_escape5(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) { +LL | pub unsafe extern "C" fn no_escape5(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) { + | _______________________________________________________________________________________^ LL | | *ap0 = ap1.clone(); -LL | | LL | | } | |_^ -note: ...does not necessarily outlive the anonymous lifetime #2 defined on the function body at 32:1 - --> $DIR/variadic-ffi-4.rs:32:1 +note: ...does not necessarily outlive the anonymous lifetime #2 defined on the function body at 30:1 + --> $DIR/variadic-ffi-4.rs:30:1 | LL | / pub unsafe extern "C" fn no_escape5(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) { LL | | *ap0 = ap1.clone(); -LL | | LL | | } | |_^ -error[E0308]: mismatched types - --> $DIR/variadic-ffi-4.rs:33:12 - | -LL | *ap0 = ap1.clone(); - | ^^^^^^^^^^^ lifetime mismatch - | - = note: expected type `core::ffi::VaListImpl<'_>` - found type `core::ffi::VaListImpl<'_>` -note: the anonymous lifetime #2 defined on the function body at 32:1... - --> $DIR/variadic-ffi-4.rs:32:1 - | -LL | / pub unsafe extern "C" fn no_escape5(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) { -LL | | *ap0 = ap1.clone(); -LL | | -LL | | } - | |_^ -note: ...does not necessarily outlive the anonymous lifetime #124 defined on the function body at 32:1 - --> $DIR/variadic-ffi-4.rs:32:1 - | -LL | / pub unsafe extern "C" fn no_escape5(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) { -LL | | *ap0 = ap1.clone(); -LL | | -LL | | } - | |_^ +error: aborting due to 8 previous errors -error: aborting due to 11 previous errors - -Some errors have detailed explanations: E0308, E0621. -For more information about an error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/error-codes/E0617.rs b/src/test/ui/error-codes/E0617.rs index 439c3db5768..c832e09ac11 100644 --- a/src/test/ui/error-codes/E0617.rs +++ b/src/test/ui/error-codes/E0617.rs @@ -1,5 +1,3 @@ -// ignore-tidy-linelength - extern { fn printf(c: *const i8, ...); } @@ -22,7 +20,7 @@ fn main() { //~^ ERROR can't pass `u16` to variadic function //~| HELP cast the value to `c_uint` printf(::std::ptr::null(), printf); - //~^ ERROR can't pass `for<'r> unsafe extern "C" fn(*const i8, std::ffi::VaListImpl<'r>, ...) {printf}` to variadic function - //~| HELP cast the value to `for<'r> unsafe extern "C" fn(*const i8, std::ffi::VaListImpl<'r>, ...)` + //~^ ERROR can't pass `unsafe extern "C" fn(*const i8, ...) {printf}` to variadic function + //~| HELP cast the value to `unsafe extern "C" fn(*const i8, ...)` } } diff --git a/src/test/ui/error-codes/E0617.stderr b/src/test/ui/error-codes/E0617.stderr index d866320bbcd..7c4df099d0d 100644 --- a/src/test/ui/error-codes/E0617.stderr +++ b/src/test/ui/error-codes/E0617.stderr @@ -1,42 +1,42 @@ error[E0617]: can't pass `f32` to variadic function - --> $DIR/E0617.rs:9:36 + --> $DIR/E0617.rs:7:36 | LL | printf(::std::ptr::null(), 0f32); | ^^^^ help: cast the value to `c_double`: `0f32 as c_double` error[E0617]: can't pass `i8` to variadic function - --> $DIR/E0617.rs:12:36 + --> $DIR/E0617.rs:10:36 | LL | printf(::std::ptr::null(), 0i8); | ^^^ help: cast the value to `c_int`: `0i8 as c_int` error[E0617]: can't pass `i16` to variadic function - --> $DIR/E0617.rs:15:36 + --> $DIR/E0617.rs:13:36 | LL | printf(::std::ptr::null(), 0i16); | ^^^^ help: cast the value to `c_int`: `0i16 as c_int` error[E0617]: can't pass `u8` to variadic function - --> $DIR/E0617.rs:18:36 + --> $DIR/E0617.rs:16:36 | LL | printf(::std::ptr::null(), 0u8); | ^^^ help: cast the value to `c_uint`: `0u8 as c_uint` error[E0617]: can't pass `u16` to variadic function - --> $DIR/E0617.rs:21:36 + --> $DIR/E0617.rs:19:36 | LL | printf(::std::ptr::null(), 0u16); | ^^^^ help: cast the value to `c_uint`: `0u16 as c_uint` -error[E0617]: can't pass `for<'r> unsafe extern "C" fn(*const i8, std::ffi::VaListImpl<'r>, ...) {printf}` to variadic function - --> $DIR/E0617.rs:24:36 +error[E0617]: can't pass `unsafe extern "C" fn(*const i8, ...) {printf}` to variadic function + --> $DIR/E0617.rs:22:36 | LL | printf(::std::ptr::null(), printf); | ^^^^^^ -help: cast the value to `for<'r> unsafe extern "C" fn(*const i8, std::ffi::VaListImpl<'r>, ...)` +help: cast the value to `unsafe extern "C" fn(*const i8, ...)` | -LL | printf(::std::ptr::null(), printf as for<'r> unsafe extern "C" fn(*const i8, std::ffi::VaListImpl<'r>, ...)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | printf(::std::ptr::null(), printf as unsafe extern "C" fn(*const i8, ...)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 6 previous errors diff --git a/src/test/ui/symbol-names/impl1.legacy.stderr b/src/test/ui/symbol-names/impl1.legacy.stderr index c1d22a919d9..a3d966bb0b0 100644 --- a/src/test/ui/symbol-names/impl1.legacy.stderr +++ b/src/test/ui/symbol-names/impl1.legacy.stderr @@ -46,26 +46,26 @@ error: def-path(bar::::baz) LL | #[rustc_def_path] | ^^^^^^^^^^^^^^^^^ -error: symbol-name(_ZN198_$LT$$u5b$$RF$dyn$u20$impl1..Foo$u2b$Assoc$u20$$u3d$$u20$extern$u20$$u22$C$u22$$u20$fn$LP$$RF$u8$RP$$u2b$impl1..AutoTrait$u3b$$u20$_$u5d$$u20$as$u20$impl1..main..$u7b$$u7b$closure$u7d$$u7d$..Bar$GT$6method17h6f205aef6a8ccc7bE) - --> $DIR/impl1.rs:63:13 +error: symbol-name(_ZN209_$LT$$u5b$$RF$dyn$u20$impl1..Foo$u2b$Assoc$u20$$u3d$$u20$extern$u20$$u22$C$u22$$u20$fn$LP$$RF$u8$C$$u20$...$RP$$u2b$impl1..AutoTrait$u3b$$u20$_$u5d$$u20$as$u20$impl1..main..$u7b$$u7b$closure$u7d$$u7d$..Bar$GT$6method17h059bf53000885489E) + --> $DIR/impl1.rs:61:13 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8)+impl1::AutoTrait; _] as impl1::main::{{closure}}::Bar>::method::h6f205aef6a8ccc7b) - --> $DIR/impl1.rs:63:13 +error: demangling(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8, ::.)+impl1::AutoTrait; _] as impl1::main::{{closure}}::Bar>::method::h059bf53000885489) + --> $DIR/impl1.rs:61:13 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling-alt(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8)+impl1::AutoTrait; _] as impl1::main::{{closure}}::Bar>::method) - --> $DIR/impl1.rs:63:13 +error: demangling-alt(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8, ::.)+impl1::AutoTrait; _] as impl1::main::{{closure}}::Bar>::method) + --> $DIR/impl1.rs:61:13 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: def-path(<[&dyn Foo extern "C" fn(&'r u8)> + AutoTrait; _] as main::{{closure}}#1::Bar>::method) - --> $DIR/impl1.rs:70:13 +error: def-path(<[&dyn Foo extern "C" fn(&'r u8, ...)> + AutoTrait; _] as main::{{closure}}#1::Bar>::method) + --> $DIR/impl1.rs:68:13 | LL | #[rustc_def_path] | ^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/symbol-names/impl1.rs b/src/test/ui/symbol-names/impl1.rs index 137b72dcd9c..add0d10ea6c 100644 --- a/src/test/ui/symbol-names/impl1.rs +++ b/src/test/ui/symbol-names/impl1.rs @@ -57,19 +57,17 @@ fn main() { } // Test type mangling, by putting them in an `impl` header. - // FIXME(eddyb) test C varargs when `core::ffi::VaListImpl` stops leaking into the signature - // (which is a problem because `core` has an unpredictable hash) - see also #44930. - impl Bar for [&'_ (dyn Foo + AutoTrait); 3] { + impl Bar for [&'_ (dyn Foo + AutoTrait); 3] { #[rustc_symbol_name] - //[legacy]~^ ERROR symbol-name(_ZN198_$LT$$u5b$$RF$dyn$u20$impl1..Foo$u2b$Assoc$u20$$u3d$$u20$extern$u20$$u22$C$u22$$u20$fn$LP$$RF$u8$RP$$u2b$impl1..AutoTrait$u3b$$u20$_$u5d$$u20$as$u20$impl1..main..$u7b$$u7b$closure$u7d$$u7d$..Bar$GT$6method - //[legacy]~| ERROR demangling(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8)+impl1::AutoTrait; _] as impl1::main::{{closure}}::Bar>::method - //[legacy]~| ERROR demangling-alt(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8)+impl1::AutoTrait; _] as impl1::main::{{closure}}::Bar>::method) - //[v0]~^^^^ ERROR symbol-name(_RNvXNCNvCs4fqI2P2rA04_5impl14mains_0ARDNtB6_3Foop5AssocFG_KCRL0_hEuNtB6_9AutoTraitEL_j3_NtB2_3Bar6method) - //[v0]~| ERROR demangling(<[&dyn impl1[317d481089b8c8fe]::Foo extern "C" fn(&'a u8)> + impl1[317d481089b8c8fe]::AutoTrait; 3: usize] as impl1[317d481089b8c8fe]::main::{closure#1}::Bar>::method) - //[v0]~| ERROR demangling-alt(<[&dyn impl1::Foo extern "C" fn(&'a u8)> + impl1::AutoTrait; 3] as impl1::main::{closure#1}::Bar>::method) + //[legacy]~^ ERROR symbol-name(_ZN209_$LT$$u5b$$RF$dyn$u20$impl1..Foo$u2b$Assoc$u20$$u3d$$u20$extern$u20$$u22$C$u22$$u20$fn$LP$$RF$u8$C$$u20$...$RP$$u2b$impl1..AutoTrait$u3b$$u20$_$u5d$$u20$as$u20$impl1..main..$u7b$$u7b$closure$u7d$$u7d$..Bar$GT$6method + //[legacy]~| ERROR demangling(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8, ::.)+impl1::AutoTrait; _] as impl1::main::{{closure}}::Bar>::method + //[legacy]~| ERROR demangling-alt(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8, ::.)+impl1::AutoTrait; _] as impl1::main::{{closure}}::Bar>::method) + //[v0]~^^^^ ERROR symbol-name(_RNvXNCNvCs4fqI2P2rA04_5impl14mains_0ARDNtB6_3Foop5AssocFG_KCRL0_hvEuNtB6_9AutoTraitEL_j3_NtB2_3Bar6method) + //[v0]~| ERROR demangling(<[&dyn impl1[317d481089b8c8fe]::Foo extern "C" fn(&'a u8, ...)> + impl1[317d481089b8c8fe]::AutoTrait; 3: usize] as impl1[317d481089b8c8fe]::main::{closure#1}::Bar>::method) + //[v0]~| ERROR demangling-alt(<[&dyn impl1::Foo extern "C" fn(&'a u8, ...)> + impl1::AutoTrait; 3] as impl1::main::{closure#1}::Bar>::method) #[rustc_def_path] - //[legacy]~^ ERROR def-path(<[&dyn Foo extern "C" fn(&'r u8)> + AutoTrait; _] as main::{{closure}}#1::Bar>::method) - //[v0]~^^ ERROR def-path(<[&dyn Foo extern "C" fn(&'r u8)> + AutoTrait; _] as main::{{closure}}#1::Bar>::method) + //[legacy]~^ ERROR def-path(<[&dyn Foo extern "C" fn(&'r u8, ...)> + AutoTrait; _] as main::{{closure}}#1::Bar>::method) + //[v0]~^^ ERROR def-path(<[&dyn Foo extern "C" fn(&'r u8, ...)> + AutoTrait; _] as main::{{closure}}#1::Bar>::method) fn method(&self) {} } }; diff --git a/src/test/ui/symbol-names/impl1.v0.stderr b/src/test/ui/symbol-names/impl1.v0.stderr index e024799df86..01fe39ddf6c 100644 --- a/src/test/ui/symbol-names/impl1.v0.stderr +++ b/src/test/ui/symbol-names/impl1.v0.stderr @@ -46,26 +46,26 @@ error: def-path(bar::::baz) LL | #[rustc_def_path] | ^^^^^^^^^^^^^^^^^ -error: symbol-name(_RNvXNCNvCs4fqI2P2rA04_5impl14mains_0ARDNtB6_3Foop5AssocFG_KCRL0_hEuNtB6_9AutoTraitEL_j3_NtB2_3Bar6method) - --> $DIR/impl1.rs:63:13 +error: symbol-name(_RNvXNCNvCs4fqI2P2rA04_5impl14mains_0ARDNtB6_3Foop5AssocFG_KCRL0_hvEuNtB6_9AutoTraitEL_j3_NtB2_3Bar6method) + --> $DIR/impl1.rs:61:13 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(<[&dyn impl1[317d481089b8c8fe]::Foo extern "C" fn(&'a u8)> + impl1[317d481089b8c8fe]::AutoTrait; 3: usize] as impl1[317d481089b8c8fe]::main::{closure#1}::Bar>::method) - --> $DIR/impl1.rs:63:13 +error: demangling(<[&dyn impl1[317d481089b8c8fe]::Foo extern "C" fn(&'a u8, ...)> + impl1[317d481089b8c8fe]::AutoTrait; 3: usize] as impl1[317d481089b8c8fe]::main::{closure#1}::Bar>::method) + --> $DIR/impl1.rs:61:13 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling-alt(<[&dyn impl1::Foo extern "C" fn(&'a u8)> + impl1::AutoTrait; 3] as impl1::main::{closure#1}::Bar>::method) - --> $DIR/impl1.rs:63:13 +error: demangling-alt(<[&dyn impl1::Foo extern "C" fn(&'a u8, ...)> + impl1::AutoTrait; 3] as impl1::main::{closure#1}::Bar>::method) + --> $DIR/impl1.rs:61:13 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: def-path(<[&dyn Foo extern "C" fn(&'r u8)> + AutoTrait; _] as main::{{closure}}#1::Bar>::method) - --> $DIR/impl1.rs:70:13 +error: def-path(<[&dyn Foo extern "C" fn(&'r u8, ...)> + AutoTrait; _] as main::{{closure}}#1::Bar>::method) + --> $DIR/impl1.rs:68:13 | LL | #[rustc_def_path] | ^^^^^^^^^^^^^^^^^