Merge pull request #4455 from RalfJung/rustup

Rustup
This commit is contained in:
Ralf Jung 2025-07-08 06:59:33 +00:00 committed by GitHub
commit 9110617cc7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
429 changed files with 6408 additions and 3971 deletions

View file

@ -14,7 +14,7 @@ it would be `T-libs-api`.
Also check for any `A-` labels to add.
-->
This is the **tracking issue** for the `YOUR_LINT_NAME_HERE` future-compatibility warning and other related errors. The goal of this page is describe why this change was made and how you can fix code that is affected by it. It also provides a place to ask questions or register a complaint if you feel the change should not be made. For more information on the policy around future-compatibility warnings, see our [breaking change policy guidelines][guidelines].
This is the **tracking issue** for the `YOUR_LINT_NAME_HERE` future-compatibility warning and other related errors. The goal of this page is to describe why this change was made and how you can fix code that is affected by it. It also provides a place to ask questions or register a complaint if you feel the change should not be made. For more information on the policy around future-compatibility warnings, see our [breaking change policy guidelines][guidelines].
[guidelines]: https://rustc-dev-guide.rust-lang.org/bug-fix-procedure.html
@ -44,7 +44,7 @@ This is the **tracking issue** for the `YOUR_LINT_NAME_HERE` future-compatibilit
- [ ] Implement the lint
- [ ] Raise lint level to deny
- [ ] Make lint report in dependencies
- [ ] Change the lint to report in dependencies
- [ ] Switch to a hard error
### Implementation history

View file

@ -4474,6 +4474,7 @@ dependencies = [
"rustc_feature",
"rustc_fluent_macro",
"rustc_hir",
"rustc_index",
"rustc_macros",
"rustc_metadata",
"rustc_middle",
@ -4552,9 +4553,6 @@ dependencies = [
"rustc_session",
"rustc_span",
"rustc_target",
"scoped-tls",
"serde",
"tracing",
]
[[package]]
@ -4622,6 +4620,7 @@ dependencies = [
"rand 0.9.1",
"rand_xorshift",
"scoped-tls",
"smallvec",
]
[[package]]
@ -5107,7 +5106,16 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
name = "stable_mir"
version = "0.1.0-preview"
dependencies = [
"rustc_abi",
"rustc_hir",
"rustc_middle",
"rustc_session",
"rustc_smir",
"rustc_span",
"rustc_target",
"scoped-tls",
"serde",
"tracing",
]
[[package]]

View file

@ -221,6 +221,20 @@ impl ReprOptions {
/// * Cranelift stores the base-2 log of the lane count in a 4 bit integer.
pub const MAX_SIMD_LANES: u64 = 1 << 0xF;
/// How pointers are represented in a given address space
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct PointerSpec {
/// The size of the bitwise representation of the pointer.
pointer_size: Size,
/// The alignment of pointers for this address space
pointer_align: AbiAlign,
/// The size of the value a pointer can be offset by in this address space.
pointer_offset: Size,
/// Pointers into this address space contain extra metadata
/// FIXME(workingjubilee): Consider adequately reflecting this in the compiler?
_is_fat: bool,
}
/// Parsed [Data layout](https://llvm.org/docs/LangRef.html#data-layout)
/// for a target, which contains everything needed to compute layouts.
#[derive(Debug, PartialEq, Eq)]
@ -236,13 +250,22 @@ pub struct TargetDataLayout {
pub f32_align: AbiAlign,
pub f64_align: AbiAlign,
pub f128_align: AbiAlign,
pub pointer_size: Size,
pub pointer_align: AbiAlign,
pub aggregate_align: AbiAlign,
/// Alignments for vector types.
pub vector_align: Vec<(Size, AbiAlign)>,
pub default_address_space: AddressSpace,
pub default_address_space_pointer_spec: PointerSpec,
/// Address space information of all known address spaces.
///
/// # Note
///
/// This vector does not contain the [`PointerSpec`] relative to the default address space,
/// which instead lives in [`Self::default_address_space_pointer_spec`].
address_space_info: Vec<(AddressSpace, PointerSpec)>,
pub instruction_address_space: AddressSpace,
/// Minimum size of #[repr(C)] enums (default c_int::BITS, usually 32)
@ -267,14 +290,20 @@ impl Default for TargetDataLayout {
f32_align: AbiAlign::new(align(32)),
f64_align: AbiAlign::new(align(64)),
f128_align: AbiAlign::new(align(128)),
pointer_size: Size::from_bits(64),
pointer_align: AbiAlign::new(align(64)),
aggregate_align: AbiAlign { abi: align(8) },
vector_align: vec![
(Size::from_bits(64), AbiAlign::new(align(64))),
(Size::from_bits(128), AbiAlign::new(align(128))),
],
instruction_address_space: AddressSpace::DATA,
default_address_space: AddressSpace::ZERO,
default_address_space_pointer_spec: PointerSpec {
pointer_size: Size::from_bits(64),
pointer_align: AbiAlign::new(align(64)),
pointer_offset: Size::from_bits(64),
_is_fat: false,
},
address_space_info: vec![],
instruction_address_space: AddressSpace::ZERO,
c_enum_min_size: Integer::I32,
}
}
@ -288,6 +317,7 @@ pub enum TargetDataLayoutErrors<'a> {
InconsistentTargetArchitecture { dl: &'a str, target: &'a str },
InconsistentTargetPointerWidth { pointer_size: u64, target: u32 },
InvalidBitsSize { err: String },
UnknownPointerSpecification { err: String },
}
impl TargetDataLayout {
@ -298,6 +328,7 @@ impl TargetDataLayout {
/// determined from llvm string.
pub fn parse_from_llvm_datalayout_string<'a>(
input: &'a str,
default_address_space: AddressSpace,
) -> Result<TargetDataLayout, TargetDataLayoutErrors<'a>> {
// Parse an address space index from a string.
let parse_address_space = |s: &'a str, cause: &'a str| {
@ -321,19 +352,27 @@ impl TargetDataLayout {
|s: &'a str, cause: &'a str| parse_bits(s, "size", cause).map(Size::from_bits);
// Parse an alignment string.
let parse_align = |s: &[&'a str], cause: &'a str| {
if s.is_empty() {
return Err(TargetDataLayoutErrors::MissingAlignment { cause });
}
let parse_align_str = |s: &'a str, cause: &'a str| {
let align_from_bits = |bits| {
Align::from_bits(bits)
.map_err(|err| TargetDataLayoutErrors::InvalidAlignment { cause, err })
};
let abi = parse_bits(s[0], "alignment", cause)?;
let abi = parse_bits(s, "alignment", cause)?;
Ok(AbiAlign::new(align_from_bits(abi)?))
};
// Parse an alignment sequence, possibly in the form `<align>[:<preferred_alignment>]`,
// ignoring the secondary alignment specifications.
let parse_align_seq = |s: &[&'a str], cause: &'a str| {
if s.is_empty() {
return Err(TargetDataLayoutErrors::MissingAlignment { cause });
}
parse_align_str(s[0], cause)
};
let mut dl = TargetDataLayout::default();
dl.default_address_space = default_address_space;
let mut i128_align_src = 64;
for spec in input.split('-') {
let spec_parts = spec.split(':').collect::<Vec<_>>();
@ -344,24 +383,107 @@ impl TargetDataLayout {
[p] if p.starts_with('P') => {
dl.instruction_address_space = parse_address_space(&p[1..], "P")?
}
["a", a @ ..] => dl.aggregate_align = parse_align(a, "a")?,
["f16", a @ ..] => dl.f16_align = parse_align(a, "f16")?,
["f32", a @ ..] => dl.f32_align = parse_align(a, "f32")?,
["f64", a @ ..] => dl.f64_align = parse_align(a, "f64")?,
["f128", a @ ..] => dl.f128_align = parse_align(a, "f128")?,
// FIXME(erikdesjardins): we should be parsing nonzero address spaces
// this will require replacing TargetDataLayout::{pointer_size,pointer_align}
// with e.g. `fn pointer_size_in(AddressSpace)`
[p @ "p", s, a @ ..] | [p @ "p0", s, a @ ..] => {
dl.pointer_size = parse_size(s, p)?;
dl.pointer_align = parse_align(a, p)?;
["a", a @ ..] => dl.aggregate_align = parse_align_seq(a, "a")?,
["f16", a @ ..] => dl.f16_align = parse_align_seq(a, "f16")?,
["f32", a @ ..] => dl.f32_align = parse_align_seq(a, "f32")?,
["f64", a @ ..] => dl.f64_align = parse_align_seq(a, "f64")?,
["f128", a @ ..] => dl.f128_align = parse_align_seq(a, "f128")?,
[p, s, a @ ..] if p.starts_with("p") => {
let mut p = p.strip_prefix('p').unwrap();
let mut _is_fat = false;
// Some targets, such as CHERI, use the 'f' suffix in the p- spec to signal that
// they use 'fat' pointers. The resulting prefix may look like `pf<addr_space>`.
if p.starts_with('f') {
p = p.strip_prefix('f').unwrap();
_is_fat = true;
}
// However, we currently don't take into account further specifications:
// an error is emitted instead.
if p.starts_with(char::is_alphabetic) {
return Err(TargetDataLayoutErrors::UnknownPointerSpecification {
err: p.to_string(),
});
}
let addr_space = if !p.is_empty() {
parse_address_space(p, "p-")?
} else {
AddressSpace::ZERO
};
let pointer_size = parse_size(s, "p-")?;
let pointer_align = parse_align_seq(a, "p-")?;
let info = PointerSpec {
pointer_offset: pointer_size,
pointer_size,
pointer_align,
_is_fat,
};
if addr_space == default_address_space {
dl.default_address_space_pointer_spec = info;
} else {
match dl.address_space_info.iter_mut().find(|(a, _)| *a == addr_space) {
Some(e) => e.1 = info,
None => {
dl.address_space_info.push((addr_space, info));
}
}
}
}
[p, s, a, _pr, i] if p.starts_with("p") => {
let mut p = p.strip_prefix('p').unwrap();
let mut _is_fat = false;
// Some targets, such as CHERI, use the 'f' suffix in the p- spec to signal that
// they use 'fat' pointers. The resulting prefix may look like `pf<addr_space>`.
if p.starts_with('f') {
p = p.strip_prefix('f').unwrap();
_is_fat = true;
}
// However, we currently don't take into account further specifications:
// an error is emitted instead.
if p.starts_with(char::is_alphabetic) {
return Err(TargetDataLayoutErrors::UnknownPointerSpecification {
err: p.to_string(),
});
}
let addr_space = if !p.is_empty() {
parse_address_space(p, "p")?
} else {
AddressSpace::ZERO
};
let info = PointerSpec {
pointer_size: parse_size(s, "p-")?,
pointer_align: parse_align_str(a, "p-")?,
pointer_offset: parse_size(i, "p-")?,
_is_fat,
};
if addr_space == default_address_space {
dl.default_address_space_pointer_spec = info;
} else {
match dl.address_space_info.iter_mut().find(|(a, _)| *a == addr_space) {
Some(e) => e.1 = info,
None => {
dl.address_space_info.push((addr_space, info));
}
}
}
}
[s, a @ ..] if s.starts_with('i') => {
let Ok(bits) = s[1..].parse::<u64>() else {
parse_size(&s[1..], "i")?; // For the user error.
continue;
};
let a = parse_align(a, s)?;
let a = parse_align_seq(a, s)?;
match bits {
1 => dl.i1_align = a,
8 => dl.i8_align = a,
@ -379,7 +501,7 @@ impl TargetDataLayout {
}
[s, a @ ..] if s.starts_with('v') => {
let v_size = parse_size(&s[1..], "v")?;
let a = parse_align(a, s)?;
let a = parse_align_seq(a, s)?;
if let Some(v) = dl.vector_align.iter_mut().find(|v| v.0 == v_size) {
v.1 = a;
continue;
@ -390,9 +512,45 @@ impl TargetDataLayout {
_ => {} // Ignore everything else.
}
}
// Inherit, if not given, address space information for specific LLVM elements from the
// default data address space.
if (dl.instruction_address_space != dl.default_address_space)
&& dl
.address_space_info
.iter()
.find(|(a, _)| *a == dl.instruction_address_space)
.is_none()
{
dl.address_space_info.push((
dl.instruction_address_space,
dl.default_address_space_pointer_spec.clone(),
));
}
Ok(dl)
}
/// Returns **exclusive** upper bound on object size in bytes, in the default data address
/// space.
///
/// The theoretical maximum object size is defined as the maximum positive `isize` value.
/// This ensures that the `offset` semantics remain well-defined by allowing it to correctly
/// index every address within an object along with one byte past the end, along with allowing
/// `isize` to store the difference between any two pointers into an object.
///
/// LLVM uses a 64-bit integer to represent object size in *bits*, but we care only for bytes,
/// so we adopt such a more-constrained size bound due to its technical limitations.
#[inline]
pub fn obj_size_bound(&self) -> u64 {
match self.pointer_size().bits() {
16 => 1 << 15,
32 => 1 << 31,
64 => 1 << 61,
bits => panic!("obj_size_bound: unknown pointer bit size {bits}"),
}
}
/// Returns **exclusive** upper bound on object size in bytes.
///
/// The theoretical maximum object size is defined as the maximum positive `isize` value.
@ -403,8 +561,8 @@ impl TargetDataLayout {
/// LLVM uses a 64-bit integer to represent object size in *bits*, but we care only for bytes,
/// so we adopt such a more-constrained size bound due to its technical limitations.
#[inline]
pub fn obj_size_bound(&self) -> u64 {
match self.pointer_size.bits() {
pub fn obj_size_bound_in(&self, address_space: AddressSpace) -> u64 {
match self.pointer_size_in(address_space).bits() {
16 => 1 << 15,
32 => 1 << 31,
64 => 1 << 61,
@ -415,7 +573,18 @@ impl TargetDataLayout {
#[inline]
pub fn ptr_sized_integer(&self) -> Integer {
use Integer::*;
match self.pointer_size.bits() {
match self.pointer_offset().bits() {
16 => I16,
32 => I32,
64 => I64,
bits => panic!("ptr_sized_integer: unknown pointer bit size {bits}"),
}
}
#[inline]
pub fn ptr_sized_integer_in(&self, address_space: AddressSpace) -> Integer {
use Integer::*;
match self.pointer_offset_in(address_space).bits() {
16 => I16,
32 => I32,
64 => I64,
@ -439,6 +608,66 @@ impl TargetDataLayout {
Align::from_bytes(vec_size.bytes().next_power_of_two()).unwrap(),
))
}
/// Get the pointer size in the default data address space.
#[inline]
pub fn pointer_size(&self) -> Size {
self.default_address_space_pointer_spec.pointer_size
}
/// Get the pointer size in a specific address space.
#[inline]
pub fn pointer_size_in(&self, c: AddressSpace) -> Size {
if c == self.default_address_space {
return self.default_address_space_pointer_spec.pointer_size;
}
if let Some(e) = self.address_space_info.iter().find(|(a, _)| a == &c) {
e.1.pointer_size
} else {
panic!("Use of unknown address space {c:?}");
}
}
/// Get the pointer index in the default data address space.
#[inline]
pub fn pointer_offset(&self) -> Size {
self.default_address_space_pointer_spec.pointer_offset
}
/// Get the pointer index in a specific address space.
#[inline]
pub fn pointer_offset_in(&self, c: AddressSpace) -> Size {
if c == self.default_address_space {
return self.default_address_space_pointer_spec.pointer_offset;
}
if let Some(e) = self.address_space_info.iter().find(|(a, _)| a == &c) {
e.1.pointer_offset
} else {
panic!("Use of unknown address space {c:?}");
}
}
/// Get the pointer alignment in the default data address space.
#[inline]
pub fn pointer_align(&self) -> AbiAlign {
self.default_address_space_pointer_spec.pointer_align
}
/// Get the pointer alignment in a specific address space.
#[inline]
pub fn pointer_align_in(&self, c: AddressSpace) -> AbiAlign {
if c == self.default_address_space {
return self.default_address_space_pointer_spec.pointer_align;
}
if let Some(e) = self.address_space_info.iter().find(|(a, _)| a == &c) {
e.1.pointer_align
} else {
panic!("Use of unknown address space {c:?}");
}
}
}
pub trait HasDataLayout {
@ -1100,10 +1329,7 @@ impl Primitive {
match self {
Int(i, _) => i.size(),
Float(f) => f.size(),
// FIXME(erikdesjardins): ignoring address space is technically wrong, pointers in
// different address spaces can have different sizes
// (but TargetDataLayout doesn't currently parse that part of the DL string)
Pointer(_) => dl.pointer_size,
Pointer(a) => dl.pointer_size_in(a),
}
}
@ -1114,10 +1340,7 @@ impl Primitive {
match self {
Int(i, _) => i.align(dl),
Float(f) => f.align(dl),
// FIXME(erikdesjardins): ignoring address space is technically wrong, pointers in
// different address spaces can have different alignments
// (but TargetDataLayout doesn't currently parse that part of the DL string)
Pointer(_) => dl.pointer_align,
Pointer(a) => dl.pointer_align_in(a),
}
}
}
@ -1421,8 +1644,8 @@ impl<FieldIdx: Idx> FieldsShape<FieldIdx> {
pub struct AddressSpace(pub u32);
impl AddressSpace {
/// The default address space, corresponding to data space.
pub const DATA: Self = AddressSpace(0);
/// LLVM's `0` address space.
pub const ZERO: Self = AddressSpace(0);
}
/// The way we represent values to the backend

View file

@ -2422,7 +2422,7 @@ impl Ty {
}
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct BareFnTy {
pub struct FnPtrTy {
pub safety: Safety,
pub ext: Extern,
pub generic_params: ThinVec<GenericParam>,
@ -2455,8 +2455,8 @@ pub enum TyKind {
///
/// Desugars into `Pin<&'a T>` or `Pin<&'a mut T>`.
PinnedRef(Option<Lifetime>, MutTy),
/// A bare function (e.g., `fn(usize) -> bool`).
BareFn(P<BareFnTy>),
/// A function pointer type (e.g., `fn(usize) -> bool`).
FnPtr(P<FnPtrTy>),
/// An unsafe existential lifetime binder (e.g., `unsafe<'a> &'a ()`).
UnsafeBinder(P<UnsafeBinderTy>),
/// The never type (`!`).

View file

@ -265,7 +265,7 @@ fn type_trailing_braced_mac_call(mut ty: &ast::Ty) -> Option<&ast::MacCall> {
ty = &binder.inner_ty;
}
ast::TyKind::BareFn(fn_ty) => match &fn_ty.decl.output {
ast::TyKind::FnPtr(fn_ty) => match &fn_ty.decl.output {
ast::FnRetTy::Default(_) => break None,
ast::FnRetTy::Ty(ret) => ty = ret,
},

View file

@ -1059,8 +1059,8 @@ macro_rules! common_visitor_and_walkers {
TyKind::Tup(tuple_element_types) => {
walk_list!(vis, visit_ty, tuple_element_types);
}
TyKind::BareFn(function_declaration) => {
let BareFnTy { safety, ext: _, generic_params, decl, decl_span } =
TyKind::FnPtr(function_declaration) => {
let FnPtrTy { safety, ext: _, generic_params, decl, decl_span } =
&$($mut)? **function_declaration;
try_visit!(visit_safety(vis, safety));
try_visit!(visit_generic_params(vis, generic_params));

View file

@ -55,7 +55,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
/// Get the maximum value of int_ty. It is platform-dependent due to the byte size of isize
fn int_ty_max(&self, int_ty: IntTy) -> u128 {
match int_ty {
IntTy::Isize => self.tcx.data_layout.pointer_size.signed_int_max() as u128,
IntTy::Isize => self.tcx.data_layout.pointer_size().signed_int_max() as u128,
IntTy::I8 => i8::MAX as u128,
IntTy::I16 => i16::MAX as u128,
IntTy::I32 => i32::MAX as u128,
@ -67,7 +67,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
/// Get the maximum value of uint_ty. It is platform-dependent due to the byte size of usize
fn uint_ty_max(&self, uint_ty: UintTy) -> u128 {
match uint_ty {
UintTy::Usize => self.tcx.data_layout.pointer_size.unsigned_int_max(),
UintTy::Usize => self.tcx.data_layout.pointer_size().unsigned_int_max(),
UintTy::U8 => u8::MAX as u128,
UintTy::U16 => u16::MAX as u128,
UintTy::U32 => u32::MAX as u128,

View file

@ -1269,9 +1269,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let path = self.make_lang_item_qpath(LangItem::Pin, span, Some(args));
hir::TyKind::Path(path)
}
TyKind::BareFn(f) => {
TyKind::FnPtr(f) => {
let generic_params = self.lower_lifetime_binder(t.id, &f.generic_params);
hir::TyKind::BareFn(self.arena.alloc(hir::BareFnTy {
hir::TyKind::FnPtr(self.arena.alloc(hir::FnPtrTy {
generic_params,
safety: self.lower_safety(f.safety, hir::Safety::Safe),
abi: self.lower_extern(f.ext),

View file

@ -48,9 +48,6 @@ ast_passes_auto_super_lifetime = auto traits cannot have super traits or lifetim
ast_passes_bad_c_variadic = only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg
ast_passes_bare_fn_invalid_safety = function pointers cannot be declared with `safe` safety qualifier
.suggestion = remove safe from this item
ast_passes_body_in_extern = incorrect `{$kind}` inside `extern` block
.cannot_have = cannot have a body
.invalid = the invalid body
@ -135,6 +132,9 @@ ast_passes_fn_param_forbidden_self =
ast_passes_fn_param_too_many =
function can not have more than {$max_num_args} arguments
ast_passes_fn_ptr_invalid_safety = function pointers cannot be declared with `safe` safety qualifier
.suggestion = remove safe from this item
ast_passes_fn_without_body =
free function without a body
.suggestion = provide a definition for the function

View file

@ -499,9 +499,9 @@ impl<'a> AstValidator<'a> {
}
}
fn check_bare_fn_safety(&self, span: Span, safety: Safety) {
fn check_fn_ptr_safety(&self, span: Span, safety: Safety) {
if matches!(safety, Safety::Safe(_)) {
self.dcx().emit_err(errors::InvalidSafetyOnBareFn { span });
self.dcx().emit_err(errors::InvalidSafetyOnFnPtr { span });
}
}
@ -785,8 +785,8 @@ impl<'a> AstValidator<'a> {
fn visit_ty_common(&mut self, ty: &'a Ty) {
match &ty.kind {
TyKind::BareFn(bfty) => {
self.check_bare_fn_safety(bfty.decl_span, bfty.safety);
TyKind::FnPtr(bfty) => {
self.check_fn_ptr_safety(bfty.decl_span, bfty.safety);
self.check_fn_decl(&bfty.decl, SelfSemantic::No);
Self::check_decl_no_pat(&bfty.decl, |span, _, _| {
self.dcx().emit_err(errors::PatternFnPointer { span });

View file

@ -225,8 +225,8 @@ pub(crate) struct InvalidSafetyOnItem {
}
#[derive(Diagnostic)]
#[diag(ast_passes_bare_fn_invalid_safety)]
pub(crate) struct InvalidSafetyOnBareFn {
#[diag(ast_passes_fn_ptr_invalid_safety)]
pub(crate) struct InvalidSafetyOnFnPtr {
#[primary_span]
pub span: Span,
}

View file

@ -286,9 +286,9 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
fn visit_ty(&mut self, ty: &'a ast::Ty) {
match &ty.kind {
ast::TyKind::BareFn(bare_fn_ty) => {
ast::TyKind::FnPtr(fn_ptr_ty) => {
// Function pointers cannot be `const`
self.check_late_bound_lifetime_defs(&bare_fn_ty.generic_params);
self.check_late_bound_lifetime_defs(&fn_ptr_ty.generic_params);
}
ast::TyKind::Never => {
gate!(&self, never_type, ty.span, "the `!` type is experimental");

View file

@ -1285,7 +1285,7 @@ impl<'a> State<'a> {
self.print_type(typ);
self.pclose();
}
ast::TyKind::BareFn(f) => {
ast::TyKind::FnPtr(f) => {
self.print_ty_fn(f.ext, f.safety, &f.decl, None, &f.generic_params);
}
ast::TyKind::UnsafeBinder(f) => {

View file

@ -149,7 +149,7 @@ pub enum UsedBy {
/// ## Attribute Processing
/// While attributes are initially parsed by [`rustc_parse`] into [`ast::Attribute`], they still contain raw token streams
/// because different attributes have different internal structures. This enum represents the final,
/// fully parsed form of these attributes, where each variant contains contains all the information and
/// fully parsed form of these attributes, where each variant contains all the information and
/// structure relevant for the specific attribute.
///
/// Some attributes can be applied multiple times to the same item, and they are "collapsed" into a single
@ -298,6 +298,9 @@ pub enum AttributeKind {
/// Represents `#[rustc_pass_by_value]` (used by the `rustc_pass_by_value` lint).
PassByValue(Span),
/// Represents `#[path]`
Path(Symbol, Span),
/// Represents `#[rustc_pub_transparent]` (used by the `repr_transparent_external_private_fields` lint).
PubTransparent(Span),

View file

@ -40,6 +40,7 @@ impl AttributeKind {
NonExhaustive(..) => Yes,
Optimize(..) => No,
PassByValue(..) => Yes,
Path(..) => No,
PubTransparent(..) => Yes,
Repr { .. } => No,
RustcLayoutScalarValidRangeEnd(..) => Yes,

View file

@ -37,6 +37,7 @@ pub(crate) mod loop_match;
pub(crate) mod must_use;
pub(crate) mod no_implicit_prelude;
pub(crate) mod non_exhaustive;
pub(crate) mod path;
pub(crate) mod repr;
pub(crate) mod rustc_internal;
pub(crate) mod semantics;

View file

@ -0,0 +1,29 @@
use rustc_attr_data_structures::AttributeKind;
use rustc_feature::{AttributeTemplate, template};
use rustc_span::{Symbol, sym};
use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser};
use crate::context::{AcceptContext, Stage};
use crate::parser::ArgParser;
pub(crate) struct PathParser;
impl<S: Stage> SingleAttributeParser<S> for PathParser {
const PATH: &[Symbol] = &[sym::path];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepLast;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "file");
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
let Some(nv) = args.name_value() else {
cx.expected_name_value(cx.attr_span, None);
return None;
};
let Some(path) = nv.value_as_str() else {
cx.expected_string_literal(nv.value_span, Some(nv.value_as_lit()));
return None;
};
Some(AttributeKind::Path(path, cx.attr_span))
}
}

View file

@ -28,6 +28,7 @@ use crate::attributes::loop_match::{ConstContinueParser, LoopMatchParser};
use crate::attributes::must_use::MustUseParser;
use crate::attributes::no_implicit_prelude::NoImplicitPreludeParser;
use crate::attributes::non_exhaustive::NonExhaustiveParser;
use crate::attributes::path::PathParser as PathAttributeParser;
use crate::attributes::repr::{AlignParser, ReprParser};
use crate::attributes::rustc_internal::{
RustcLayoutScalarValidRangeEnd, RustcLayoutScalarValidRangeStart,
@ -133,6 +134,7 @@ attribute_parsers!(
Single<LinkSectionParser>,
Single<MustUseParser>,
Single<OptimizeParser>,
Single<PathAttributeParser>,
Single<RustcForceInlineParser>,
Single<RustcLayoutScalarValidRangeEnd>,
Single<RustcLayoutScalarValidRangeStart>,

View file

@ -414,12 +414,12 @@ fn find_type_parameters(
impl<'a, 'b> visit::Visitor<'a> for Visitor<'a, 'b> {
fn visit_ty(&mut self, ty: &'a ast::Ty) {
let stack_len = self.bound_generic_params_stack.len();
if let ast::TyKind::BareFn(bare_fn) = &ty.kind
&& !bare_fn.generic_params.is_empty()
if let ast::TyKind::FnPtr(fn_ptr) = &ty.kind
&& !fn_ptr.generic_params.is_empty()
{
// Given a field `x: for<'a> fn(T::SomeType<'a>)`, we wan't to account for `'a` so
// that we generate `where for<'a> T::SomeType<'a>: ::core::clone::Clone`. #122622
self.bound_generic_params_stack.extend(bare_fn.generic_params.iter().cloned());
self.bound_generic_params_stack.extend(fn_ptr.generic_params.iter().cloned());
}
if let ast::TyKind::Path(_, path) = &ty.kind

View file

@ -786,7 +786,7 @@ pub(crate) fn codegen_drop<'tcx>(
pub(crate) fn lib_call_arg_param(tcx: TyCtxt<'_>, ty: Type, is_signed: bool) -> AbiParam {
let param = AbiParam::new(ty);
if ty.is_int() && u64::from(ty.bits()) < tcx.data_layout.pointer_size.bits() {
if ty.is_int() && u64::from(ty.bits()) < tcx.data_layout.pointer_size().bits() {
match (&*tcx.sess.target.arch, &*tcx.sess.target.vendor) {
("x86_64", _) | ("aarch64", "apple") => match (ty, is_signed) {
(types::I8 | types::I16, true) => param.sext(),

View file

@ -127,7 +127,7 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
PassMode::Indirect { attrs, meta_attrs: None, on_stack } => {
if on_stack {
// Abi requires aligning struct size to pointer size
let size = self.layout.size.align_to(tcx.data_layout.pointer_align.abi);
let size = self.layout.size.align_to(tcx.data_layout.pointer_align().abi);
let size = u32::try_from(size.bytes()).unwrap();
smallvec![apply_attrs_to_abi_param(
AbiParam::special(pointer_ty(tcx), ArgumentPurpose::StructArgument(size),),

View file

@ -15,7 +15,7 @@ use crate::debuginfo::FunctionDebugContext;
use crate::prelude::*;
pub(crate) fn pointer_ty(tcx: TyCtxt<'_>) -> types::Type {
match tcx.data_layout.pointer_size.bits() {
match tcx.data_layout.pointer_size().bits() {
16 => types::I16,
32 => types::I32,
64 => types::I64,

View file

@ -443,7 +443,7 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
let addend = {
let endianness = tcx.data_layout.endian;
let offset = offset.bytes() as usize;
let ptr_size = tcx.data_layout.pointer_size;
let ptr_size = tcx.data_layout.pointer_size();
let bytes = &alloc.inspect_with_uninit_and_ptr_outside_interpreter(
offset..offset + ptr_size.bytes() as usize,
);

View file

@ -162,7 +162,7 @@ impl<'gcc, 'tcx> ConstCodegenMethods for CodegenCx<'gcc, 'tcx> {
}
fn const_usize(&self, i: u64) -> RValue<'gcc> {
let bit_size = self.data_layout().pointer_size.bits();
let bit_size = self.data_layout().pointer_size().bits();
if bit_size < 64 {
// make sure it doesn't overflow
assert!(i < (1 << bit_size));

View file

@ -294,7 +294,7 @@ pub(crate) fn const_alloc_to_gcc_uncached<'gcc>(
let alloc = alloc.inner();
let mut llvals = Vec::with_capacity(alloc.provenance().ptrs().len() + 1);
let dl = cx.data_layout();
let pointer_size = dl.pointer_size.bytes() as usize;
let pointer_size = dl.pointer_size().bytes() as usize;
let mut next_offset = 0;
for &(offset, prov) in alloc.provenance().ptrs().iter() {
@ -331,7 +331,7 @@ pub(crate) fn const_alloc_to_gcc_uncached<'gcc>(
),
abi::Scalar::Initialized {
value: Primitive::Pointer(address_space),
valid_range: WrappingRange::full(dl.pointer_size),
valid_range: WrappingRange::full(dl.pointer_size()),
},
cx.type_i8p_ext(address_space),
));

View file

@ -541,7 +541,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
// For rusty ABIs, small aggregates are actually passed
// as `RegKind::Integer` (see `FnAbi::adjust_for_abi`),
// so we re-use that same threshold here.
layout.size() <= self.data_layout().pointer_size * 2
layout.size() <= self.data_layout().pointer_size() * 2
}
};

View file

@ -1184,7 +1184,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
let lhs = args[0].immediate();
let rhs = args[1].immediate();
let is_add = name == sym::simd_saturating_add;
let ptr_bits = bx.tcx().data_layout.pointer_size.bits() as _;
let ptr_bits = bx.tcx().data_layout.pointer_size().bits() as _;
let (signed, elem_width, elem_ty) = match *in_elem.kind() {
ty::Int(i) => (true, i.bit_width().unwrap_or(ptr_bits) / 8, bx.cx.type_int_from_ty(i)),
ty::Uint(i) => {

View file

@ -19,7 +19,6 @@
#![doc(rust_logo)]
#![feature(rustdoc_internals)]
#![feature(rustc_private)]
#![allow(broken_intra_doc_links)]
#![recursion_limit = "256"]
#![warn(rust_2018_idioms)]
#![warn(unused_lifetimes)]

View file

@ -370,22 +370,6 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>(
};
to_add.extend(inline_attr(cx, inline));
// The `uwtable` attribute according to LLVM is:
//
// This attribute indicates that the ABI being targeted requires that an
// unwind table entry be produced for this function even if we can show
// that no exceptions passes by it. This is normally the case for the
// ELF x86-64 abi, but it can be disabled for some compilation units.
//
// Typically when we're compiling with `-C panic=abort` (which implies this
// `no_landing_pads` check) we don't need `uwtable` because we can't
// generate any exceptions! On Windows, however, exceptions include other
// events such as illegal instructions, segfaults, etc. This means that on
// Windows we end up still needing the `uwtable` attribute even if the `-C
// panic=abort` flag is passed.
//
// You can also find more info on why Windows always requires uwtables here:
// https://bugzilla.mozilla.org/show_bug.cgi?id=1302078
if cx.sess().must_emit_unwind_tables() {
to_add.push(uwtable_attr(cx.llcx, cx.sess().opts.unstable_opts.use_sync_unwind));
}

View file

@ -175,7 +175,7 @@ impl<'ll, 'tcx> ConstCodegenMethods for CodegenCx<'ll, 'tcx> {
}
fn const_usize(&self, i: u64) -> &'ll Value {
let bit_size = self.data_layout().pointer_size.bits();
let bit_size = self.data_layout().pointer_size().bits();
if bit_size < 64 {
// make sure it doesn't overflow
assert!(i < (1 << bit_size));

View file

@ -43,7 +43,8 @@ pub(crate) fn const_alloc_to_llvm<'ll>(
}
let mut llvals = Vec::with_capacity(alloc.provenance().ptrs().len() + 1);
let dl = cx.data_layout();
let pointer_size = dl.pointer_size.bytes() as usize;
let pointer_size = dl.pointer_size();
let pointer_size_bytes = pointer_size.bytes() as usize;
// Note: this function may call `inspect_with_uninit_and_ptr_outside_interpreter`, so `range`
// must be within the bounds of `alloc` and not contain or overlap a pointer provenance.
@ -100,7 +101,9 @@ pub(crate) fn const_alloc_to_llvm<'ll>(
// This `inspect` is okay since it is within the bounds of the allocation, it doesn't
// affect interpreter execution (we inspect the result after interpreter execution),
// and we properly interpret the provenance as a relocation pointer offset.
alloc.inspect_with_uninit_and_ptr_outside_interpreter(offset..(offset + pointer_size)),
alloc.inspect_with_uninit_and_ptr_outside_interpreter(
offset..(offset + pointer_size_bytes),
),
)
.expect("const_alloc_to_llvm: could not read relocation pointer")
as u64;
@ -111,11 +114,11 @@ pub(crate) fn const_alloc_to_llvm<'ll>(
InterpScalar::from_pointer(Pointer::new(prov, Size::from_bytes(ptr_offset)), &cx.tcx),
Scalar::Initialized {
value: Primitive::Pointer(address_space),
valid_range: WrappingRange::full(dl.pointer_size),
valid_range: WrappingRange::full(pointer_size),
},
cx.type_ptr_ext(address_space),
));
next_offset = offset + pointer_size;
next_offset = offset + pointer_size_bytes;
}
if alloc.len() >= next_offset {
let range = next_offset..alloc.len();

View file

@ -605,7 +605,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
GenericCx(
FullCx {
tcx,
scx: SimpleCx::new(llmod, llcx, tcx.data_layout.pointer_size),
scx: SimpleCx::new(llmod, llcx, tcx.data_layout.pointer_size()),
use_dll_storage_attrs,
tls_model,
codegen_unit,

View file

@ -159,13 +159,15 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
return_if_di_node_created_in_meantime!(cx, unique_type_id);
let data_layout = &cx.tcx.data_layout;
let pointer_size = data_layout.pointer_size();
let pointer_align = data_layout.pointer_align();
let ptr_type_debuginfo_name = compute_debuginfo_type_name(cx.tcx, ptr_type, true);
match wide_pointer_kind(cx, pointee_type) {
None => {
// This is a thin pointer. Create a regular pointer type and give it the correct name.
assert_eq!(
(data_layout.pointer_size, data_layout.pointer_align.abi),
(pointer_size, pointer_align.abi),
cx.size_and_align_of(ptr_type),
"ptr_type={ptr_type}, pointee_type={pointee_type}",
);
@ -174,8 +176,8 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
llvm::LLVMRustDIBuilderCreatePointerType(
DIB(cx),
pointee_type_di_node,
data_layout.pointer_size.bits(),
data_layout.pointer_align.abi.bits() as u32,
pointer_size.bits(),
pointer_align.abi.bits() as u32,
0, // Ignore DWARF address space.
ptr_type_debuginfo_name.as_c_char_ptr(),
ptr_type_debuginfo_name.len(),
@ -319,7 +321,9 @@ fn build_subroutine_type_di_node<'ll, 'tcx>(
let name = compute_debuginfo_type_name(cx.tcx, fn_ty, false);
let (size, align) = match fn_ty.kind() {
ty::FnDef(..) => (Size::ZERO, Align::ONE),
ty::FnPtr(..) => (cx.tcx.data_layout.pointer_size, cx.tcx.data_layout.pointer_align.abi),
ty::FnPtr(..) => {
(cx.tcx.data_layout.pointer_size(), cx.tcx.data_layout.pointer_align().abi)
}
_ => unreachable!(),
};
let di_node = unsafe {
@ -504,7 +508,7 @@ fn recursion_marker_type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) -> &'ll D
create_basic_type(
cx,
"<recur_type>",
cx.tcx.data_layout.pointer_size,
cx.tcx.data_layout.pointer_size(),
dwarf_const::DW_ATE_unsigned,
)
})

View file

@ -458,7 +458,7 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
// For rusty ABIs, small aggregates are actually passed
// as `RegKind::Integer` (see `FnAbi::adjust_for_abi`),
// so we re-use that same threshold here.
layout.size() <= self.data_layout().pointer_size * 2
layout.size() <= self.data_layout().pointer_size() * 2
}
};
@ -758,8 +758,8 @@ fn codegen_msvc_try<'ll, 'tcx>(
// }
//
// More information can be found in libstd's seh.rs implementation.
let ptr_size = bx.tcx().data_layout.pointer_size;
let ptr_align = bx.tcx().data_layout.pointer_align.abi;
let ptr_size = bx.tcx().data_layout.pointer_size();
let ptr_align = bx.tcx().data_layout.pointer_align().abi;
let slot = bx.alloca(ptr_size, ptr_align);
let try_func_ty = bx.type_func(&[bx.type_ptr()], bx.type_void());
bx.invoke(try_func_ty, None, None, try_func, &[data], normal, catchswitch, None, None);
@ -1031,8 +1031,8 @@ fn codegen_emcc_try<'ll, 'tcx>(
// We need to pass two values to catch_func (ptr and is_rust_panic), so
// create an alloca and pass a pointer to that.
let ptr_size = bx.tcx().data_layout.pointer_size;
let ptr_align = bx.tcx().data_layout.pointer_align.abi;
let ptr_size = bx.tcx().data_layout.pointer_size();
let ptr_align = bx.tcx().data_layout.pointer_align().abi;
let i8_align = bx.tcx().data_layout.i8_align.abi;
// Required in order for there to be no padding between the fields.
assert!(i8_align <= ptr_align);
@ -1158,9 +1158,11 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
macro_rules! require_int_or_uint_ty {
($ty: expr, $diag: expr) => {
match $ty {
ty::Int(i) => i.bit_width().unwrap_or_else(|| bx.data_layout().pointer_size.bits()),
ty::Int(i) => {
i.bit_width().unwrap_or_else(|| bx.data_layout().pointer_size().bits())
}
ty::Uint(i) => {
i.bit_width().unwrap_or_else(|| bx.data_layout().pointer_size.bits())
i.bit_width().unwrap_or_else(|| bx.data_layout().pointer_size().bits())
}
_ => {
return_error!($diag);
@ -2014,10 +2016,10 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
} else {
let bitwidth = match in_elem.kind() {
ty::Int(i) => {
i.bit_width().unwrap_or_else(|| bx.data_layout().pointer_size.bits())
i.bit_width().unwrap_or_else(|| bx.data_layout().pointer_size().bits())
}
ty::Uint(i) => {
i.bit_width().unwrap_or_else(|| bx.data_layout().pointer_size.bits())
i.bit_width().unwrap_or_else(|| bx.data_layout().pointer_size().bits())
}
_ => return_error!(InvalidMonomorphization::UnsupportedSymbol {
span,

View file

@ -113,7 +113,7 @@ impl ExtraBackendMethods for LlvmCodegenBackend {
) -> ModuleLlvm {
let module_llvm = ModuleLlvm::new_metadata(tcx, module_name);
let cx =
SimpleCx::new(module_llvm.llmod(), &module_llvm.llcx, tcx.data_layout.pointer_size);
SimpleCx::new(module_llvm.llmod(), &module_llvm.llcx, tcx.data_layout.pointer_size());
unsafe {
allocator::codegen(tcx, cx, module_name, kind, alloc_error_handler_kind);
}

View file

@ -1,4 +1,3 @@
#![allow(non_camel_case_types)]
#![expect(dead_code)]
use libc::{c_char, c_uint};

View file

@ -208,7 +208,7 @@ impl<'ll, CX: Borrow<SCx<'ll>>> BaseTypeCodegenMethods for GenericCx<'ll, CX> {
}
fn type_ptr(&self) -> &'ll Type {
self.type_ptr_ext(AddressSpace::DATA)
self.type_ptr_ext(AddressSpace::ZERO)
}
fn type_ptr_ext(&self, address_space: AddressSpace) -> &'ll Type {
@ -258,7 +258,7 @@ impl Type {
}
pub(crate) fn ptr_llcx(llcx: &llvm::Context) -> &Type {
unsafe { llvm::LLVMPointerTypeInContext(llcx, AddressSpace::DATA.0) }
unsafe { llvm::LLVMPointerTypeInContext(llcx, AddressSpace::ZERO.0) }
}
}

View file

@ -45,7 +45,8 @@ fn emit_direct_ptr_va_arg<'ll, 'tcx>(
let va_list_ty = bx.type_ptr();
let va_list_addr = list.immediate();
let ptr = bx.load(va_list_ty, va_list_addr, bx.tcx().data_layout.pointer_align.abi);
let ptr_align_abi = bx.tcx().data_layout.pointer_align().abi;
let ptr = bx.load(va_list_ty, va_list_addr, ptr_align_abi);
let (addr, addr_align) = if allow_higher_align && align > slot_size {
(round_pointer_up_to_alignment(bx, ptr, align, bx.type_ptr()), align)
@ -56,7 +57,7 @@ fn emit_direct_ptr_va_arg<'ll, 'tcx>(
let aligned_size = size.align_to(slot_size).bytes() as i32;
let full_direct_size = bx.cx().const_i32(aligned_size);
let next = bx.inbounds_ptradd(addr, full_direct_size);
bx.store(next, va_list_addr, bx.tcx().data_layout.pointer_align.abi);
bx.store(next, va_list_addr, ptr_align_abi);
if size.bytes() < slot_size.bytes()
&& bx.tcx().sess.target.endian == Endian::Big
@ -108,8 +109,8 @@ fn emit_ptr_va_arg<'ll, 'tcx>(
let (llty, size, align) = if indirect {
(
bx.cx.layout_of(Ty::new_imm_ptr(bx.cx.tcx, target_ty)).llvm_type(bx.cx),
bx.cx.data_layout().pointer_size,
bx.cx.data_layout().pointer_align,
bx.cx.data_layout().pointer_size(),
bx.cx.data_layout().pointer_align(),
)
} else {
(layout.llvm_type(bx.cx), layout.size, layout.align)
@ -204,7 +205,7 @@ fn emit_aapcs_va_arg<'ll, 'tcx>(
bx.switch_to_block(in_reg);
let top_type = bx.type_ptr();
let top = bx.load(top_type, reg_top, dl.pointer_align.abi);
let top = bx.load(top_type, reg_top, dl.pointer_align().abi);
// reg_value = *(@top + reg_off_v);
let mut reg_addr = bx.ptradd(top, reg_off_v);
@ -297,6 +298,7 @@ fn emit_powerpc_va_arg<'ll, 'tcx>(
let max_regs = 8u8;
let use_regs = bx.icmp(IntPredicate::IntULT, num_regs, bx.const_u8(max_regs));
let ptr_align_abi = bx.tcx().data_layout.pointer_align().abi;
let in_reg = bx.append_sibling_block("va_arg.in_reg");
let in_mem = bx.append_sibling_block("va_arg.in_mem");
@ -308,7 +310,7 @@ fn emit_powerpc_va_arg<'ll, 'tcx>(
bx.switch_to_block(in_reg);
let reg_safe_area_ptr = bx.inbounds_ptradd(va_list_addr, bx.cx.const_usize(1 + 1 + 2 + 4));
let mut reg_addr = bx.load(bx.type_ptr(), reg_safe_area_ptr, dl.pointer_align.abi);
let mut reg_addr = bx.load(bx.type_ptr(), reg_safe_area_ptr, ptr_align_abi);
// Floating-point registers start after the general-purpose registers.
if !is_int && !is_soft_float_abi {
@ -342,11 +344,11 @@ fn emit_powerpc_va_arg<'ll, 'tcx>(
let size = if !is_indirect {
layout.layout.size.align_to(overflow_area_align)
} else {
dl.pointer_size
dl.pointer_size()
};
let overflow_area_ptr = bx.inbounds_ptradd(va_list_addr, bx.cx.const_usize(1 + 1 + 2));
let mut overflow_area = bx.load(bx.type_ptr(), overflow_area_ptr, dl.pointer_align.abi);
let mut overflow_area = bx.load(bx.type_ptr(), overflow_area_ptr, ptr_align_abi);
// Round up address of argument to alignment
if layout.layout.align.abi > overflow_area_align {
@ -362,7 +364,7 @@ fn emit_powerpc_va_arg<'ll, 'tcx>(
// Increase the overflow area.
overflow_area = bx.inbounds_ptradd(overflow_area, bx.const_usize(size.bytes()));
bx.store(overflow_area, overflow_area_ptr, dl.pointer_align.abi);
bx.store(overflow_area, overflow_area_ptr, ptr_align_abi);
bx.br(end);
@ -373,11 +375,8 @@ fn emit_powerpc_va_arg<'ll, 'tcx>(
bx.switch_to_block(end);
let val_addr = bx.phi(bx.type_ptr(), &[reg_addr, mem_addr], &[in_reg, in_mem]);
let val_type = layout.llvm_type(bx);
let val_addr = if is_indirect {
bx.load(bx.cx.type_ptr(), val_addr, dl.pointer_align.abi)
} else {
val_addr
};
let val_addr =
if is_indirect { bx.load(bx.cx.type_ptr(), val_addr, ptr_align_abi) } else { val_addr };
bx.load(val_type, val_addr, layout.align.abi)
}
@ -414,6 +413,7 @@ fn emit_s390x_va_arg<'ll, 'tcx>(
let in_reg = bx.append_sibling_block("va_arg.in_reg");
let in_mem = bx.append_sibling_block("va_arg.in_mem");
let end = bx.append_sibling_block("va_arg.end");
let ptr_align_abi = dl.pointer_align().abi;
// FIXME: vector ABI not yet supported.
let target_ty_size = bx.cx.size_of(target_ty).bytes();
@ -435,7 +435,7 @@ fn emit_s390x_va_arg<'ll, 'tcx>(
bx.switch_to_block(in_reg);
// Work out the address of the value in the register save area.
let reg_ptr_v = bx.load(bx.type_ptr(), reg_save_area, dl.pointer_align.abi);
let reg_ptr_v = bx.load(bx.type_ptr(), reg_save_area, ptr_align_abi);
let scaled_reg_count = bx.mul(reg_count_v, bx.const_u64(8));
let reg_off = bx.add(scaled_reg_count, bx.const_u64(reg_save_index * 8 + reg_padding));
let reg_addr = bx.ptradd(reg_ptr_v, reg_off);
@ -449,15 +449,14 @@ fn emit_s390x_va_arg<'ll, 'tcx>(
bx.switch_to_block(in_mem);
// Work out the address of the value in the argument overflow area.
let arg_ptr_v =
bx.load(bx.type_ptr(), overflow_arg_area, bx.tcx().data_layout.pointer_align.abi);
let arg_ptr_v = bx.load(bx.type_ptr(), overflow_arg_area, ptr_align_abi);
let arg_off = bx.const_u64(padding);
let mem_addr = bx.ptradd(arg_ptr_v, arg_off);
// Update the argument overflow area pointer.
let arg_size = bx.cx().const_u64(padded_size);
let new_arg_ptr_v = bx.inbounds_ptradd(arg_ptr_v, arg_size);
bx.store(new_arg_ptr_v, overflow_arg_area, dl.pointer_align.abi);
bx.store(new_arg_ptr_v, overflow_arg_area, ptr_align_abi);
bx.br(end);
// Return the appropriate result.
@ -465,7 +464,7 @@ fn emit_s390x_va_arg<'ll, 'tcx>(
let val_addr = bx.phi(bx.type_ptr(), &[reg_addr, mem_addr], &[in_reg, in_mem]);
let val_type = layout.llvm_type(bx);
let val_addr =
if indirect { bx.load(bx.cx.type_ptr(), val_addr, dl.pointer_align.abi) } else { val_addr };
if indirect { bx.load(bx.cx.type_ptr(), val_addr, ptr_align_abi) } else { val_addr };
bx.load(val_type, val_addr, layout.align.abi)
}
@ -607,7 +606,7 @@ fn emit_x86_64_sysv64_va_arg<'ll, 'tcx>(
// loads than necessary. Can we clean this up?
let reg_save_area_ptr =
bx.inbounds_ptradd(va_list_addr, bx.cx.const_usize(2 * unsigned_int_offset + ptr_offset));
let reg_save_area_v = bx.load(bx.type_ptr(), reg_save_area_ptr, dl.pointer_align.abi);
let reg_save_area_v = bx.load(bx.type_ptr(), reg_save_area_ptr, dl.pointer_align().abi);
let reg_addr = match layout.layout.backend_repr() {
BackendRepr::Scalar(scalar) => match scalar.primitive() {
@ -749,10 +748,11 @@ fn x86_64_sysv64_va_arg_from_memory<'ll, 'tcx>(
layout: TyAndLayout<'tcx, Ty<'tcx>>,
) -> &'ll Value {
let dl = bx.cx.data_layout();
let ptr_align_abi = dl.data_layout().pointer_align().abi;
let overflow_arg_area_ptr = bx.inbounds_ptradd(va_list_addr, bx.const_usize(8));
let overflow_arg_area_v = bx.load(bx.type_ptr(), overflow_arg_area_ptr, dl.pointer_align.abi);
let overflow_arg_area_v = bx.load(bx.type_ptr(), overflow_arg_area_ptr, ptr_align_abi);
// AMD64-ABI 3.5.7p5: Step 7. Align l->overflow_arg_area upwards to a 16
// byte boundary if alignment needed by type exceeds 8 byte boundary.
// It isn't stated explicitly in the standard, but in practice we use
@ -771,7 +771,7 @@ fn x86_64_sysv64_va_arg_from_memory<'ll, 'tcx>(
let size_in_bytes = layout.layout.size().bytes();
let offset = bx.const_i32(size_in_bytes.next_multiple_of(8) as i32);
let overflow_arg_area = bx.inbounds_ptradd(overflow_arg_area_v, offset);
bx.store(overflow_arg_area, overflow_arg_area_ptr, dl.pointer_align.abi);
bx.store(overflow_arg_area, overflow_arg_area_ptr, ptr_align_abi);
mem_addr
}
@ -803,6 +803,7 @@ fn emit_xtensa_va_arg<'ll, 'tcx>(
let from_stack = bx.append_sibling_block("va_arg.from_stack");
let from_regsave = bx.append_sibling_block("va_arg.from_regsave");
let end = bx.append_sibling_block("va_arg.end");
let ptr_align_abi = bx.tcx().data_layout.pointer_align().abi;
// (*va).va_ndx
let va_reg_offset = 4;
@ -825,12 +826,11 @@ fn emit_xtensa_va_arg<'ll, 'tcx>(
bx.switch_to_block(from_regsave);
// update va_ndx
bx.store(offset_next, offset_ptr, bx.tcx().data_layout.pointer_align.abi);
bx.store(offset_next, offset_ptr, ptr_align_abi);
// (*va).va_reg
let regsave_area_ptr = bx.inbounds_ptradd(va_list_addr, bx.cx.const_usize(va_reg_offset));
let regsave_area =
bx.load(bx.type_ptr(), regsave_area_ptr, bx.tcx().data_layout.pointer_align.abi);
let regsave_area = bx.load(bx.type_ptr(), regsave_area_ptr, ptr_align_abi);
let regsave_value_ptr = bx.inbounds_ptradd(regsave_area, offset);
bx.br(end);
@ -849,11 +849,11 @@ fn emit_xtensa_va_arg<'ll, 'tcx>(
// va_ndx = offset_next_corrected;
let offset_next_corrected = bx.add(offset_next, bx.const_i32(slot_size));
// update va_ndx
bx.store(offset_next_corrected, offset_ptr, bx.tcx().data_layout.pointer_align.abi);
bx.store(offset_next_corrected, offset_ptr, ptr_align_abi);
// let stack_value_ptr = unsafe { (*va).va_stk.byte_add(offset_corrected) };
let stack_area_ptr = bx.inbounds_ptradd(va_list_addr, bx.cx.const_usize(0));
let stack_area = bx.load(bx.type_ptr(), stack_area_ptr, bx.tcx().data_layout.pointer_align.abi);
let stack_area = bx.load(bx.type_ptr(), stack_area_ptr, ptr_align_abi);
let stack_value_ptr = bx.inbounds_ptradd(stack_area, offset_corrected);
bx.br(end);

View file

@ -1208,7 +1208,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
split_debuginfo: tcx.sess.split_debuginfo(),
split_dwarf_kind: tcx.sess.opts.unstable_opts.split_dwarf_kind,
parallel: backend.supports_parallel() && !sess.opts.unstable_opts.no_parallel_backend,
pointer_size: tcx.data_layout.pointer_size,
pointer_size: tcx.data_layout.pointer_size(),
invocation_temp: sess.invocation_temp.clone(),
};

View file

@ -200,7 +200,7 @@ fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
let vptr_entry_idx = cx.tcx().supertrait_vtable_slot((source, target));
if let Some(entry_idx) = vptr_entry_idx {
let ptr_size = bx.data_layout().pointer_size;
let ptr_size = bx.data_layout().pointer_size();
let vtable_byte_offset = u64::try_from(entry_idx).unwrap() * ptr_size.bytes();
load_vtable(bx, old_info, bx.type_ptr(), vtable_byte_offset, source, true)
} else {
@ -577,8 +577,8 @@ fn get_argc_argv<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(bx: &mut Bx) -> (Bx::Va
// Params for UEFI
let param_handle = bx.get_param(0);
let param_system_table = bx.get_param(1);
let ptr_size = bx.tcx().data_layout.pointer_size;
let ptr_align = bx.tcx().data_layout.pointer_align.abi;
let ptr_size = bx.tcx().data_layout.pointer_size();
let ptr_align = bx.tcx().data_layout.pointer_align().abi;
let arg_argc = bx.const_int(bx.cx().type_isize(), 2);
let arg_argv = bx.alloca(2 * ptr_size, ptr_align);
bx.store(param_handle, arg_argv, ptr_align);

View file

@ -4,7 +4,7 @@ use rustc_abi::{Align, ExternAbi};
use rustc_ast::expand::autodiff_attrs::{AutoDiffAttrs, DiffActivity, DiffMode};
use rustc_ast::{LitKind, MetaItem, MetaItemInner, attr};
use rustc_attr_data_structures::{
AttributeKind, InlineAttr, InstructionSetAttr, OptimizeAttr, ReprAttr, UsedBy, find_attr,
AttributeKind, InlineAttr, InstructionSetAttr, OptimizeAttr, UsedBy, find_attr,
};
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId};
@ -109,14 +109,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
if let hir::Attribute::Parsed(p) = attr {
match p {
AttributeKind::Repr { reprs, first_span: _ } => {
codegen_fn_attrs.alignment = reprs
.iter()
.filter_map(
|(r, _)| if let ReprAttr::ReprAlign(x) = r { Some(*x) } else { None },
)
.max();
}
AttributeKind::Cold(_) => codegen_fn_attrs.flags |= CodegenFnAttrFlags::COLD,
AttributeKind::ExportName { name, .. } => {
codegen_fn_attrs.export_name = Some(*name);

View file

@ -457,7 +457,7 @@ impl<G: EmissionGuarantee> Diagnostic<'_, G> for LinkingFailed<'_> {
} else if arg.as_encoded_bytes().ends_with(b".rlib") {
let rlib_path = Path::new(&arg);
let dir = rlib_path.parent().unwrap();
let filename = rlib_path.file_name().unwrap().to_owned();
let filename = rlib_path.file_stem().unwrap().to_owned();
if let Some(ArgGroup::Rlibs(parent, rlibs)) = args.last_mut() {
if parent == dir {
rlibs.push(filename);
@ -471,7 +471,7 @@ impl<G: EmissionGuarantee> Diagnostic<'_, G> for LinkingFailed<'_> {
args.push(ArgGroup::Regular(arg));
}
}
let crate_hash = regex::bytes::Regex::new(r"-[0-9a-f]+\.rlib$").unwrap();
let crate_hash = regex::bytes::Regex::new(r"-[0-9a-f]+").unwrap();
self.command.args(args.into_iter().map(|arg_group| {
match arg_group {
// SAFETY: we are only matching on ASCII, not any surrogate pairs, so any replacements we do will still be valid.
@ -494,7 +494,11 @@ impl<G: EmissionGuarantee> Diagnostic<'_, G> for LinkingFailed<'_> {
Err(_) => false,
};
let mut arg = dir.into_os_string();
arg.push("/{");
arg.push("/");
let needs_braces = rlibs.len() >= 2;
if needs_braces {
arg.push("{");
}
let mut first = true;
for mut rlib in rlibs {
if !first {
@ -513,7 +517,10 @@ impl<G: EmissionGuarantee> Diagnostic<'_, G> for LinkingFailed<'_> {
}
arg.push(rlib);
}
arg.push("}.rlib");
if needs_braces {
arg.push("}");
}
arg.push(".rlib");
arg
}
}

View file

@ -27,7 +27,7 @@ impl<'a, 'tcx> VirtualIndex {
debug!("get_fn({llvtable:?}, {ty:?}, {self:?})");
let llty = bx.fn_ptr_backend_type(fn_abi);
let ptr_size = bx.data_layout().pointer_size;
let ptr_size = bx.data_layout().pointer_size();
let vtable_byte_offset = self.0 * ptr_size.bytes();
load_vtable(bx, llvtable, llty, vtable_byte_offset, ty, nonnull)
@ -63,7 +63,7 @@ impl<'a, 'tcx> VirtualIndex {
debug!("get_int({:?}, {:?})", llvtable, self);
let llty = bx.type_isize();
let ptr_size = bx.data_layout().pointer_size;
let ptr_size = bx.data_layout().pointer_size();
let vtable_byte_offset = self.0 * ptr_size.bytes();
load_vtable(bx, llvtable, llty, vtable_byte_offset, ty, false)
@ -115,7 +115,7 @@ pub(crate) fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>(
let vtable_alloc_id = tcx.vtable_allocation((ty, trait_ref));
let vtable_allocation = tcx.global_alloc(vtable_alloc_id).unwrap_memory();
let vtable_const = cx.const_data_from_alloc(vtable_allocation);
let align = cx.data_layout().pointer_align.abi;
let align = cx.data_layout().pointer_align().abi;
let vtable = cx.static_addr_of(vtable_const, align, Some("vtable"));
cx.apply_vcall_visibility_metadata(ty, trait_ref, vtable);
@ -133,7 +133,7 @@ pub(crate) fn load_vtable<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
ty: Ty<'tcx>,
nonnull: bool,
) -> Bx::Value {
let ptr_align = bx.data_layout().pointer_align.abi;
let ptr_align = bx.data_layout().pointer_align().abi;
if bx.cx().sess().opts.unstable_opts.virtual_function_elimination
&& bx.cx().sess().lto() == Lto::Fat

View file

@ -326,7 +326,7 @@ fn prefix_and_suffix<'tcx>(
fn wasm_functype<'tcx>(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> String {
let mut signature = String::with_capacity(64);
let ptr_type = match tcx.data_layout.pointer_size.bits() {
let ptr_type = match tcx.data_layout.pointer_size().bits() {
32 => "i32",
64 => "i64",
other => bug!("wasm pointer size cannot be {other} bits"),

View file

@ -1135,7 +1135,7 @@ fn assume_scalar_range<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
let range = scalar.valid_range(bx.cx());
bx.assume_integer_range(imm, backend_ty, range);
}
abi::Primitive::Pointer(abi::AddressSpace::DATA)
abi::Primitive::Pointer(abi::AddressSpace::ZERO)
if !scalar.valid_range(bx.cx()).contains(0) =>
{
bx.assume_nonnull(imm);

View file

@ -19,7 +19,7 @@ use super::{CanAccessMutGlobal, CompileTimeInterpCx, CompileTimeMachine};
use crate::const_eval::CheckAlignment;
use crate::interpret::{
CtfeValidationMode, GlobalId, Immediate, InternKind, InternResult, InterpCx, InterpErrorKind,
InterpResult, MPlaceTy, MemoryKind, OpTy, RefTracking, StackPopCleanup, create_static_alloc,
InterpResult, MPlaceTy, MemoryKind, OpTy, RefTracking, ReturnContinuation, create_static_alloc,
intern_const_alloc_recursive, interp_ok, throw_exhaust,
};
use crate::{CTRL_C_RECEIVED, errors};
@ -76,7 +76,7 @@ fn eval_body_using_ecx<'tcx, R: InterpretationResult<'tcx>>(
cid.instance,
body,
&ret.clone().into(),
StackPopCleanup::Root { cleanup: false },
ReturnContinuation::Stop { cleanup: false },
)?;
ecx.storage_live_for_always_live_locals()?;

View file

@ -331,10 +331,10 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
fn load_mir(
ecx: &InterpCx<'tcx, Self>,
instance: ty::InstanceKind<'tcx>,
) -> InterpResult<'tcx, &'tcx mir::Body<'tcx>> {
) -> &'tcx mir::Body<'tcx> {
match instance {
ty::InstanceKind::Item(def) => interp_ok(ecx.tcx.mir_for_ctfe(def)),
_ => interp_ok(ecx.tcx.instance_mir(instance)),
ty::InstanceKind::Item(def) => ecx.tcx.mir_for_ctfe(def),
_ => ecx.tcx.instance_mir(instance),
}
}

View file

@ -15,7 +15,7 @@ use tracing::{info, instrument, trace};
use super::{
CtfeProvenance, FnVal, ImmTy, InterpCx, InterpResult, MPlaceTy, Machine, OpTy, PlaceTy,
Projectable, Provenance, ReturnAction, Scalar, StackPopCleanup, StackPopInfo, interp_ok,
Projectable, Provenance, ReturnAction, ReturnContinuation, Scalar, StackPopInfo, interp_ok,
throw_ub, throw_ub_custom, throw_unsup_format,
};
use crate::fluent_generated as fluent;
@ -340,7 +340,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
args: &[FnArg<'tcx, M::Provenance>],
with_caller_location: bool,
destination: &PlaceTy<'tcx, M::Provenance>,
mut stack_pop: StackPopCleanup,
mut cont: ReturnContinuation,
) -> InterpResult<'tcx> {
// Compute callee information.
// FIXME: for variadic support, do we have to somehow determine callee's extra_args?
@ -365,15 +365,15 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
if !callee_fn_abi.can_unwind {
// The callee cannot unwind, so force the `Unreachable` unwind handling.
match &mut stack_pop {
StackPopCleanup::Root { .. } => {}
StackPopCleanup::Goto { unwind, .. } => {
match &mut cont {
ReturnContinuation::Stop { .. } => {}
ReturnContinuation::Goto { unwind, .. } => {
*unwind = mir::UnwindAction::Unreachable;
}
}
}
self.push_stack_frame_raw(instance, body, destination, stack_pop)?;
self.push_stack_frame_raw(instance, body, destination, cont)?;
// If an error is raised here, pop the frame again to get an accurate backtrace.
// To this end, we wrap it all in a `try` block.
@ -617,7 +617,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
&args,
with_caller_location,
destination,
StackPopCleanup::Goto { ret: target, unwind },
ReturnContinuation::Goto { ret: target, unwind },
)
}
// `InstanceKind::Virtual` does not have callable MIR. Calls to `Virtual` instances must be
@ -755,8 +755,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
// Note that we are using `pop_stack_frame_raw` and not `return_from_current_stack_frame`,
// as the latter "executes" the goto to the return block, but we don't want to,
// only the tail called function should return to the current return block.
let StackPopInfo { return_action, return_to_block, return_place } = self
.pop_stack_frame_raw(false, |_this, _return_place| {
let StackPopInfo { return_action, return_cont, return_place } =
self.pop_stack_frame_raw(false, |_this, _return_place| {
// This function's return value is just discarded, the tail-callee will fill in the return place instead.
interp_ok(())
})?;
@ -764,7 +764,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
assert_eq!(return_action, ReturnAction::Normal);
// Take the "stack pop cleanup" info, and use that to initiate the next call.
let StackPopCleanup::Goto { ret, unwind } = return_to_block else {
let ReturnContinuation::Goto { ret, unwind } = return_cont else {
bug!("can't tailcall as root");
};
@ -896,23 +896,23 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
// Normal return, figure out where to jump.
if unwinding {
// Follow the unwind edge.
match stack_pop_info.return_to_block {
StackPopCleanup::Goto { unwind, .. } => {
match stack_pop_info.return_cont {
ReturnContinuation::Goto { unwind, .. } => {
// This must be the very last thing that happens, since it can in fact push a new stack frame.
self.unwind_to_block(unwind)
}
StackPopCleanup::Root { .. } => {
panic!("encountered StackPopCleanup::Root when unwinding!")
ReturnContinuation::Stop { .. } => {
panic!("encountered ReturnContinuation::Stop when unwinding!")
}
}
} else {
// Follow the normal return edge.
match stack_pop_info.return_to_block {
StackPopCleanup::Goto { ret, .. } => self.return_to_block(ret),
StackPopCleanup::Root { .. } => {
match stack_pop_info.return_cont {
ReturnContinuation::Goto { ret, .. } => self.return_to_block(ret),
ReturnContinuation::Stop { .. } => {
assert!(
self.stack().is_empty(),
"only the bottommost frame can have StackPopCleanup::Root"
"only the bottommost frame can have ReturnContinuation::Stop"
);
interp_ok(())
}

View file

@ -272,7 +272,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
let def = instance.def_id();
&self.tcx.promoted_mir(def)[promoted]
} else {
M::load_mir(self, instance)?
M::load_mir(self, instance)
};
// do not continue if typeck errors occurred (can only occur in local crate)
if let Some(err) = body.tainted_by_errors {

View file

@ -189,8 +189,8 @@ pub trait Machine<'tcx>: Sized {
fn load_mir(
ecx: &InterpCx<'tcx, Self>,
instance: ty::InstanceKind<'tcx>,
) -> InterpResult<'tcx, &'tcx mir::Body<'tcx>> {
interp_ok(ecx.tcx.instance_mir(instance))
) -> &'tcx mir::Body<'tcx> {
ecx.tcx.instance_mir(instance)
}
/// Entry point to all function calls.

View file

@ -1233,7 +1233,7 @@ impl<'a, 'tcx, Prov: Provenance, Extra, Bytes: AllocBytes>
/// `offset` is relative to this allocation reference, not the base of the allocation.
pub fn write_ptr_sized(&mut self, offset: Size, val: Scalar<Prov>) -> InterpResult<'tcx> {
self.write_scalar(alloc_range(offset, self.tcx.data_layout().pointer_size), val)
self.write_scalar(alloc_range(offset, self.tcx.data_layout().pointer_size()), val)
}
/// Mark the given sub-range (relative to this allocation reference) as uninitialized.
@ -1285,7 +1285,7 @@ impl<'a, 'tcx, Prov: Provenance, Extra, Bytes: AllocBytes> AllocRef<'a, 'tcx, Pr
/// `offset` is relative to this allocation reference, not the base of the allocation.
pub fn read_pointer(&self, offset: Size) -> InterpResult<'tcx, Scalar<Prov>> {
self.read_scalar(
alloc_range(offset, self.tcx.data_layout().pointer_size),
alloc_range(offset, self.tcx.data_layout().pointer_size()),
/*read_provenance*/ true,
)
}

View file

@ -36,7 +36,7 @@ pub use self::operand::{ImmTy, Immediate, OpTy};
pub use self::place::{MPlaceTy, MemPlaceMeta, PlaceTy, Writeable};
use self::place::{MemPlace, Place};
pub use self::projection::{OffsetMode, Projectable};
pub use self::stack::{Frame, FrameInfo, LocalState, StackPopCleanup, StackPopInfo};
pub use self::stack::{Frame, FrameInfo, LocalState, ReturnContinuation, StackPopInfo};
pub(crate) use self::util::create_static_alloc;
pub use self::validity::{CtfeValidationMode, RangeSet, RefTracking};
pub use self::visitor::ValueVisitor;

View file

@ -72,8 +72,8 @@ pub struct Frame<'tcx, Prov: Provenance = CtfeProvenance, Extra = ()> {
////////////////////////////////////////////////////////////////////////////////
// Return place and locals
////////////////////////////////////////////////////////////////////////////////
/// Work to perform when returning from this function.
return_to_block: StackPopCleanup,
/// Where to continue when returning from this function.
return_cont: ReturnContinuation,
/// The location where the result of the current stack frame should be written to,
/// and its layout in the caller. This place is to be interpreted relative to the
@ -106,19 +106,19 @@ pub struct Frame<'tcx, Prov: Provenance = CtfeProvenance, Extra = ()> {
pub(super) loc: Either<mir::Location, Span>,
}
/// Where and how to continue when returning/unwinding from the current function.
#[derive(Clone, Copy, Eq, PartialEq, Debug)] // Miri debug-prints these
pub enum StackPopCleanup {
pub enum ReturnContinuation {
/// Jump to the next block in the caller, or cause UB if None (that's a function
/// that may never return). Also store layout of return place so
/// we can validate it at that layout.
/// that may never return).
/// `ret` stores the block we jump to on a normal return, while `unwind`
/// stores the block used for cleanup during unwinding.
Goto { ret: Option<mir::BasicBlock>, unwind: mir::UnwindAction },
/// The root frame of the stack: nowhere else to jump to.
/// The root frame of the stack: nowhere else to jump to, so we stop.
/// `cleanup` says whether locals are deallocated. Static computation
/// wants them leaked to intern what they need (and just throw away
/// the entire `ecx` when it is done).
Root { cleanup: bool },
Stop { cleanup: bool },
}
/// Return type of [`InterpCx::pop_stack_frame_raw`].
@ -127,8 +127,8 @@ pub struct StackPopInfo<'tcx, Prov: Provenance> {
/// stack frame.
pub return_action: ReturnAction,
/// [`return_to_block`](Frame::return_to_block) of the popped stack frame.
pub return_to_block: StackPopCleanup,
/// [`return_cont`](Frame::return_cont) of the popped stack frame.
pub return_cont: ReturnContinuation,
/// [`return_place`](Frame::return_place) of the popped stack frame.
pub return_place: PlaceTy<'tcx, Prov>,
@ -255,7 +255,7 @@ impl<'tcx, Prov: Provenance> Frame<'tcx, Prov> {
Frame {
body: self.body,
instance: self.instance,
return_to_block: self.return_to_block,
return_cont: self.return_cont,
return_place: self.return_place,
locals: self.locals,
loc: self.loc,
@ -350,20 +350,20 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
/// the arguments or local variables.
///
/// The high-level version of this is `init_stack_frame`.
#[instrument(skip(self, body, return_place, return_to_block), level = "debug")]
#[instrument(skip(self, body, return_place, return_cont), level = "debug")]
pub(crate) fn push_stack_frame_raw(
&mut self,
instance: ty::Instance<'tcx>,
body: &'tcx mir::Body<'tcx>,
return_place: &PlaceTy<'tcx, M::Provenance>,
return_to_block: StackPopCleanup,
return_cont: ReturnContinuation,
) -> InterpResult<'tcx> {
trace!("body: {:#?}", body);
// We can push a `Root` frame if and only if the stack is empty.
debug_assert_eq!(
self.stack().is_empty(),
matches!(return_to_block, StackPopCleanup::Root { .. })
matches!(return_cont, ReturnContinuation::Stop { .. })
);
// First push a stack frame so we have access to `instantiate_from_current_frame` and other
@ -373,7 +373,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
let pre_frame = Frame {
body,
loc: Right(body.span), // Span used for errors caused during preamble.
return_to_block,
return_cont,
return_place: return_place.clone(),
locals,
instance,
@ -429,15 +429,15 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
copy_ret_val(self, &frame.return_place)?;
}
let return_to_block = frame.return_to_block;
let return_cont = frame.return_cont;
let return_place = frame.return_place.clone();
// Cleanup: deallocate locals.
// Usually we want to clean up (deallocate locals), but in a few rare cases we don't.
// We do this while the frame is still on the stack, so errors point to the callee.
let cleanup = match return_to_block {
StackPopCleanup::Goto { .. } => true,
StackPopCleanup::Root { cleanup, .. } => cleanup,
let cleanup = match return_cont {
ReturnContinuation::Goto { .. } => true,
ReturnContinuation::Stop { cleanup, .. } => cleanup,
};
let return_action = if cleanup {
@ -455,7 +455,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
ReturnAction::NoCleanup
};
interp_ok(StackPopInfo { return_action, return_to_block, return_place })
interp_ok(StackPopInfo { return_action, return_cont, return_place })
}
/// In the current stack frame, mark all locals as live that are not arguments and don't have

View file

@ -142,7 +142,7 @@ const EVENT_FILTERS_BY_NAME: &[(&str, EventFilter)] = &[
("generic-activity", EventFilter::GENERIC_ACTIVITIES),
("query-provider", EventFilter::QUERY_PROVIDERS),
("query-cache-hit", EventFilter::QUERY_CACHE_HITS),
("query-cache-hit-count", EventFilter::QUERY_CACHE_HITS),
("query-cache-hit-count", EventFilter::QUERY_CACHE_HIT_COUNTS),
("query-blocked", EventFilter::QUERY_BLOCKED),
("incr-cache-load", EventFilter::INCR_CACHE_LOADS),
("query-keys", EventFilter::QUERY_KEYS),

View file

@ -41,5 +41,8 @@ errors_target_invalid_bits =
errors_target_invalid_bits_size = {$err}
errors_target_invalid_datalayout_pointer_spec =
unknown pointer specification `{$err}` in datalayout string
errors_target_missing_alignment =
missing alignment for `{$cause}` in "data-layout"

View file

@ -374,6 +374,10 @@ impl<G: EmissionGuarantee> Diagnostic<'_, G> for TargetDataLayoutErrors<'_> {
TargetDataLayoutErrors::InvalidBitsSize { err } => {
Diag::new(dcx, level, fluent::errors_target_invalid_bits_size).with_arg("err", err)
}
TargetDataLayoutErrors::UnknownPointerSpecification { err } => {
Diag::new(dcx, level, fluent::errors_target_invalid_datalayout_pointer_spec)
.with_arg("err", err)
}
}
}
}

View file

@ -3,7 +3,6 @@
//! This module contains the code for creating and emitting diagnostics.
// tidy-alphabetical-start
#![allow(incomplete_features)]
#![allow(internal_features)]
#![allow(rustc::diagnostic_outside_of_impl)]
#![allow(rustc::direct_use_of_rustc_type_ir)]

View file

@ -373,17 +373,10 @@ pub fn compile_declarative_macro(
node_id: NodeId,
edition: Edition,
) -> (SyntaxExtension, usize) {
let is_local = node_id != DUMMY_NODE_ID;
let mk_syn_ext = |expander| {
SyntaxExtension::new(
sess,
SyntaxExtensionKind::LegacyBang(expander),
span,
Vec::new(),
edition,
ident.name,
attrs,
node_id != DUMMY_NODE_ID,
)
let kind = SyntaxExtensionKind::LegacyBang(expander);
SyntaxExtension::new(sess, kind, span, Vec::new(), edition, ident.name, attrs, is_local)
};
let dummy_syn_ext = |guar| (mk_syn_ext(Arc::new(DummyExpander(guar))), 0);
@ -393,7 +386,8 @@ pub fn compile_declarative_macro(
let body = macro_def.body.tokens.clone();
let mut p = Parser::new(&sess.psess, body, rustc_parse::MACRO_ARGUMENTS);
// Don't abort iteration early, so that multiple errors can be reported.
// Don't abort iteration early, so that multiple errors can be reported. We only abort early on
// parse failures we can't recover from.
let mut guar = None;
let mut check_emission = |ret: Result<(), ErrorGuaranteed>| guar = guar.or(ret.err());
@ -402,20 +396,11 @@ pub fn compile_declarative_macro(
while p.token != token::Eof {
let lhs_tt = p.parse_token_tree();
let lhs_tt = parse_one_tt(lhs_tt, RulePart::Pattern, sess, node_id, features, edition);
// We don't handle errors here, the driver will abort after parsing/expansion. We can
// report every error in every macro this way.
check_emission(check_lhs_nt_follows(sess, node_id, &lhs_tt));
check_emission(check_lhs_no_empty_seq(sess, slice::from_ref(&lhs_tt)));
check_emission(check_lhs(sess, node_id, &lhs_tt));
if let Err(e) = p.expect(exp!(FatArrow)) {
return dummy_syn_ext(e.emit());
}
if p.token == token::Eof {
let err_sp = p.token.span.shrink_to_hi();
let guar = sess
.dcx()
.struct_span_err(err_sp, "macro definition ended unexpectedly")
.with_span_label(err_sp, "expected right-hand side of macro rule")
.emit();
if let Some(guar) = check_no_eof(sess, &p, "expected right-hand side of macro rule") {
return dummy_syn_ext(guar);
}
let rhs_tt = p.parse_token_tree();
@ -454,13 +439,32 @@ pub fn compile_declarative_macro(
}
// Return the number of rules for unused rule linting, if this is a local macro.
let nrules = if node_id != DUMMY_NODE_ID { rules.len() } else { 0 };
let nrules = if is_local { rules.len() } else { 0 };
let expander =
Arc::new(MacroRulesMacroExpander { name: ident, span, node_id, transparency, rules });
(mk_syn_ext(expander), nrules)
}
fn check_no_eof(sess: &Session, p: &Parser<'_>, msg: &'static str) -> Option<ErrorGuaranteed> {
if p.token == token::Eof {
let err_sp = p.token.span.shrink_to_hi();
let guar = sess
.dcx()
.struct_span_err(err_sp, "macro definition ended unexpectedly")
.with_span_label(err_sp, msg)
.emit();
return Some(guar);
}
None
}
fn check_lhs(sess: &Session, node_id: NodeId, lhs: &mbe::TokenTree) -> Result<(), ErrorGuaranteed> {
let e1 = check_lhs_nt_follows(sess, node_id, lhs);
let e2 = check_lhs_no_empty_seq(sess, slice::from_ref(lhs));
e1.and(e2)
}
fn check_lhs_nt_follows(
sess: &Session,
node_id: NodeId,

View file

@ -831,7 +831,7 @@ pub enum LifetimeRes {
/// Id of the introducing place. That can be:
/// - an item's id, for the item's generic parameters;
/// - a TraitRef's ref_id, identifying the `for<...>` binder;
/// - a BareFn type's id.
/// - a FnPtr type's id.
///
/// This information is used for impl-trait lifetime captures, to know when to or not to
/// capture any given lifetime.

View file

@ -3526,7 +3526,7 @@ impl PrimTy {
}
#[derive(Debug, Clone, Copy, HashStable_Generic)]
pub struct BareFnTy<'hir> {
pub struct FnPtrTy<'hir> {
pub safety: Safety,
pub abi: ExternAbi,
pub generic_params: &'hir [GenericParam<'hir>],
@ -3645,8 +3645,8 @@ pub enum TyKind<'hir, Unambig = ()> {
Ptr(MutTy<'hir>),
/// A reference (i.e., `&'a T` or `&'a mut T`).
Ref(&'hir Lifetime, MutTy<'hir>),
/// A bare function (e.g., `fn(usize) -> bool`).
BareFn(&'hir BareFnTy<'hir>),
/// A function pointer (e.g., `fn(usize) -> bool`).
FnPtr(&'hir FnPtrTy<'hir>),
/// An unsafe binder type (e.g. `unsafe<'a> Foo<'a>`).
UnsafeBinder(&'hir UnsafeBinderTy<'hir>),
/// The never type (`!`).
@ -4498,7 +4498,7 @@ pub enum ForeignItemKind<'hir> {
///
/// All argument idents are actually always present (i.e. `Some`), but
/// `&[Option<Ident>]` is used because of code paths shared with `TraitFn`
/// and `BareFnTy`. The sharing is due to all of these cases not allowing
/// and `FnPtrTy`. The sharing is due to all of these cases not allowing
/// arbitrary patterns for parameters.
Fn(FnSig<'hir>, &'hir [Option<Ident>], &'hir Generics<'hir>),
/// A foreign static item (`static ext: u8`).

View file

@ -1001,7 +1001,7 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v, AmbigArg>) -
TyKind::Tup(tuple_element_types) => {
walk_list!(visitor, visit_ty_unambig, tuple_element_types);
}
TyKind::BareFn(ref function_declaration) => {
TyKind::FnPtr(ref function_declaration) => {
walk_list!(visitor, visit_generic_param, function_declaration.generic_params);
try_visit!(visitor.visit_fn_decl(function_declaration.decl));
}

View file

@ -768,15 +768,14 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(),
check_static_inhabited(tcx, def_id);
check_static_linkage(tcx, def_id);
res = res.and(wfcheck::check_static_item(tcx, def_id));
// Only `Node::Item` and `Node::ForeignItem` still have HIR based
// checks. Returning early here does not miss any checks and
// avoids this query from having a direct dependency edge on the HIR
return res;
}
DefKind::Const => {}
DefKind::Const => res = res.and(wfcheck::check_const_item(tcx, def_id)),
_ => unreachable!(),
}
// Only `Node::Item` and `Node::ForeignItem` still have HIR based
// checks. Returning early here does not miss any checks and
// avoids this query from having a direct dependency edge on the HIR
return res;
}
DefKind::Enum => {
tcx.ensure_ok().generics_of(def_id);

View file

@ -290,7 +290,6 @@ pub(super) fn check_item<'tcx>(
res
}
hir::ItemKind::Fn { sig, .. } => check_item_fn(tcx, def_id, sig.decl),
hir::ItemKind::Const(_, _, ty, _) => check_const_item(tcx, def_id, ty.span),
hir::ItemKind::Struct(..) => check_type_defn(tcx, item, false),
hir::ItemKind::Union(..) => check_type_defn(tcx, item, true),
hir::ItemKind::Enum(..) => check_type_defn(tcx, item, true),
@ -1185,7 +1184,8 @@ pub(super) fn check_static_item(
) -> Result<(), ErrorGuaranteed> {
enter_wf_checking_ctxt(tcx, item_id, |wfcx| {
let ty = tcx.type_of(item_id).instantiate_identity();
let item_ty = wfcx.deeply_normalize(DUMMY_SP, Some(WellFormedLoc::Ty(item_id)), ty);
let span = tcx.ty_span(item_id);
let item_ty = wfcx.deeply_normalize(span, Some(WellFormedLoc::Ty(item_id)), ty);
let is_foreign_item = tcx.is_foreign_item(item_id);
@ -1194,7 +1194,7 @@ pub(super) fn check_static_item(
!matches!(tail.kind(), ty::Foreign(_))
};
wfcx.register_wf_obligation(DUMMY_SP, Some(WellFormedLoc::Ty(item_id)), item_ty.into());
wfcx.register_wf_obligation(span, Some(WellFormedLoc::Ty(item_id)), item_ty.into());
if forbid_unsized {
let span = tcx.def_span(item_id);
wfcx.register_bound(
@ -1216,7 +1216,6 @@ pub(super) fn check_static_item(
&& !tcx.is_thread_local_static(item_id.to_def_id());
if should_check_for_sync {
let span = tcx.def_span(item_id);
wfcx.register_bound(
traits::ObligationCause::new(
span,
@ -1232,13 +1231,10 @@ pub(super) fn check_static_item(
})
}
fn check_const_item(
tcx: TyCtxt<'_>,
def_id: LocalDefId,
ty_span: Span,
) -> Result<(), ErrorGuaranteed> {
pub(crate) fn check_const_item(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGuaranteed> {
enter_wf_checking_ctxt(tcx, def_id, |wfcx| {
let ty = tcx.type_of(def_id).instantiate_identity();
let ty_span = tcx.ty_span(def_id);
let ty = wfcx.deeply_normalize(ty_span, Some(WellFormedLoc::Ty(def_id)), ty);
wfcx.register_wf_obligation(ty_span, Some(WellFormedLoc::Ty(def_id)), ty.into());
@ -1505,7 +1501,7 @@ pub(super) fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, def_id:
let cause = traits::ObligationCause::new(
sp,
wfcx.body_def_id,
ObligationCauseCode::WhereClause(def_id.to_def_id(), DUMMY_SP),
ObligationCauseCode::WhereClause(def_id.to_def_id(), sp),
);
Obligation::new(tcx, cause, wfcx.param_env, pred)
});

View file

@ -198,7 +198,7 @@ fn placeholder_type_error_diag<'cx, 'tcx>(
let mut is_const_or_static = false;
if let Some(hir_ty) = hir_ty
&& let hir::TyKind::BareFn(_) = hir_ty.kind
&& let hir::TyKind::FnPtr(_) = hir_ty.kind
{
is_fn = true;

View file

@ -454,7 +454,7 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option<S
type Result = ControlFlow<Span>;
fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx, AmbigArg>) -> ControlFlow<Span> {
match ty.kind {
hir::TyKind::BareFn(..) => {
hir::TyKind::FnPtr(..) => {
self.outer_index.shift_in(1);
let res = intravisit::walk_ty(self, ty);
self.outer_index.shift_out(1);

View file

@ -704,7 +704,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
#[instrument(level = "debug", skip(self))]
fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx, AmbigArg>) {
match ty.kind {
hir::TyKind::BareFn(c) => {
hir::TyKind::FnPtr(c) => {
let (mut bound_vars, binders): (FxIndexMap<LocalDefId, ResolvedArg>, Vec<_>) = c
.generic_params
.iter()
@ -728,8 +728,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
where_bound_origin: None,
};
self.with(scope, |this| {
// a bare fn has no bounds, so everything
// contained within is scoped within its binder.
// a FnPtr has no bounds, so everything within is scoped within its binder
intravisit::walk_ty(this, ty);
});
}
@ -758,8 +757,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
where_bound_origin: None,
};
self.with(scope, |this| {
// a bare fn has no bounds, so everything
// contained within is scoped within its binder.
// everything within is scoped within its binder
intravisit::walk_ty(this, ty);
});
}
@ -1419,7 +1417,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
hir::Node::OpaqueTy(_) => "higher-ranked lifetime from outer `impl Trait`",
// Other items are fine.
hir::Node::Item(_) | hir::Node::TraitItem(_) | hir::Node::ImplItem(_) => return Ok(()),
hir::Node::Ty(hir::Ty { kind: hir::TyKind::BareFn(_), .. }) => {
hir::Node::Ty(hir::Ty { kind: hir::TyKind::FnPtr(_), .. }) => {
"higher-ranked lifetime from function pointer"
}
hir::Node::Ty(hir::Ty { kind: hir::TyKind::TraitObject(..), .. }) => {

View file

@ -393,9 +393,9 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
let params = if let Some(generics) = node.generics() {
generics.params
} else if let hir::Node::Ty(ty) = node
&& let hir::TyKind::BareFn(bare_fn) = ty.kind
&& let hir::TyKind::FnPtr(fn_ptr) = ty.kind
{
bare_fn.generic_params
fn_ptr.generic_params
} else {
&[]
};

View file

@ -21,8 +21,8 @@ pub(crate) fn validate_cmse_abi<'tcx>(
ExternAbi::CmseNonSecureCall => {
let hir_node = tcx.hir_node(hir_id);
let hir::Node::Ty(hir::Ty {
span: bare_fn_span,
kind: hir::TyKind::BareFn(bare_fn_ty),
span: fn_ptr_span,
kind: hir::TyKind::FnPtr(fn_ptr_ty),
..
}) = hir_node
else {
@ -49,18 +49,18 @@ pub(crate) fn validate_cmse_abi<'tcx>(
Ok(Err(index)) => {
// fn(x: u32, u32, u32, u16, y: u16) -> u32,
// ^^^^^^
let span = if let Some(ident) = bare_fn_ty.param_idents[index] {
ident.span.to(bare_fn_ty.decl.inputs[index].span)
let span = if let Some(ident) = fn_ptr_ty.param_idents[index] {
ident.span.to(fn_ptr_ty.decl.inputs[index].span)
} else {
bare_fn_ty.decl.inputs[index].span
fn_ptr_ty.decl.inputs[index].span
}
.to(bare_fn_ty.decl.inputs.last().unwrap().span);
let plural = bare_fn_ty.param_idents.len() - index != 1;
.to(fn_ptr_ty.decl.inputs.last().unwrap().span);
let plural = fn_ptr_ty.param_idents.len() - index != 1;
dcx.emit_err(errors::CmseInputsStackSpill { span, plural, abi });
}
Err(layout_err) => {
if should_emit_generic_error(abi, layout_err) {
dcx.emit_err(errors::CmseCallGeneric { span: *bare_fn_span });
dcx.emit_err(errors::CmseCallGeneric { span: *fn_ptr_span });
}
}
}
@ -68,12 +68,12 @@ pub(crate) fn validate_cmse_abi<'tcx>(
match is_valid_cmse_output(tcx, fn_sig) {
Ok(true) => {}
Ok(false) => {
let span = bare_fn_ty.decl.output.span();
let span = fn_ptr_ty.decl.output.span();
dcx.emit_err(errors::CmseOutputStackSpill { span, abi });
}
Err(layout_err) => {
if should_emit_generic_error(abi, layout_err) {
dcx.emit_err(errors::CmseCallGeneric { span: *bare_fn_span });
dcx.emit_err(errors::CmseCallGeneric { span: *fn_ptr_span });
}
}
};

View file

@ -2402,7 +2402,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
hir::TyKind::Tup(fields) => {
Ty::new_tup_from_iter(tcx, fields.iter().map(|t| self.lower_ty(t)))
}
hir::TyKind::BareFn(bf) => {
hir::TyKind::FnPtr(bf) => {
require_c_abi_if_c_variadic(tcx, bf.decl, bf.abi, hir_ty.span);
Ty::new_fn_ptr(
@ -2660,28 +2660,28 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
debug!(?output_ty);
let fn_ty = tcx.mk_fn_sig(input_tys, output_ty, decl.c_variadic, safety, abi);
let bare_fn_ty = ty::Binder::bind_with_vars(fn_ty, bound_vars);
let fn_ptr_ty = ty::Binder::bind_with_vars(fn_ty, bound_vars);
if let hir::Node::Ty(hir::Ty { kind: hir::TyKind::BareFn(bare_fn_ty), span, .. }) =
if let hir::Node::Ty(hir::Ty { kind: hir::TyKind::FnPtr(fn_ptr_ty), span, .. }) =
tcx.hir_node(hir_id)
{
check_abi(tcx, hir_id, *span, bare_fn_ty.abi);
check_abi(tcx, hir_id, *span, fn_ptr_ty.abi);
}
// reject function types that violate cmse ABI requirements
cmse::validate_cmse_abi(self.tcx(), self.dcx(), hir_id, abi, bare_fn_ty);
cmse::validate_cmse_abi(self.tcx(), self.dcx(), hir_id, abi, fn_ptr_ty);
if !bare_fn_ty.references_error() {
if !fn_ptr_ty.references_error() {
// Find any late-bound regions declared in return type that do
// not appear in the arguments. These are not well-formed.
//
// Example:
// for<'a> fn() -> &'a str <-- 'a is bad
// for<'a> fn(&'a String) -> &'a str <-- 'a is ok
let inputs = bare_fn_ty.inputs();
let inputs = fn_ptr_ty.inputs();
let late_bound_in_args =
tcx.collect_constrained_late_bound_regions(inputs.map_bound(|i| i.to_owned()));
let output = bare_fn_ty.output();
let output = fn_ptr_ty.output();
let late_bound_in_ret = tcx.collect_referenced_late_bound_regions(output);
self.validate_late_bound_regions(late_bound_in_args, late_bound_in_ret, |br_name| {
@ -2695,7 +2695,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
});
}
bare_fn_ty
fn_ptr_ty
}
/// Given a fn_hir_id for a impl function, suggest the type that is found on the

View file

@ -405,7 +405,7 @@ impl<'a> State<'a> {
}
self.pclose();
}
hir::TyKind::BareFn(f) => {
hir::TyKind::FnPtr(f) => {
self.print_ty_fn(f.abi, f.safety, f.decl, None, f.generic_params, f.param_idents);
}
hir::TyKind::UnsafeBinder(unsafe_binder) => {

View file

@ -82,13 +82,6 @@ hir_typeck_cast_unknown_pointer = cannot cast {$to ->
hir_typeck_const_continue_bad_label =
`#[const_continue]` must break to a labeled block that participates in a `#[loop_match]`
hir_typeck_const_select_must_be_const = this argument must be a `const fn`
.help = consult the documentation on `const_eval_select` for more information
hir_typeck_const_select_must_be_fn = this argument must be a function item
.note = expected a function item, found {$ty}
.help = consult the documentation on `const_eval_select` for more information
hir_typeck_continue_labeled_block =
`continue` pointing to a labeled block
.label = labeled blocks cannot be `continue`'d

View file

@ -203,7 +203,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let adjusted_ty =
self.structurally_resolve_type(autoderef.span(), autoderef.final_ty(false));
// If the callee is a bare function or a closure, then we're all set.
// If the callee is a function pointer or a closure, then we're all set.
match *adjusted_ty.kind() {
ty::FnDef(..) | ty::FnPtr(..) => {
let adjustments = self.adjust_steps(autoderef);
@ -578,29 +578,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
if let Some(def_id) = def_id
&& self.tcx.def_kind(def_id) == hir::def::DefKind::Fn
&& self.tcx.is_intrinsic(def_id, sym::const_eval_select)
{
let fn_sig = self.resolve_vars_if_possible(fn_sig);
for idx in 0..=1 {
let arg_ty = fn_sig.inputs()[idx + 1];
let span = arg_exprs.get(idx + 1).map_or(call_expr.span, |arg| arg.span);
// Check that second and third argument of `const_eval_select` must be `FnDef`, and additionally that
// the second argument must be `const fn`. The first argument must be a tuple, but this is already expressed
// in the function signature (`F: FnOnce<ARG>`), so I did not bother to add another check here.
//
// This check is here because there is currently no way to express a trait bound for `FnDef` types only.
if let ty::FnDef(def_id, _args) = *arg_ty.kind() {
if idx == 0 && !self.tcx.is_const_fn(def_id) {
self.dcx().emit_err(errors::ConstSelectMustBeConst { span });
}
} else {
self.dcx().emit_err(errors::ConstSelectMustBeFn { span, ty: arg_ty });
}
}
}
fn_sig.output()
}

View file

@ -605,24 +605,6 @@ impl Subdiagnostic for RemoveSemiForCoerce {
}
}
#[derive(Diagnostic)]
#[diag(hir_typeck_const_select_must_be_const)]
#[help]
pub(crate) struct ConstSelectMustBeConst {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(hir_typeck_const_select_must_be_fn)]
#[note]
#[help]
pub(crate) struct ConstSelectMustBeFn<'a> {
#[primary_span]
pub span: Span,
pub ty: Ty<'a>,
}
#[derive(Diagnostic)]
#[diag(hir_typeck_union_pat_multiple_fields)]
pub(crate) struct UnionPatMultipleFields {

View file

@ -184,9 +184,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return true;
}
for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
.into_iter()
.flatten()
for param in [
predicate_self_type_to_point_at,
param_to_point_at,
fallback_param_to_point_at,
self_param_to_point_at,
]
.into_iter()
.flatten()
{
if self.blame_specific_arg_if_possible(
error,

View file

@ -529,7 +529,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// process any deferred resolutions.
let deferred_call_resolutions = self.remove_deferred_call_resolutions(closure_def_id);
for deferred_call_resolution in deferred_call_resolutions {
deferred_call_resolution.resolve(self);
deferred_call_resolution.resolve(&mut FnCtxt::new(
self,
self.param_env,
closure_def_id,
));
}
}

View file

@ -14,9 +14,7 @@
// tidy-alphabetical-start
#![allow(internal_features)]
#![allow(rustc::diagnostic_outside_of_impl)]
#![allow(rustc::direct_use_of_rustc_type_ir)]
#![allow(rustc::untranslatable_diagnostic)]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![doc(rust_logo)]
#![feature(assert_matches)]

View file

@ -1,6 +1,3 @@
#![allow(rustc::diagnostic_outside_of_impl)]
#![allow(rustc::untranslatable_diagnostic)]
use std::borrow::Cow;
use rustc_ast::util::unicode::TEXT_FLOW_CONTROL_CHARS;

View file

@ -1,4 +1,3 @@
#![allow(rustc::diagnostic_outside_of_impl)]
#![allow(rustc::untranslatable_diagnostic)]
use std::num::NonZero;

View file

@ -431,7 +431,7 @@ impl<'tcx> LateLintPass<'tcx> for NonSnakeCase {
}
fn check_ty(&mut self, cx: &LateContext<'_>, ty: &hir::Ty<'_, hir::AmbigArg>) {
if let hir::TyKind::BareFn(hir::BareFnTy { param_idents, .. }) = &ty.kind {
if let hir::TyKind::FnPtr(hir::FnPtrTy { param_idents, .. }) = &ty.kind {
for param_ident in *param_idents {
if let Some(param_ident) = param_ident {
self.check_snake_case(cx, "variable", param_ident);

View file

@ -1577,7 +1577,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
impl<'tcx> hir::intravisit::Visitor<'_> for FnPtrFinder<'tcx> {
fn visit_ty(&mut self, ty: &'_ hir::Ty<'_, AmbigArg>) {
debug!(?ty);
if let hir::TyKind::BareFn(hir::BareFnTy { abi, .. }) = ty.kind
if let hir::TyKind::FnPtr(hir::FnPtrTy { abi, .. }) = ty.kind
&& !abi.is_rustic_abi()
{
self.spans.push(ty.span);

View file

@ -1312,7 +1312,7 @@ impl EarlyLintPass for UnusedParens {
None => true,
}
}
ast::TyKind::BareFn(b) => {
ast::TyKind::FnPtr(b) => {
!self.with_self_ty_parens || b.generic_params.is_empty()
}
_ => true,

View file

@ -1275,7 +1275,7 @@ extern "C" void LLVMRustSetModuleCodeModel(LLVMModuleRef M,
//
// Otherwise I'll apologize in advance, it probably requires a relatively
// significant investment on your part to "truly understand" what's going on
// here. Not saying I do myself, but it took me awhile staring at LLVM's source
// here. Not saying I do myself, but it took me a while staring at LLVM's source
// and various online resources about ThinLTO to make heads or tails of all
// this.

View file

@ -1,5 +1,3 @@
#![allow(rustc::usage_of_ty_tykind)]
/// This higher-order macro declares a list of types which can be allocated by `Arena`.
///
/// Specifying the `decode` modifier will add decode impls for `&T` and `&[T]` where `T` is the type

View file

@ -239,8 +239,16 @@ pub fn provide(providers: &mut Providers) {
let hir_id = tcx.local_def_id_to_hir_id(def_id);
tcx.hir_opt_ident_span(hir_id)
};
providers.ty_span = |tcx, def_id| {
let node = tcx.hir_node_by_def_id(def_id);
match node.ty() {
Some(ty) => ty.span,
None => bug!("{def_id:?} doesn't have a type: {node:#?}"),
}
};
providers.fn_arg_idents = |tcx, def_id| {
if let Some(body_id) = tcx.hir_node_by_def_id(def_id).body_id() {
let node = tcx.hir_node_by_def_id(def_id);
if let Some(body_id) = node.body_id() {
tcx.arena.alloc_from_iter(tcx.hir_body_param_idents(body_id))
} else if let Node::TraitItem(&TraitItem {
kind: TraitItemKind::Fn(_, TraitFn::Required(idents)),
@ -249,7 +257,7 @@ pub fn provide(providers: &mut Providers) {
| Node::ForeignItem(&ForeignItem {
kind: ForeignItemKind::Fn(_, idents, _),
..
}) = tcx.hir_node(tcx.local_def_id_to_hir_id(def_id))
}) = node
{
idents
} else {

View file

@ -142,7 +142,7 @@ impl<'tcx> ConstValue<'tcx> {
// The reference itself is stored behind an indirection.
// Load the reference, and then load the actual slice contents.
let a = tcx.global_alloc(alloc_id).unwrap_memory().inner();
let ptr_size = tcx.data_layout.pointer_size;
let ptr_size = tcx.data_layout.pointer_size();
if a.size() < offset + 2 * ptr_size {
// (partially) dangling reference
return None;

View file

@ -519,7 +519,7 @@ impl Allocation {
let mut bytes = alloc_bytes(&*self.bytes, self.align)?;
// Adjust provenance of pointers stored in this allocation.
let mut new_provenance = Vec::with_capacity(self.provenance.ptrs().len());
let ptr_size = cx.data_layout().pointer_size.bytes_usize();
let ptr_size = cx.data_layout().pointer_size().bytes_usize();
let endian = cx.data_layout().endian;
for &(offset, alloc_id) in self.provenance.ptrs().iter() {
let idx = offset.bytes_usize();
@ -709,7 +709,7 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
let bits = read_target_uint(cx.data_layout().endian, bytes).unwrap();
if read_provenance {
assert_eq!(range.size, cx.data_layout().pointer_size);
assert_eq!(range.size, cx.data_layout().pointer_size());
// When reading data with provenance, the easy case is finding provenance exactly where we
// are reading, then we can put data and provenance back together and return that.
@ -782,7 +782,7 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
// See if we have to also store some provenance.
if let Some(provenance) = provenance {
assert_eq!(range.size, cx.data_layout().pointer_size);
assert_eq!(range.size, cx.data_layout().pointer_size());
self.provenance.insert_ptr(range.start, provenance, cx);
}

View file

@ -71,7 +71,7 @@ impl<Prov: Provenance> ProvenanceMap<Prov> {
// We have to go back `pointer_size - 1` bytes, as that one would still overlap with
// the beginning of this range.
let adjusted_start = Size::from_bytes(
range.start.bytes().saturating_sub(cx.data_layout().pointer_size.bytes() - 1),
range.start.bytes().saturating_sub(cx.data_layout().pointer_size().bytes() - 1),
);
adjusted_start..range.end()
}
@ -142,7 +142,7 @@ impl<Prov: Provenance> ProvenanceMap<Prov> {
}
pub fn insert_ptr(&mut self, offset: Size, prov: Prov, cx: &impl HasDataLayout) {
debug_assert!(self.range_empty(alloc_range(offset, cx.data_layout().pointer_size), cx));
debug_assert!(self.range_empty(alloc_range(offset, cx.data_layout().pointer_size()), cx));
self.ptrs.insert(offset, prov);
}
@ -160,6 +160,8 @@ impl<Prov: Provenance> ProvenanceMap<Prov> {
debug_assert!(self.bytes.is_none());
}
let pointer_size = cx.data_layout().pointer_size();
// For the ptr-sized part, find the first (inclusive) and last (exclusive) byte of
// provenance that overlaps with the given range.
let (first, last) = {
@ -172,10 +174,7 @@ impl<Prov: Provenance> ProvenanceMap<Prov> {
// This redoes some of the work of `range_get_ptrs_is_empty`, but this path is much
// colder than the early return above, so it's worth it.
let provenance = self.range_ptrs_get(range, cx);
(
provenance.first().unwrap().0,
provenance.last().unwrap().0 + cx.data_layout().pointer_size,
)
(provenance.first().unwrap().0, provenance.last().unwrap().0 + pointer_size)
};
// We need to handle clearing the provenance from parts of a pointer.
@ -192,7 +191,7 @@ impl<Prov: Provenance> ProvenanceMap<Prov> {
}
}
if last > end {
let begin_of_last = last - cx.data_layout().pointer_size;
let begin_of_last = last - pointer_size;
if !Prov::OFFSET_IS_ADDR {
// We can't split up the provenance into less than a pointer.
return Err(AllocError::OverwritePartialPointer(begin_of_last));
@ -255,7 +254,7 @@ impl<Prov: Provenance> ProvenanceMap<Prov> {
// shift offsets from source allocation to destination allocation
(offset - src.start) + dest_offset // `Size` operations
};
let ptr_size = cx.data_layout().pointer_size;
let ptr_size = cx.data_layout().pointer_size();
// # Pointer-sized provenances
// Get the provenances that are entirely within this range.

View file

@ -297,7 +297,7 @@ impl<'tcx> GlobalAlloc<'tcx> {
match self {
GlobalAlloc::Function { .. } => cx.data_layout().instruction_address_space,
GlobalAlloc::Static(..) | GlobalAlloc::Memory(..) | GlobalAlloc::VTable(..) => {
AddressSpace::DATA
AddressSpace::ZERO
}
}
}
@ -380,7 +380,7 @@ impl<'tcx> GlobalAlloc<'tcx> {
GlobalAlloc::Function { .. } => (Size::ZERO, Align::ONE),
GlobalAlloc::VTable(..) => {
// No data to be accessed here. But vtables are pointer-aligned.
return (Size::ZERO, tcx.data_layout.pointer_align.abi);
return (Size::ZERO, tcx.data_layout.pointer_align().abi);
}
}
}

View file

@ -16,7 +16,7 @@ pub trait PointerArithmetic: HasDataLayout {
#[inline(always)]
fn pointer_size(&self) -> Size {
self.data_layout().pointer_size
self.data_layout().pointer_size()
}
#[inline(always)]

View file

@ -167,7 +167,7 @@ impl<Prov> Scalar<Prov> {
#[inline]
pub fn from_target_usize(i: u64, cx: &impl HasDataLayout) -> Self {
Self::from_uint(i, cx.data_layout().pointer_size)
Self::from_uint(i, cx.data_layout().pointer_offset())
}
#[inline]
@ -205,7 +205,7 @@ impl<Prov> Scalar<Prov> {
#[inline]
pub fn from_target_isize(i: i64, cx: &impl HasDataLayout) -> Self {
Self::from_int(i, cx.data_layout().pointer_size)
Self::from_int(i, cx.data_layout().pointer_offset())
}
#[inline]
@ -393,7 +393,7 @@ impl<'tcx, Prov: Provenance> Scalar<Prov> {
/// Converts the scalar to produce a machine-pointer-sized unsigned integer.
/// Fails if the scalar is a pointer.
pub fn to_target_usize(self, cx: &impl HasDataLayout) -> InterpResult<'tcx, u64> {
let b = self.to_uint(cx.data_layout().pointer_size)?;
let b = self.to_uint(cx.data_layout().pointer_size())?;
interp_ok(u64::try_from(b).unwrap())
}
@ -433,7 +433,7 @@ impl<'tcx, Prov: Provenance> Scalar<Prov> {
/// Converts the scalar to produce a machine-pointer-sized signed integer.
/// Fails if the scalar is a pointer.
pub fn to_target_isize(self, cx: &impl HasDataLayout) -> InterpResult<'tcx, i64> {
let b = self.to_int(cx.data_layout().pointer_size)?;
let b = self.to_int(cx.data_layout().pointer_size())?;
interp_ok(i64::try_from(b).unwrap())
}

View file

@ -1753,7 +1753,7 @@ pub fn write_allocation_bytes<'tcx, Prov: Provenance, Extra, Bytes: AllocBytes>(
let mut i = Size::ZERO;
let mut line_start = Size::ZERO;
let ptr_size = tcx.data_layout.pointer_size;
let ptr_size = tcx.data_layout.pointer_size();
let mut ascii = String::new();

View file

@ -1452,6 +1452,13 @@ rustc_queries! {
feedable
}
/// Gets the span for the type of the definition.
/// Panics if it is not a definition that has a single type.
query ty_span(def_id: LocalDefId) -> Span {
desc { |tcx| "looking up span for `{}`'s type", tcx.def_path_str(def_id) }
cache_on_disk_if { true }
}
query lookup_stability(def_id: DefId) -> Option<attr::Stability> {
desc { |tcx| "looking up stability of `{}`", tcx.def_path_str(def_id) }
cache_on_disk_if { def_id.is_local() }

View file

@ -97,9 +97,7 @@ pub type EvaluationCache<'tcx, ENV> = Cache<(ENV, ty::PolyTraitPredicate<'tcx>),
pub enum SelectionCandidate<'tcx> {
/// A built-in implementation for the `Sized` trait. This is preferred
/// over all other candidates.
SizedCandidate {
has_nested: bool,
},
SizedCandidate,
/// A builtin implementation for some specific traits, used in cases
/// where we cannot rely an ordinary library implementations.
@ -107,10 +105,7 @@ pub enum SelectionCandidate<'tcx> {
/// The most notable examples are `Copy` and `Clone`. This is also
/// used for the `DiscriminantKind` and `Pointee` trait, both of which have
/// an associated type.
BuiltinCandidate {
/// `false` if there are no *further* obligations.
has_nested: bool,
},
BuiltinCandidate,
/// Implementation of transmutability trait.
TransmutabilityCandidate,

View file

@ -252,7 +252,7 @@ impl ScalarInt {
#[inline]
pub fn try_from_target_usize(i: impl Into<u128>, tcx: TyCtxt<'_>) -> Option<Self> {
Self::try_from_uint(i, tcx.data_layout.pointer_size)
Self::try_from_uint(i, tcx.data_layout.pointer_size())
}
/// Try to convert this ScalarInt to the raw underlying bits.
@ -328,7 +328,7 @@ impl ScalarInt {
#[inline]
pub fn to_target_usize(&self, tcx: TyCtxt<'_>) -> u64 {
self.to_uint(tcx.data_layout.pointer_size).try_into().unwrap()
self.to_uint(tcx.data_layout.pointer_size()).try_into().unwrap()
}
#[inline]
@ -402,7 +402,7 @@ impl ScalarInt {
#[inline]
pub fn to_target_isize(&self, tcx: TyCtxt<'_>) -> i64 {
self.to_int(tcx.data_layout.pointer_size).try_into().unwrap()
self.to_int(tcx.data_layout.pointer_size()).try_into().unwrap()
}
#[inline]

View file

@ -1067,7 +1067,7 @@ where
if let Some(variant) = data_variant {
// FIXME(erikdesjardins): handle non-default addrspace ptr sizes
// (requires passing in the expected address space from the caller)
let ptr_end = offset + Primitive::Pointer(AddressSpace::DATA).size(cx);
let ptr_end = offset + Primitive::Pointer(AddressSpace::ZERO).size(cx);
for i in 0..variant.fields.count() {
let field_start = variant.fields.offset(i);
if field_start <= offset {

View file

@ -1842,7 +1842,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
}
// Pointer types
ty::Ref(..) | ty::RawPtr(_, _) | ty::FnPtr(..) => {
let data = int.to_bits(self.tcx().data_layout.pointer_size);
let data = int.to_bits(self.tcx().data_layout.pointer_size());
self.typed_value(
|this| {
write!(this, "0x{data:x}")?;

View file

@ -106,8 +106,8 @@ pub(super) fn vtable_allocation_provider<'tcx>(
let size = layout.size.bytes();
let align = layout.align.abi.bytes();
let ptr_size = tcx.data_layout.pointer_size;
let ptr_align = tcx.data_layout.pointer_align.abi;
let ptr_size = tcx.data_layout.pointer_size();
let ptr_align = tcx.data_layout.pointer_align().abi;
let vtable_size = ptr_size * u64::try_from(vtable_entries.len()).unwrap();
let mut vtable = Allocation::new(vtable_size, ptr_align, AllocInit::Uninit, ());

View file

@ -936,7 +936,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
valtree
}
Err(ErrorHandled::Reported(..)) => return self.cfg.start_new_block().unit(),
Err(ErrorHandled::Reported(..)) => {
return block.unit();
}
Err(ErrorHandled::TooGeneric(_)) => {
self.tcx.dcx().emit_fatal(ConstContinueBadConst { span: constant.span });
}

View file

@ -20,7 +20,7 @@ pub(crate) fn lit_to_const<'tcx>(
let trunc = |n, width: ty::UintTy| {
let width = width
.normalize(tcx.data_layout.pointer_size.bits().try_into().unwrap())
.normalize(tcx.data_layout.pointer_size().bits().try_into().unwrap())
.bit_width()
.unwrap();
let width = Size::from_bits(width);

View file

@ -155,15 +155,8 @@ pub(crate) fn mir_callgraph_cyclic<'tcx>(
let recursion_limit = tcx.recursion_limit() / 2;
let mut involved = FxHashSet::default();
let typing_env = ty::TypingEnv::post_analysis(tcx, root);
let Ok(Some(root_instance)) = ty::Instance::try_resolve(
tcx,
typing_env,
root.to_def_id(),
ty::GenericArgs::identity_for_item(tcx, root.to_def_id()),
) else {
trace!("cannot resolve, skipping");
return involved.into();
};
let root_instance =
ty::Instance::new_raw(root.to_def_id(), ty::GenericArgs::identity_for_item(tcx, root));
if !should_recurse(tcx, root_instance) {
trace!("cannot walk, skipping");
return involved.into();

Some files were not shown because too many files have changed in this diff Show more