diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index f8f59fbeab449..cdc37a2f11485 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -414,6 +414,7 @@ impl<'tcx> fmt::Display for Instance<'tcx> { } impl<'tcx> Instance<'tcx> { + /// Creates a new instance of type `InstanceDef::Item`, with appropiate `def_id` and `args` set. pub fn new(def_id: DefId, args: GenericArgsRef<'tcx>) -> Instance<'tcx> { assert!( !args.has_escaping_bound_vars(), @@ -437,6 +438,7 @@ impl<'tcx> Instance<'tcx> { Instance::new(def_id, args) } + /// Returns the `def_id` of this instance. #[inline] pub fn def_id(&self) -> DefId { self.def.def_id() @@ -482,6 +484,7 @@ impl<'tcx> Instance<'tcx> { tcx.resolve_instance(tcx.erase_regions(param_env.and((def_id, args)))) } + /// Behaves exactly like [`Self::resolve`], but panics on error. pub fn expect_resolve( tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, @@ -618,6 +621,7 @@ impl<'tcx> Instance<'tcx> { } } + /// Returns an instance representing closure of type `requested_kind` with `def_id` and subst set to `args`. pub fn resolve_closure( tcx: TyCtxt<'tcx>, def_id: DefId, @@ -632,6 +636,7 @@ impl<'tcx> Instance<'tcx> { } } + /// Returns an instance representing the function [`core::ptr::drop_in_place`] with its generic argument set to `ty`. pub fn resolve_drop_in_place(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ty::Instance<'tcx> { let def_id = tcx.require_lang_item(LangItem::DropInPlace, None); let args = tcx.mk_args(&[ty.into()]); @@ -741,6 +746,10 @@ impl<'tcx> Instance<'tcx> { self.def.has_polymorphic_mir_body().then_some(self.args) } + /// Instantiates a generic value `v`(like `Vec`), substituting its generic arguments and turning it into a concrete one(like `i32`, or `Vec`). + /// If a value is not generic, this will do nothing. + /// This function does not erase lifetimes, so a value like `&'a i32` will remain unchanged. + /// For monomorphizing generics while also erasing lifetimes, try using [`Self::instantiate_mir_and_normalize_erasing_regions`]. pub fn instantiate_mir(&self, tcx: TyCtxt<'tcx>, v: EarlyBinder<&T>) -> T where T: TypeFoldable> + Copy, @@ -753,6 +762,11 @@ impl<'tcx> Instance<'tcx> { } } + /// Instantiates a generic value `v`(like `Vec`), substituting its generic arguments and turning it into a concrete one(like `i32`, or `Vec`). + /// This function erases lifetimes, so a value like `&'a i32` will become `&ReErased i32`. + /// If a value is not generic and has no lifetime info, this will do nothing. + /// For monomorphizing generics while preserving lifetimes, use [`Self::instantiate_mir`]. + /// This function will panic if normalization fails. If you want to handle normalization errors, use [`Self::try_instantiate_mir_and_normalize_erasing_regions`] #[inline(always)] // Keep me in sync with try_instantiate_mir_and_normalize_erasing_regions pub fn instantiate_mir_and_normalize_erasing_regions( @@ -771,6 +785,7 @@ impl<'tcx> Instance<'tcx> { } } + /// A version of [`Self::instantiate_mir_and_normalize_erasing_regions`] which will returns a [`NormalizationError`] on normalization failure instead of panicking. #[inline(always)] // Keep me in sync with instantiate_mir_and_normalize_erasing_regions pub fn try_instantiate_mir_and_normalize_erasing_regions( @@ -939,6 +954,7 @@ fn needs_fn_once_adapter_shim( // Set bits represent unused generic parameters. // An empty set indicates that all parameters are used. +/// A data structure used to store information about which generic parameters are in use, and which are not. #[derive(Debug, Copy, Clone, Eq, PartialEq, Decodable, Encodable, HashStable)] pub struct UnusedGenericParams(FiniteBitSet); @@ -949,36 +965,44 @@ impl Default for UnusedGenericParams { } impl UnusedGenericParams { + /// Creates a new [`UnusedGenericParams`] where all generic pameters are set as unused. pub fn new_all_unused(amount: u32) -> Self { let mut bitset = FiniteBitSet::new_empty(); bitset.set_range(0..amount); Self(bitset) } + /// Creates a new [`UnusedGenericParams`] where all generic pameters are set as used. pub fn new_all_used() -> Self { Self(FiniteBitSet::new_empty()) } + /// Marks a generic paramenter at index `idx` as used. pub fn mark_used(&mut self, idx: u32) { self.0.clear(idx); } + /// Returns true if generic paramenter at index `idx` unused, and false otherwise. pub fn is_unused(&self, idx: u32) -> bool { self.0.contains(idx).unwrap_or(false) } + /// Returns true if generic paramenter at index `idx` used, and false otherwise. pub fn is_used(&self, idx: u32) -> bool { !self.is_unused(idx) } + /// Returns true if all generic parameters are used, and false otherwise. pub fn all_used(&self) -> bool { self.0.is_empty() } + /// Turns a [`UnusedGenericParams`] into its underlying bit representation. pub fn bits(&self) -> u32 { self.0.0 } + /// Creates a [`UnusedGenericParams`] from its bit representation. pub fn from_bits(bits: u32) -> UnusedGenericParams { UnusedGenericParams(FiniteBitSet(bits)) } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index dd73f0f4a350d..4dad8e8f0895a 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1274,24 +1274,28 @@ pub struct GenSig<'tcx> { /// Signature of a function type, which we have arbitrarily /// decided to use to refer to the input/output types. -/// -/// - `inputs`: is the list of arguments and their modes. -/// - `output`: is the return type. -/// - `c_variadic`: indicates whether this is a C-variadic function. +/// NOTE: this signature may not match exactly with the signature of a compiled function. +/// Attributes like `#[track_caller]` may introduce additional arguments, which are not present here, but are represented in [`rustc_target::abi::call::FnAbi`]. +/// If you are interested in the exact signature and the way arguments are aligned/passed, use [`rustc_target::abi::call::FnAbi`]. #[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] pub struct FnSig<'tcx> { + /// A list, containing the inputs and the output of this function. To get them, please use [`FnSig::inputs`] and [`FnSig::output`]. pub inputs_and_output: &'tcx List>, + /// Indicates if a function is variadic or not pub c_variadic: bool, + /// Indicates if a function is safe or unsafe pub unsafety: hir::Unsafety, + /// The ABI of this function pub abi: abi::Abi, } impl<'tcx> FnSig<'tcx> { + /// Inputs of this signature. pub fn inputs(&self) -> &'tcx [Ty<'tcx>] { &self.inputs_and_output[..self.inputs_and_output.len() - 1] } - + /// The return type of this siganture. pub fn output(&self) -> Ty<'tcx> { self.inputs_and_output[self.inputs_and_output.len() - 1] } @@ -1317,28 +1321,41 @@ impl<'tcx> IntoDiagArg for FnSig<'tcx> { pub type PolyFnSig<'tcx> = Binder<'tcx, FnSig<'tcx>>; impl<'tcx> PolyFnSig<'tcx> { + /// Returns a [`Binder`] containing the inputs of this signature. #[inline] pub fn inputs(&self) -> Binder<'tcx, &'tcx [Ty<'tcx>]> { self.map_bound_ref_unchecked(|fn_sig| fn_sig.inputs()) } - #[inline] + + /// Returns a [`Binder`] containing the `index`th input of this signature. #[track_caller] + #[inline] pub fn input(&self, index: usize) -> ty::Binder<'tcx, Ty<'tcx>> { self.map_bound_ref(|fn_sig| fn_sig.inputs()[index]) } + + /// Returns a [`Binder`] containing the inputs and outputs of this signature. pub fn inputs_and_output(&self) -> ty::Binder<'tcx, &'tcx List>> { self.map_bound_ref(|fn_sig| fn_sig.inputs_and_output) } + + /// Returns a [`Binder`] containing the return type this signature. #[inline] pub fn output(&self) -> ty::Binder<'tcx, Ty<'tcx>> { self.map_bound_ref(|fn_sig| fn_sig.output()) } + + /// Checks if a function is variadic(accepts a variable number of arguments). pub fn c_variadic(&self) -> bool { self.skip_binder().c_variadic } + + /// Returns information about the safety of this function. pub fn unsafety(&self) -> hir::Unsafety { self.skip_binder().unsafety } + + /// Retunrs the ABI of this function pub fn abi(&self) -> abi::Abi { self.skip_binder().abi } @@ -1488,11 +1505,13 @@ impl<'tcx> Ty<'tcx> { .unwrap_or_else(|| Ty::new_infer(tcx, ty::FreshFloatTy(n))) } + /// Creates a new [`Ty`] representing a parameter, with index `index` and name `name`. #[inline] pub fn new_param(tcx: TyCtxt<'tcx>, index: u32, name: Symbol) -> Ty<'tcx> { tcx.mk_ty_from_kind(Param(ParamTy { index, name })) } + /// Creates an new [`Ty`] representing a bound type variable, with debruijn index `index` and bound type `bound_ty`. #[inline] pub fn new_bound( tcx: TyCtxt<'tcx>, @@ -1555,6 +1574,7 @@ impl<'tcx> Ty<'tcx> { Ty::new(tcx, Error(reported)) } + /// Creates a new [`Ty`] representing a signed integer `i`. #[inline] pub fn new_int(tcx: TyCtxt<'tcx>, i: ty::IntTy) -> Ty<'tcx> { use ty::IntTy::*; @@ -1568,6 +1588,7 @@ impl<'tcx> Ty<'tcx> { } } + /// Creates a new [`Ty`] representing an unsigned integer `ui`. #[inline] pub fn new_uint(tcx: TyCtxt<'tcx>, ui: ty::UintTy) -> Ty<'tcx> { use ty::UintTy::*; @@ -1581,6 +1602,7 @@ impl<'tcx> Ty<'tcx> { } } + /// Creates a new [`Ty`] representing a floating-point number `f`. #[inline] pub fn new_float(tcx: TyCtxt<'tcx>, f: ty::FloatTy) -> Ty<'tcx> { use ty::FloatTy::*; @@ -1592,6 +1614,7 @@ impl<'tcx> Ty<'tcx> { } } + /// Creates a new [`Ty`] representing a reference to type `tm.ty` with mutability `tm.mutbl` in region `r`. #[inline] pub fn new_ref( tcx: TyCtxt<'tcx>, @@ -1602,31 +1625,37 @@ impl<'tcx> Ty<'tcx> { Ty::new(tcx, Ref(r, ty, mutbl)) } + /// Creates a new [`Ty`] representing a mutable reference to type `ty` in region `r`. #[inline] pub fn new_mut_ref(tcx: TyCtxt<'tcx>, r: Region<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { Ty::new_ref(tcx, r, ty, hir::Mutability::Mut) } + /// Creates a new [`Ty`] representing an immutable reference to type `ty` in region `r`. #[inline] pub fn new_imm_ref(tcx: TyCtxt<'tcx>, r: Region<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { Ty::new_ref(tcx, r, ty, hir::Mutability::Not) } + /// Creates a new [`Ty`] representing a pointer to type `tm.ty` with mutability `tm.mutbl`. #[inline] pub fn new_ptr(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, mutbl: ty::Mutability) -> Ty<'tcx> { Ty::new(tcx, ty::RawPtr(ty, mutbl)) } + /// Creates a new [`Ty`] representing a mutable pointer to type `ty`. #[inline] pub fn new_mut_ptr(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { Ty::new_ptr(tcx, ty, hir::Mutability::Mut) } + /// Creates a new [`Ty`] representing an immutable pointer to type `ty`. #[inline] pub fn new_imm_ptr(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { Ty::new_ptr(tcx, ty, hir::Mutability::Not) } + /// Creates a new [`Ty`] representing an ADT with definition `def` and generic args `args`. #[inline] pub fn new_adt(tcx: TyCtxt<'tcx>, def: AdtDef<'tcx>, args: GenericArgsRef<'tcx>) -> Ty<'tcx> { tcx.debug_assert_args_compatible(def.did(), args); @@ -1638,6 +1667,7 @@ impl<'tcx> Ty<'tcx> { Ty::new(tcx, Foreign(def_id)) } + /// Creates a new [`Ty`] representing an array of `n` elements of type `ty`. #[inline] pub fn new_array(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, n: u64) -> Ty<'tcx> { Ty::new(tcx, Array(ty, ty::Const::from_target_usize(tcx, n))) @@ -1652,16 +1682,19 @@ impl<'tcx> Ty<'tcx> { Ty::new(tcx, Array(ty, ct)) } + /// Creates a new [`Ty`] representing a slice of elements of type `ty`. #[inline] pub fn new_slice(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { Ty::new(tcx, Slice(ty)) } + /// Creates a new [`Ty`] representing a tuple contining `ts` types. #[inline] pub fn new_tup(tcx: TyCtxt<'tcx>, ts: &[Ty<'tcx>]) -> Ty<'tcx> { if ts.is_empty() { tcx.types.unit } else { Ty::new(tcx, Tuple(tcx.mk_type_list(ts))) } } + /// Creates a new [`Ty`] representing a tuple contining types from the iterator `iter`. pub fn new_tup_from_iter(tcx: TyCtxt<'tcx>, iter: I) -> T::Output where I: Iterator, @@ -1670,6 +1703,7 @@ impl<'tcx> Ty<'tcx> { T::collect_and_apply(iter, |ts| Ty::new_tup(tcx, ts)) } + /// Creates a new [`Ty`] representing a function definition type, with `def_id` and `args` generic args. #[inline] pub fn new_fn_def( tcx: TyCtxt<'tcx>, @@ -1843,21 +1877,25 @@ impl<'tcx> Ty<'tcx> { } } + /// Checks if this type is of [`TyKind::Never`]. #[inline] pub fn is_never(self) -> bool { matches!(self.kind(), Never) } + /// Checks if this type is primitive #[inline] pub fn is_primitive(self) -> bool { self.kind().is_primitive() } + /// Checks if this type is an Algebraic Data Type(a struct, union, or enum). #[inline] pub fn is_adt(self) -> bool { matches!(self.kind(), Adt(..)) } + /// Checks if a type is a reference. #[inline] pub fn is_ref(self) -> bool { matches!(self.kind(), Ref(..)) @@ -1881,11 +1919,13 @@ impl<'tcx> Ty<'tcx> { matches!(self.kind(), Infer(_)) } + /// Checks if this type is [`core::marker::PhantomData`]. #[inline] pub fn is_phantom_data(self) -> bool { if let Adt(def, _) = self.kind() { def.is_phantom_data() } else { false } } + /// Checks if this type is a boolean. #[inline] pub fn is_bool(self) -> bool { *self.kind() == Bool @@ -1897,6 +1937,7 @@ impl<'tcx> Ty<'tcx> { *self.kind() == Str } + /// Checks if a type is a parameter type, with index `index`. #[inline] pub fn is_param(self, index: u32) -> bool { match self.kind() { @@ -1905,11 +1946,13 @@ impl<'tcx> Ty<'tcx> { } } + /// Checks if this type is a silice type. #[inline] pub fn is_slice(self) -> bool { matches!(self.kind(), Slice(_)) } + /// Checks if this type is a slice or a reference/pointer to a slice. #[inline] pub fn is_array_slice(self) -> bool { match self.kind() { @@ -1919,6 +1962,7 @@ impl<'tcx> Ty<'tcx> { } } + /// Checks if this type is an array. #[inline] pub fn is_array(self) -> bool { matches!(self.kind(), Array(..)) @@ -1932,6 +1976,8 @@ impl<'tcx> Ty<'tcx> { } } + /// If the type is a slice, array, or a string slice, it will returns its element type. + /// If this type is not one of those, this function will panic. pub fn sequence_element_type(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { match self.kind() { Array(ty, _) | Slice(ty) => *ty, @@ -1966,6 +2012,7 @@ impl<'tcx> Ty<'tcx> { } } + /// Checks if this type is a mutable reference or a mutable pointer. #[inline] pub fn is_mutable_ptr(self) -> bool { matches!(self.kind(), RawPtr(_, hir::Mutability::Mut) | Ref(_, _, hir::Mutability::Mut)) @@ -1980,6 +2027,7 @@ impl<'tcx> Ty<'tcx> { } } + /// Checks if this type is a raw pointer. #[inline] pub fn is_unsafe_ptr(self) -> bool { matches!(self.kind(), RawPtr(_, _)) @@ -1991,6 +2039,7 @@ impl<'tcx> Ty<'tcx> { self.is_ref() || self.is_unsafe_ptr() || self.is_fn_ptr() } + /// Checks if this type is an [`Box`]. #[inline] pub fn is_box(self) -> bool { match self.kind() { @@ -2017,6 +2066,7 @@ impl<'tcx> Ty<'tcx> { } } + /// Returns the type contained within a `Box`. /// Panics if called on any type other than `Box`. pub fn boxed_ty(self) -> Ty<'tcx> { match self.kind() { @@ -2049,26 +2099,31 @@ impl<'tcx> Ty<'tcx> { matches!(self.kind(), Float(_) | Infer(FloatVar(_))) } + /// Checks if this type is an unsized trait object(`dyn Trait`). #[inline] pub fn is_trait(self) -> bool { matches!(self.kind(), Dynamic(_, _, ty::Dyn)) } + /// Checks if this type is an sized trait object(`dyn* Trait`). #[inline] pub fn is_dyn_star(self) -> bool { matches!(self.kind(), Dynamic(_, _, ty::DynStar)) } + /// Checks if this type is an enum. #[inline] pub fn is_enum(self) -> bool { matches!(self.kind(), Adt(adt_def, _) if adt_def.is_enum()) } + /// Checks if this type is an union. #[inline] pub fn is_union(self) -> bool { matches!(self.kind(), Adt(adt_def, _) if adt_def.is_union()) } + /// Checks if this type is a closure. #[inline] pub fn is_closure(self) -> bool { matches!(self.kind(), Closure(..)) @@ -2079,6 +2134,7 @@ impl<'tcx> Ty<'tcx> { matches!(self.kind(), Coroutine(..)) } + /// Checks if this type is an intgeral type(signed, unsigned on infered). #[inline] pub fn is_coroutine_closure(self) -> bool { matches!(self.kind(), CoroutineClosure(..)) @@ -2099,21 +2155,25 @@ impl<'tcx> Ty<'tcx> { matches!(self.kind(), Infer(FreshTy(_) | FreshIntTy(_) | FreshFloatTy(_))) } + /// Checks if this type is a `char`. #[inline] pub fn is_char(self) -> bool { matches!(self.kind(), Char) } + /// Checks if this type is numeric(integral or floating point). #[inline] pub fn is_numeric(self) -> bool { self.is_integral() || self.is_floating_point() } + /// Checks if this type is a signed intiger. #[inline] pub fn is_signed(self) -> bool { matches!(self.kind(), Int(_)) } + /// Checks if this type is `usize` or `isize`. #[inline] pub fn is_ptr_sized_integral(self) -> bool { matches!(self.kind(), Int(ty::IntTy::Isize) | Uint(ty::UintTy::Usize)) @@ -2187,6 +2247,7 @@ impl<'tcx> Ty<'tcx> { } } + /// If this type is a function definition or a function pointer, this will retunrn its signature. Otherwise, this function will panic. pub fn fn_sig(self, tcx: TyCtxt<'tcx>) -> PolyFnSig<'tcx> { match self.kind() { FnDef(def_id, args) => tcx.fn_sig(*def_id).instantiate(tcx, args), @@ -2202,11 +2263,13 @@ impl<'tcx> Ty<'tcx> { } } + /// Checks if this type is a function definition or a function pointer. #[inline] pub fn is_fn(self) -> bool { matches!(self.kind(), FnDef(..) | FnPtr(_)) } + /// Checks if this type is a function pointer. #[inline] pub fn is_fn_ptr(self) -> bool { matches!(self.kind(), FnPtr(_)) @@ -2216,7 +2279,7 @@ impl<'tcx> Ty<'tcx> { pub fn is_impl_trait(self) -> bool { matches!(self.kind(), Alias(ty::Opaque, ..)) } - + /// Returns the `AdtDef` defining this type, if it is an ADT(struct,union or enum). If this type is not an ADT, returns `None`. #[inline] pub fn ty_adt_def(self) -> Option> { match self.kind() { diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index e422fb0d0203c..52771cc859a7f 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -1139,6 +1139,7 @@ impl<'tcx> TypeFolder> for WeakAliasTypeExpander<'tcx> { impl<'tcx> Ty<'tcx> { /// Returns the `Size` for primitive types (bool, uint, int, char, float). + /// If the type is not primitive, will panic with message "non primitive type". pub fn primitive_size(self, tcx: TyCtxt<'tcx>) -> Size { match *self.kind() { ty::Bool => Size::from_bytes(1), @@ -1150,7 +1151,8 @@ impl<'tcx> Ty<'tcx> { _ => bug!("non primitive type"), } } - + /// Returns the size and sign of an inieger type. + /// If the type is not an intieger, will panic with message "non integer discriminant". pub fn int_size_and_signed(self, tcx: TyCtxt<'tcx>) -> (Size, bool) { match *self.kind() { ty::Int(ity) => (Integer::from_int_ty(&tcx, ity).size(), true), diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs index 4502df339d1d8..3795230acffc8 100644 --- a/compiler/rustc_target/src/abi/call/mod.rs +++ b/compiler/rustc_target/src/abi/call/mod.rs @@ -776,6 +776,10 @@ impl RiscvInterruptKind { /// Metadata describing how the arguments to a native function /// should be passed in order to respect the native ABI. /// +/// Signature contained within this function does not have to match the one present in MIR. +/// Certain attributtes, like `#[track_caller]` can introduce addtional arguments, which are present in [`FnAbi`], but not in[`rustc_middle::ty::FnSig`. +/// This difference is not relevant in most cases, but should still be kept in mind. +/// /// I will do my best to describe this structure, but these /// comments are reverse-engineered and may be inaccurate. -NDM #[derive(Clone, PartialEq, Eq, Hash, HashStable_Generic)] @@ -795,7 +799,7 @@ pub struct FnAbi<'a, Ty> { pub fixed_count: u32, pub conv: Conv, - + /// This variable desribes if unwind can cross this function, or if it is invalid to unwind troguh it. pub can_unwind: bool, }