Auto merge of #155223 - teor2345:fndef-refactor, r=mati865

Refactor FnDecl and FnSig non-type fields into a new wrapper type





#### Why this Refactor?

This PR is part of an initial cleanup for the [arg splat experiment](https://github.com/rust-lang/rust/issues/153629), but it's a useful refactor by itself.

It refactors the non-type fields of `FnDecl`, `FnSig`, and `FnHeader` into a new packed wrapper types, based on this comment in the `splat` experiment PR:
https://github.com/rust-lang/rust/pull/153697#discussion_r3004637413

It also refactors some common `FnSig` creation settings into their own methods. I did this instead of creating a struct with defaults.

#### Relationship to `splat` Experiment

I don't think we can use functional struct updates (`..default()`) to create `FnDecl` and `FnSig`, because we need the bit-packing for the `splat` experiment.

Bit-packing will avoid breaking "type is small" assertions for commonly used types when `splat` is added.
This PR packs these types:
- ExternAbi: enum + `unwind` variants (38) -> 6 bits
- ImplicitSelfKind: enum variants (5) -> 3 bits
- lifetime_elision_allowed, safety, c_variadic: bool -> 1 bit

#### Minor Changes

Fixes some typos, and applies rustfmt to clippy files that got skipped somehow.
This commit is contained in:
bors
2026-04-18 23:46:37 +00:00
97 changed files with 760 additions and 546 deletions
-1
View File
@@ -4579,7 +4579,6 @@ name = "rustc_query_impl"
version = "0.0.0"
dependencies = [
"measureme",
"rustc_abi",
"rustc_data_structures",
"rustc_errors",
"rustc_hir",
+23
View File
@@ -131,6 +131,29 @@ pub const fn as_str(&self) -> &'static str {
$($e_name::$variant $( { unwind: $uw } )* => $tok,)*
}
}
// FIXME(FnSigKind): when PartialEq is stably const, use it instead
const fn internal_const_eq(&self, other: &Self) -> bool {
match (self, other) {
$( ( $e_name::$variant $( { unwind: $uw } )* , $e_name::$variant $( { unwind: $uw } )* ) => true,)*
_ => false,
}
}
// ALL_VARIANTS.iter().position(|v| v == self), but const
pub const fn as_packed(&self) -> u8 {
let mut index = 0;
while index < $e_name::ALL_VARIANTS.len() {
if self.internal_const_eq(&$e_name::ALL_VARIANTS[index]) {
return index as u8;
}
index += 1;
}
panic!("unreachable: invalid ExternAbi variant");
}
pub const fn from_packed(index: u8) -> Self {
let index = index as usize;
assert!(index < $e_name::ALL_VARIANTS.len(), "invalid ExternAbi index");
$e_name::ALL_VARIANTS[index]
}
}
impl ::core::str::FromStr for $e_name {
+8 -14
View File
@@ -46,9 +46,9 @@
use rustc_ast::*;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir;
use rustc_hir::attrs::{AttributeKind, InlineAttr};
use rustc_hir::def_id::DefId;
use rustc_hir::{self as hir, FnDeclFlags};
use rustc_middle::span_bug;
use rustc_middle::ty::Asyncness;
use rustc_span::symbol::kw;
@@ -271,7 +271,7 @@ fn get_resolution_id(&self, node_id: NodeId) -> Option<DefId> {
// Function parameter count, including C variadic `...` if present.
fn param_count(&self, def_id: DefId) -> (usize, bool /*c_variadic*/) {
let sig = self.tcx.fn_sig(def_id).skip_binder().skip_binder();
(sig.inputs().len() + usize::from(sig.c_variadic), sig.c_variadic)
(sig.inputs().len() + usize::from(sig.c_variadic()), sig.c_variadic())
}
fn lower_delegation_decl(
@@ -309,9 +309,9 @@ fn lower_delegation_decl(
self.arena.alloc(hir::FnDecl {
inputs,
output: hir::FnRetTy::Return(output),
c_variadic,
lifetime_elision_allowed: true,
implicit_self: hir::ImplicitSelfKind::None,
fn_decl_kind: FnDeclFlags::default()
.set_lifetime_elision_allowed(true)
.set_c_variadic(c_variadic),
})
}
@@ -331,11 +331,11 @@ fn lower_delegation_sig(
safety: if self.tcx.codegen_fn_attrs(sig_id).safe_target_features {
hir::HeaderSafety::SafeTargetFeatures
} else {
hir::HeaderSafety::Normal(sig.safety)
hir::HeaderSafety::Normal(sig.safety())
},
constness: self.tcx.constness(sig_id),
asyncness,
abi: sig.abi,
abi: sig.abi(),
};
hir::FnSig { decl, header, span }
@@ -603,13 +603,7 @@ fn generate_delegation_error(
span: Span,
delegation: &Delegation,
) -> DelegationResults<'hir> {
let decl = self.arena.alloc(hir::FnDecl {
inputs: &[],
output: hir::FnRetTy::DefaultReturn(span),
c_variadic: false,
lifetime_elision_allowed: true,
implicit_self: hir::ImplicitSelfKind::None,
});
let decl = self.arena.alloc(hir::FnDecl::dummy(span));
let header = self.generate_header_error();
let sig = hir::FnSig { decl, header, span };
+1 -3
View File
@@ -755,9 +755,7 @@ pub(super) fn make_desugared_coroutine_expr(
let fn_decl = self.arena.alloc(hir::FnDecl {
inputs,
output,
c_variadic: false,
implicit_self: hir::ImplicitSelfKind::None,
lifetime_elision_allowed: false,
fn_decl_kind: hir::FnDeclFlags::default(),
});
let body = self.lower_body(move |this| {
+8 -9
View File
@@ -1849,7 +1849,7 @@ fn lower_fn_decl(
// 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 {
if decl.c_variadic() {
inputs = &inputs[..inputs.len() - 1];
}
let inputs = self.arena.alloc_from_iter(inputs.iter().map(|param| {
@@ -1912,12 +1912,8 @@ fn lower_fn_decl(
},
};
self.arena.alloc(hir::FnDecl {
inputs,
output,
c_variadic,
lifetime_elision_allowed: self.resolver.lifetime_elision_allowed(fn_node_id),
implicit_self: decl.inputs.get(0).map_or(hir::ImplicitSelfKind::None, |arg| {
let fn_decl_kind = hir::FnDeclFlags::default()
.set_implicit_self(decl.inputs.get(0).map_or(hir::ImplicitSelfKind::None, |arg| {
let is_mutable_pat = matches!(
arg.pat.kind,
PatKind::Ident(hir::BindingMode(_, Mutability::Mut), ..)
@@ -1939,8 +1935,11 @@ fn lower_fn_decl(
}
_ => hir::ImplicitSelfKind::None,
}
}),
})
}))
.set_lifetime_elision_allowed(self.resolver.lifetime_elision_allowed(fn_node_id))
.set_c_variadic(c_variadic);
self.arena.alloc(hir::FnDecl { inputs, output, fn_decl_kind })
}
// Transforms `-> T` for `async fn` into `-> OpaqueTy { .. }`
@@ -493,7 +493,7 @@ pub(crate) fn report_mutability_error(
for (_, node) in self.infcx.tcx.hir_parent_iter(upvar_hir_id) {
if let Some(fn_decl) = node.fn_decl() {
if !matches!(
fn_decl.implicit_self,
fn_decl.implicit_self(),
hir::ImplicitSelfKind::RefImm | hir::ImplicitSelfKind::RefMut
) {
err.span_suggestion_verbose(
@@ -810,7 +810,7 @@ fn is_error_in_trait(&self, local: Local) -> (bool, bool, Option<Span>) {
&& let Some(ty) = sig.decl.inputs.get(local.index() - 1)
&& let hir::TyKind::Ref(_, mut_ty) = ty.kind
&& let hir::Mutability::Not = mut_ty.mutbl
&& sig.decl.implicit_self.has_implicit_self()
&& sig.decl.implicit_self().has_implicit_self()
{
Some(ty.span)
} else {
@@ -1147,7 +1147,7 @@ fn expected_fn_found_fn_mut_call(&self, err: &mut Diag<'_>, sp: Span, act: &str)
arg_pos
.and_then(|pos| {
sig.decl.inputs.get(
pos + if sig.decl.implicit_self.has_implicit_self() {
pos + if sig.decl.implicit_self().has_implicit_self() {
1
} else {
0
@@ -15,7 +15,8 @@
use rustc_middle::hir::place::PlaceBase;
use rustc_middle::mir::{AnnotationSource, ConstraintCategory, ReturnConstraint};
use rustc_middle::ty::{
self, GenericArgs, Region, RegionVid, Ty, TyCtxt, TypeFoldable, TypeVisitor, fold_regions,
self, FnSigKind, GenericArgs, Region, RegionVid, Ty, TyCtxt, TypeFoldable, TypeVisitor,
fold_regions,
};
use rustc_span::{Ident, Span, kw};
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
@@ -1083,14 +1084,14 @@ fn suggest_deref_closure_return(&self, diag: &mut Diag<'_>) {
}
// Build a new closure where the return type is an owned value, instead of a ref.
let fn_sig_kind =
FnSigKind::default().set_safe(true).set_c_variadic(liberated_sig.c_variadic());
let closure_sig_as_fn_ptr_ty = Ty::new_fn_ptr(
tcx,
ty::Binder::dummy(tcx.mk_fn_sig(
liberated_sig.inputs().iter().copied(),
peeled_ty,
liberated_sig.c_variadic,
hir::Safety::Safe,
rustc_abi::ExternAbi::Rust,
fn_sig_kind,
)),
);
let closure_ty = Ty::new_closure(
@@ -103,9 +103,7 @@ pub(super) fn check_signature_annotation(&mut self) {
user_provided_sig = self.tcx().mk_fn_sig(
user_provided_sig.inputs().iter().copied(),
output_ty,
user_provided_sig.c_variadic,
user_provided_sig.safety,
user_provided_sig.abi,
user_provided_sig.fn_sig_kind,
);
}
@@ -1015,7 +1015,7 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
if let ty::FnDef(def_id, _) = *src_ty.kind()
&& let ty::FnPtr(_, target_hdr) = *ty.kind()
&& tcx.codegen_fn_attrs(def_id).safe_target_features
&& target_hdr.safety.is_safe()
&& target_hdr.safety().is_safe()
&& let Some(safe_sig) = tcx.adjust_target_feature_sig(
def_id,
src_sig,
@@ -1971,7 +1971,8 @@ fn check_call_inputs(
term_location: Location,
call_source: CallSource,
) {
if args.len() < sig.inputs().len() || (args.len() > sig.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);
}
@@ -870,20 +870,10 @@ pub(crate) fn assert_assignable<'tcx>(
let from_sig = fx
.tcx
.normalize_erasing_late_bound_regions(fx.typing_env(), from_ty.fn_sig(fx.tcx));
let FnSig {
inputs_and_output: types_from,
c_variadic: c_variadic_from,
safety: unsafety_from,
abi: abi_from,
} = from_sig;
let FnSig { inputs_and_output: types_from, fn_sig_kind: fn_sig_kind_from } = from_sig;
let to_sig =
fx.tcx.normalize_erasing_late_bound_regions(fx.typing_env(), to_ty.fn_sig(fx.tcx));
let FnSig {
inputs_and_output: types_to,
c_variadic: c_variadic_to,
safety: unsafety_to,
abi: abi_to,
} = to_sig;
let FnSig { inputs_and_output: types_to, fn_sig_kind: fn_sig_kind_to } = to_sig;
let mut types_from = types_from.iter();
let mut types_to = types_to.iter();
loop {
@@ -894,17 +884,7 @@ pub(crate) fn assert_assignable<'tcx>(
}
}
assert_eq!(
c_variadic_from, c_variadic_to,
"Can't write fn ptr with incompatible sig {:?} to place with sig {:?}\n\n{:#?}",
from_sig, to_sig, fx,
);
assert_eq!(
unsafety_from, unsafety_to,
"Can't write fn ptr with incompatible sig {:?} to place with sig {:?}\n\n{:#?}",
from_sig, to_sig, fx,
);
assert_eq!(
abi_from, abi_to,
fn_sig_kind_from, fn_sig_kind_to,
"Can't write fn ptr with incompatible sig {:?} to place with sig {:?}\n\n{:#?}",
from_sig, to_sig, fx,
);
@@ -7,8 +7,6 @@
#[cfg(feature = "master")]
use gccjit::Type;
use gccjit::{ComparisonOp, Function, FunctionType, RValue, ToRValue, UnaryOp};
#[cfg(feature = "master")]
use rustc_abi::ExternAbi;
use rustc_abi::{BackendRepr, HasDataLayout, WrappingRange};
use rustc_codegen_ssa::MemFlags;
use rustc_codegen_ssa::base::wants_msvc_seh;
@@ -1483,32 +1481,26 @@ fn get_rust_try_fn<'a, 'gcc, 'tcx>(
// `unsafe fn(*mut i8) -> ()`
let try_fn_ty = Ty::new_fn_ptr(
tcx,
ty::Binder::dummy(tcx.mk_fn_sig(
ty::Binder::dummy(tcx.mk_fn_sig_rust_abi(
iter::once(i8p),
tcx.types.unit,
false,
rustc_hir::Safety::Unsafe,
ExternAbi::Rust,
)),
);
// `unsafe fn(*mut i8, *mut i8) -> ()`
let catch_fn_ty = Ty::new_fn_ptr(
tcx,
ty::Binder::dummy(tcx.mk_fn_sig(
ty::Binder::dummy(tcx.mk_fn_sig_rust_abi(
[i8p, i8p].iter().cloned(),
tcx.types.unit,
false,
rustc_hir::Safety::Unsafe,
ExternAbi::Rust,
)),
);
// `unsafe fn(unsafe fn(*mut i8) -> (), *mut i8, unsafe fn(*mut i8, *mut i8) -> ()) -> i32`
let rust_fn_sig = ty::Binder::dummy(cx.tcx.mk_fn_sig(
let rust_fn_sig = ty::Binder::dummy(cx.tcx.mk_fn_sig_rust_abi(
[try_fn_ty, i8p, catch_fn_ty],
tcx.types.i32,
false,
rustc_hir::Safety::Unsafe,
ExternAbi::Rust,
));
let rust_try = gen_fn(cx, "__rust_try", rust_fn_sig, codegen);
cx.rust_try_fn.set(Some(rust_try));
+5 -20
View File
@@ -3,8 +3,7 @@
use std::{assert_matches, iter, ptr};
use rustc_abi::{
Align, BackendRepr, ExternAbi, Float, HasDataLayout, NumScalableVectors, Primitive, Size,
WrappingRange,
Align, BackendRepr, Float, HasDataLayout, NumScalableVectors, Primitive, Size, WrappingRange,
};
use rustc_codegen_ssa::base::{compare_simd_types, wants_msvc_seh, wants_wasm_eh};
use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
@@ -820,7 +819,7 @@ fn codegen_llvm_intrinsic_call(
}
_ => unreachable!(),
};
assert!(!fn_sig.c_variadic);
assert!(!fn_sig.c_variadic());
let ret_layout = self.layout_of(fn_sig.output());
let llreturn_ty = if ret_layout.is_zst() {
@@ -1640,32 +1639,18 @@ fn get_rust_try_fn<'a, 'll, 'tcx>(
// `unsafe fn(*mut i8) -> ()`
let try_fn_ty = Ty::new_fn_ptr(
tcx,
ty::Binder::dummy(tcx.mk_fn_sig(
[i8p],
tcx.types.unit,
false,
hir::Safety::Unsafe,
ExternAbi::Rust,
)),
ty::Binder::dummy(tcx.mk_fn_sig_rust_abi([i8p], tcx.types.unit, hir::Safety::Unsafe)),
);
// `unsafe fn(*mut i8, *mut i8) -> ()`
let catch_fn_ty = Ty::new_fn_ptr(
tcx,
ty::Binder::dummy(tcx.mk_fn_sig(
[i8p, i8p],
tcx.types.unit,
false,
hir::Safety::Unsafe,
ExternAbi::Rust,
)),
ty::Binder::dummy(tcx.mk_fn_sig_rust_abi([i8p, i8p], tcx.types.unit, hir::Safety::Unsafe)),
);
// `unsafe fn(unsafe fn(*mut i8) -> (), *mut i8, unsafe fn(*mut i8, *mut i8) -> ()) -> i32`
let rust_fn_sig = ty::Binder::dummy(cx.tcx.mk_fn_sig(
let rust_fn_sig = ty::Binder::dummy(cx.tcx.mk_fn_sig_rust_abi(
[try_fn_ty, i8p, catch_fn_ty],
tcx.types.i32,
false,
hir::Safety::Unsafe,
ExternAbi::Rust,
));
let rust_try = gen_fn(cx, "__rust_try", rust_fn_sig, codegen);
cx.rust_try_fn.set(Some(rust_try));
@@ -364,10 +364,10 @@ fn push_debuginfo_type_name<'tcx>(
}
output.push_str(" (*)(");
} else {
output.push_str(sig.safety.prefix_str());
output.push_str(sig.safety().prefix_str());
if sig.abi != rustc_abi::ExternAbi::Rust {
let _ = write!(output, "extern {} ", sig.abi);
if sig.abi() != rustc_abi::ExternAbi::Rust {
let _ = write!(output, "extern {} ", sig.abi());
}
output.push_str("fn(");
@@ -381,7 +381,7 @@ fn push_debuginfo_type_name<'tcx>(
pop_arg_separator(output);
}
if sig.c_variadic {
if sig.c_variadic() {
if !sig.inputs().is_empty() {
output.push_str(", ...");
} else {
@@ -419,7 +419,7 @@ pub(crate) fn write_fn_ptr_type_info(
sig: &FnSigTys<TyCtxt<'tcx>>,
fn_header: &FnHeader<TyCtxt<'tcx>>,
) -> InterpResult<'tcx> {
let FnHeader { safety, c_variadic, abi } = fn_header;
let FnHeader { fn_sig_kind } = fn_header;
for (field_idx, field) in
place.layout().ty.ty_adt_def().unwrap().non_enum_variant().fields.iter_enumerated()
@@ -428,9 +428,9 @@ pub(crate) fn write_fn_ptr_type_info(
match field.name {
sym::unsafety => {
self.write_scalar(Scalar::from_bool(safety.is_unsafe()), &field_place)?;
self.write_scalar(Scalar::from_bool(!fn_sig_kind.is_safe()), &field_place)?;
}
sym::abi => match abi {
sym::abi => match fn_sig_kind.abi() {
ExternAbi::C { .. } => {
let (rust_variant, _rust_place) =
self.downcast(&field_place, sym::ExternC)?;
@@ -463,7 +463,7 @@ pub(crate) fn write_fn_ptr_type_info(
self.write_type_id(output, &field_place)?;
}
sym::variadic => {
self.write_scalar(Scalar::from_bool(*c_variadic), &field_place)?;
self.write_scalar(Scalar::from_bool(fn_sig_kind.c_variadic()), &field_place)?;
}
other => span_bug!(self.tcx.def_span(field.did), "unimplemented field {other}"),
}
@@ -542,7 +542,7 @@ fn eval_terminator(&mut self, terminator: &mir::Terminator<'tcx>) -> InterpResul
let destination = self.eval_place(destination)?;
self.init_fn_call(
callee,
(fn_sig.abi, fn_abi),
(fn_sig.abi(), fn_abi),
&args,
with_caller_location,
&destination,
@@ -565,7 +565,12 @@ fn eval_terminator(&mut self, terminator: &mir::Terminator<'tcx>) -> InterpResul
let EvaluatedCalleeAndArgs { callee, args, fn_sig, fn_abi, with_caller_location } =
self.eval_callee_and_args(terminator, func, args, &mir::Place::return_place())?;
self.init_fn_tail_call(callee, (fn_sig.abi, fn_abi), &args, with_caller_location)?;
self.init_fn_tail_call(
callee,
(fn_sig.abi(), fn_abi),
&args,
with_caller_location,
)?;
if self.frame_idx() != old_frame_idx {
span_bug!(
+133 -5
View File
@@ -3921,6 +3921,117 @@ pub struct Param<'hir> {
pub span: Span,
}
/// Contains the packed non-type fields of a function declaration.
// FIXME(splat): add the splatted argument index as a u16
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[derive(Encodable, Decodable, HashStable_Generic)]
pub struct FnDeclFlags {
/// Holds the c_variadic and lifetime_elision_allowed bitflags, and 3 bits for the `ImplicitSelfKind`.
flags: u8,
}
impl fmt::Debug for FnDeclFlags {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut f = f.debug_tuple("FnDeclFlags");
f.field(&format!("ImplicitSelfKind({:?})", self.implicit_self()));
if self.lifetime_elision_allowed() {
f.field(&"LifetimeElisionAllowed");
} else {
f.field(&"NoLifetimeElision");
};
if self.c_variadic() {
f.field(&"CVariadic");
};
f.finish()
}
}
impl FnDeclFlags {
/// Mask for the implicit self kind.
const IMPLICIT_SELF_MASK: u8 = 0b111;
/// Bitflag for a trailing C-style variadic argument.
const C_VARIADIC_FLAG: u8 = 1 << 3;
/// Bitflag for lifetime elision.
const LIFETIME_ELISION_ALLOWED_FLAG: u8 = 1 << 4;
/// Create a new FnDeclKind with no implicit self, no lifetime elision, and no C-style variadic argument.
/// To modify these flags, use the `set_*` methods, for readability.
// FIXME: use Default instead when that trait is const stable.
pub const fn default() -> Self {
Self { flags: 0 }
.set_implicit_self(ImplicitSelfKind::None)
.set_lifetime_elision_allowed(false)
.set_c_variadic(false)
}
/// Set the implicit self kind.
#[must_use = "this method does not modify the receiver"]
pub const fn set_implicit_self(mut self, implicit_self: ImplicitSelfKind) -> Self {
self.flags &= !Self::IMPLICIT_SELF_MASK;
match implicit_self {
ImplicitSelfKind::None => self.flags |= 0,
ImplicitSelfKind::Imm => self.flags |= 1,
ImplicitSelfKind::Mut => self.flags |= 2,
ImplicitSelfKind::RefImm => self.flags |= 3,
ImplicitSelfKind::RefMut => self.flags |= 4,
}
self
}
/// Set the C-style variadic argument flag.
#[must_use = "this method does not modify the receiver"]
pub const fn set_c_variadic(mut self, c_variadic: bool) -> Self {
if c_variadic {
self.flags |= Self::C_VARIADIC_FLAG;
} else {
self.flags &= !Self::C_VARIADIC_FLAG;
}
self
}
/// Set the lifetime elision allowed flag.
#[must_use = "this method does not modify the receiver"]
pub const fn set_lifetime_elision_allowed(mut self, allowed: bool) -> Self {
if allowed {
self.flags |= Self::LIFETIME_ELISION_ALLOWED_FLAG;
} else {
self.flags &= !Self::LIFETIME_ELISION_ALLOWED_FLAG;
}
self
}
/// Get the implicit self kind.
pub const fn implicit_self(self) -> ImplicitSelfKind {
match self.flags & Self::IMPLICIT_SELF_MASK {
0 => ImplicitSelfKind::None,
1 => ImplicitSelfKind::Imm,
2 => ImplicitSelfKind::Mut,
3 => ImplicitSelfKind::RefImm,
4 => ImplicitSelfKind::RefMut,
_ => unreachable!(),
}
}
/// Do the function arguments end with a C-style variadic argument?
pub const fn c_variadic(self) -> bool {
self.flags & Self::C_VARIADIC_FLAG != 0
}
/// Is lifetime elision allowed?
pub const fn lifetime_elision_allowed(self) -> bool {
self.flags & Self::LIFETIME_ELISION_ALLOWED_FLAG != 0
}
}
/// Represents the header (not the body) of a function declaration.
#[derive(Debug, Clone, Copy, HashStable_Generic)]
pub struct FnDecl<'hir> {
@@ -3929,11 +4040,8 @@ pub struct FnDecl<'hir> {
/// Additional argument data is stored in the function's [body](Body::params).
pub inputs: &'hir [Ty<'hir>],
pub output: FnRetTy<'hir>,
pub c_variadic: bool,
/// Does the function have an implicit self?
pub implicit_self: ImplicitSelfKind,
/// Is lifetime elision allowed.
pub lifetime_elision_allowed: bool,
/// The packed function declaration attributes.
pub fn_decl_kind: FnDeclFlags,
}
impl<'hir> FnDecl<'hir> {
@@ -3956,6 +4064,26 @@ pub fn opt_delegation_generics(&self) -> Option<&'hir DelegationGenerics> {
None
}
pub fn implicit_self(&self) -> ImplicitSelfKind {
self.fn_decl_kind.implicit_self()
}
pub fn c_variadic(&self) -> bool {
self.fn_decl_kind.c_variadic()
}
pub fn lifetime_elision_allowed(&self) -> bool {
self.fn_decl_kind.lifetime_elision_allowed()
}
pub fn dummy(span: Span) -> Self {
Self {
inputs: &[],
output: FnRetTy::DefaultReturn(span),
fn_decl_kind: FnDeclFlags::default().set_lifetime_elision_allowed(true),
}
}
}
/// Represents what type of implicit self a function has, if any.
+1 -2
View File
@@ -1216,8 +1216,7 @@ pub fn walk_fn_decl<'v, V: Visitor<'v>>(
visitor: &mut V,
function_declaration: &'v FnDecl<'v>,
) -> V::Result {
let FnDecl { inputs, output, c_variadic: _, implicit_self: _, lifetime_elision_allowed: _ } =
function_declaration;
let FnDecl { inputs, output, fn_decl_kind: _ } = function_declaration;
walk_list!(visitor, visit_ty_unambig, *inputs);
visitor.visit_fn_ret_ty(output)
}
@@ -91,7 +91,7 @@ fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> {
}
pub fn check_custom_abi(tcx: TyCtxt<'_>, def_id: LocalDefId, fn_sig: FnSig<'_>, fn_sig_span: Span) {
if fn_sig.abi == ExternAbi::Custom {
if fn_sig.abi() == ExternAbi::Custom {
// Function definitions that use `extern "custom"` must be naked functions.
if !find_attr!(tcx, def_id, Naked(_)) {
tcx.dcx().emit_err(crate::errors::AbiCustomClothedFunction {
@@ -1,6 +1,5 @@
use std::ops::Not;
use rustc_abi::ExternAbi;
use rustc_hir as hir;
use rustc_hir::{Node, find_attr};
use rustc_infer::infer::TyCtxtInferExt;
@@ -152,13 +151,7 @@ fn main_fn_return_type_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Span> {
expected_return_type = tcx.types.unit;
}
let expected_sig = ty::Binder::dummy(tcx.mk_fn_sig(
[],
expected_return_type,
false,
hir::Safety::Safe,
ExternAbi::Rust,
));
let expected_sig = ty::Binder::dummy(tcx.mk_fn_sig_safe_rust_abi([], expected_return_type));
check_function_signature(
tcx,
@@ -1,6 +1,5 @@
//! Type-checking for the `#[rustc_intrinsic]` intrinsics that the compiler exposes.
use rustc_abi::ExternAbi;
use rustc_errors::DiagMessage;
use rustc_hir::{self as hir, LangItem};
use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
@@ -636,20 +635,10 @@ pub(crate) fn check_intrinsic_type(
sym::catch_unwind => {
let mut_u8 = Ty::new_mut_ptr(tcx, tcx.types.u8);
let try_fn_ty = ty::Binder::dummy(tcx.mk_fn_sig(
[mut_u8],
tcx.types.unit,
false,
hir::Safety::Safe,
ExternAbi::Rust,
));
let catch_fn_ty = ty::Binder::dummy(tcx.mk_fn_sig(
[mut_u8, mut_u8],
tcx.types.unit,
false,
hir::Safety::Safe,
ExternAbi::Rust,
));
let try_fn_ty =
ty::Binder::dummy(tcx.mk_fn_sig_safe_rust_abi([mut_u8], tcx.types.unit));
let catch_fn_ty =
ty::Binder::dummy(tcx.mk_fn_sig_safe_rust_abi([mut_u8, mut_u8], tcx.types.unit));
(
0,
0,
@@ -817,7 +806,7 @@ pub(crate) fn check_intrinsic_type(
return;
}
};
let sig = tcx.mk_fn_sig(inputs, output, false, safety, ExternAbi::Rust);
let sig = tcx.mk_fn_sig_rust_abi(inputs, output, safety);
let sig = ty::Binder::bind_with_vars(sig, bound_vars);
equate_intrinsic_type(tcx, span, intrinsic_id, n_tps, n_lts, n_cts, sig)
}
+2 -2
View File
@@ -478,7 +478,7 @@ fn fn_sig_suggestion<'tcx>(
}
})
})
.chain(std::iter::once(if sig.c_variadic { Some("...".to_string()) } else { None }))
.chain(std::iter::once(if sig.c_variadic() { Some("...".to_string()) } else { None }))
.flatten()
.collect::<Vec<String>>()
.join(", ");
@@ -506,7 +506,7 @@ fn fn_sig_suggestion<'tcx>(
let output = if !output.is_unit() { format!(" -> {output}") } else { String::new() };
let safety = sig.safety.prefix_str();
let safety = sig.safety().prefix_str();
let (generics, where_clauses) = bounds_from_generic_predicates(tcx, predicates, assoc);
// FIXME: this is not entirely correct, as the lifetimes from borrowed params will
@@ -1701,9 +1701,9 @@ fn check_fn_or_method<'tcx>(
check_where_clauses(wfcx, def_id);
if sig.abi == ExternAbi::RustCall {
if sig.abi() == ExternAbi::RustCall {
let span = tcx.def_span(def_id);
let has_implicit_self = hir_decl.implicit_self != hir::ImplicitSelfKind::None;
let has_implicit_self = hir_decl.implicit_self() != hir::ImplicitSelfKind::None;
let mut inputs = sig.inputs().iter().skip(if has_implicit_self { 1 } else { 0 });
// Check that the argument is a tuple and is sized
if let Some(ty) = inputs.next() {
+2 -4
View File
@@ -1040,7 +1040,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFn
(Bound::Unbounded, Bound::Unbounded) => hir::Safety::Safe,
_ => hir::Safety::Unsafe,
};
ty::Binder::dummy(tcx.mk_fn_sig(inputs, ty, false, safety, ExternAbi::Rust))
ty::Binder::dummy(tcx.mk_fn_sig_rust_abi(inputs, ty, safety))
}
Expr(&hir::Expr { kind: hir::ExprKind::Closure { .. }, .. }) => {
@@ -1233,9 +1233,7 @@ fn recover_infer_ret_ty<'tcx>(
let fn_sig = tcx.mk_fn_sig(
fn_sig.inputs().iter().copied(),
recovered_ret_ty.unwrap_or_else(|| Ty::new_error(tcx, guar)),
fn_sig.c_variadic,
fn_sig.safety,
fn_sig.abi,
fn_sig.fn_sig_kind,
);
late_param_regions_to_bound(tcx, scope, bound_vars, fn_sig)
@@ -530,7 +530,7 @@ fn check_constraints<'tcx>(
}));
};
if tcx.fn_sig(sig_id).skip_binder().skip_binder().c_variadic {
if tcx.fn_sig(sig_id).skip_binder().skip_binder().c_variadic() {
// See issue #127443 for explanation.
emit("delegation to C-variadic functions is not allowed");
}
@@ -360,7 +360,7 @@ fn get_lifetime_args_suggestions_from_param_names(
let in_ret =
matches!(fn_decl.output, hir::FnRetTy::Return(ty) if ty.hir_id == ty_id);
if in_arg || (in_ret && fn_decl.lifetime_elision_allowed) {
if in_arg || (in_ret && fn_decl.lifetime_elision_allowed()) {
return std::iter::repeat_n("'_".to_owned(), num_params_to_take)
.collect::<Vec<_>>()
.join(", ");
@@ -48,7 +48,7 @@ pub(crate) fn validate_cmse_abi<'tcx>(
// An `extern "cmse-nonsecure-entry"` function cannot be c-variadic. We run
// into https://github.com/rust-lang/rust/issues/132142 if we don't explicitly bail.
if decl.c_variadic {
if decl.c_variadic() {
return;
}
@@ -38,8 +38,9 @@
use rustc_middle::middle::stability::AllowUnstable;
use rustc_middle::ty::print::PrintPolyTraitRefExt as _;
use rustc_middle::ty::{
self, Const, GenericArgKind, GenericArgsRef, GenericParamDefKind, LitToConstInput, Ty, TyCtxt,
TypeSuperFoldable, TypeVisitableExt, TypingMode, Upcast, const_lit_matches_ty, fold_regions,
self, Const, FnSigKind, GenericArgKind, GenericArgsRef, GenericParamDefKind, LitToConstInput,
Ty, TyCtxt, TypeSuperFoldable, TypeVisitableExt, TypingMode, Upcast, const_lit_matches_ty,
fold_regions,
};
use rustc_middle::{bug, span_bug};
use rustc_session::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS;
@@ -3578,7 +3579,11 @@ pub fn lower_fn_ty(
debug!(?output_ty);
let fn_ty = tcx.mk_fn_sig(input_tys, output_ty, decl.c_variadic, safety, abi);
let fn_sig_kind = FnSigKind::default()
.set_abi(abi)
.set_safe(safety.is_safe())
.set_c_variadic(decl.fn_decl_kind.c_variadic());
let fn_ty = tcx.mk_fn_sig(input_tys, output_ty, fn_sig_kind);
let fn_ptr_ty = ty::Binder::bind_with_vars(fn_ty, bound_vars);
if let hir::Node::Ty(hir::Ty { kind: hir::TyKind::FnPtr(fn_ptr_ty), span, .. }) =
+1 -1
View File
@@ -97,7 +97,7 @@
use crate::hir_ty_lowering::HirTyLowerer;
fn check_c_variadic_abi(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: ExternAbi, span: Span) {
if !decl.c_variadic {
if !decl.c_variadic() {
// Not even a variadic function.
return;
}
+3 -3
View File
@@ -2264,8 +2264,8 @@ fn print_fn(
assert!(arg_idents.is_empty() || body_id.is_none());
let mut i = 0;
let mut print_arg = |s: &mut Self, ty: Option<&hir::Ty<'_>>| {
if i == 0 && decl.implicit_self.has_implicit_self() {
s.print_implicit_self(&decl.implicit_self);
if i == 0 && decl.implicit_self().has_implicit_self() {
s.print_implicit_self(&decl.implicit_self());
} else {
if let Some(arg_ident) = arg_idents.get(i) {
if let Some(arg_ident) = arg_ident {
@@ -2289,7 +2289,7 @@ fn print_fn(
print_arg(s, Some(ty));
s.end(ib);
});
if decl.c_variadic {
if decl.c_variadic() {
if !decl.inputs.is_empty() {
self.word(", ");
}
+7 -9
View File
@@ -89,11 +89,11 @@ pub(crate) fn check_expr_call(
match *autoderef.final_ty().kind() {
ty::FnDef(def_id, _) => {
let abi = self.tcx.fn_sig(def_id).skip_binder().skip_binder().abi;
let abi = self.tcx.fn_sig(def_id).skip_binder().skip_binder().abi();
self.check_call_abi(abi, call_expr.span);
}
ty::FnPtr(_, header) => {
self.check_call_abi(header.abi, call_expr.span);
self.check_call_abi(header.abi(), call_expr.span);
}
_ => { /* cannot have a non-rust abi */ }
}
@@ -275,9 +275,7 @@ fn try_overloaded_call_step(
self.tcx.coroutine_for_closure(def_id),
tupled_upvars_ty,
),
coroutine_closure_sig.c_variadic,
coroutine_closure_sig.safety,
coroutine_closure_sig.abi,
coroutine_closure_sig.fn_sig_kind,
);
let adjustments = self.adjust_steps(autoderef);
self.record_deferred_call_resolution(
@@ -595,12 +593,12 @@ fn confirm_builtin_call(
fn_sig.output(),
expected,
arg_exprs,
fn_sig.c_variadic,
fn_sig.c_variadic(),
TupleArgumentsFlag::DontTupleArguments,
def_id,
);
if fn_sig.abi == rustc_abi::ExternAbi::RustCall {
if fn_sig.abi() == rustc_abi::ExternAbi::RustCall {
let sp = arg_exprs.last().map_or(call_expr.span, |expr| expr.span);
if let Some(ty) = fn_sig.inputs().last().copied() {
self.register_bound(
@@ -905,7 +903,7 @@ fn confirm_deferred_closure_call(
fn_sig.output(),
expected,
arg_exprs,
fn_sig.c_variadic,
fn_sig.c_variadic(),
TupleArgumentsFlag::TupleArguments,
Some(closure_def_id.to_def_id()),
);
@@ -984,7 +982,7 @@ fn confirm_overloaded_call(
method.sig.output(),
expected,
arg_exprs,
method.sig.c_variadic,
method.sig.c_variadic(),
TupleArgumentsFlag::TupleArguments,
Some(method.def_id),
);
+6 -11
View File
@@ -1,6 +1,5 @@
use std::cell::RefCell;
use rustc_abi::ExternAbi;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::lang_items::LangItem;
@@ -55,7 +54,7 @@ pub(super) fn check_fn<'a, 'tcx>(
// 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 = fn_sig.c_variadic.then(|| {
let maybe_va_list = fn_sig.c_variadic().then(|| {
let span = body.params.last().unwrap().span;
let va_list_did = tcx.require_lang_item(LangItem::VaList, span);
let region = fcx.next_region_var(RegionVariableOrigin::Misc(span));
@@ -204,7 +203,7 @@ fn check_panic_info_fn(tcx: TyCtxt<'_>, fn_id: LocalDefId, fn_sig: ty::FnSig<'_>
ty::BoundVariableKind::Region(ty::BoundRegionKind::Anon),
]);
let expected_sig = ty::Binder::bind_with_vars(
tcx.mk_fn_sig([panic_info_ref_ty], tcx.types.never, false, fn_sig.safety, ExternAbi::Rust),
tcx.mk_fn_sig_rust_abi([panic_info_ref_ty], tcx.types.never, fn_sig.safety()),
bounds,
);
@@ -225,12 +224,10 @@ fn check_lang_start_fn<'tcx>(tcx: TyCtxt<'tcx>, fn_sig: ty::FnSig<'tcx>, def_id:
let generics = tcx.generics_of(def_id);
let fn_generic = generics.param_at(0, tcx);
let generic_ty = Ty::new_param(tcx, fn_generic.index, fn_generic.name);
let main_fn_ty = Ty::new_fn_ptr(
tcx,
Binder::dummy(tcx.mk_fn_sig([], generic_ty, false, hir::Safety::Safe, ExternAbi::Rust)),
);
let main_fn_ty =
Ty::new_fn_ptr(tcx, Binder::dummy(tcx.mk_fn_sig_safe_rust_abi([], generic_ty)));
let expected_sig = ty::Binder::dummy(tcx.mk_fn_sig(
let expected_sig = ty::Binder::dummy(tcx.mk_fn_sig_rust_abi(
[
main_fn_ty,
tcx.types.isize,
@@ -238,9 +235,7 @@ fn check_lang_start_fn<'tcx>(tcx: TyCtxt<'tcx>, fn_sig: ty::FnSig<'tcx>, def_id:
tcx.types.u8,
],
tcx.types.isize,
false,
fn_sig.safety,
ExternAbi::Rust,
fn_sig.safety(),
));
let _ = check_function_signature(
+28 -57
View File
@@ -13,7 +13,7 @@
use rustc_macros::{TypeFoldable, TypeVisitable};
use rustc_middle::span_bug;
use rustc_middle::ty::{
self, ClosureKind, GenericArgs, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable,
self, ClosureKind, FnSigKind, GenericArgs, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable,
TypeVisitableExt, TypeVisitor,
};
use rustc_span::def_id::LocalDefId;
@@ -85,13 +85,7 @@ pub(crate) fn check_expr_closure(
// Tuple up the arguments and insert the resulting function type into
// the `closures` table.
let sig = bound_sig.map_bound(|sig| {
tcx.mk_fn_sig(
[Ty::new_tup(tcx, sig.inputs())],
sig.output(),
sig.c_variadic,
sig.safety,
sig.abi,
)
tcx.mk_fn_sig([Ty::new_tup(tcx, sig.inputs())], sig.output(), sig.fn_sig_kind)
});
debug!(?sig, ?expected_kind);
@@ -231,9 +225,7 @@ pub(crate) fn check_expr_closure(
Ty::new_tup_from_iter(tcx, sig.inputs().iter().copied()),
],
Ty::new_tup(tcx, &[bound_yield_ty, bound_return_ty]),
sig.c_variadic,
sig.safety,
sig.abi,
sig.fn_sig_kind,
)
}),
),
@@ -273,9 +265,7 @@ pub(crate) fn check_expr_closure(
liberated_sig = tcx.mk_fn_sig(
liberated_sig.inputs().iter().copied(),
coroutine_output_ty,
liberated_sig.c_variadic,
liberated_sig.safety,
liberated_sig.abi,
liberated_sig.fn_sig_kind,
);
(Ty::new_coroutine_closure(tcx, expr_def_id.to_def_id(), closure_args.args), None)
@@ -544,13 +534,7 @@ fn extract_sig_from_projection(
let ret_param_ty = projection.skip_binder().term.expect_type();
debug!(?ret_param_ty);
let sig = projection.rebind(self.tcx.mk_fn_sig(
input_tys,
ret_param_ty,
false,
hir::Safety::Safe,
ExternAbi::Rust,
));
let sig = projection.rebind(self.tcx.mk_fn_sig_safe_rust_abi(input_tys, ret_param_ty));
Some(ExpectedSig { cause_span, sig })
}
@@ -630,13 +614,7 @@ fn extract_sig_from_projection_and_future_bound(
let return_ty =
return_ty.unwrap_or_else(|| self.next_ty_var(cause_span.unwrap_or(DUMMY_SP)));
let sig = projection.rebind(self.tcx.mk_fn_sig(
input_tys,
return_ty,
false,
hir::Safety::Safe,
ExternAbi::Rust,
));
let sig = projection.rebind(self.tcx.mk_fn_sig_safe_rust_abi(input_tys, return_ty));
Some(ExpectedSig { cause_span, sig })
}
@@ -727,7 +705,7 @@ fn sig_of_closure_with_expectation(
// Watch out for some surprises and just ignore the
// expectation if things don't see to match up with what we
// expect.
if expected_sig.sig.c_variadic() != decl.c_variadic {
if expected_sig.sig.c_variadic() != decl.c_variadic() {
return self.sig_of_closure_no_expectation(expr_def_id, decl, closure_kind);
} else if expected_sig.sig.skip_binder().inputs_and_output.len() != decl.inputs.len() + 1 {
return self.sig_of_closure_with_mismatched_number_of_arguments(
@@ -742,13 +720,11 @@ fn sig_of_closure_with_expectation(
// in this binder we are creating.
assert!(!expected_sig.sig.skip_binder().has_vars_bound_above(ty::INNERMOST));
let bound_sig = expected_sig.sig.map_bound(|sig| {
self.tcx.mk_fn_sig(
sig.inputs().iter().cloned(),
sig.output(),
sig.c_variadic,
hir::Safety::Safe,
ExternAbi::RustCall,
)
let fn_sig_kind = FnSigKind::default()
.set_abi(ExternAbi::RustCall)
.set_safe(true)
.set_c_variadic(sig.c_variadic());
self.tcx.mk_fn_sig(sig.inputs().iter().cloned(), sig.output(), fn_sig_kind)
});
// `deduce_expectations_from_expected_type` introduces
@@ -881,13 +857,12 @@ fn merge_supplied_sig_with_expectation(
let inputs =
supplied_sig.inputs().into_iter().map(|&ty| self.resolve_vars_if_possible(ty));
expected_sigs.liberated_sig = self.tcx.mk_fn_sig(
inputs,
supplied_output_ty,
expected_sigs.liberated_sig.c_variadic,
hir::Safety::Safe,
ExternAbi::RustCall,
);
let fn_sig_kind = FnSigKind::default()
.set_abi(ExternAbi::RustCall)
.set_safe(true)
.set_c_variadic(expected_sigs.liberated_sig.c_variadic());
expected_sigs.liberated_sig =
self.tcx.mk_fn_sig(inputs, supplied_output_ty, fn_sig_kind);
Ok(InferOk { value: expected_sigs, obligations: all_obligations })
})
@@ -957,14 +932,12 @@ fn supplied_sig_of_closure(
},
};
let fn_sig_kind = FnSigKind::default()
.set_abi(ExternAbi::RustCall)
.set_safe(true)
.set_c_variadic(decl.c_variadic());
let result = ty::Binder::bind_with_vars(
self.tcx.mk_fn_sig(
supplied_arguments,
supplied_return,
decl.c_variadic,
hir::Safety::Safe,
ExternAbi::RustCall,
),
self.tcx.mk_fn_sig(supplied_arguments, supplied_return, fn_sig_kind),
bound_vars,
);
@@ -1121,13 +1094,11 @@ fn error_sig_of_closure(
lowerer.lower_ty(output);
}
let result = ty::Binder::dummy(self.tcx.mk_fn_sig(
supplied_arguments,
err_ty,
decl.c_variadic,
hir::Safety::Safe,
ExternAbi::RustCall,
));
let fn_sig_kind = FnSigKind::default()
.set_abi(ExternAbi::RustCall)
.set_safe(true)
.set_c_variadic(decl.c_variadic());
let result = ty::Binder::dummy(self.tcx.mk_fn_sig(supplied_arguments, err_ty, fn_sig_kind));
debug!("supplied_sig_of_closure: result={:?}", result);
+5 -5
View File
@@ -944,7 +944,7 @@ fn coerce_from_fn_pointer(
debug_assert!(self.shallow_resolve(b) == b);
match b.kind() {
ty::FnPtr(_, b_hdr) if a_sig.safety().is_safe() && b_hdr.safety.is_unsafe() => {
ty::FnPtr(_, b_hdr) if a_sig.safety().is_safe() && b_hdr.safety().is_unsafe() => {
let a = self.tcx.safe_to_unsafe_fn_ty(a_sig);
let adjust = Adjust::Pointer(PointerCoercion::UnsafeFnPointer);
self.unify_and(a, b, [], adjust, ForceLeakCheck::Yes)
@@ -960,13 +960,13 @@ fn coerce_from_fn_item(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> {
match b.kind() {
ty::FnPtr(_, b_hdr) => {
let a_sig = self.sig_for_fn_def_coercion(a, Some(b_hdr.safety))?;
let a_sig = self.sig_for_fn_def_coercion(a, Some(b_hdr.safety()))?;
let InferOk { value: a_sig, mut obligations } =
self.at(&self.cause, self.param_env).normalize(a_sig);
let a = Ty::new_fn_ptr(self.tcx, a_sig);
let adjust = Adjust::Pointer(PointerCoercion::ReifyFnPointer(b_hdr.safety));
let adjust = Adjust::Pointer(PointerCoercion::ReifyFnPointer(b_hdr.safety()));
let InferOk { value, obligations: o2 } =
self.unify_and(a, b, [], adjust, ForceLeakCheck::Yes)?;
@@ -985,9 +985,9 @@ fn coerce_closure_to_fn(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> {
match b.kind() {
ty::FnPtr(_, hdr) => {
let safety = hdr.safety;
let safety = hdr.safety();
let terr = TypeError::Sorts(ty::error::ExpectedFound::new(a, b));
let closure_sig = self.sig_for_closure_coercion(a, Some(hdr.safety), terr)?;
let closure_sig = self.sig_for_closure_coercion(a, Some(hdr.safety()), terr)?;
let pointer_ty = Ty::new_fn_ptr(self.tcx, closure_sig);
debug!("coerce_closure_to_fn(a={:?}, b={:?}, pty={:?})", a, b, pointer_ty);
+2 -2
View File
@@ -1489,12 +1489,12 @@ fn check_expr_method_call(
method.sig.output(),
expected,
args,
method.sig.c_variadic,
method.sig.c_variadic(),
TupleArgumentsFlag::DontTupleArguments,
Some(method.def_id),
);
self.check_call_abi(method.sig.abi, expr.span);
self.check_call_abi(method.sig.abi(), expr.span);
method.sig.output()
}
@@ -183,6 +183,7 @@ pub(in super::super) fn check_argument_types(
// The expressions for each provided argument
provided_args: &'tcx [hir::Expr<'tcx>],
// Whether the function is variadic, for example when imported from C
// FIXME(splat): maybe change this to FnSigKind?
c_variadic: bool,
// Whether the arguments have been bundled in a tuple (ex: closures)
tuple_arguments: TupleArgumentsFlag,
@@ -1808,14 +1809,14 @@ fn get_hir_param_info(
(Some(_), Some(_)) | (None, None) => unreachable!(),
(Some(body), None) => {
let params = self.tcx.hir_body(body).params;
let params =
params.get(is_method as usize..params.len() - sig.decl.c_variadic as usize)?;
let params = params
.get(is_method as usize..params.len() - sig.decl.c_variadic() as usize)?;
debug_assert_eq!(params.len(), fn_inputs.len());
Some((fn_inputs.zip(params.iter().map(FnParam::Param)).collect(), generics))
}
(None, Some(params)) => {
let params =
params.get(is_method as usize..params.len() - sig.decl.c_variadic as usize)?;
let params = params
.get(is_method as usize..params.len() - sig.decl.c_variadic() as usize)?;
debug_assert_eq!(params.len(), fn_inputs.len());
Some((
fn_inputs.zip(params.iter().map(|&ident| FnParam::Ident(ident))).collect(),
@@ -4366,7 +4366,7 @@ fn suggest_traits_to_import(
_ => false,
};
if !fn_sig.decl.implicit_self.has_implicit_self()
if !fn_sig.decl.implicit_self().has_implicit_self()
&& self_first_arg
{
if let Some(ty) = fn_sig.decl.inputs.get(0) {
+1 -7
View File
@@ -438,13 +438,7 @@ fn analyze_closure(
let coroutine_captures_by_ref_ty = Ty::new_fn_ptr(
self.tcx,
ty::Binder::bind_with_vars(
self.tcx.mk_fn_sig(
[],
tupled_upvars_ty_for_borrow,
false,
hir::Safety::Safe,
rustc_abi::ExternAbi::Rust,
),
self.tcx.mk_fn_sig_safe_rust_abi([], tupled_upvars_ty_for_borrow),
self.tcx.mk_bound_variable_kinds(&[ty::BoundVariableKind::Region(
ty::BoundRegionKind::ClosureEnv,
)]),
+2 -2
View File
@@ -329,8 +329,8 @@ fn structurally_same_type_impl<'tcx>(
let a_sig = tcx.instantiate_bound_regions_with_erased(a_poly_sig);
let b_sig = tcx.instantiate_bound_regions_with_erased(b_poly_sig);
(a_sig.abi, a_sig.safety, a_sig.c_variadic)
== (b_sig.abi, b_sig.safety, b_sig.c_variadic)
(a_sig.abi(), a_sig.safety(), a_sig.c_variadic())
== (b_sig.abi(), b_sig.safety(), b_sig.c_variadic())
&& a_sig.inputs().iter().eq_by(b_sig.inputs().iter(), |a, b| {
structurally_same_type_impl(seen_types, tcx, typing_env, *a, *b)
})
@@ -801,7 +801,7 @@ impl<'tcx> ty::TypeVisitor<TyCtxt<'tcx>> for FnPtrFinder<'tcx> {
fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
if let ty::FnPtr(_, hdr) = ty.kind()
&& !hdr.abi.is_rustic_abi()
&& !hdr.abi().is_rustic_abi()
{
self.tys.push(ty);
}
+2 -2
View File
@@ -707,7 +707,7 @@ pub fn hir_id_to_string(self, id: HirId) -> String {
Node::ImplItem(ii) => {
let kind = match ii.kind {
ImplItemKind::Const(..) => "associated constant",
ImplItemKind::Fn(fn_sig, _) => match fn_sig.decl.implicit_self {
ImplItemKind::Fn(fn_sig, _) => match fn_sig.decl.implicit_self() {
ImplicitSelfKind::None => "associated function",
_ => "method",
},
@@ -718,7 +718,7 @@ pub fn hir_id_to_string(self, id: HirId) -> String {
Node::TraitItem(ti) => {
let kind = match ti.kind {
TraitItemKind::Const(..) => "associated constant",
TraitItemKind::Fn(fn_sig, _) => match fn_sig.decl.implicit_self {
TraitItemKind::Fn(fn_sig, _) => match fn_sig.decl.implicit_self() {
ImplicitSelfKind::None => "associated function",
_ => "trait method",
},
+80 -16
View File
@@ -47,7 +47,9 @@
use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym};
use rustc_type_ir::TyKind::*;
pub use rustc_type_ir::lift::Lift;
use rustc_type_ir::{CollectAndApply, TypeFlags, WithCachedTypeInfo, elaborate, search_graph};
use rustc_type_ir::{
CollectAndApply, FnSigKind, TypeFlags, WithCachedTypeInfo, elaborate, search_graph,
};
use tracing::{debug, instrument};
use crate::arena::Arena;
@@ -84,7 +86,33 @@ fn as_local(self) -> Option<LocalDefId> {
}
}
impl<'tcx> rustc_type_ir::inherent::FSigKind<TyCtxt<'tcx>> for FnSigKind {
fn fn_sig_kind(self) -> Self {
self
}
fn new(abi: ExternAbi, safety: hir::Safety, c_variadic: bool) -> Self {
FnSigKind::default().set_abi(abi).set_safe(safety.is_safe()).set_c_variadic(c_variadic)
}
fn abi(self) -> ExternAbi {
self.abi()
}
fn safety(self) -> hir::Safety {
if self.is_safe() { hir::Safety::Safe } else { hir::Safety::Unsafe }
}
fn c_variadic(self) -> bool {
self.c_variadic()
}
}
impl<'tcx> rustc_type_ir::inherent::Abi<TyCtxt<'tcx>> for ExternAbi {
fn abi(self) -> Self {
self
}
fn rust() -> Self {
ExternAbi::Rust
}
@@ -92,6 +120,14 @@ fn rust() -> Self {
fn is_rust(self) -> bool {
matches!(self, ExternAbi::Rust)
}
fn pack_abi(self) -> u8 {
self.as_packed()
}
fn unpack_abi(abi_index: u8) -> Self {
Self::from_packed(abi_index)
}
}
impl<'tcx> rustc_type_ir::inherent::Safety<TyCtxt<'tcx>> for hir::Safety {
@@ -99,6 +135,10 @@ fn safe() -> Self {
hir::Safety::Safe
}
fn unsafe_mode() -> Self {
hir::Safety::Unsafe
}
fn is_safe(self) -> bool {
self.is_safe()
}
@@ -1332,7 +1372,10 @@ pub fn adjust_target_feature_sig(
let fun_features = &self.codegen_fn_attrs(fun_def).target_features;
let caller_features = &self.body_codegen_attrs(caller).target_features;
if self.is_target_feature_call_safe(&fun_features, &caller_features) {
return Some(fun_sig.map_bound(|sig| ty::FnSig { safety: hir::Safety::Safe, ..sig }));
return Some(fun_sig.map_bound(|sig| ty::FnSig {
fn_sig_kind: fun_sig.fn_sig_kind().set_safe(true),
..sig
}));
}
None
}
@@ -2096,7 +2139,10 @@ impl<'tcx> TyCtxt<'tcx> {
/// unsafe.
pub fn safe_to_unsafe_fn_ty(self, sig: PolyFnSig<'tcx>) -> Ty<'tcx> {
assert!(sig.safety().is_safe());
Ty::new_fn_ptr(self, sig.map_bound(|sig| ty::FnSig { safety: hir::Safety::Unsafe, ..sig }))
Ty::new_fn_ptr(
self,
sig.map_bound(|sig| ty::FnSig { fn_sig_kind: sig.fn_sig_kind.set_safe(false), ..sig }),
)
}
/// Given a `fn` sig, returns an equivalent `unsafe fn` sig;
@@ -2104,7 +2150,7 @@ pub fn safe_to_unsafe_fn_ty(self, sig: PolyFnSig<'tcx>) -> Ty<'tcx> {
/// unsafe.
pub fn safe_to_unsafe_sig(self, sig: PolyFnSig<'tcx>) -> PolyFnSig<'tcx> {
assert!(sig.safety().is_safe());
sig.map_bound(|sig| ty::FnSig { safety: hir::Safety::Unsafe, ..sig })
sig.map_bound(|sig| ty::FnSig { fn_sig_kind: sig.fn_sig_kind.set_safe(false), ..sig })
}
/// Given the def_id of a Trait `trait_def_id` and the name of an associated item `assoc_name`
@@ -2146,7 +2192,11 @@ pub fn signature_unclosure(self, sig: PolyFnSig<'tcx>, safety: hir::Safety) -> P
ty::Tuple(params) => *params,
_ => bug!(),
};
self.mk_fn_sig(params, s.output(), s.c_variadic, safety, ExternAbi::Rust)
self.mk_fn_sig(
params,
s.output(),
s.fn_sig_kind.set_safe(safety.is_safe()).set_abi(ExternAbi::Rust),
)
})
}
@@ -2419,26 +2469,40 @@ pub fn mk_const_list_from_iter<I, T>(self, iter: I) -> T::Output
// IntoIterator` instead of `I: Iterator`, and it doesn't have a slice
// variant, because of the need to combine `inputs` and `output`. This
// explains the lack of `_from_iter` suffix.
pub fn mk_fn_sig<I, T>(
self,
inputs: I,
output: I::Item,
c_variadic: bool,
safety: hir::Safety,
abi: ExternAbi,
) -> T::Output
pub fn mk_fn_sig<I, T>(self, inputs: I, output: I::Item, fn_sig_kind: FnSigKind) -> T::Output
where
I: IntoIterator<Item = T>,
T: CollectAndApply<Ty<'tcx>, ty::FnSig<'tcx>>,
{
T::collect_and_apply(inputs.into_iter().chain(iter::once(output)), |xs| ty::FnSig {
inputs_and_output: self.mk_type_list(xs),
c_variadic,
safety,
abi,
fn_sig_kind,
})
}
/// `mk_fn_sig`, but with a Rust ABI, and no C-variadic argument.
pub fn mk_fn_sig_rust_abi<I, T>(
self,
inputs: I,
output: I::Item,
safety: hir::Safety,
) -> T::Output
where
I: IntoIterator<Item = T>,
T: CollectAndApply<Ty<'tcx>, ty::FnSig<'tcx>>,
{
self.mk_fn_sig(inputs, output, FnSigKind::default().set_safe(safety.is_safe()))
}
/// `mk_fn_sig`, but with a safe Rust ABI, and no C-variadic argument.
pub fn mk_fn_sig_safe_rust_abi<I, T>(self, inputs: I, output: I::Item) -> T::Output
where
I: IntoIterator<Item = T>,
T: CollectAndApply<Ty<'tcx>, ty::FnSig<'tcx>>,
{
self.mk_fn_sig(inputs, output, FnSigKind::default().set_safe(true))
}
pub fn mk_poly_existential_predicates_from_iter<I, T>(self, iter: I) -> T::Output
where
I: Iterator<Item = T>,
@@ -10,7 +10,7 @@
use rustc_hir::lang_items::LangItem;
use rustc_span::{DUMMY_SP, Span, Symbol};
use rustc_type_ir::lang_items::{SolverAdtLangItem, SolverLangItem, SolverTraitLangItem};
use rustc_type_ir::{CollectAndApply, Interner, TypeFoldable, search_graph};
use rustc_type_ir::{CollectAndApply, FnSigKind, Interner, TypeFoldable, search_graph};
use crate::dep_graph::{DepKind, DepNodeIndex};
use crate::infer::canonical::CanonicalVarKinds;
@@ -90,6 +90,7 @@ fn with_cached_task<T>(self, task: impl FnOnce() -> T) -> (T, DepNodeIndex) {
type AllocId = crate::mir::interpret::AllocId;
type Pat = Pattern<'tcx>;
type PatList = &'tcx List<Pattern<'tcx>>;
type FSigKind = FnSigKind;
type Safety = hir::Safety;
type Abi = ExternAbi;
type Const = ty::Const<'tcx>;
+1 -1
View File
@@ -106,7 +106,7 @@
pub use self::sty::{
AliasTy, AliasTyKind, Article, Binder, BoundConst, BoundRegion, BoundRegionKind, BoundTy,
BoundTyKind, BoundVariableKind, CanonicalPolyFnSig, CoroutineArgsExt, EarlyBinder, FnSig,
InlineConstArgs, InlineConstArgsParts, ParamConst, ParamTy, PlaceholderConst,
FnSigKind, InlineConstArgs, InlineConstArgsParts, ParamConst, ParamTy, PlaceholderConst,
PlaceholderRegion, PlaceholderType, PolyFnSig, TyKind, TypeAndMut, TypingMode,
TypingModeEqWrapper, UpvarArgs,
};
+5 -5
View File
@@ -750,7 +750,7 @@ fn pretty_print_type(&mut self, ty: Ty<'tcx>) -> Result<(), PrintError> {
if self.tcx().codegen_fn_attrs(def_id).safe_target_features {
write!(self, "#[target_features] ")?;
sig = sig.map_bound(|mut sig| {
sig.safety = hir::Safety::Safe;
sig.fn_sig_kind = sig.fn_sig_kind.set_safe(true);
sig
});
}
@@ -3130,14 +3130,14 @@ macro_rules! define_print_and_forward_display {
(self, p):
ty::FnSig<'tcx> {
write!(p, "{}", self.safety.prefix_str())?;
write!(p, "{}", self.safety().prefix_str())?;
if self.abi != ExternAbi::Rust {
write!(p, "extern {} ", self.abi)?;
if self.abi() != ExternAbi::Rust {
write!(p, "extern {} ", self.abi())?;
}
write!(p, "fn")?;
p.pretty_print_fn_sig(self.inputs(), self.c_variadic, self.output())?;
p.pretty_print_fn_sig(self.inputs(), self.c_variadic(), self.output())?;
}
ty::TraitRef<'tcx> {
@@ -198,6 +198,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
rustc_hir::Safety,
rustc_middle::mir::ConstValue,
rustc_type_ir::BoundConstness,
rustc_type_ir::FnSigKind,
rustc_type_ir::PredicatePolarity,
// tidy-alphabetical-end
}
+1
View File
@@ -37,6 +37,7 @@
pub type AliasTy<'tcx> = ir::AliasTy<TyCtxt<'tcx>>;
pub type AliasTyKind<'tcx> = ir::AliasTyKind<TyCtxt<'tcx>>;
pub type FnSig<'tcx> = ir::FnSig<TyCtxt<'tcx>>;
pub type FnSigKind = ir::FnSigKind;
pub type Binder<'tcx, T> = ir::Binder<TyCtxt<'tcx>, T>;
pub type EarlyBinder<'tcx, T> = ir::EarlyBinder<TyCtxt<'tcx>, T>;
pub type TypingMode<'tcx> = ir::TypingMode<TyCtxt<'tcx>>;
+1 -1
View File
@@ -470,7 +470,7 @@ fn construct_fn<'tcx>(
.output
.span();
let mut abi = fn_sig.abi;
let mut abi = fn_sig.abi();
if let DefKind::Closure = tcx.def_kind(fn_def) {
// HACK(eddyb) Avoid having RustCall on closures,
// as it adds unnecessary (and wrong) auto-tupling.
@@ -131,12 +131,12 @@ fn check_tail_call(&mut self, call: &Expr<'_>, expr: &Expr<'_>) {
let callee_sig =
self.tcx.normalize_erasing_late_bound_regions(self.typing_env, ty.fn_sig(self.tcx));
if caller_sig.abi != callee_sig.abi {
self.report_abi_mismatch(expr.span, caller_sig.abi, callee_sig.abi);
if caller_sig.abi() != callee_sig.abi() {
self.report_abi_mismatch(expr.span, caller_sig.abi(), callee_sig.abi());
}
if !callee_sig.abi.supports_guaranteed_tail_call() {
self.report_unsupported_abi(expr.span, callee_sig.abi);
if !callee_sig.abi().supports_guaranteed_tail_call() {
self.report_unsupported_abi(expr.span, callee_sig.abi());
}
// FIXME(explicit_tail_calls): this currently fails for cases where opaques are used.
@@ -180,11 +180,11 @@ fn check_tail_call(&mut self, call: &Expr<'_>, expr: &Expr<'_>) {
}
}
if caller_sig.c_variadic {
if caller_sig.c_variadic() {
self.report_c_variadic_caller(expr.span);
}
if callee_sig.c_variadic {
if callee_sig.c_variadic() {
self.report_c_variadic_callee(expr.span);
}
}
+3 -3
View File
@@ -184,15 +184,15 @@ fn explicit_params(
// Make sure that inferred closure args have no type span
.and_then(|ty| if param.pat.span != ty.span { Some(ty.span) } else { None });
let self_kind = if index == 0 && fn_decl.implicit_self.has_implicit_self() {
Some(fn_decl.implicit_self)
let self_kind = if index == 0 && fn_decl.implicit_self().has_implicit_self() {
Some(fn_decl.implicit_self())
} else {
None
};
// 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_decl.c_variadic && index == fn_decl.inputs.len() {
let ty = if fn_decl.c_variadic() && index == fn_decl.inputs.len() {
let va_list_did = self.tcx.require_lang_item(LangItem::VaList, param.span);
self.tcx
+2 -4
View File
@@ -1020,7 +1020,7 @@ fn build_call_shim<'tcx>(
let mut body =
new_body(MirSource::from_instance(instance), blocks, local_decls, sig.inputs().len(), span);
if let ExternAbi::RustCall = sig.abi {
if let ExternAbi::RustCall = sig.abi() {
body.spread_arg = Some(Local::new(sig.inputs().len()));
}
@@ -1171,9 +1171,7 @@ fn build_construct_coroutine_by_move_shim<'tcx>(
args.as_coroutine_closure().tupled_upvars_ty(),
args.as_coroutine_closure().coroutine_captures_by_ref_ty(),
),
sig.c_variadic,
sig.safety,
sig.abi,
sig.fn_sig_kind,
)
});
let sig = tcx.liberate_late_bound_regions(coroutine_closure_def_id, poly_sig);
@@ -1,6 +1,6 @@
use rustc_hir::def_id::DefId;
use rustc_hir::lang_items::LangItem;
use rustc_hir::{CoroutineDesugaring, CoroutineKind, CoroutineSource, Safety};
use rustc_hir::{CoroutineDesugaring, CoroutineKind, CoroutineSource};
use rustc_index::{Idx, IndexVec};
use rustc_middle::mir::{
BasicBlock, BasicBlockData, Body, Local, LocalDecl, MirSource, Operand, Place, Rvalue,
@@ -67,13 +67,7 @@ pub(super) fn build_async_drop_shim<'tcx>(
let resume_adt = tcx.adt_def(tcx.require_lang_item(LangItem::ResumeTy, DUMMY_SP));
let resume_ty = Ty::new_adt(tcx, resume_adt, ty::List::empty());
let fn_sig = ty::Binder::dummy(tcx.mk_fn_sig(
[ty, resume_ty],
tcx.types.unit,
false,
Safety::Safe,
ExternAbi::Rust,
));
let fn_sig = ty::Binder::dummy(tcx.mk_fn_sig_safe_rust_abi([ty, resume_ty], tcx.types.unit));
let sig = tcx.instantiate_bound_regions_with_erased(fn_sig);
assert!(!drop_ty.is_coroutine());
@@ -310,13 +304,7 @@ fn build_adrop_for_adrop_shim<'tcx>(
let pin_adt_ref = tcx.adt_def(tcx.require_lang_item(LangItem::Pin, span));
let env_ty = Ty::new_adt(tcx, pin_adt_ref, tcx.mk_args(&[proxy_ref.into()]));
// sig = `fn (Pin<&mut proxy_ty>, &mut Context) -> Poll<()>`
let sig = tcx.mk_fn_sig(
[env_ty, Ty::new_task_context(tcx)],
ret_ty,
false,
hir::Safety::Safe,
ExternAbi::Rust,
);
let sig = tcx.mk_fn_sig_safe_rust_abi([env_ty, Ty::new_task_context(tcx)], ret_ty);
// This function will be called with pinned proxy coroutine layout.
// We need to extract `Arg0.0` to get proxy layout, and then get `.0`
// further to receive impl coroutine (may be needed)
+2 -5
View File
@@ -25,7 +25,7 @@
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{
self as hir, Attribute, CRATE_HIR_ID, Constness, FnSig, ForeignItem, GenericParamKind, HirId,
Item, ItemKind, MethodKind, Node, ParamName, Safety, Target, TraitItem, find_attr,
Item, ItemKind, MethodKind, Node, ParamName, Target, TraitItem, find_attr,
};
use rustc_macros::Diagnostic;
use rustc_middle::hir::nested_filter;
@@ -1672,7 +1672,7 @@ fn check_proc_macro(&self, hir_id: HirId, target: Target, kind: ProcMacroKind) {
return;
}
let expected_sig = tcx.mk_fn_sig(
let expected_sig = tcx.mk_fn_sig_safe_rust_abi(
std::iter::repeat_n(
token_stream,
match kind {
@@ -1681,9 +1681,6 @@ fn check_proc_macro(&self, hir_id: HirId, target: Target, kind: ProcMacroKind) {
},
),
token_stream,
false,
Safety::Safe,
ExternAbi::Rust,
);
if let Err(terr) = ocx.eq(&cause, param_env, expected_sig, sig) {
+1 -1
View File
@@ -204,7 +204,7 @@ fn check_fn(&mut self) {
}
let sig = self.tcx.fn_sig(def_id).instantiate_identity().skip_binder();
if !matches!(sig.abi, ExternAbi::C { .. }) {
if !matches!(sig.abi(), ExternAbi::C { .. }) {
self.tcx.dcx().emit_err(UnexportableItem::FnAbi(span));
return;
}
@@ -308,11 +308,13 @@ fn internal<'tcx>(
tables: &mut Tables<'_, BridgeTys>,
tcx: impl InternalCx<'tcx>,
) -> Self::T<'tcx> {
let fn_sig_kind = rustc_ty::FnSigKind::default()
.set_abi(self.abi.internal(tables, tcx))
.set_safe(self.safety == Safety::Safe)
.set_c_variadic(self.c_variadic);
tcx.lift(rustc_ty::FnSig {
inputs_and_output: tcx.mk_type_list(&self.inputs_and_output.internal(tables, tcx)),
c_variadic: self.c_variadic,
safety: self.safety.internal(tables, tcx),
abi: self.abi.internal(tables, tcx),
fn_sig_kind,
})
.unwrap()
}
@@ -252,6 +252,23 @@ fn stable<'cx>(
}
}
// This internal type isn't publicly exposed, because it is an implementation detail.
// But it's a public field of FnSig (which has a public mirror type), so allow conversions.
impl<'tcx> Stable<'tcx> for ty::FnSigKind {
type T = (bool /*c_variadic*/, crate::mir::Safety, crate::ty::Abi);
fn stable<'cx>(
&self,
tables: &mut Tables<'cx, BridgeTys>,
cx: &CompilerCtxt<'cx, BridgeTys>,
) -> Self::T {
(
self.c_variadic(),
if self.is_safe() { crate::mir::Safety::Safe } else { crate::mir::Safety::Unsafe },
self.abi().stable(tables, cx),
)
}
}
impl<'tcx> Stable<'tcx> for ty::FnSig<'tcx> {
type T = crate::ty::FnSig;
fn stable<'cx>(
@@ -260,6 +277,7 @@ fn stable<'cx>(
cx: &CompilerCtxt<'cx, BridgeTys>,
) -> Self::T {
use crate::ty::FnSig;
let (c_variadic, safety, abi) = self.fn_sig_kind.stable(tables, cx);
FnSig {
inputs_and_output: self
@@ -267,9 +285,9 @@ fn stable<'cx>(
.iter()
.map(|ty| ty.stable(tables, cx))
.collect(),
c_variadic: self.c_variadic,
safety: self.safety.stable(tables, cx),
abi: self.abi.stable(tables, cx),
c_variadic,
safety,
abi,
}
}
}
-1
View File
@@ -6,7 +6,6 @@ edition = "2024"
[dependencies]
# tidy-alphabetical-start
measureme = "12.0.1"
rustc_abi = { path = "../rustc_abi" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" }
rustc_hir = { path = "../rustc_hir" }
@@ -43,13 +43,9 @@ pub(crate) fn fn_sig<'tcx>(
unreachable!()
};
ty::EarlyBinder::bind(ty::Binder::dummy(tcx.mk_fn_sig(
std::iter::repeat_n(err, arity),
err,
false,
rustc_hir::Safety::Safe,
rustc_abi::ExternAbi::Rust,
)))
ty::EarlyBinder::bind(ty::Binder::dummy(
tcx.mk_fn_sig_safe_rust_abi(std::iter::repeat_n(err, arity), err),
))
}
pub(crate) fn check_representability<'tcx>(
@@ -183,7 +183,7 @@ fn encode_fnsig<'tcx>(
let mut encode_ty_options = EncodeTyOptions::from_bits(options.bits())
.unwrap_or_else(|| bug!("encode_fnsig: invalid option(s) `{:?}`", options.bits()));
match fn_sig.abi {
match fn_sig.abi() {
ExternAbi::C { .. } => {
encode_ty_options.insert(EncodeTyOptions::GENERALIZE_REPR_C);
}
@@ -207,10 +207,10 @@ fn encode_fnsig<'tcx>(
s.push_str(&encode_ty(tcx, ty, dict, encode_ty_options));
}
if fn_sig.c_variadic {
if fn_sig.c_variadic() {
s.push('z');
}
} else if fn_sig.c_variadic {
} else if fn_sig.c_variadic() {
s.push('z');
} else {
// Empty parameter lists, whether declared as () or conventionally as (void), are
+1 -1
View File
@@ -134,7 +134,7 @@ fn abi_hash(&self, tcx: TyCtxt<'tcx>, hasher: &mut StableHasher) {
for ty in self.inputs_and_output {
ty.abi_hash(tcx, hasher);
}
self.safety.is_safe().abi_hash(tcx, hasher);
self.safety().is_safe().abi_hash(tcx, hasher);
}
}
+3 -3
View File
@@ -551,10 +551,10 @@ fn print_type(&mut self, ty: Ty<'tcx>) -> Result<(), PrintError> {
let sig = sig_tys.with(hdr);
self.push("F");
self.wrap_binder(&sig, |p, sig| {
if sig.safety.is_unsafe() {
if sig.safety().is_unsafe() {
p.push("U");
}
match sig.abi {
match sig.abi() {
ExternAbi::Rust => {}
ExternAbi::C { unwind: false } => p.push("KC"),
abi => {
@@ -570,7 +570,7 @@ fn print_type(&mut self, ty: Ty<'tcx>) -> Result<(), PrintError> {
for &ty in sig.inputs() {
ty.print(p)?;
}
if sig.c_variadic {
if sig.c_variadic() {
p.push("v");
}
p.push("E");
@@ -783,12 +783,12 @@ fn cmp_fn_sig(
// unsafe extern "C" for<'a> fn(&'a T) -> &'a T
// ^^^^^^
let safety = |fn_def, sig: ty::FnSig<'_>| match fn_def {
None => sig.safety.prefix_str(),
None => sig.safety().prefix_str(),
Some((did, _)) => {
if self.tcx.codegen_fn_attrs(did).safe_target_features {
"#[target_features] "
} else {
sig.safety.prefix_str()
sig.safety().prefix_str()
}
}
};
@@ -799,11 +799,11 @@ fn cmp_fn_sig(
// unsafe extern "C" for<'a> fn(&'a T) -> &'a T
// ^^^^^^^^^^
if sig1.abi != ExternAbi::Rust {
values.0.push(format!("extern {} ", sig1.abi), sig1.abi != sig2.abi);
if sig1.abi() != ExternAbi::Rust {
values.0.push(format!("extern {} ", sig1.abi()), sig1.abi() != sig2.abi());
}
if sig2.abi != ExternAbi::Rust {
values.1.push(format!("extern {} ", sig2.abi), sig1.abi != sig2.abi);
if sig2.abi() != ExternAbi::Rust {
values.1.push(format!("extern {} ", sig2.abi()), sig1.abi() != sig2.abi());
}
// unsafe extern "C" for<'a> fn(&'a T) -> &'a T
@@ -843,17 +843,17 @@ fn cmp_fn_sig(
}
}
if sig1.c_variadic {
if sig1.c_variadic() {
if len1 > 0 {
values.0.push_normal(", ");
}
values.0.push("...", !sig2.c_variadic);
values.0.push("...", !sig2.c_variadic());
}
if sig2.c_variadic {
if sig2.c_variadic() {
if len2 > 0 {
values.1.push_normal(", ");
}
values.1.push("...", !sig1.c_variadic);
values.1.push("...", !sig1.c_variadic());
}
// unsafe extern "C" for<'a> fn(&'a T) -> &'a T
@@ -71,7 +71,7 @@ pub fn find_param_with_region<'tcx>(
let fn_sig = tcx.liberate_late_bound_regions(id, poly_fn_sig);
body.params
.iter()
.take(if fn_sig.c_variadic {
.take(if fn_sig.c_variadic() {
fn_sig.inputs().len()
} else {
assert_eq!(fn_sig.inputs().len(), body.params.len());
@@ -523,7 +523,7 @@ fn foo(&self, x: T) -> T { x }
}
(ty::FnPtr(_, hdr), ty::FnDef(def_id, _))
| (ty::FnDef(def_id, _), ty::FnPtr(_, hdr)) => {
if tcx.fn_sig(def_id).skip_binder().safety() < hdr.safety {
if tcx.fn_sig(def_id).skip_binder().safety() < hdr.safety() {
if !tcx.codegen_fn_attrs(def_id).safe_target_features {
diag.note(
"unsafe functions cannot be coerced into safe function pointers",
@@ -4,7 +4,6 @@
use std::collections::hash_set;
use std::path::PathBuf;
use rustc_abi::ExternAbi;
use rustc_ast::ast::LitKind;
use rustc_ast::{LitIntType, TraitObjectSyntax};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@@ -3203,23 +3202,11 @@ fn add_help_message_for_fn_trait(
let given_ty = Ty::new_fn_ptr(
self.tcx,
params.rebind(self.tcx.mk_fn_sig(
given,
self.tcx.types.unit,
false,
hir::Safety::Safe,
ExternAbi::Rust,
)),
params.rebind(self.tcx.mk_fn_sig_safe_rust_abi(given, self.tcx.types.unit)),
);
let expected_ty = Ty::new_fn_ptr(
self.tcx,
trait_pred.rebind(self.tcx.mk_fn_sig(
expected,
self.tcx.types.unit,
false,
hir::Safety::Safe,
ExternAbi::Rust,
)),
trait_pred.rebind(self.tcx.mk_fn_sig_safe_rust_abi(expected, self.tcx.types.unit)),
);
if !self.same_type_modulo_infer(given_ty, expected_ty) {
@@ -2344,21 +2344,9 @@ pub(crate) fn build_fn_sig_ty<'tcx>(
let inputs = trait_ref.args.type_at(1);
let sig = match inputs.kind() {
ty::Tuple(inputs) if infcx.tcx.is_fn_trait(trait_ref.def_id) => {
infcx.tcx.mk_fn_sig(
*inputs,
infcx.next_ty_var(DUMMY_SP),
false,
hir::Safety::Safe,
ExternAbi::Rust,
)
infcx.tcx.mk_fn_sig_safe_rust_abi(*inputs, infcx.next_ty_var(DUMMY_SP))
}
_ => infcx.tcx.mk_fn_sig(
[inputs],
infcx.next_ty_var(DUMMY_SP),
false,
hir::Safety::Safe,
ExternAbi::Rust,
),
_ => infcx.tcx.mk_fn_sig_safe_rust_abi([inputs], infcx.next_ty_var(DUMMY_SP)),
};
Ty::new_fn_ptr(infcx.tcx, ty::Binder::dummy(sig))
@@ -4669,11 +4657,11 @@ fn suggest_option_method_if_applicable<G: EmissionGuarantee>(
&& let [self_ty, found_ty] = trait_ref.args.as_slice()
&& let Some(fn_ty) = self_ty.as_type().filter(|ty| ty.is_fn())
&& let fn_sig @ ty::FnSig {
abi: ExternAbi::Rust,
c_variadic: false,
safety: hir::Safety::Safe,
..
} = fn_ty.fn_sig(tcx).skip_binder()
&& fn_sig.abi() == ExternAbi::Rust
&& !fn_sig.c_variadic()
&& fn_sig.safety() == hir::Safety::Safe
// Extract first param of fn sig with peeled refs, e.g. `fn(&T)` -> `T`
&& let Some(&ty::Ref(_, target_ty, needs_mut)) = fn_sig.inputs().first().map(|t| t.kind())
@@ -465,7 +465,7 @@ fn virtual_call_violations_for_method<'tcx>(
if let Some(error) = contains_illegal_impl_trait_in_trait(tcx, method.def_id, sig.output()) {
errors.push(error);
}
if sig.skip_binder().c_variadic {
if sig.skip_binder().c_variadic() {
errors.push(MethodViolation::CVariadic);
}
@@ -1655,13 +1655,8 @@ fn confirm_closure_candidate<'cx, 'tcx>(
tupled_upvars_ty,
)
};
tcx.mk_fn_sig(
[sig.tupled_inputs_ty],
output_ty,
sig.c_variadic,
sig.safety,
sig.abi,
)
tcx.mk_fn_sig([sig.tupled_inputs_ty], output_ty, sig.fn_sig_kind)
})
}
+14 -36
View File
@@ -39,13 +39,7 @@ fn fn_sig_for_fn_abi<'tcx>(
typing_env: ty::TypingEnv<'tcx>,
) -> ty::FnSig<'tcx> {
if let InstanceKind::ThreadLocalShim(..) = instance.def {
return tcx.mk_fn_sig(
[],
tcx.thread_local_ptr_ty(instance.def_id()),
false,
hir::Safety::Safe,
rustc_abi::ExternAbi::Rust,
);
return tcx.mk_fn_sig_safe_rust_abi([], tcx.thread_local_ptr_ty(instance.def_id()));
}
let ty = instance.ty(tcx, typing_env);
@@ -74,9 +68,7 @@ fn fn_sig_for_fn_abi<'tcx>(
tcx.mk_fn_sig(
iter::once(env_ty).chain(sig.inputs().iter().cloned()),
sig.output(),
sig.c_variadic,
sig.safety,
sig.abi,
sig.fn_sig_kind,
)
}
ty::CoroutineClosure(def_id, args) => {
@@ -119,9 +111,7 @@ fn fn_sig_for_fn_abi<'tcx>(
args.as_coroutine_closure().tupled_upvars_ty(),
args.as_coroutine_closure().coroutine_captures_by_ref_ty(),
),
sig.c_variadic,
sig.safety,
sig.abi,
sig.fn_sig_kind,
)
}
ty::Coroutine(did, args) => {
@@ -224,22 +214,10 @@ fn fn_sig_for_fn_abi<'tcx>(
};
if let Some(resume_ty) = resume_ty {
tcx.mk_fn_sig(
[env_ty, resume_ty],
ret_ty,
false,
hir::Safety::Safe,
rustc_abi::ExternAbi::Rust,
)
tcx.mk_fn_sig_safe_rust_abi([env_ty, resume_ty], ret_ty)
} else {
// `Iterator::next` doesn't have a `resume` argument.
tcx.mk_fn_sig(
[env_ty],
ret_ty,
false,
hir::Safety::Safe,
rustc_abi::ExternAbi::Rust,
)
tcx.mk_fn_sig_safe_rust_abi([env_ty], ret_ty)
}
}
_ => bug!("unexpected type {:?} in Instance::fn_sig", ty),
@@ -334,7 +312,7 @@ fn fn_abi_of_instance_raw<'tcx>(
// If the function's body can be used to deduce parameter attributes, then adjust such
// "no deduced attrs" ABI; otherwise, return that ABI unadjusted.
params.determined_fn_def_id.map_or(fn_abi, |fn_def_id| {
fn_abi_adjust_for_deduced_attrs(&params.layout_cx, fn_abi, params.sig.abi, fn_def_id)
fn_abi_adjust_for_deduced_attrs(&params.layout_cx, fn_abi, params.sig.abi(), fn_def_id)
})
})
}
@@ -583,11 +561,11 @@ fn fn_abi_new_uncached<'tcx>(
let tcx = cx.tcx();
let abi_map = AbiMap::from_target(&tcx.sess.target);
let conv = abi_map.canonize_abi(sig.abi, sig.c_variadic).unwrap();
let conv = abi_map.canonize_abi(sig.abi(), sig.c_variadic()).unwrap();
let mut inputs = sig.inputs();
let extra_args = if sig.abi == ExternAbi::RustCall {
assert!(!sig.c_variadic && extra_args.is_empty());
let extra_args = if sig.abi() == ExternAbi::RustCall {
assert!(!sig.c_variadic() && extra_args.is_empty());
if let Some(input) = sig.inputs().last()
&& let ty::Tuple(tupled_arguments) = input.kind()
@@ -601,7 +579,7 @@ fn fn_abi_new_uncached<'tcx>(
);
}
} else {
assert!(sig.c_variadic || extra_args.is_empty());
assert!(sig.c_variadic() || extra_args.is_empty());
extra_args
};
@@ -655,7 +633,7 @@ fn fn_abi_new_uncached<'tcx>(
.enumerate()
.map(|(i, ty)| arg_of(ty, Some(i)))
.collect::<Result<_, _>>()?,
c_variadic: sig.c_variadic,
c_variadic: sig.c_variadic(),
fixed_count: inputs.len() as u32,
conv,
// FIXME return false for tls shim
@@ -663,12 +641,12 @@ fn fn_abi_new_uncached<'tcx>(
tcx,
// Since `#[rustc_nounwind]` can change unwinding, we cannot infer unwinding by `fn_def_id` for a virtual call.
determined_fn_def_id,
sig.abi,
sig.abi(),
),
};
fn_abi_adjust_for_abi(cx, &mut fn_abi, sig.abi);
fn_abi_adjust_for_abi(cx, &mut fn_abi, sig.abi());
debug!("fn_abi_new_uncached = {:?}", fn_abi);
fn_abi_sanity_check(cx, &fn_abi, sig.abi);
fn_abi_sanity_check(cx, &fn_abi, sig.abi());
Ok(tcx.arena.alloc(fn_abi))
}
+34 -1
View File
@@ -203,18 +203,51 @@ pub trait Tys<I: Interner<Tys = Self>>:
fn output(self) -> I::Ty;
}
pub trait FSigKind<I: Interner<FSigKind = Self>>: Copy + Debug + Hash + Eq {
/// The identity function.
fn fn_sig_kind(self) -> Self;
/// Create a new FnSigKind with the given ABI, safety, and C-style variadic flag.
fn new(abi: I::Abi, safety: I::Safety, c_variadic: bool) -> Self;
/// Returns the ABI.
fn abi(self) -> I::Abi;
/// Returns the safety mode.
fn safety(self) -> I::Safety;
/// Do the function arguments end with a C-style variadic argument?
fn c_variadic(self) -> bool;
}
pub trait Abi<I: Interner<Abi = Self>>: Copy + Debug + Hash + Eq {
fn rust() -> Self;
/// The identity function.
fn abi(self) -> Self;
/// The ABI `extern "Rust"`.
fn rust() -> I::Abi;
/// Whether this ABI is `extern "Rust"`.
fn is_rust(self) -> bool;
/// Pack the ABI into a small dense integer, so it can be stored as packed `FnSigKind` flags.
fn pack_abi(self) -> u8;
/// Unpack the ABI from packed `FnSigKind` flags.
fn unpack_abi(abi_index: u8) -> Self;
}
pub trait Safety<I: Interner<Safety = Self>>: Copy + Debug + Hash + Eq {
/// The `safe` safety mode.
fn safe() -> Self;
/// The `unsafe` safety mode.
fn unsafe_mode() -> Self;
/// Is the safety mode `Safe`?
fn is_safe(self) -> bool;
/// The string prefix for this safety mode.
fn prefix_str(self) -> &'static str;
}
+1
View File
@@ -145,6 +145,7 @@ fn mk_tracked<T: Debug + Clone>(
+ Eq
+ TypeVisitable<Self>
+ SliceLike<Item = Self::Pat>;
type FSigKind: FSigKind<Self>;
type Safety: Safety<Self>;
type Abi: Abi<Self>;
+8 -10
View File
@@ -154,19 +154,19 @@ fn relate<R: TypeRelation<I>>(
) -> RelateResult<I, ty::FnSig<I>> {
let cx = relation.cx();
if a.c_variadic != b.c_variadic {
if a.c_variadic() != b.c_variadic() {
return Err(TypeError::VariadicMismatch(ExpectedFound::new(
a.c_variadic,
b.c_variadic,
a.c_variadic(),
b.c_variadic(),
)));
}
if a.safety != b.safety {
return Err(TypeError::SafetyMismatch(ExpectedFound::new(a.safety, b.safety)));
if a.safety() != b.safety() {
return Err(TypeError::SafetyMismatch(ExpectedFound::new(a.safety(), b.safety())));
}
if a.abi != b.abi {
return Err(TypeError::AbiMismatch(ExpectedFound::new(a.abi, b.abi)));
if a.abi() != b.abi() {
return Err(TypeError::AbiMismatch(ExpectedFound::new(a.abi(), b.abi())));
};
let a_inputs = a.inputs();
@@ -202,9 +202,7 @@ fn relate<R: TypeRelation<I>>(
});
Ok(ty::FnSig {
inputs_and_output: cx.mk_type_list_from_iter(inputs_and_output)?,
c_variadic: a.c_variadic,
safety: a.safety,
abi: a.abi,
fn_sig_kind: a.fn_sig_kind,
})
}
}
+172 -29
View File
@@ -2,6 +2,7 @@
use std::ops::Deref;
use derive_where::derive_where;
use rustc_abi::ExternAbi;
use rustc_ast_ir::Mutability;
#[cfg(feature = "nightly")]
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
@@ -308,12 +309,7 @@ pub fn fn_sig(self, interner: I) -> ty::Binder<I, ty::FnSig<I>> {
ty::FnDef(def_id, args) => interner.fn_sig(def_id).instantiate(interner, args),
ty::Error(_) => {
// ignore errors (#54954)
ty::Binder::dummy(ty::FnSig {
inputs_and_output: Default::default(),
c_variadic: false,
safety: I::Safety::safe(),
abi: I::Abi::rust(),
})
ty::Binder::dummy(ty::FnSig::dummy())
}
ty::Closure(..) => panic!(
"to get the signature of a closure, use `args.as_closure().sig()` not `fn_sig()`",
@@ -762,6 +758,109 @@ pub struct TypeAndMut<I: Interner> {
impl<I: Interner> Eq for TypeAndMut<I> {}
/// Contains the packed non-type fields of a function signature.
// FIXME(splat): add the splatted argument index as a u16
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(
feature = "nightly",
derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext)
)]
pub struct FnSigKind {
/// Holds the c_variadic and safety bitflags, and 6 bits for the `ExternAbi` variant and unwind
/// flag.
flags: u8,
}
impl fmt::Debug for FnSigKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut f = f.debug_tuple("FnSigKind");
if self.is_safe() {
f.field(&"Safe");
} else {
f.field(&"Unsafe");
}
f.field(&self.abi());
if self.c_variadic() {
f.field(&"CVariadic");
};
f.finish()
}
}
impl FnSigKind {
/// Mask for the `ExternAbi` variant, including the unwind flag.
const EXTERN_ABI_MASK: u8 = 0b111111;
/// Bitflag for `Safety::Safe`. The default is `Unsafe`.
const SAFE_FLAG: u8 = 1 << 6;
/// Bitflag for a trailing C-style variadic argument.
const C_VARIADIC_FLAG: u8 = 1 << 7;
/// Create a new FnSigKind with the "Rust" ABI, "Unsafe" safety, and no C-style variadic argument.
/// To modify these flags, use the `set_*` methods, for readability.
// FIXME: use Default instead when that trait is const stable.
pub const fn default() -> Self {
Self { flags: 0 }.set_abi(ExternAbi::Rust).set_safe(false).set_c_variadic(false)
}
/// Set the ABI, including the unwind flag.
#[must_use = "this method does not modify the receiver"]
pub const fn set_abi(mut self, abi: ExternAbi) -> Self {
let abi_index = abi.as_packed();
assert!(abi_index <= Self::EXTERN_ABI_MASK);
self.flags &= !Self::EXTERN_ABI_MASK;
self.flags |= abi_index;
self
}
/// Set the safety flag, `true` is `Safe`.
#[must_use = "this method does not modify the receiver"]
pub const fn set_safe(mut self, is_safe: bool) -> Self {
if is_safe {
self.flags |= Self::SAFE_FLAG;
} else {
self.flags &= !Self::SAFE_FLAG;
}
self
}
/// Set the C-style variadic argument flag.
#[must_use = "this method does not modify the receiver"]
pub const fn set_c_variadic(mut self, c_variadic: bool) -> Self {
if c_variadic {
self.flags |= Self::C_VARIADIC_FLAG;
} else {
self.flags &= !Self::C_VARIADIC_FLAG;
}
self
}
/// Get the ABI, including the unwind flag.
pub const fn abi(self) -> ExternAbi {
let abi_index = self.flags & Self::EXTERN_ABI_MASK;
ExternAbi::from_packed(abi_index)
}
/// Get the safety flag.
pub const fn is_safe(self) -> bool {
self.flags & Self::SAFE_FLAG != 0
}
/// Do the function arguments end with a C-style variadic argument?
pub const fn c_variadic(self) -> bool {
self.flags & Self::C_VARIADIC_FLAG != 0
}
}
#[derive_where(Clone, Copy, PartialEq, Hash; I: Interner)]
#[cfg_attr(
feature = "nightly",
@@ -770,13 +869,9 @@ impl<I: Interner> Eq for TypeAndMut<I> {}
#[derive(TypeVisitable_Generic, GenericTypeVisitable, TypeFoldable_Generic, Lift_Generic)]
pub struct FnSig<I: Interner> {
pub inputs_and_output: I::Tys,
pub c_variadic: bool,
#[type_visitable(ignore)]
#[type_foldable(identity)]
pub safety: I::Safety,
#[type_visitable(ignore)]
#[type_foldable(identity)]
pub abi: I::Abi,
pub fn_sig_kind: I::FSigKind,
}
impl<I: Interner> Eq for FnSig<I> {}
@@ -791,8 +886,37 @@ pub fn output(self) -> I::Ty {
}
pub fn is_fn_trait_compatible(self) -> bool {
let FnSig { safety, abi, c_variadic, .. } = self;
!c_variadic && safety.is_safe() && abi.is_rust()
!self.c_variadic() && self.safety().is_safe() && self.abi().is_rust()
}
pub fn set_safe(self, is_safe: bool) -> Self {
Self {
fn_sig_kind: I::FSigKind::new(
self.abi(),
if is_safe { I::Safety::safe() } else { I::Safety::unsafe_mode() },
self.c_variadic(),
),
..self
}
}
pub fn safety(self) -> I::Safety {
self.fn_sig_kind.safety()
}
pub fn abi(self) -> I::Abi {
self.fn_sig_kind.abi()
}
pub fn c_variadic(self) -> bool {
self.fn_sig_kind.c_variadic()
}
pub fn dummy() -> Self {
Self {
inputs_and_output: Default::default(),
fn_sig_kind: I::FSigKind::new(I::Abi::rust(), I::Safety::safe(), false),
}
}
}
@@ -817,16 +941,20 @@ pub fn output(self) -> ty::Binder<I, I::Ty> {
self.map_bound(|fn_sig| fn_sig.output())
}
pub fn fn_sig_kind(self) -> I::FSigKind {
self.skip_binder().fn_sig_kind
}
pub fn c_variadic(self) -> bool {
self.skip_binder().c_variadic
self.skip_binder().c_variadic()
}
pub fn safety(self) -> I::Safety {
self.skip_binder().safety
self.skip_binder().safety()
}
pub fn abi(self) -> I::Abi {
self.skip_binder().abi
self.skip_binder().abi()
}
pub fn is_fn_trait_compatible(&self) -> bool {
@@ -835,8 +963,7 @@ pub fn is_fn_trait_compatible(&self) -> bool {
// Used to split a single value into the two fields in `TyKind::FnPtr`.
pub fn split(self) -> (ty::Binder<I, FnSigTys<I>>, FnHeader<I>) {
let hdr =
FnHeader { c_variadic: self.c_variadic(), safety: self.safety(), abi: self.abi() };
let hdr = FnHeader { fn_sig_kind: self.fn_sig_kind() };
(self.map_bound(|sig| FnSigTys { inputs_and_output: sig.inputs_and_output }), hdr)
}
}
@@ -844,11 +971,11 @@ pub fn split(self) -> (ty::Binder<I, FnSigTys<I>>, FnHeader<I>) {
impl<I: Interner> fmt::Debug for FnSig<I> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let sig = self;
let FnSig { inputs_and_output: _, c_variadic, safety, abi } = sig;
let FnSig { inputs_and_output: _, fn_sig_kind } = sig;
write!(f, "{}", safety.prefix_str())?;
if !abi.is_rust() {
write!(f, "extern \"{abi:?}\" ")?;
write!(f, "{}", fn_sig_kind.safety().prefix_str())?;
if !fn_sig_kind.abi().is_rust() {
write!(f, "extern \"{:?}\" ", fn_sig_kind.abi())?;
}
write!(f, "fn(")?;
@@ -859,7 +986,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
}
write!(f, "{ty:?}")?;
}
if *c_variadic {
if fn_sig_kind.c_variadic() {
if inputs.is_empty() {
write!(f, "...")?;
} else {
@@ -968,9 +1095,7 @@ impl<I: Interner> ty::Binder<I, FnSigTys<I>> {
pub fn with(self, hdr: FnHeader<I>) -> ty::Binder<I, FnSig<I>> {
self.map_bound(|sig_tys| FnSig {
inputs_and_output: sig_tys.inputs_and_output,
c_variadic: hdr.c_variadic,
safety: hdr.safety,
abi: hdr.abi,
fn_sig_kind: hdr.fn_sig_kind,
})
}
@@ -1002,9 +1127,27 @@ pub fn output(self) -> ty::Binder<I, I::Ty> {
)]
#[derive(TypeVisitable_Generic, GenericTypeVisitable, TypeFoldable_Generic, Lift_Generic)]
pub struct FnHeader<I: Interner> {
pub c_variadic: bool,
pub safety: I::Safety,
pub abi: I::Abi,
#[type_visitable(ignore)]
#[type_foldable(identity)]
pub fn_sig_kind: I::FSigKind,
}
impl<I: Interner> FnHeader<I> {
pub fn c_variadic(self) -> bool {
self.fn_sig_kind.c_variadic()
}
pub fn safety(self) -> I::Safety {
self.fn_sig_kind.safety()
}
pub fn abi(self) -> I::Abi {
self.fn_sig_kind.abi()
}
pub fn dummy() -> Self {
Self { fn_sig_kind: I::FSigKind::new(I::Abi::rust(), I::Safety::safe(), false) }
}
}
impl<I: Interner> Eq for FnHeader<I> {}
+3 -11
View File
@@ -307,9 +307,7 @@ pub fn coroutine_closure_sig(self) -> ty::Binder<I, CoroutineClosureSignature<I>
resume_ty,
yield_ty,
return_ty,
c_variadic: hdr.c_variadic,
safety: hdr.safety,
abi: hdr.abi,
fn_sig_kind: hdr.fn_sig_kind,
}
})
}
@@ -366,16 +364,10 @@ pub struct CoroutineClosureSignature<I: Interner> {
// Like the `fn_sig_as_fn_ptr_ty` of a regular closure, these types
// never actually differ. But we save them rather than recreating them
// from scratch just for good measure.
/// Always false
pub c_variadic: bool,
/// Always `Normal` (safe)
/// Always safe, RustCall, non-c-variadic
#[type_visitable(ignore)]
#[type_foldable(identity)]
pub safety: I::Safety,
/// Always `RustCall`
#[type_visitable(ignore)]
#[type_foldable(identity)]
pub abi: I::Abi,
pub fn_sig_kind: I::FSigKind,
}
impl<I: Interner> Eq for CoroutineClosureSignature<I> {}
@@ -550,7 +550,7 @@ pub fn build(&mut self, ctx: &mut Context) -> context::Result {
/// Alters all the unsigned types from the signature. This is required where
/// a signed and unsigned variant require the same binding to an exposed
/// LLVM instrinsic.
/// LLVM intrinsic.
pub fn sanitise_uints(&mut self) {
let transform = |tk: &mut TypeKind| {
if let Some(BaseType::Sized(BaseTypeKind::UInt, size)) = tk.base_type() {
@@ -1138,7 +1138,7 @@ fn generate_big_endian(&self, variant: &mut Intrinsic) {
} else {
/* If we do not need to reorder anything then immediately add
* the expressions from the big_endian_expressions and
* concatinate the compose vector */
* concatenate the compose vector */
variant.big_endian_compose.extend(big_endian_expressions);
variant
.big_endian_compose
@@ -1156,11 +1156,11 @@ fn generate_big_endian(&self, variant: &mut Intrinsic) {
/* If we do not create a shuffle call we do not need modify the
* return value and append to the big endian ast array. A bit confusing
* as in code we are making the final call before caputuring the return
* as in code we are making the final call before capturing the return
* value of the intrinsic that has been called.*/
let ret_val_name = "ret_val".to_string();
if let Some(simd_shuffle_call) = create_shuffle_call(&ret_val_name, return_type) {
/* There is a possibility that the funcion arguments did not
/* There is a possibility that the function arguments did not
* require big endian treatment, thus we need to now add the
* original function body before appending the return value.*/
if variant.big_endian_compose.is_empty() {
@@ -1694,8 +1694,8 @@ enum Endianness {
NA,
}
/// Based on the endianess will create the appropriate intrinsic, or simply
/// create the desired intrinsic without any endianess
/// Based on the endianness will create the appropriate intrinsic, or simply
/// create the desired intrinsic without any endianness
fn create_tokens(intrinsic: &Intrinsic, endianness: Endianness, tokens: &mut TokenStream) {
let signature = &intrinsic.signature;
let fn_name = signature.fn_name().to_string();
+2 -2
View File
@@ -1173,7 +1173,7 @@ fn clean_fn_decl_with_params<'tcx>(
{
output = output.sugared_async_return_type();
}
FnDecl { inputs: params, output, c_variadic: decl.c_variadic }
FnDecl { inputs: params, output, c_variadic: decl.c_variadic() }
}
fn clean_poly_fn_sig<'tcx>(
@@ -1211,7 +1211,7 @@ fn clean_poly_fn_sig<'tcx>(
})
.collect();
FnDecl { inputs: params, output, c_variadic: sig.skip_binder().c_variadic }
FnDecl { inputs: params, output, c_variadic: sig.skip_binder().c_variadic() }
}
fn clean_trait_ref<'tcx>(trait_ref: &hir::TraitRef<'tcx>, cx: &mut DocContext<'tcx>) -> Path {
@@ -4,7 +4,6 @@
use clippy_utils::source::{snippet_opt, snippet_with_applicability};
use clippy_utils::usage::{local_used_after_expr, local_used_in};
use clippy_utils::{get_path_from_caller_to_method_type, is_adjusted, is_no_std_crate};
use rustc_abi::ExternAbi;
use rustc_errors::Applicability;
use rustc_hir::{BindingMode, Expr, ExprKind, FnRetTy, GenericArgs, Param, PatKind, QPath, Safety, TyKind, find_attr};
use rustc_infer::infer::TyCtxtInferExt;
@@ -173,7 +172,7 @@ fn check_closure<'tcx>(cx: &LateContext<'tcx>, outer_receiver: Option<&Expr<'tcx
&& let output = typeck.expr_ty(body.value)
&& let ty::Tuple(tys) = *subs.type_at(1).kind()
{
cx.tcx.mk_fn_sig(tys, output, false, Safety::Safe, ExternAbi::Rust)
cx.tcx.mk_fn_sig_safe_rust_abi(tys, output)
} else {
return;
}
@@ -318,7 +317,7 @@ fn check_inputs(
}
fn check_sig<'tcx>(closure_sig: FnSig<'tcx>, call_sig: FnSig<'tcx>) -> bool {
call_sig.safety.is_safe() && !has_late_bound_to_non_late_bound_regions(closure_sig, call_sig)
call_sig.safety().is_safe() && !has_late_bound_to_non_late_bound_regions(closure_sig, call_sig)
}
/// This walks through both signatures and checks for any time a late-bound region is expected by an
@@ -23,7 +23,7 @@ pub fn check_fn(cx: &LateContext<'_>, kind: FnKind<'_>, decl: &FnDecl<'_>, body:
let name = ident.name.as_str();
let name = match decl.implicit_self {
let name = match decl.implicit_self() {
ImplicitSelfKind::RefMut => {
let Some(name) = name.strip_suffix("_mut") else {
return;
@@ -59,7 +59,7 @@ fn check_raw_ptr<'tcx>(
},
hir::ExprKind::MethodCall(_, recv, args, _) => {
let def_id = typeck.type_dependent_def_id(e.hir_id).unwrap();
if cx.tcx.fn_sig(def_id).skip_binder().skip_binder().safety.is_unsafe() {
if cx.tcx.fn_sig(def_id).skip_binder().skip_binder().safety().is_unsafe() {
check_arg(cx, &raw_ptrs, recv);
for arg in args {
check_arg(cx, &raw_ptrs, arg);
@@ -103,7 +103,7 @@ fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx ImplItem<
&& header.abi == ExternAbi::Rust
&& impl_item.ident.name == sym::to_string
&& let decl = signature.decl
&& decl.implicit_self.has_implicit_self()
&& decl.implicit_self().has_implicit_self()
&& decl.inputs.len() == 1
&& impl_item.generics.params.iter().all(|p| matches!(p.kind, GenericParamKind::Lifetime { .. }))
&& !impl_item.span.from_expansion()
@@ -64,7 +64,7 @@ fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'tcx>
}
fn check_sig(cx: &LateContext<'_>, name: Symbol, sig: &FnSig<'_>, fn_id: LocalDefId) {
if sig.decl.implicit_self.has_implicit_self() {
if sig.decl.implicit_self().has_implicit_self() {
let ret_ty = cx
.tcx
.instantiate_bound_regions_with_erased(cx.tcx.fn_sig(fn_id).instantiate_identity().output());
@@ -205,7 +205,7 @@ fn check_impl_item(&mut self, cx: &LateContext<'_>, item: &rustc_hir::ImplItem<'
&& let FnRetTy::Return(ret) = sig.decl.output
&& is_nameable_in_impl_trait(ret)
&& cx.tcx.generics_of(item_did).is_own_empty()
&& sig.decl.implicit_self == expected_implicit_self
&& sig.decl.implicit_self() == expected_implicit_self
&& sig.decl.inputs.len() == 1
&& let Some(imp) = get_parent_as_impl(cx.tcx, item.hir_id())
&& imp.of_trait.is_none()
@@ -54,7 +54,7 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) {
if item.ident.name == sym::len
&& let ImplItemKind::Fn(sig, _) = &item.kind
&& sig.decl.implicit_self.has_implicit_self()
&& sig.decl.implicit_self().has_implicit_self()
&& sig.decl.inputs.len() == 1
&& cx.effective_visibilities.is_exported(item.owner_id.def_id)
&& matches!(sig.decl.output, FnRetTy::Return(_))
@@ -79,7 +79,7 @@ fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>)
check_for_is_empty(
cx,
sig.span,
sig.decl.implicit_self,
sig.decl.implicit_self(),
output,
ty_id,
name,
@@ -411,7 +411,7 @@ fn allowed_lts_from(named_generics: &[GenericParam<'_>]) -> FxIndexSet<LocalDefI
fn non_elidable_self_type<'tcx>(cx: &LateContext<'tcx>, func: &FnDecl<'tcx>, ident: Option<Ident>, msrv: Msrv) -> bool {
if let Some(ident) = ident
&& ident.name == kw::SelfLower
&& !func.implicit_self.has_implicit_self()
&& !func.implicit_self().has_implicit_self()
&& let Some(self_ty) = func.inputs.first()
&& !msrv.meets(cx, msrvs::EXPLICIT_SELF_TYPE_ELISION)
{
@@ -697,7 +697,7 @@ fn visit_lifetime(&mut self, lifetime: &Lifetime) -> Self::Result {
}
}
if fd.lifetime_elision_allowed
if fd.lifetime_elision_allowed()
&& let Return(ret_ty) = fd.output
&& walk_unambig_ty(&mut V, ret_ty).is_break()
{
@@ -5064,7 +5064,7 @@ fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx hir::Impl
let first_arg_ty_opt = method_sig.inputs().iter().next().copied();
should_implement_trait::check_impl_item(cx, impl_item, self_ty, implements_trait, first_arg_ty_opt, sig);
if sig.decl.implicit_self.has_implicit_self()
if sig.decl.implicit_self().has_implicit_self()
&& !(self.avoid_breaking_exported_api
&& cx.effective_visibilities.is_exported(impl_item.owner_id.def_id))
&& let Some(first_arg) = iter_input_pats(sig.decl, cx.tcx.hir_body(id)).next()
@@ -5091,7 +5091,7 @@ fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>
}
if let TraitItemKind::Fn(ref sig, _) = item.kind {
if sig.decl.implicit_self.has_implicit_self()
if sig.decl.implicit_self().has_implicit_self()
&& let Some(first_arg_hir_ty) = sig.decl.inputs.first()
&& let Some(&first_arg_ty) = cx
.tcx
@@ -321,7 +321,7 @@ fn check_body(&mut self, cx: &LateContext<'tcx>, body: &Body<'tcx>) {
}) => (
owner_id.to_def_id(),
FnKind::TraitFn,
usize::from(sig.decl.implicit_self.has_implicit_self()),
usize::from(sig.decl.implicit_self().has_implicit_self()),
),
Node::ImplItem(&ImplItem {
kind: ImplItemKind::Fn(ref sig, _),
@@ -339,7 +339,7 @@ fn check_body(&mut self, cx: &LateContext<'tcx>, body: &Body<'tcx>) {
FnKind::ImplTraitFn(
std::ptr::from_ref(cx.tcx.erase_and_anonymize_regions(trait_ref.args)) as usize
),
usize::from(sig.decl.implicit_self.has_implicit_self()),
usize::from(sig.decl.implicit_self().has_implicit_self()),
)
} else {
(owner_id.to_def_id(), FnKind::Fn, 0)
@@ -70,7 +70,7 @@
fn check_method(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_def: LocalDefId, span: Span, owner_id: OwnerId) {
if !span.in_external_macro(cx.sess().source_map())
// If it comes from an external macro, better ignore it.
&& decl.implicit_self.has_implicit_self()
&& decl.implicit_self().has_implicit_self()
// We only show this warning for public exported methods.
&& cx.effective_visibilities.is_exported(fn_def)
// We don't want to emit this lint if the `#[must_use]` attribute is already there.
@@ -44,7 +44,7 @@ impl<'tcx> LateLintPass<'tcx> for SelfNamedConstructors {
fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx ImplItem<'_>) {
match impl_item.kind {
ImplItemKind::Fn(ref sig, _) => {
if sig.decl.implicit_self.has_implicit_self() {
if sig.decl.implicit_self().has_implicit_self() {
return;
}
},
@@ -376,7 +376,7 @@ fn check_default_new<'tcx>(
method_def_id: LocalDefId,
) {
// We're only interested into static methods.
if decl.implicit_self.has_implicit_self() {
if decl.implicit_self().has_implicit_self() {
return;
}
// We don't check trait implementations.
@@ -257,9 +257,9 @@ fn eq_fn_decl(&mut self, left: &FnDecl<'_>, right: &FnDecl<'_>) -> bool {
(FnRetTy::Return(l_ty), FnRetTy::Return(r_ty)) => self.eq_ty(l_ty, r_ty),
_ => false,
})
&& left.c_variadic == right.c_variadic
&& left.implicit_self == right.implicit_self
&& left.lifetime_elision_allowed == right.lifetime_elision_allowed
&& left.c_variadic() == right.c_variadic()
&& left.implicit_self() == right.implicit_self()
&& left.lifetime_elision_allowed() == right.lifetime_elision_allowed()
}
fn eq_generics(&mut self, left: &Generics<'_>, right: &Generics<'_>) -> bool {
@@ -1571,7 +1571,7 @@ pub fn hash_tykind(&mut self, ty: &TyKind<'_>) {
self.hash_ty(ty);
},
}
fn_ptr.decl.c_variadic.hash(&mut self.s);
fn_ptr.decl.c_variadic().hash(&mut self.s);
},
TyKind::Tup(ty_list) => {
for ty in *ty_list {
@@ -437,7 +437,7 @@ fn visit_expr(&mut self, e: &'tcx Expr<'_>) -> Self::Result {
ty::FnDef(id, _) if self.cx.tcx.fn_sig(id).skip_binder().safety().is_unsafe() => {
ControlFlow::Break(())
},
ty::FnPtr(_, hdr) if hdr.safety.is_unsafe() => ControlFlow::Break(()),
ty::FnPtr(_, hdr) if hdr.safety().is_unsafe() => ControlFlow::Break(()),
_ => walk_expr(self, e),
},
ExprKind::Path(ref p)
+1 -6
View File
@@ -7,7 +7,6 @@
)]
// The rustc crates we need
extern crate rustc_abi;
extern crate rustc_codegen_ssa;
extern crate rustc_data_structures;
extern crate rustc_driver;
@@ -47,7 +46,6 @@
BacktraceStyle, BorrowTrackerMethod, GenmcConfig, GenmcCtx, MiriConfig, MiriEntryFnType,
ProvenanceMode, TreeBorrowsParams, ValidationMode, run_genmc_mode,
};
use rustc_abi::ExternAbi;
use rustc_codegen_ssa::traits::CodegenBackend;
use rustc_data_structures::sync::{self, DynSync};
use rustc_driver::Compilation;
@@ -98,12 +96,9 @@ fn entry_fn(tcx: TyCtxt<'_>) -> (DefId, MiriEntryFnType) {
let start_def_id = id.expect_local();
let start_span = tcx.def_span(start_def_id);
let expected_sig = ty::Binder::dummy(tcx.mk_fn_sig(
let expected_sig = ty::Binder::dummy(tcx.mk_fn_sig_safe_rust_abi(
[tcx.types.isize, Ty::new_imm_ptr(tcx, Ty::new_imm_ptr(tcx, tcx.types.u8))],
tcx.types.isize,
false,
hir::Safety::Safe,
ExternAbi::Rust,
));
let correct_func_sig = check_function_signature(
+2 -5
View File
@@ -6,14 +6,13 @@
use rand::RngCore;
use rustc_abi::{Align, ExternAbi, FieldIdx, FieldsShape, Size, Variants};
use rustc_data_structures::fx::{FxBuildHasher, FxHashSet};
use rustc_hir::Safety;
use rustc_hir::def::{DefKind, Namespace};
use rustc_hir::def_id::{CRATE_DEF_INDEX, CrateNum, DefId, LOCAL_CRATE};
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::middle::dependency_format::Linkage;
use rustc_middle::middle::exported_symbols::ExportedSymbol;
use rustc_middle::ty::layout::{LayoutOf, MaybeResult, TyAndLayout};
use rustc_middle::ty::{self, IntTy, Ty, TyCtxt, UintTy};
use rustc_middle::ty::{self, FnSigKind, IntTy, Ty, TyCtxt, UintTy};
use rustc_session::config::CrateType;
use rustc_span::{Span, Symbol};
use rustc_symbol_mangling::mangle_internal_symbol;
@@ -408,9 +407,7 @@ fn call_function(
let sig = this.tcx.mk_fn_sig(
args.iter().map(|a| a.layout.ty),
dest.layout.ty,
/*c_variadic*/ false,
Safety::Safe,
caller_abi,
FnSigKind::default().set_abi(caller_abi).set_safe(true),
);
let caller_fn_abi = this.fn_abi_of_fn_ptr(ty::Binder::dummy(sig), ty::List::empty())?;
+3 -6
View File
@@ -1,8 +1,7 @@
//! Everything related to checking the signature of shim invocations.
use rustc_abi::{CanonAbi, ExternAbi};
use rustc_hir::Safety;
use rustc_middle::ty::{Binder, FnSig, Ty};
use rustc_middle::ty::{Binder, FnSig, FnSigKind, Ty};
use rustc_span::Symbol;
use rustc_target::callconv::FnAbi;
@@ -275,10 +274,8 @@ fn check_shim_sig<'a, const N: usize>(
inputs_and_output.push(shim_sig.ret);
let fn_sig_binder = Binder::dummy(FnSig {
inputs_and_output: this.machine.tcx.mk_type_list(&inputs_and_output),
c_variadic: false,
// This does not matter for the ABI.
safety: Safety::Safe,
abi: shim_sig.abi,
// Safety does not matter for the ABI.
fn_sig_kind: FnSigKind::default().set_abi(shim_sig.abi).set_safe(true),
});
let callee_fn_abi = this.fn_abi_of_fn_ptr(fn_sig_binder, Default::default())?;
@@ -164,13 +164,7 @@ pub(super) fn infer_closure(
let coroutine_captures_by_ref_ty = Ty::new_fn_ptr(
interner,
Binder::bind_with_vars(
interner.mk_fn_sig(
[],
self.types.types.unit,
false,
Safety::Safe,
FnAbi::Rust,
),
interner.mk_fn_sig_safe_rust_abi([], self.types.types.unit),
self.types.coroutine_captures_by_ref_bound_var_kinds,
),
);
@@ -484,13 +478,8 @@ fn extract_sig_from_projection(
let ret_param_ty = projection.skip_binder().term.expect_type();
debug!(?ret_param_ty);
let sig = projection.rebind(self.interner().mk_fn_sig(
input_tys,
ret_param_ty,
false,
Safety::Safe,
FnAbi::Rust,
));
let sig =
projection.rebind(self.interner().mk_fn_sig_safe_rust_abi(input_tys, ret_param_ty));
Some(sig)
}
@@ -572,13 +561,8 @@ fn extract_sig_from_projection_and_future_bound(
// that does not misuse a `FnSig` type, but that can be done separately.
let return_ty = return_ty.unwrap_or_else(|| self.table.next_ty_var());
let sig = projection.rebind(self.interner().mk_fn_sig(
input_tys,
return_ty,
false,
Safety::Safe,
FnAbi::Rust,
));
let sig =
projection.rebind(self.interner().mk_fn_sig_safe_rust_abi(input_tys, return_ty));
Some(sig)
}
@@ -2358,6 +2358,22 @@ pub fn mk_fn_sig<I>(
abi,
}
}
/// `mk_fn_sig`, but with a safe Rust ABI, and no C-variadic argument.
pub fn mk_fn_sig_safe_rust_abi<I>(self, inputs: I, output: Ty<'db>) -> FnSig<'db>
where
I: IntoIterator<Item = Ty<'db>>,
{
FnSig {
inputs_and_output: Tys::new_from_iter(
self,
inputs.into_iter().chain(std::iter::once(output)),
),
c_variadic: false,
safety: Safety::Safe,
abi: FnAbi::Rust,
}
}
}
fn predicates_of(db: &dyn HirDatabase, def_id: SolverDefId) -> &GenericPredicates {
+2 -2
View File
@@ -1,10 +1,10 @@
error: symbol-name(_ZN5basic4main17h1dddcfd03744167fE)
error: symbol-name(_ZN5basic4main17h947b7a9ed2b2bf56E)
--> $DIR/basic.rs:8:1
|
LL | #[rustc_dump_symbol_name]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error: demangling(basic::main::h1dddcfd03744167f)
error: demangling(basic::main::h947b7a9ed2b2bf56)
--> $DIR/basic.rs:8:1
|
LL | #[rustc_dump_symbol_name]
@@ -1,10 +1,10 @@
error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17h4b3099ec5dc5d306E)
error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17hba5ac046b858f549E)
--> $DIR/issue-60925.rs:21:9
|
LL | #[rustc_dump_symbol_name]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error: demangling(issue_60925::foo::Foo<issue_60925::llvm::Foo>::foo::h4b3099ec5dc5d306)
error: demangling(issue_60925::foo::Foo<issue_60925::llvm::Foo>::foo::hba5ac046b858f549)
--> $DIR/issue-60925.rs:21:9
|
LL | #[rustc_dump_symbol_name]