Auto merge of #3489 - rust-lang:rustup-2024-04-19, r=RalfJung

Automatic Rustup
This commit is contained in:
bors 2024-04-19 09:00:46 +00:00
commit 95ae2dd7ff
342 changed files with 3253 additions and 2433 deletions

View file

@ -6332,9 +6332,9 @@ dependencies = [
[[package]]
name = "windows-bindgen"
version = "0.55.0"
version = "0.56.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "073ff8a486ebad239d557809d2cd5fe5e04ee1de29e09c6cd83fb0bae19b8a4c"
checksum = "a28e3ea6330cf17fdcdce8bf08d0549ce93769dca9bedc6c39c36c8c0e17db46"
dependencies = [
"proc-macro2",
"rayon",
@ -6355,9 +6355,9 @@ dependencies = [
[[package]]
name = "windows-metadata"
version = "0.55.0"
version = "0.56.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b602635050172a1fc57a35040d4d225baefc6098fefd97094919921d95961a7d"
checksum = "3993f7827fff10c454e3a24847075598c7c08108304b8b07943c2c73d78f3b34"
[[package]]
name = "windows-sys"

View file

@ -568,7 +568,7 @@ impl Pat {
// In a type expression `_` is an inference variable.
PatKind::Wild => TyKind::Infer,
// An IDENT pattern with no binding mode would be valid as path to a type. E.g. `u32`.
PatKind::Ident(BindingAnnotation::NONE, ident, None) => {
PatKind::Ident(BindingMode::NONE, ident, None) => {
TyKind::Path(None, Path::from_ident(*ident))
}
PatKind::Path(qself, path) => TyKind::Path(qself.clone(), path.clone()),
@ -675,7 +675,7 @@ impl Pat {
pub fn descr(&self) -> Option<String> {
match &self.kind {
PatKind::Wild => Some("_".to_string()),
PatKind::Ident(BindingAnnotation::NONE, ident, None) => Some(format!("{ident}")),
PatKind::Ident(BindingMode::NONE, ident, None) => Some(format!("{ident}")),
PatKind::Ref(pat, mutbl) => pat.descr().map(|d| format!("&{}{d}", mutbl.prefix_str())),
_ => None,
}
@ -707,14 +707,25 @@ pub enum ByRef {
No,
}
/// Explicit binding annotations given in the HIR for a binding. Note
/// that this is not the final binding *mode* that we infer after type
/// inference.
impl ByRef {
pub fn cap_ref_mutability(mut self, mutbl: Mutability) -> Self {
if let ByRef::Yes(old_mutbl) = &mut self {
*old_mutbl = cmp::min(*old_mutbl, mutbl);
}
self
}
}
/// The mode of a binding (`mut`, `ref mut`, etc).
/// Used for both the explicit binding annotations given in the HIR for a binding
/// and the final binding mode that we infer after type inference/match ergonomics.
/// `.0` is the by-reference mode (`ref`, `ref mut`, or by value),
/// `.1` is the mutability of the binding.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[derive(Encodable, Decodable, HashStable_Generic)]
pub struct BindingAnnotation(pub ByRef, pub Mutability);
pub struct BindingMode(pub ByRef, pub Mutability);
impl BindingAnnotation {
impl BindingMode {
pub const NONE: Self = Self(ByRef::No, Mutability::Not);
pub const REF: Self = Self(ByRef::Yes(Mutability::Not), Mutability::Not);
pub const MUT: Self = Self(ByRef::No, Mutability::Mut);
@ -732,13 +743,6 @@ impl BindingAnnotation {
Self::MUT_REF_MUT => "mut ref mut ",
}
}
pub fn cap_ref_mutability(mut self, mutbl: Mutability) -> Self {
if let ByRef::Yes(old_mutbl) = &mut self.0 {
*old_mutbl = cmp::min(*old_mutbl, mutbl);
}
self
}
}
#[derive(Clone, Encodable, Decodable, Debug)]
@ -769,7 +773,7 @@ pub enum PatKind {
/// or a unit struct/variant pattern, or a const pattern (in the last two cases the third
/// field must be `None`). Disambiguation cannot be done with parser alone, so it happens
/// during name resolution.
Ident(BindingAnnotation, Ident, Option<P<Pat>>),
Ident(BindingMode, Ident, Option<P<Pat>>),
/// A struct or struct variant pattern (e.g., `Variant {x, y, ..}`).
Struct(Option<P<QSelf>>, Path, ThinVec<PatField>, PatFieldsRest),
@ -2382,7 +2386,7 @@ pub type ExplicitSelf = Spanned<SelfKind>;
impl Param {
/// Attempts to cast parameter to `ExplicitSelf`.
pub fn to_self(&self) -> Option<ExplicitSelf> {
if let PatKind::Ident(BindingAnnotation(ByRef::No, mutbl), ident, _) = self.pat.kind {
if let PatKind::Ident(BindingMode(ByRef::No, mutbl), ident, _) = self.pat.kind {
if ident.name == kw::SelfLower {
return match self.ty.kind {
TyKind::ImplicitSelf => Some(respan(self.pat.span, SelfKind::Value(mutbl))),
@ -2434,7 +2438,7 @@ impl Param {
attrs,
pat: P(Pat {
id: DUMMY_NODE_ID,
kind: PatKind::Ident(BindingAnnotation(ByRef::No, mutbl), eself_ident, None),
kind: PatKind::Ident(BindingMode(ByRef::No, mutbl), eself_ident, None),
span,
tokens: None,
}),
@ -3363,7 +3367,7 @@ impl TryFrom<ItemKind> for ForeignItemKind {
pub type ForeignItem = Item<ForeignItemKind>;
// Some nodes are used a lot. Make sure they don't unintentionally get bigger.
#[cfg(all(any(target_arch = "x86_64", target_arch = "aarch64"), target_pointer_width = "64"))]
#[cfg(target_pointer_width = "64")]
mod size_asserts {
use super::*;
use rustc_data_structures::static_assert_size;

View file

@ -1023,7 +1023,7 @@ where
}
// Some types are used a lot. Make sure they don't unintentionally get bigger.
#[cfg(all(any(target_arch = "x86_64", target_arch = "aarch64"), target_pointer_width = "64"))]
#[cfg(target_pointer_width = "64")]
mod size_asserts {
use super::*;
use rustc_data_structures::static_assert_size;

View file

@ -768,7 +768,7 @@ impl DelimSpacing {
}
// Some types are used a lot. Make sure they don't unintentionally get bigger.
#[cfg(all(any(target_arch = "x86_64", target_arch = "aarch64"), target_pointer_width = "64"))]
#[cfg(target_pointer_width = "64")]
mod size_asserts {
use super::*;
use rustc_data_structures::static_assert_size;

View file

@ -178,7 +178,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let pat_id = self.lower_node_id(pat_node_id);
let pat = self.arena.alloc(hir::Pat {
hir_id: pat_id,
kind: hir::PatKind::Binding(hir::BindingAnnotation::NONE, pat_id, Ident::empty(), None),
kind: hir::PatKind::Binding(hir::BindingMode::NONE, pat_id, Ident::empty(), None),
span: ty.span,
default_binding_modes: false,
});

View file

@ -643,7 +643,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let (pat, task_context_hid) = self.pat_ident_binding_mode(
span,
Ident::with_dummy_span(sym::_task_context),
hir::BindingAnnotation::MUT,
hir::BindingMode::MUT,
);
let param = hir::Param {
hir_id: self.next_id(),
@ -805,11 +805,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
// debuggers and debugger extensions expect it to be called `__awaitee`. They use
// this name to identify what is being awaited by a suspended async functions.
let awaitee_ident = Ident::with_dummy_span(sym::__awaitee);
let (awaitee_pat, awaitee_pat_hid) = self.pat_ident_binding_mode(
gen_future_span,
awaitee_ident,
hir::BindingAnnotation::MUT,
);
let (awaitee_pat, awaitee_pat_hid) =
self.pat_ident_binding_mode(gen_future_span, awaitee_ident, hir::BindingMode::MUT);
let task_context_ident = Ident::with_dummy_span(sym::_task_context);
@ -1648,7 +1645,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
// `mut iter`
let iter = Ident::with_dummy_span(sym::iter);
let (iter_pat, iter_pat_nid) =
self.pat_ident_binding_mode(head_span, iter, hir::BindingAnnotation::MUT);
self.pat_ident_binding_mode(head_span, iter, hir::BindingMode::MUT);
let match_expr = {
let iter = self.expr_ident(head_span, iter, iter_pat_nid);

View file

@ -1179,9 +1179,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
// Check if this is a binding pattern, if so, we can optimize and avoid adding a
// `let <pat> = __argN;` statement. In this case, we do not rename the parameter.
let (ident, is_simple_parameter) = match parameter.pat.kind {
hir::PatKind::Binding(hir::BindingAnnotation(ByRef::No, _), _, ident, _) => {
(ident, true)
}
hir::PatKind::Binding(hir::BindingMode(ByRef::No, _), _, ident, _) => (ident, true),
// For `ref mut` or wildcard arguments, we can't reuse the binding, but
// we can keep the same name for the parameter.
// This lets rustdoc render it correctly in documentation.
@ -1244,7 +1242,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
// because the user may have specified a `ref mut` binding in the next
// statement.
let (move_pat, move_id) =
self.pat_ident_binding_mode(desugared_span, ident, hir::BindingAnnotation::MUT);
self.pat_ident_binding_mode(desugared_span, ident, hir::BindingMode::MUT);
let move_expr = self.expr_ident(desugared_span, ident, new_parameter_id);
let move_stmt = self.stmt_let_pat(
None,

View file

@ -1895,7 +1895,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
implicit_self: decl.inputs.get(0).map_or(hir::ImplicitSelfKind::None, |arg| {
let is_mutable_pat = matches!(
arg.pat.kind,
PatKind::Ident(hir::BindingAnnotation(_, Mutability::Mut), ..)
PatKind::Ident(hir::BindingMode(_, Mutability::Mut), ..)
);
match &arg.ty.kind {
@ -2478,18 +2478,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}
fn pat_ident(&mut self, span: Span, ident: Ident) -> (&'hir hir::Pat<'hir>, HirId) {
self.pat_ident_binding_mode(span, ident, hir::BindingAnnotation::NONE)
self.pat_ident_binding_mode(span, ident, hir::BindingMode::NONE)
}
fn pat_ident_mut(&mut self, span: Span, ident: Ident) -> (hir::Pat<'hir>, HirId) {
self.pat_ident_binding_mode_mut(span, ident, hir::BindingAnnotation::NONE)
self.pat_ident_binding_mode_mut(span, ident, hir::BindingMode::NONE)
}
fn pat_ident_binding_mode(
&mut self,
span: Span,
ident: Ident,
bm: hir::BindingAnnotation,
bm: hir::BindingMode,
) -> (&'hir hir::Pat<'hir>, HirId) {
let (pat, hir_id) = self.pat_ident_binding_mode_mut(span, ident, bm);
(self.arena.alloc(pat), hir_id)
@ -2499,7 +2499,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
&mut self,
span: Span,
ident: Ident,
bm: hir::BindingAnnotation,
bm: hir::BindingMode,
) -> (hir::Pat<'hir>, HirId) {
let hir_id = self.next_id();

View file

@ -243,7 +243,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
fn lower_pat_ident(
&mut self,
p: &Pat,
annotation: BindingAnnotation,
annotation: BindingMode,
ident: Ident,
lower_sub: impl FnOnce(&mut Self) -> Option<&'hir hir::Pat<'hir>>,
) -> hir::PatKind<'hir> {

View file

@ -276,8 +276,8 @@ impl<'a> AstValidator<'a> {
fn check_decl_no_pat(decl: &FnDecl, mut report_err: impl FnMut(Span, Option<Ident>, bool)) {
for Param { pat, .. } in &decl.inputs {
match pat.kind {
PatKind::Ident(BindingAnnotation::NONE, _, None) | PatKind::Wild => {}
PatKind::Ident(BindingAnnotation::MUT, ident, None) => {
PatKind::Ident(BindingMode::NONE, _, None) | PatKind::Wild => {}
PatKind::Ident(BindingMode::MUT, ident, None) => {
report_err(pat.span, Some(ident), true)
}
_ => report_err(pat.span, None, false),

View file

@ -17,7 +17,7 @@ use rustc_ast::util::classify;
use rustc_ast::util::comments::{Comment, CommentStyle};
use rustc_ast::util::parser;
use rustc_ast::{self as ast, AttrArgs, AttrArgsEq, BlockCheckMode, PatKind};
use rustc_ast::{attr, BindingAnnotation, ByRef, DelimArgs, RangeEnd, RangeSyntax, Term};
use rustc_ast::{attr, BindingMode, ByRef, DelimArgs, RangeEnd, RangeSyntax, Term};
use rustc_ast::{GenericArg, GenericBound, SelfKind};
use rustc_ast::{InlineAsmOperand, InlineAsmRegOrRegClass};
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
@ -1558,7 +1558,7 @@ impl<'a> State<'a> {
match &pat.kind {
PatKind::Wild => self.word("_"),
PatKind::Never => self.word("!"),
PatKind::Ident(BindingAnnotation(by_ref, mutbl), ident, sub) => {
PatKind::Ident(BindingMode(by_ref, mutbl), ident, sub) => {
if mutbl.is_mut() {
self.word_nbsp("mut");
}
@ -1654,7 +1654,7 @@ impl<'a> State<'a> {
if mutbl.is_mut() {
self.word("mut ");
}
if let PatKind::Ident(ast::BindingAnnotation::MUT, ..) = inner.kind {
if let PatKind::Ident(ast::BindingMode::MUT, ..) = inner.kind {
self.popen();
self.print_pat(inner);
self.pclose();

View file

@ -377,7 +377,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
if p.span == self.expr_span {
self.pat = Some(p);
}
if let hir::PatKind::Binding(hir::BindingAnnotation::NONE, _, i, sub) = p.kind {
if let hir::PatKind::Binding(hir::BindingMode::NONE, _, i, sub) = p.kind {
if i.span == self.expr_span || p.span == self.expr_span {
self.pat = Some(p);
}

View file

@ -5,7 +5,7 @@ use core::ops::ControlFlow;
use hir::{ExprKind, Param};
use rustc_errors::{Applicability, Diag};
use rustc_hir::intravisit::Visitor;
use rustc_hir::{self as hir, BindingAnnotation, ByRef, Node};
use rustc_hir::{self as hir, BindingMode, ByRef, Node};
use rustc_infer::traits;
use rustc_middle::mir::{Mutability, Place, PlaceRef, ProjectionElem};
use rustc_middle::ty::{self, InstanceDef, ToPredicate, Ty, TyCtxt};
@ -303,7 +303,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
{
match *decl.local_info() {
LocalInfo::User(BindingForm::Var(mir::VarBindingForm {
binding_mode: BindingAnnotation(ByRef::No, Mutability::Not),
binding_mode: BindingMode(ByRef::No, Mutability::Not),
opt_ty_info: Some(sp),
opt_match_place: _,
pat_span: _,
@ -398,7 +398,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
let upvar_hir_id = captured_place.get_root_variable();
if let Node::Pat(pat) = self.infcx.tcx.hir_node(upvar_hir_id)
&& let hir::PatKind::Binding(hir::BindingAnnotation::NONE, _, upvar_ident, _) =
&& let hir::PatKind::Binding(hir::BindingMode::NONE, _, upvar_ident, _) =
pat.kind
{
if upvar_ident.name == kw::SelfLower {
@ -729,7 +729,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
debug!("local_decl: {:?}", local_decl);
let pat_span = match *local_decl.local_info() {
LocalInfo::User(BindingForm::Var(mir::VarBindingForm {
binding_mode: BindingAnnotation(ByRef::No, Mutability::Not),
binding_mode: BindingMode(ByRef::No, Mutability::Not),
opt_ty_info: _,
opt_match_place: _,
pat_span,
@ -1086,7 +1086,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
}
LocalInfo::User(mir::BindingForm::Var(mir::VarBindingForm {
binding_mode: BindingAnnotation(ByRef::No, _),
binding_mode: BindingMode(ByRef::No, _),
opt_ty_info,
..
})) => {
@ -1154,7 +1154,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
}
LocalInfo::User(mir::BindingForm::Var(mir::VarBindingForm {
binding_mode: BindingAnnotation(ByRef::Yes(_), _),
binding_mode: BindingMode(ByRef::Yes(_), _),
..
})) => {
let pattern_span: Span = local_decl.source_info.span;
@ -1356,7 +1356,7 @@ pub fn mut_borrow_of_mutable_ref(local_decl: &LocalDecl<'_>, local_name: Option<
match *local_decl.local_info() {
// Check if mutably borrowing a mutable reference.
LocalInfo::User(mir::BindingForm::Var(mir::VarBindingForm {
binding_mode: BindingAnnotation(ByRef::No, Mutability::Not),
binding_mode: BindingMode(ByRef::No, Mutability::Not),
..
})) => matches!(local_decl.ty.kind(), ty::Ref(_, _, hir::Mutability::Mut)),
LocalInfo::User(mir::BindingForm::ImplicitSelf(kind)) => {

View file

@ -180,7 +180,7 @@ pub use SubstructureFields::*;
use crate::{deriving, errors};
use rustc_ast::ptr::P;
use rustc_ast::{
self as ast, BindingAnnotation, ByRef, EnumDef, Expr, GenericArg, GenericParamKind, Generics,
self as ast, BindingMode, ByRef, EnumDef, Expr, GenericArg, GenericParamKind, Generics,
Mutability, PatKind, TyKind, VariantData,
};
use rustc_attr as attr;
@ -1479,11 +1479,7 @@ impl<'a> TraitDef<'a> {
struct_field.ident,
cx.pat(
path.span,
PatKind::Ident(
BindingAnnotation(by_ref, Mutability::Not),
path,
None,
),
PatKind::Ident(BindingMode(by_ref, Mutability::Not), path, None),
),
)
});

View file

@ -415,6 +415,7 @@ impl<'a> LlvmArchiveBuilder<'a> {
members.as_ptr() as *const &_,
true,
kind,
self.sess.target.arch == "arm64ec",
);
let ret = if r.into_result().is_err() {
let err = llvm::LLVMRustGetLastError();

View file

@ -255,21 +255,38 @@ impl<'ll, 'tcx> ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
let (prov, offset) = ptr.into_parts();
let (base_addr, base_addr_space) = match self.tcx.global_alloc(prov.alloc_id()) {
GlobalAlloc::Memory(alloc) => {
let init = const_alloc_to_llvm(self, alloc);
let alloc = alloc.inner();
let value = match alloc.mutability {
Mutability::Mut => self.static_addr_of_mut(init, alloc.align, None),
_ => self.static_addr_of(init, alloc.align, None),
};
if !self.sess().fewer_names() && llvm::get_value_name(value).is_empty() {
let hash = self.tcx.with_stable_hashing_context(|mut hcx| {
let mut hasher = StableHasher::new();
alloc.hash_stable(&mut hcx, &mut hasher);
hasher.finish::<Hash128>()
});
llvm::set_value_name(value, format!("alloc_{hash:032x}").as_bytes());
// For ZSTs directly codegen an aligned pointer.
// This avoids generating a zero-sized constant value and actually needing a
// real address at runtime.
if alloc.inner().len() == 0 {
assert_eq!(offset.bytes(), 0);
let llval = self.const_usize(alloc.inner().align.bytes());
return if matches!(layout.primitive(), Pointer(_)) {
unsafe { llvm::LLVMConstIntToPtr(llval, llty) }
} else {
self.const_bitcast(llval, llty)
};
} else {
let init = const_alloc_to_llvm(self, alloc, /*static*/ false);
let alloc = alloc.inner();
let value = match alloc.mutability {
Mutability::Mut => self.static_addr_of_mut(init, alloc.align, None),
_ => self.static_addr_of(init, alloc.align, None),
};
if !self.sess().fewer_names() && llvm::get_value_name(value).is_empty()
{
let hash = self.tcx.with_stable_hashing_context(|mut hcx| {
let mut hasher = StableHasher::new();
alloc.hash_stable(&mut hcx, &mut hasher);
hasher.finish::<Hash128>()
});
llvm::set_value_name(
value,
format!("alloc_{hash:032x}").as_bytes(),
);
}
(value, AddressSpace::DATA)
}
(value, AddressSpace::DATA)
}
GlobalAlloc::Function(fn_instance) => (
self.get_fn_addr(fn_instance.polymorphize(self.tcx)),
@ -280,7 +297,7 @@ impl<'ll, 'tcx> ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
.tcx
.global_alloc(self.tcx.vtable_allocation((ty, trait_ref)))
.unwrap_memory();
let init = const_alloc_to_llvm(self, alloc);
let init = const_alloc_to_llvm(self, alloc, /*static*/ false);
let value = self.static_addr_of(init, alloc.inner().align, None);
(value, AddressSpace::DATA)
}
@ -308,7 +325,7 @@ impl<'ll, 'tcx> ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
}
fn const_data_from_alloc(&self, alloc: ConstAllocation<'tcx>) -> Self::Value {
const_alloc_to_llvm(self, alloc)
const_alloc_to_llvm(self, alloc, /*static*/ false)
}
fn const_bitcast(&self, val: &'ll Value, ty: &'ll Type) -> &'ll Value {

View file

@ -26,8 +26,22 @@ use rustc_target::abi::{
};
use std::ops::Range;
pub fn const_alloc_to_llvm<'ll>(cx: &CodegenCx<'ll, '_>, alloc: ConstAllocation<'_>) -> &'ll Value {
pub fn const_alloc_to_llvm<'ll>(
cx: &CodegenCx<'ll, '_>,
alloc: ConstAllocation<'_>,
is_static: bool,
) -> &'ll Value {
let alloc = alloc.inner();
// We expect that callers of const_alloc_to_llvm will instead directly codegen a pointer or
// integer for any &ZST where the ZST is a constant (i.e. not a static). We should never be
// producing empty LLVM allocations as they're just adding noise to binaries and forcing less
// optimal codegen.
//
// Statics have a guaranteed meaningful address so it's less clear that we want to do
// something like this; it's also harder.
if !is_static {
assert!(alloc.len() != 0);
}
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;
@ -120,7 +134,7 @@ fn codegen_static_initializer<'ll, 'tcx>(
def_id: DefId,
) -> Result<(&'ll Value, ConstAllocation<'tcx>), ErrorHandled> {
let alloc = cx.tcx.eval_static_initializer(def_id)?;
Ok((const_alloc_to_llvm(cx, alloc), alloc))
Ok((const_alloc_to_llvm(cx, alloc, /*static*/ true), alloc))
}
fn set_global_alignment<'ll>(cx: &CodegenCx<'ll, '_>, gv: &'ll Value, mut align: Align) {

View file

@ -2303,6 +2303,7 @@ extern "C" {
Members: *const &RustArchiveMember<'_>,
WriteSymbtab: bool,
Kind: ArchiveKind,
isEC: bool,
) -> LLVMRustResult;
pub fn LLVMRustArchiveMemberNew<'a>(
Filename: *const c_char,

View file

@ -270,9 +270,10 @@ pub fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> LLVMFeature<'a> {
"sve2-bitperm",
TargetFeatureFoldStrength::EnableOnly("neon"),
),
// The unaligned-scalar-mem feature was renamed to fast-unaligned-access.
("riscv32" | "riscv64", "fast-unaligned-access") if get_version().0 <= 17 => {
LLVMFeature::new("unaligned-scalar-mem")
// In LLVM 18, `unaligned-scalar-mem` was merged with `unaligned-vector-mem` into a single feature called
// `fast-unaligned-access`. In LLVM 19, it was split back out.
("riscv32" | "riscv64", "unaligned-scalar-mem") if get_version().0 == 18 => {
LLVMFeature::new("fast-unaligned-access")
}
// For LLVM 18, enable the evex512 target feature if a avx512 target feature is enabled.
("x86", s) if get_version().0 >= 18 && s.starts_with("avx512") => {

View file

@ -10,20 +10,21 @@ use rustc_middle::traits::Reveal;
use rustc_middle::ty::layout::LayoutOf;
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_session::lint;
use rustc_span::def_id::LocalDefId;
use rustc_span::Span;
use rustc_target::abi::{self, Abi};
use super::{CanAccessMutGlobal, CompileTimeEvalContext, CompileTimeInterpreter};
use crate::const_eval::CheckAlignment;
use crate::errors;
use crate::errors::ConstEvalError;
use crate::interpret::eval_nullary_intrinsic;
use crate::errors::{self, DanglingPtrInFinal};
use crate::interpret::{
create_static_alloc, intern_const_alloc_recursive, CtfeValidationMode, GlobalId, Immediate,
InternKind, InterpCx, InterpError, InterpResult, MPlaceTy, MemoryKind, OpTy, RefTracking,
StackPopCleanup,
};
use crate::interpret::{eval_nullary_intrinsic, InternResult};
use crate::CTRL_C_RECEIVED;
// Returns a pointer to where the result lives
@ -89,11 +90,35 @@ fn eval_body_using_ecx<'mir, 'tcx, R: InterpretationResult<'tcx>>(
}
// Intern the result
intern_const_alloc_recursive(ecx, intern_kind, &ret)?;
let intern_result = intern_const_alloc_recursive(ecx, intern_kind, &ret);
// Since evaluation had no errors, validate the resulting constant.
const_validate_mplace(&ecx, &ret, cid)?;
// Only report this after validation, as validaiton produces much better diagnostics.
// FIXME: ensure validation always reports this and stop making interning care about it.
match intern_result {
Ok(()) => {}
Err(InternResult::FoundDanglingPointer) => {
return Err(ecx
.tcx
.dcx()
.emit_err(DanglingPtrInFinal { span: ecx.tcx.span, kind: intern_kind })
.into());
}
Err(InternResult::FoundBadMutablePointer) => {
// only report mutable pointers if there were no dangling pointers
let err_diag = errors::MutablePtrInFinal { span: ecx.tcx.span, kind: intern_kind };
ecx.tcx.emit_node_span_lint(
lint::builtin::CONST_EVAL_MUTABLE_PTR_IN_FINAL_VALUE,
ecx.best_lint_scope(),
err_diag.span,
err_diag,
)
}
}
Ok(R::make_result(ret, ecx))
}

View file

@ -16,19 +16,17 @@
use hir::def::DefKind;
use rustc_ast::Mutability;
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
use rustc_middle::mir::interpret::{ConstAllocation, CtfeProvenance, InterpResult};
use rustc_middle::query::TyCtxtAt;
use rustc_middle::ty::layout::TyAndLayout;
use rustc_session::lint;
use rustc_span::def_id::LocalDefId;
use rustc_span::sym;
use super::{AllocId, Allocation, InterpCx, MPlaceTy, Machine, MemoryKind, PlaceTy};
use crate::const_eval;
use crate::errors::{DanglingPtrInFinal, MutablePtrInFinal, NestedStaticInThreadLocal};
use crate::errors::NestedStaticInThreadLocal;
pub trait CompileTimeMachine<'mir, 'tcx: 'mir, T> = Machine<
'mir,
@ -134,6 +132,12 @@ pub enum InternKind {
Promoted,
}
#[derive(Debug)]
pub enum InternResult {
FoundBadMutablePointer,
FoundDanglingPointer,
}
/// Intern `ret` and everything it references.
///
/// This *cannot raise an interpreter error*. Doing so is left to validation, which
@ -149,7 +153,7 @@ pub fn intern_const_alloc_recursive<
ecx: &mut InterpCx<'mir, 'tcx, M>,
intern_kind: InternKind,
ret: &MPlaceTy<'tcx>,
) -> Result<(), ErrorGuaranteed> {
) -> Result<(), InternResult> {
// We are interning recursively, and for mutability we are distinguishing the "root" allocation
// that we are starting in, and all other allocations that we are encountering recursively.
let (base_mutability, inner_mutability, is_static) = match intern_kind {
@ -201,7 +205,7 @@ pub fn intern_const_alloc_recursive<
// Whether we encountered a bad mutable pointer.
// We want to first report "dangling" and then "mutable", so we need to delay reporting these
// errors.
let mut found_bad_mutable_pointer = false;
let mut result = Ok(());
// Keep interning as long as there are things to intern.
// We show errors if there are dangling pointers, or mutable pointers in immutable contexts
@ -251,7 +255,10 @@ pub fn intern_const_alloc_recursive<
// on the promotion analysis not screwing up to ensure that it is sound to intern
// promoteds as immutable.
trace!("found bad mutable pointer");
found_bad_mutable_pointer = true;
// Prefer dangling pointer errors over mutable pointer errors
if result.is_ok() {
result = Err(InternResult::FoundBadMutablePointer);
}
}
if ecx.tcx.try_get_global_alloc(alloc_id).is_some() {
// Already interned.
@ -269,21 +276,15 @@ pub fn intern_const_alloc_recursive<
// pointers before deciding which allocations can be made immutable; but for now we are
// okay with losing some potential for immutability here. This can anyway only affect
// `static mut`.
todo.extend(intern_shallow(ecx, alloc_id, inner_mutability).map_err(|()| {
ecx.tcx.dcx().emit_err(DanglingPtrInFinal { span: ecx.tcx.span, kind: intern_kind })
})?);
match intern_shallow(ecx, alloc_id, inner_mutability) {
Ok(nested) => todo.extend(nested),
Err(()) => {
ecx.tcx.dcx().delayed_bug("found dangling pointer during const interning");
result = Err(InternResult::FoundDanglingPointer);
}
}
}
if found_bad_mutable_pointer {
let err_diag = MutablePtrInFinal { span: ecx.tcx.span, kind: intern_kind };
ecx.tcx.emit_node_span_lint(
lint::builtin::CONST_EVAL_MUTABLE_PTR_IN_FINAL_VALUE,
ecx.best_lint_scope(),
err_diag.span,
err_diag,
)
}
Ok(())
result
}
/// Intern `ret`. This function assumes that `ret` references no other allocation.

View file

@ -23,6 +23,7 @@ pub use rustc_middle::mir::interpret::*; // have all the `interpret` symbols in
pub use self::eval_context::{format_interp_error, Frame, FrameInfo, InterpCx, StackPopCleanup};
pub use self::intern::{
intern_const_alloc_for_constprop, intern_const_alloc_recursive, HasStaticRootDefId, InternKind,
InternResult,
};
pub use self::machine::{compile_time_machine, AllocMap, Machine, MayLeak, StackPopJump};
pub use self::memory::{AllocKind, AllocRef, AllocRefMut, FnVal, Memory, MemoryKind};

View file

@ -792,7 +792,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
}
// Some nodes are used a lot. Make sure they don't unintentionally get bigger.
#[cfg(all(any(target_arch = "x86_64", target_arch = "aarch64"), target_pointer_width = "64"))]
#[cfg(target_pointer_width = "64")]
mod size_asserts {
use super::*;
use rustc_data_structures::static_assert_size;

View file

@ -1058,7 +1058,7 @@ where
}
// Some nodes are used a lot. Make sure they don't unintentionally get bigger.
#[cfg(all(any(target_arch = "x86_64", target_arch = "aarch64"), target_pointer_width = "64"))]
#[cfg(target_pointer_width = "64")]
mod size_asserts {
use super::*;
use rustc_data_structures::static_assert_size;

View file

@ -449,67 +449,41 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
// `!` is a ZST and we want to validate it.
if let Ok((alloc_id, _offset, _prov)) = self.ecx.ptr_try_get_alloc_id(place.ptr()) {
let mut skip_recursive_check = false;
// Let's see what kind of memory this points to.
// `unwrap` since dangling pointers have already been handled.
let alloc_kind = self.ecx.tcx.try_get_global_alloc(alloc_id).unwrap();
let alloc_actual_mutbl = match alloc_kind {
GlobalAlloc::Static(did) => {
// Special handling for pointers to statics (irrespective of their type).
assert!(!self.ecx.tcx.is_thread_local_static(did));
assert!(self.ecx.tcx.is_static(did));
// Mode-specific checks
match self.ctfe_mode {
Some(
CtfeValidationMode::Static { .. }
| CtfeValidationMode::Promoted { .. },
) => {
// We skip recursively checking other statics. These statics must be sound by
// themselves, and the only way to get broken statics here is by using
// unsafe code.
// The reasons we don't check other statics is twofold. For one, in all
// sound cases, the static was already validated on its own, and second, we
// trigger cycle errors if we try to compute the value of the other static
// and that static refers back to us (potentially through a promoted).
// This could miss some UB, but that's fine.
skip_recursive_check = true;
}
Some(CtfeValidationMode::Const { .. }) => {
// We can't recursively validate `extern static`, so we better reject them.
if self.ecx.tcx.is_foreign_item(did) {
throw_validation_failure!(self.path, ConstRefToExtern);
}
}
None => {}
let alloc_actual_mutbl = mutability(self.ecx, alloc_id);
if let GlobalAlloc::Static(did) = self.ecx.tcx.global_alloc(alloc_id) {
let DefKind::Static { nested, .. } = self.ecx.tcx.def_kind(did) else { bug!() };
// Special handling for pointers to statics (irrespective of their type).
assert!(!self.ecx.tcx.is_thread_local_static(did));
assert!(self.ecx.tcx.is_static(did));
// Mode-specific checks
match self.ctfe_mode {
Some(
CtfeValidationMode::Static { .. } | CtfeValidationMode::Promoted { .. },
) => {
// We skip recursively checking other statics. These statics must be sound by
// themselves, and the only way to get broken statics here is by using
// unsafe code.
// The reasons we don't check other statics is twofold. For one, in all
// sound cases, the static was already validated on its own, and second, we
// trigger cycle errors if we try to compute the value of the other static
// and that static refers back to us (potentially through a promoted).
// This could miss some UB, but that's fine.
// We still walk nested allocations, as they are fundamentally part of this validation run.
// This means we will also recurse into nested statics of *other*
// statics, even though we do not recurse into other statics directly.
// That's somewhat inconsistent but harmless.
skip_recursive_check = !nested;
}
// Return alloc mutability. For "root" statics we look at the type to account for interior
// mutability; for nested statics we have no type and directly use the annotated mutability.
let DefKind::Static { mutability, nested } = self.ecx.tcx.def_kind(did)
else {
bug!()
};
match (mutability, nested) {
(Mutability::Mut, _) => Mutability::Mut,
(Mutability::Not, true) => Mutability::Not,
(Mutability::Not, false)
if !self
.ecx
.tcx
.type_of(did)
.no_bound_vars()
.expect("statics should not have generic parameters")
.is_freeze(*self.ecx.tcx, ty::ParamEnv::reveal_all()) =>
{
Mutability::Mut
Some(CtfeValidationMode::Const { .. }) => {
// We can't recursively validate `extern static`, so we better reject them.
if self.ecx.tcx.is_foreign_item(did) {
throw_validation_failure!(self.path, ConstRefToExtern);
}
(Mutability::Not, false) => Mutability::Not,
}
None => {}
}
GlobalAlloc::Memory(alloc) => alloc.inner().mutability,
GlobalAlloc::Function(..) | GlobalAlloc::VTable(..) => {
// These are immutable, we better don't allow mutable pointers here.
Mutability::Not
}
};
}
// Mutability check.
// If this allocation has size zero, there is no actual mutability here.
let (size, _align, _alloc_kind) = self.ecx.get_alloc_info(alloc_id);
@ -708,20 +682,61 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
fn in_mutable_memory(&self, op: &OpTy<'tcx, M::Provenance>) -> bool {
if let Some(mplace) = op.as_mplace_or_imm().left() {
if let Some(alloc_id) = mplace.ptr().provenance.and_then(|p| p.get_alloc_id()) {
let mutability = match self.ecx.tcx.global_alloc(alloc_id) {
GlobalAlloc::Static(_) => {
self.ecx.memory.alloc_map.get(alloc_id).unwrap().1.mutability
}
GlobalAlloc::Memory(alloc) => alloc.inner().mutability,
_ => span_bug!(self.ecx.tcx.span, "not a memory allocation"),
};
return mutability == Mutability::Mut;
return mutability(self.ecx, alloc_id).is_mut();
}
}
false
}
}
/// Returns whether the allocation is mutable, and whether it's actually a static.
/// For "root" statics we look at the type to account for interior
/// mutability; for nested statics we have no type and directly use the annotated mutability.
fn mutability<'mir, 'tcx: 'mir>(
ecx: &InterpCx<'mir, 'tcx, impl Machine<'mir, 'tcx>>,
alloc_id: AllocId,
) -> Mutability {
// Let's see what kind of memory this points to.
// We're not using `try_global_alloc` since dangling pointers have already been handled.
match ecx.tcx.global_alloc(alloc_id) {
GlobalAlloc::Static(did) => {
let DefKind::Static { mutability, nested } = ecx.tcx.def_kind(did) else { bug!() };
if nested {
assert!(
ecx.memory.alloc_map.get(alloc_id).is_none(),
"allocations of nested statics are already interned: {alloc_id:?}, {did:?}"
);
// Nested statics in a `static` are never interior mutable,
// so just use the declared mutability.
mutability
} else {
let mutability = match mutability {
Mutability::Not
if !ecx
.tcx
.type_of(did)
.no_bound_vars()
.expect("statics should not have generic parameters")
.is_freeze(*ecx.tcx, ty::ParamEnv::reveal_all()) =>
{
Mutability::Mut
}
_ => mutability,
};
if let Some((_, alloc)) = ecx.memory.alloc_map.get(alloc_id) {
assert_eq!(alloc.mutability, mutability);
}
mutability
}
}
GlobalAlloc::Memory(alloc) => alloc.inner().mutability,
GlobalAlloc::Function(..) | GlobalAlloc::VTable(..) => {
// These are immutable, we better don't allow mutable pointers here.
Mutability::Not
}
}
}
impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
for ValidityVisitor<'rt, 'mir, 'tcx, M>
{

View file

@ -102,9 +102,9 @@ pub type PResult<'a, T> = Result<T, PErr<'a>>;
rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
// `PResult` is used a lot. Make sure it doesn't unintentionally get bigger.
#[cfg(all(any(target_arch = "x86_64", target_arch = "aarch64"), target_pointer_width = "64"))]
#[cfg(target_pointer_width = "64")]
rustc_data_structures::static_assert_size!(PResult<'_, ()>, 16);
#[cfg(all(any(target_arch = "x86_64", target_arch = "aarch64"), target_pointer_width = "64"))]
#[cfg(target_pointer_width = "64")]
rustc_data_structures::static_assert_size!(PResult<'_, bool>, 16);
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, Encodable, Decodable)]

View file

@ -202,7 +202,7 @@ impl<'a> ExtCtxt<'a> {
ex: P<ast::Expr>,
) -> ast::Stmt {
let pat = if mutbl {
self.pat_ident_binding_mode(sp, ident, ast::BindingAnnotation::MUT)
self.pat_ident_binding_mode(sp, ident, ast::BindingMode::MUT)
} else {
self.pat_ident(sp, ident)
};
@ -490,14 +490,14 @@ impl<'a> ExtCtxt<'a> {
self.pat(span, PatKind::Lit(expr))
}
pub fn pat_ident(&self, span: Span, ident: Ident) -> P<ast::Pat> {
self.pat_ident_binding_mode(span, ident, ast::BindingAnnotation::NONE)
self.pat_ident_binding_mode(span, ident, ast::BindingMode::NONE)
}
pub fn pat_ident_binding_mode(
&self,
span: Span,
ident: Ident,
ann: ast::BindingAnnotation,
ann: ast::BindingMode,
) -> P<ast::Pat> {
let pat = PatKind::Ident(ann, ident.with_span_pos(span), None);
self.pat(span, pat)

View file

@ -266,7 +266,7 @@ struct MatcherPos {
}
// This type is used a lot. Make sure it doesn't unintentionally get bigger.
#[cfg(all(any(target_arch = "x86_64", target_arch = "aarch64"), target_pointer_width = "64"))]
#[cfg(target_pointer_width = "64")]
rustc_data_structures::static_assert_size!(MatcherPos, 16);
impl MatcherPos {

View file

@ -7,7 +7,7 @@ use crate::LangItem;
use rustc_ast as ast;
use rustc_ast::util::parser::ExprPrecedence;
use rustc_ast::{Attribute, FloatTy, IntTy, Label, LitKind, TraitObjectSyntax, UintTy};
pub use rustc_ast::{BinOp, BinOpKind, BindingAnnotation, BorrowKind, ByRef, CaptureBy};
pub use rustc_ast::{BinOp, BinOpKind, BindingMode, BorrowKind, ByRef, CaptureBy};
pub use rustc_ast::{ImplPolarity, IsAuto, Movability, Mutability, UnOp};
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
use rustc_data_structures::fingerprint::Fingerprint;
@ -1151,7 +1151,7 @@ pub enum PatKind<'hir> {
/// The `HirId` is the canonical ID for the variable being bound,
/// (e.g., in `Ok(x) | Err(x)`, both `x` use the same canonical ID),
/// which is the pattern ID of the first `x`.
Binding(BindingAnnotation, HirId, Ident, Option<&'hir Pat<'hir>>),
Binding(BindingMode, HirId, Ident, Option<&'hir Pat<'hir>>),
/// A struct or struct variant pattern (e.g., `Variant {x, y, ..}`).
/// The `bool` is `true` in the presence of a `..`.
@ -3786,7 +3786,7 @@ impl<'hir> Node<'hir> {
}
// Some nodes are used a lot. Make sure they don't unintentionally get bigger.
#[cfg(all(any(target_arch = "x86_64", target_arch = "aarch64"), target_pointer_width = "64"))]
#[cfg(target_pointer_width = "64")]
mod size_asserts {
use super::*;
// tidy-alphabetical-start

View file

@ -1,6 +1,6 @@
use crate::def::{CtorOf, DefKind, Res};
use crate::def_id::{DefId, DefIdSet};
use crate::hir::{self, BindingAnnotation, ByRef, HirId, PatKind};
use crate::hir::{self, BindingMode, ByRef, HirId, PatKind};
use rustc_span::symbol::Ident;
use rustc_span::Span;
@ -60,7 +60,7 @@ impl<T: ExactSizeIterator> EnumerateAndAdjustIterator for T {
impl hir::Pat<'_> {
/// Call `f` on every "binding" in a pattern, e.g., on `a` in
/// `match foo() { Some(a) => (), None => () }`
pub fn each_binding(&self, mut f: impl FnMut(hir::BindingAnnotation, HirId, Span, Ident)) {
pub fn each_binding(&self, mut f: impl FnMut(hir::BindingMode, HirId, Span, Ident)) {
self.walk_always(|p| {
if let PatKind::Binding(binding_mode, _, ident, _) = p.kind {
f(binding_mode, p.hir_id, p.span, ident);
@ -74,10 +74,7 @@ impl hir::Pat<'_> {
/// When encountering an or-pattern `p_0 | ... | p_n` only the first non-never pattern will be
/// visited. If they're all never patterns we visit nothing, which is ok since a never pattern
/// cannot have bindings.
pub fn each_binding_or_first(
&self,
f: &mut impl FnMut(hir::BindingAnnotation, HirId, Span, Ident),
) {
pub fn each_binding_or_first(&self, f: &mut impl FnMut(hir::BindingMode, HirId, Span, Ident)) {
self.walk(|p| match &p.kind {
PatKind::Or(ps) => {
for p in *ps {
@ -98,7 +95,7 @@ impl hir::Pat<'_> {
pub fn simple_ident(&self) -> Option<Ident> {
match self.kind {
PatKind::Binding(BindingAnnotation(ByRef::No, _), _, ident, None) => Some(ident),
PatKind::Binding(BindingMode(ByRef::No, _), _, ident, None) => Some(ident),
_ => None,
}
}
@ -135,8 +132,8 @@ impl hir::Pat<'_> {
pub fn contains_explicit_ref_binding(&self) -> Option<hir::Mutability> {
let mut result = None;
self.each_binding(|annotation, _, _, _| match annotation {
hir::BindingAnnotation::REF if result.is_none() => result = Some(hir::Mutability::Not),
hir::BindingAnnotation::REF_MUT => result = Some(hir::Mutability::Mut),
hir::BindingMode::REF if result.is_none() => result = Some(hir::Mutability::Not),
hir::BindingMode::REF_MUT => result = Some(hir::Mutability::Mut),
_ => {}
});
result

View file

@ -654,7 +654,7 @@ fn resolve_local<'tcx>(
// & expression, and its lifetime would be extended to the end of the block (due
// to a different rule, not the below code).
match pat.kind {
PatKind::Binding(hir::BindingAnnotation(hir::ByRef::Yes(_), _), ..) => true,
PatKind::Binding(hir::BindingMode(hir::ByRef::Yes(_), _), ..) => true,
PatKind::Struct(_, field_pats, _) => field_pats.iter().any(|fp| is_binding_pat(fp.pat)),
@ -671,7 +671,7 @@ fn resolve_local<'tcx>(
PatKind::Box(subpat) | PatKind::Deref(subpat) => is_binding_pat(subpat),
PatKind::Ref(_, _)
| PatKind::Binding(hir::BindingAnnotation(hir::ByRef::No, _), ..)
| PatKind::Binding(hir::BindingMode(hir::ByRef::No, _), ..)
| PatKind::Wild
| PatKind::Never
| PatKind::Path(_)

View file

@ -10,7 +10,7 @@ use rustc_ast_pretty::pp::{self, Breaks};
use rustc_ast_pretty::pprust::{Comments, PrintState};
use rustc_hir as hir;
use rustc_hir::{
BindingAnnotation, ByRef, GenericArg, GenericBound, GenericParam, GenericParamKind, HirId,
BindingMode, ByRef, GenericArg, GenericBound, GenericParam, GenericParamKind, HirId,
LifetimeParamKind, Node, PatKind, RangeEnd, Term, TraitBoundModifier,
};
use rustc_span::source_map::SourceMap;
@ -1723,7 +1723,7 @@ impl<'a> State<'a> {
match pat.kind {
PatKind::Wild => self.word("_"),
PatKind::Never => self.word("!"),
PatKind::Binding(BindingAnnotation(by_ref, mutbl), _, ident, sub) => {
PatKind::Binding(BindingMode(by_ref, mutbl), _, ident, sub) => {
if mutbl.is_mut() {
self.word_nbsp("mut");
}

View file

@ -7,7 +7,7 @@ use rustc_errors::{
};
use rustc_hir::def::{CtorKind, DefKind, Res};
use rustc_hir::pat_util::EnumerateAndAdjustIterator;
use rustc_hir::{self as hir, BindingAnnotation, ByRef, HirId, Mutability, Pat, PatKind};
use rustc_hir::{self as hir, BindingMode, ByRef, HirId, Mutability, Pat, PatKind};
use rustc_infer::infer;
use rustc_infer::infer::type_variable::TypeVariableOrigin;
use rustc_lint as lint;
@ -79,7 +79,7 @@ struct TopInfo<'tcx> {
#[derive(Copy, Clone)]
struct PatInfo<'tcx, 'a> {
binding_mode: BindingAnnotation,
binding_mode: ByRef,
max_ref_mutbl: Mutability,
top_info: TopInfo<'tcx>,
decl_origin: Option<DeclOrigin<'a>>,
@ -125,8 +125,6 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
}
}
const INITIAL_BM: BindingAnnotation = BindingAnnotation(ByRef::No, Mutability::Not);
/// Mode for adjusting the expected type and binding mode.
enum AdjustMode {
/// Peel off all immediate reference types.
@ -163,7 +161,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
) {
let info = TopInfo { expected, origin_expr, span };
let pat_info = PatInfo {
binding_mode: INITIAL_BM,
binding_mode: ByRef::No,
max_ref_mutbl: Mutability::Mut,
top_info: info,
decl_origin,
@ -296,43 +294,43 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&self,
pat: &'tcx Pat<'tcx>,
expected: Ty<'tcx>,
def_bm: BindingAnnotation,
def_br: ByRef,
adjust_mode: AdjustMode,
max_ref_mutbl: Mutability,
) -> (Ty<'tcx>, BindingAnnotation, Mutability, bool) {
if let ByRef::Yes(mutbl) = def_bm.0 {
) -> (Ty<'tcx>, ByRef, Mutability, bool) {
if let ByRef::Yes(mutbl) = def_br {
debug_assert!(mutbl <= max_ref_mutbl);
}
match adjust_mode {
AdjustMode::Pass => (expected, def_bm, max_ref_mutbl, false),
AdjustMode::Reset => (expected, INITIAL_BM, Mutability::Mut, false),
AdjustMode::Pass => (expected, def_br, max_ref_mutbl, false),
AdjustMode::Reset => (expected, ByRef::No, Mutability::Mut, false),
AdjustMode::ResetAndConsumeRef(ref_pat_mutbl) => {
let mutbls_match = def_bm.0 == ByRef::Yes(ref_pat_mutbl);
let mutbls_match = def_br == ByRef::Yes(ref_pat_mutbl);
if pat.span.at_least_rust_2024() && self.tcx.features().ref_pat_eat_one_layer_2024 {
if mutbls_match {
debug!("consuming inherited reference");
(expected, INITIAL_BM, cmp::min(max_ref_mutbl, ref_pat_mutbl), true)
(expected, ByRef::No, cmp::min(max_ref_mutbl, ref_pat_mutbl), true)
} else {
let (new_ty, new_bm, max_ref_mutbl) = if ref_pat_mutbl == Mutability::Mut {
self.peel_off_references(
pat,
expected,
def_bm,
def_br,
Mutability::Not,
max_ref_mutbl,
)
} else {
(expected, def_bm.cap_ref_mutability(Mutability::Not), Mutability::Not)
(expected, def_br.cap_ref_mutability(Mutability::Not), Mutability::Not)
};
(new_ty, new_bm, max_ref_mutbl, false)
}
} else {
(expected, INITIAL_BM, max_ref_mutbl, mutbls_match)
(expected, ByRef::No, max_ref_mutbl, mutbls_match)
}
}
AdjustMode::Peel => {
let peeled =
self.peel_off_references(pat, expected, def_bm, Mutability::Mut, max_ref_mutbl);
self.peel_off_references(pat, expected, def_br, Mutability::Mut, max_ref_mutbl);
(peeled.0, peeled.1, peeled.2, false)
}
}
@ -413,10 +411,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&self,
pat: &'tcx Pat<'tcx>,
expected: Ty<'tcx>,
mut def_bm: BindingAnnotation,
mut def_br: ByRef,
max_peelable_mutability: Mutability,
mut max_ref_mutability: Mutability,
) -> (Ty<'tcx>, BindingAnnotation, Mutability) {
) -> (Ty<'tcx>, ByRef, Mutability) {
let mut expected = self.try_structurally_resolve_type(pat.span, expected);
// Peel off as many `&` or `&mut` from the scrutinee type as possible. For example,
// for `match &&&mut Some(5)` the loop runs three times, aborting when it reaches
@ -437,7 +435,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pat_adjustments.push(expected);
expected = self.try_structurally_resolve_type(pat.span, inner_ty);
def_bm.0 = ByRef::Yes(match def_bm.0 {
def_br = ByRef::Yes(match def_br {
// If default binding mode is by value, make it `ref` or `ref mut`
// (depending on whether we observe `&` or `&mut`).
ByRef::No |
@ -450,21 +448,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
if pat.span.at_least_rust_2024() && self.tcx.features().ref_pat_eat_one_layer_2024 {
def_bm = def_bm.cap_ref_mutability(max_ref_mutability);
if def_bm.0 == ByRef::Yes(Mutability::Not) {
def_br = def_br.cap_ref_mutability(max_ref_mutability);
if def_br == ByRef::Yes(Mutability::Not) {
max_ref_mutability = Mutability::Not;
}
}
if !pat_adjustments.is_empty() {
debug!("default binding mode is now {:?}", def_bm);
debug!("default binding mode is now {:?}", def_br);
self.typeck_results
.borrow_mut()
.pat_adjustments_mut()
.insert(pat.hir_id, pat_adjustments);
}
(expected, def_bm, max_ref_mutability)
(expected, def_br, max_ref_mutability)
}
fn check_pat_lit(
@ -669,17 +667,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
fn check_pat_ident(
&self,
pat: &'tcx Pat<'tcx>,
ba: BindingAnnotation,
ba: BindingMode,
var_id: HirId,
sub: Option<&'tcx Pat<'tcx>>,
expected: Ty<'tcx>,
pat_info: PatInfo<'tcx, '_>,
) -> Ty<'tcx> {
let PatInfo { binding_mode: BindingAnnotation(def_br, _), top_info: ti, .. } = pat_info;
let PatInfo { binding_mode: def_br, top_info: ti, .. } = pat_info;
// Determine the binding mode...
let bm = match ba {
BindingAnnotation(ByRef::No, Mutability::Mut)
BindingMode(ByRef::No, Mutability::Mut)
if !(pat.span.at_least_rust_2024()
&& self.tcx.features().mut_preserve_binding_mode_2024)
&& matches!(def_br, ByRef::Yes(_)) =>
@ -691,10 +689,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pat.span,
errors::DereferencingMutBinding { span: pat.span },
);
BindingAnnotation(ByRef::No, Mutability::Mut)
BindingMode(ByRef::No, Mutability::Mut)
}
BindingAnnotation(ByRef::No, mutbl) => BindingAnnotation(def_br, mutbl),
BindingAnnotation(ByRef::Yes(_), _) => ba,
BindingMode(ByRef::No, mutbl) => BindingMode(def_br, mutbl),
BindingMode(ByRef::Yes(_), _) => ba,
};
// ...and store it in a side table:
self.typeck_results.borrow_mut().pat_binding_modes_mut().insert(pat.hir_id, bm);
@ -736,7 +734,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// bindings have the same type by comparing them all against the type of that first pat.
fn check_binding_alt_eq_ty(
&self,
ba: BindingAnnotation,
ba: BindingMode,
span: Span,
var_id: HirId,
ty: Ty<'tcx>,
@ -776,10 +774,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
span: Span,
expected: Ty<'tcx>,
actual: Ty<'tcx>,
ba: BindingAnnotation,
ba: BindingMode,
) {
match (expected.kind(), actual.kind(), ba) {
(ty::Ref(_, inner_ty, _), _, BindingAnnotation::NONE)
(ty::Ref(_, inner_ty, _), _, BindingMode::NONE)
if self.can_eq(self.param_env, *inner_ty, actual) =>
{
err.span_suggestion_verbose(
@ -789,7 +787,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Applicability::MaybeIncorrect,
);
}
(_, ty::Ref(_, inner_ty, _), BindingAnnotation::REF)
(_, ty::Ref(_, inner_ty, _), BindingMode::REF)
if self.can_eq(self.param_env, expected, *inner_ty) =>
{
err.span_suggestion_verbose(
@ -881,7 +879,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if let PatKind::Ref(the_ref, _) = i.kind
&& let PatKind::Binding(mt, _, ident, _) = the_ref.kind
{
let BindingAnnotation(_, mtblty) = mt;
let BindingMode(_, mtblty) = mt;
err.span_suggestion_verbose(
i.span,
format!("consider removing `&{mutability}` from the pattern"),

View file

@ -229,8 +229,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
else {
bug!();
};
let hir::PatKind::Binding(hir::BindingAnnotation(hir::ByRef::No, _), _, _, _) =
pat.kind
let hir::PatKind::Binding(hir::BindingMode(hir::ByRef::No, _), _, _, _) = pat.kind
else {
// Complex pattern, skip the non-upvar local.
continue;

View file

@ -400,7 +400,7 @@ enum Chunk {
}
// This type is used a lot. Make sure it doesn't unintentionally get bigger.
#[cfg(all(any(target_arch = "x86_64", target_arch = "aarch64"), target_pointer_width = "64"))]
#[cfg(target_pointer_width = "64")]
crate::static_assert_size!(Chunk, 16);
impl<T> ChunkedBitSet<T> {

View file

@ -477,7 +477,7 @@ pub enum SubregionOrigin<'tcx> {
}
// `SubregionOrigin` is used a lot. Make sure it doesn't unintentionally get bigger.
#[cfg(all(any(target_arch = "x86_64", target_arch = "aarch64"), target_pointer_width = "64"))]
#[cfg(target_pointer_width = "64")]
static_assert_size!(SubregionOrigin<'_>, 32);
impl<'tcx> SubregionOrigin<'tcx> {

View file

@ -32,7 +32,7 @@
#[macro_use]
extern crate rustc_macros;
#[cfg(all(any(target_arch = "x86_64", target_arch = "aarch64"), target_pointer_width = "64"))]
#[cfg(target_pointer_width = "64")]
#[macro_use]
extern crate rustc_data_structures;
#[macro_use]

View file

@ -112,7 +112,7 @@ impl<'tcx> PolyTraitObligation<'tcx> {
}
// `PredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger.
#[cfg(all(any(target_arch = "x86_64", target_arch = "aarch64"), target_pointer_width = "64"))]
#[cfg(target_pointer_width = "64")]
static_assert_size!(PredicateObligation<'_>, 48);
pub type PredicateObligations<'tcx> = Vec<PredicateObligation<'tcx>>;

View file

@ -1056,7 +1056,7 @@ impl UnusedParens {
avoid_mut: bool,
keep_space: (bool, bool),
) {
use ast::{BindingAnnotation, PatKind};
use ast::{BindingMode, PatKind};
if let PatKind::Paren(inner) = &value.kind {
match inner.kind {
@ -1068,7 +1068,7 @@ impl UnusedParens {
// Avoid `p0 | .. | pn` if we should.
PatKind::Or(..) if avoid_or => return,
// Avoid `mut x` and `mut x @ p` if we should:
PatKind::Ident(BindingAnnotation::MUT, ..) if avoid_mut => {
PatKind::Ident(BindingMode::MUT, ..) if avoid_mut => {
return;
}
// Otherwise proceed with linting.

View file

@ -175,7 +175,7 @@ extern "C" void LLVMRustArchiveMemberFree(LLVMRustArchiveMemberRef Member) {
extern "C" LLVMRustResult
LLVMRustWriteArchive(char *Dst, size_t NumMembers,
const LLVMRustArchiveMemberRef *NewMembers,
bool WriteSymbtab, LLVMRustArchiveKind RustKind) {
bool WriteSymbtab, LLVMRustArchiveKind RustKind, bool isEC) {
std::vector<NewArchiveMember> Members;
auto Kind = fromRust(RustKind);
@ -207,7 +207,7 @@ LLVMRustWriteArchive(char *Dst, size_t NumMembers,
auto Result = writeArchive(Dst, Members, WriteSymbtab, Kind, true, false);
#else
auto SymtabMode = WriteSymbtab ? SymtabWritingMode::NormalSymtab : SymtabWritingMode::NoSymtab;
auto Result = writeArchive(Dst, Members, SymtabMode, Kind, true, false);
auto Result = writeArchive(Dst, Members, SymtabMode, Kind, true, false, nullptr, isEC);
#endif
if (!Result)
return LLVMRustResult::Success;

View file

@ -70,7 +70,7 @@ pub enum ConstValue<'tcx> {
},
}
#[cfg(all(any(target_arch = "x86_64", target_arch = "aarch64"), target_pointer_width = "64"))]
#[cfg(target_pointer_width = "64")]
static_assert_size!(ConstValue<'_>, 24);
impl<'tcx> ConstValue<'tcx> {

View file

@ -88,7 +88,7 @@ pub type EvalToConstValueResult<'tcx> = Result<ConstValue<'tcx>, ErrorHandled>;
/// This is needed in `thir::pattern::lower_inline_const`.
pub type EvalToValTreeResult<'tcx> = Result<Option<ValTree<'tcx>>, ErrorHandled>;
#[cfg(all(any(target_arch = "x86_64", target_arch = "aarch64"), target_pointer_width = "64"))]
#[cfg(target_pointer_width = "64")]
static_assert_size!(InterpErrorInfo<'_>, 8);
/// Packages the kind of error we got from the const code interpreter

View file

@ -37,7 +37,7 @@ pub enum Scalar<Prov = CtfeProvenance> {
Ptr(Pointer<Prov>, u8),
}
#[cfg(all(any(target_arch = "x86_64", target_arch = "aarch64"), target_pointer_width = "64"))]
#[cfg(target_pointer_width = "64")]
static_assert_size!(Scalar, 24);
// We want the `Debug` output to be readable as it is used by `derive(Debug)` for

View file

@ -18,8 +18,7 @@ use rustc_errors::{DiagArgName, DiagArgValue, DiagMessage, ErrorGuaranteed, Into
use rustc_hir::def::{CtorKind, Namespace};
use rustc_hir::def_id::{DefId, CRATE_DEF_ID};
use rustc_hir::{
self as hir, BindingAnnotation, ByRef, CoroutineDesugaring, CoroutineKind, HirId,
ImplicitSelfKind,
self as hir, BindingMode, ByRef, CoroutineDesugaring, CoroutineKind, HirId, ImplicitSelfKind,
};
use rustc_session::Session;
use rustc_span::source_map::Spanned;
@ -930,7 +929,7 @@ pub enum LocalKind {
#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
pub struct VarBindingForm<'tcx> {
/// Is variable bound via `x`, `mut x`, `ref x`, `ref mut x`, `mut ref x`, or `mut ref mut x`?
pub binding_mode: BindingAnnotation,
pub binding_mode: BindingMode,
/// If an explicit type was provided for this variable binding,
/// this holds the source Span of that type.
///
@ -1155,7 +1154,7 @@ impl<'tcx> LocalDecl<'tcx> {
self.local_info(),
LocalInfo::User(
BindingForm::Var(VarBindingForm {
binding_mode: BindingAnnotation(ByRef::No, _),
binding_mode: BindingMode(ByRef::No, _),
opt_ty_info: _,
opt_match_place: _,
pat_span: _,
@ -1172,7 +1171,7 @@ impl<'tcx> LocalDecl<'tcx> {
self.local_info(),
LocalInfo::User(
BindingForm::Var(VarBindingForm {
binding_mode: BindingAnnotation(ByRef::No, _),
binding_mode: BindingMode(ByRef::No, _),
opt_ty_info: _,
opt_match_place: _,
pat_span: _,
@ -1814,7 +1813,7 @@ impl DefLocation {
}
// Some nodes are used a lot. Make sure they don't unintentionally get bigger.
#[cfg(all(any(target_arch = "x86_64", target_arch = "aarch64"), target_pointer_width = "64"))]
#[cfg(target_pointer_width = "64")]
mod size_asserts {
use super::*;
use rustc_data_structures::static_assert_size;

View file

@ -213,7 +213,7 @@ pub struct ClosureOutlivesRequirement<'tcx> {
}
// Make sure this enum doesn't unintentionally grow
#[cfg(all(any(target_arch = "x86_64", target_arch = "aarch64"), target_pointer_width = "64"))]
#[cfg(target_pointer_width = "64")]
rustc_data_structures::static_assert_size!(ConstraintCategory<'_>, 16);
/// Outlives-constraints can be categorized to determine whether and why they

View file

@ -1453,7 +1453,7 @@ pub enum BinOp {
}
// Some nodes are used a lot. Make sure they don't unintentionally get bigger.
#[cfg(all(any(target_arch = "x86_64", target_arch = "aarch64"), target_pointer_width = "64"))]
#[cfg(target_pointer_width = "64")]
mod size_asserts {
use super::*;
// tidy-alphabetical-start

View file

@ -14,7 +14,7 @@ pub struct PlaceTy<'tcx> {
}
// At least on 64 bit systems, `PlaceTy` should not be larger than two or three pointers.
#[cfg(all(any(target_arch = "x86_64", target_arch = "aarch64"), target_pointer_width = "64"))]
#[cfg(target_pointer_width = "64")]
static_assert_size!(PlaceTy<'_>, 16);
impl<'tcx> PlaceTy<'tcx> {

View file

@ -322,7 +322,7 @@ macro_rules! define_callbacks {
// Ensure that keys grow no larger than 72 bytes by accident.
// Increase this limit if necessary, but do try to keep the size low if possible
#[cfg(all(any(target_arch = "x86_64", target_arch="aarch64"), target_pointer_width = "64"))]
#[cfg(target_pointer_width = "64")]
const _: () = {
if mem::size_of::<Key<'static>>() > 72 {
panic!("{}", concat!(
@ -337,7 +337,7 @@ macro_rules! define_callbacks {
// Ensure that values grow no larger than 64 bytes by accident.
// Increase this limit if necessary, but do try to keep the size low if possible
#[cfg(all(any(target_arch = "x86_64", target_arch="aarch64"), target_pointer_width = "64"))]
#[cfg(target_pointer_width = "64")]
const _: () = {
if mem::size_of::<Value<'static>>() > 64 {
panic!("{}", concat!(

View file

@ -12,7 +12,7 @@ use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
use rustc_errors::{DiagArgValue, IntoDiagArg};
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_hir::{BindingAnnotation, ByRef, HirId, MatchSource, RangeEnd};
use rustc_hir::{BindingMode, ByRef, HirId, MatchSource, RangeEnd};
use rustc_index::newtype_index;
use rustc_index::IndexVec;
use rustc_middle::middle::region;
@ -603,10 +603,7 @@ impl<'tcx> Pat<'tcx> {
pub fn simple_ident(&self) -> Option<Symbol> {
match self.kind {
PatKind::Binding {
name,
mode: BindingAnnotation(ByRef::No, _),
subpattern: None,
..
name, mode: BindingMode(ByRef::No, _), subpattern: None, ..
} => Some(name),
_ => None,
}
@ -730,7 +727,7 @@ pub enum PatKind<'tcx> {
Binding {
name: Symbol,
#[type_visitable(ignore)]
mode: BindingAnnotation,
mode: BindingMode,
#[type_visitable(ignore)]
var: LocalVarId,
ty: Ty<'tcx>,
@ -1206,7 +1203,7 @@ impl<'tcx> fmt::Display for Pat<'tcx> {
}
// Some nodes are used a lot. Make sure they don't unintentionally get bigger.
#[cfg(all(any(target_arch = "x86_64", target_arch = "aarch64"), target_pointer_width = "64"))]
#[cfg(target_pointer_width = "64")]
mod size_asserts {
use super::*;
// tidy-alphabetical-start

View file

@ -551,7 +551,7 @@ impl<'tcx> ObligationCauseCode<'tcx> {
}
// `ObligationCauseCode` is used a lot. Make sure it doesn't unintentionally get bigger.
#[cfg(all(any(target_arch = "x86_64", target_arch = "aarch64"), target_pointer_width = "64"))]
#[cfg(target_pointer_width = "64")]
static_assert_size!(ObligationCauseCode<'_>, 48);
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]

View file

@ -22,6 +22,9 @@ pub use valtree::*;
pub type ConstKind<'tcx> = IrConstKind<TyCtxt<'tcx>>;
#[cfg(target_pointer_width = "64")]
static_assert_size!(ConstKind<'_>, 32);
/// Use this rather than `ConstData`, whenever possible.
#[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable)]
#[rustc_pass_by_value]
@ -59,7 +62,7 @@ pub struct ConstData<'tcx> {
pub kind: ConstKind<'tcx>,
}
#[cfg(all(any(target_arch = "x86_64", target_arch = "aarch64"), target_pointer_width = "64"))]
#[cfg(target_pointer_width = "64")]
static_assert_size!(ConstData<'_>, 40);
impl<'tcx> Const<'tcx> {

View file

@ -71,8 +71,5 @@ pub enum Expr<'tcx> {
Cast(CastKind, Const<'tcx>, Ty<'tcx>),
}
#[cfg(all(any(target_arch = "x86_64", target_arch = "aarch64"), target_pointer_width = "64"))]
#[cfg(target_pointer_width = "64")]
static_assert_size!(Expr<'_>, 24);
#[cfg(all(any(target_arch = "x86_64", target_arch = "aarch64"), target_pointer_width = "64"))]
static_assert_size!(super::ConstKind<'_>, 32);

View file

@ -2183,7 +2183,7 @@ pub struct DestructuredConst<'tcx> {
}
// Some types are used a lot. Make sure they don't unintentionally get bigger.
#[cfg(all(any(target_arch = "x86_64", target_arch = "aarch64"), target_pointer_width = "64"))]
#[cfg(target_pointer_width = "64")]
mod size_asserts {
use super::*;
use rustc_data_structures::static_assert_size;

View file

@ -2697,7 +2697,7 @@ impl<'tcx> VarianceDiagInfo<'tcx> {
}
// Some types are used a lot. Make sure they don't unintentionally get bigger.
#[cfg(all(any(target_arch = "x86_64", target_arch = "aarch64"), target_pointer_width = "64"))]
#[cfg(target_pointer_width = "64")]
mod size_asserts {
use super::*;
use rustc_data_structures::static_assert_size;

View file

@ -17,7 +17,7 @@ use rustc_hir::{
def::{DefKind, Res},
def_id::{DefId, LocalDefId, LocalDefIdMap},
hir_id::OwnerId,
BindingAnnotation, ByRef, HirId, ItemLocalId, ItemLocalMap, ItemLocalSet, Mutability,
BindingMode, ByRef, HirId, ItemLocalId, ItemLocalMap, ItemLocalSet, Mutability,
};
use rustc_index::IndexVec;
use rustc_macros::HashStable;
@ -78,8 +78,8 @@ pub struct TypeckResults<'tcx> {
adjustments: ItemLocalMap<Vec<ty::adjustment::Adjustment<'tcx>>>,
/// Stores the actual binding mode for all instances of [`BindingAnnotation`].
pat_binding_modes: ItemLocalMap<BindingAnnotation>,
/// Stores the actual binding mode for all instances of [`BindingMode`].
pat_binding_modes: ItemLocalMap<BindingMode>,
/// Stores the types which were implicitly dereferenced in pattern binding modes
/// for later usage in THIR lowering. For example,
@ -413,22 +413,17 @@ impl<'tcx> TypeckResults<'tcx> {
matches!(self.type_dependent_defs().get(expr.hir_id), Some(Ok((DefKind::AssocFn, _))))
}
pub fn extract_binding_mode(
&self,
s: &Session,
id: HirId,
sp: Span,
) -> Option<BindingAnnotation> {
pub fn extract_binding_mode(&self, s: &Session, id: HirId, sp: Span) -> Option<BindingMode> {
self.pat_binding_modes().get(id).copied().or_else(|| {
s.dcx().span_bug(sp, "missing binding mode");
})
}
pub fn pat_binding_modes(&self) -> LocalTableInContext<'_, BindingAnnotation> {
pub fn pat_binding_modes(&self) -> LocalTableInContext<'_, BindingMode> {
LocalTableInContext { hir_owner: self.hir_owner, data: &self.pat_binding_modes }
}
pub fn pat_binding_modes_mut(&mut self) -> LocalTableInContextMut<'_, BindingAnnotation> {
pub fn pat_binding_modes_mut(&mut self) -> LocalTableInContextMut<'_, BindingMode> {
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_binding_modes }
}
@ -460,7 +455,7 @@ impl<'tcx> TypeckResults<'tcx> {
let mut has_ref_mut = false;
pat.walk(|pat| {
if let hir::PatKind::Binding(_, id, _, _) = pat.kind
&& let Some(BindingAnnotation(ByRef::Yes(Mutability::Mut), _)) =
&& let Some(BindingMode(ByRef::Yes(Mutability::Mut), _)) =
self.pat_binding_modes().get(id)
{
has_ref_mut = true;

View file

@ -14,7 +14,7 @@ use rustc_data_structures::{
fx::{FxHashSet, FxIndexMap, FxIndexSet},
stack::ensure_sufficient_stack,
};
use rustc_hir::{BindingAnnotation, ByRef};
use rustc_hir::{BindingMode, ByRef};
use rustc_middle::middle::region;
use rustc_middle::mir::{self, *};
use rustc_middle::thir::{self, *};
@ -385,15 +385,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let fake_borrows = match_has_guard
.then(|| util::FakeBorrowCollector::collect_fake_borrows(self, candidates));
// See the doc comment on `match_candidates` for why we have an
// otherwise block. Match checking will ensure this is actually
// unreachable.
let otherwise_block = self.cfg.start_new_block();
// This will generate code to test scrutinee_place and
// branch to the appropriate arm block
self.match_candidates(match_start_span, scrutinee_span, block, otherwise_block, candidates);
// See the doc comment on `match_candidates` for why we may have an
// otherwise block. Match checking will ensure this is actually
// unreachable.
let source_info = self.source_info(scrutinee_span);
// Matching on a `scrutinee_place` with an uninhabited type doesn't
@ -621,12 +621,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
) -> BlockAnd<()> {
match irrefutable_pat.kind {
// Optimize the case of `let x = ...` to write directly into `x`
PatKind::Binding {
mode: BindingAnnotation(ByRef::No, _),
var,
subpattern: None,
..
} => {
PatKind::Binding { mode: BindingMode(ByRef::No, _), var, subpattern: None, .. } => {
let place =
self.storage_live_binding(block, var, irrefutable_pat.span, OutsideGuard, true);
unpack!(block = self.expr_into_dest(place, block, initializer_id));
@ -652,7 +647,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
box Pat {
kind:
PatKind::Binding {
mode: BindingAnnotation(ByRef::No, _),
mode: BindingMode(ByRef::No, _),
var,
subpattern: None,
..
@ -893,7 +888,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
f: &mut impl FnMut(
&mut Self,
Symbol,
BindingAnnotation,
BindingMode,
LocalVarId,
Span,
Ty<'tcx>,
@ -1148,7 +1143,7 @@ struct Binding<'tcx> {
span: Span,
source: Place<'tcx>,
var_id: LocalVarId,
binding_mode: BindingAnnotation,
binding_mode: BindingMode,
}
/// Indicates that the type of `source` must be a subtype of the
@ -2412,7 +2407,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
source_info: SourceInfo,
visibility_scope: SourceScope,
name: Symbol,
mode: BindingAnnotation,
mode: BindingMode,
var_id: LocalVarId,
var_ty: Ty<'tcx>,
user_ty: UserTypeProjections,

View file

@ -9,7 +9,7 @@ use rustc_data_structures::sorted_map::SortedIndexMultiMap;
use rustc_errors::ErrorGuaranteed;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::{self as hir, BindingAnnotation, ByRef, HirId, Node};
use rustc_hir::{self as hir, BindingMode, ByRef, HirId, Node};
use rustc_index::bit_set::GrowableBitSet;
use rustc_index::{Idx, IndexSlice, IndexVec};
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
@ -931,7 +931,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// Don't introduce extra copies for simple bindings
PatKind::Binding {
var,
mode: BindingAnnotation(ByRef::No, mutability),
mode: BindingMode(ByRef::No, mutability),
subpattern: None,
..
} => {
@ -941,7 +941,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
if let Some(kind) = param.self_kind {
LocalInfo::User(BindingForm::ImplicitSelf(kind))
} else {
let binding_mode = BindingAnnotation(ByRef::No, mutability);
let binding_mode = BindingMode(ByRef::No, mutability);
LocalInfo::User(BindingForm::Var(VarBindingForm {
binding_mode,
opt_ty_info: param.ty_span,

View file

@ -2,7 +2,7 @@ use crate::build::ExprCategory;
use crate::errors::*;
use rustc_errors::DiagArgValue;
use rustc_hir::{self as hir, BindingAnnotation, ByRef, HirId, Mutability};
use rustc_hir::{self as hir, BindingMode, ByRef, HirId, Mutability};
use rustc_middle::mir::BorrowKind;
use rustc_middle::thir::visit::Visitor;
use rustc_middle::thir::*;
@ -288,7 +288,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
visit::walk_pat(self, pat);
}
}
PatKind::Binding { mode: BindingAnnotation(ByRef::Yes(rm), _), ty, .. } => {
PatKind::Binding { mode: BindingMode(ByRef::Yes(rm), _), ty, .. } => {
if self.inside_adt {
let ty::Ref(_, ty, _) = ty.kind() else {
span_bug!(

View file

@ -15,7 +15,7 @@ use rustc_errors::{
};
use rustc_hir::def::*;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::{self as hir, BindingAnnotation, ByRef, HirId};
use rustc_hir::{self as hir, BindingMode, ByRef, HirId};
use rustc_middle::middle::limits::get_limit_size;
use rustc_middle::thir::visit::Visitor;
use rustc_middle::thir::*;
@ -839,7 +839,7 @@ fn check_for_bindings_named_same_as_variants(
) {
if let PatKind::Binding {
name,
mode: BindingAnnotation(ByRef::No, Mutability::Not),
mode: BindingMode(ByRef::No, Mutability::Not),
subpattern: None,
ty,
..

View file

@ -11,7 +11,7 @@ use rustc_middle::mir::visit::*;
use rustc_middle::mir::*;
use rustc_middle::ty::TypeVisitableExt;
use rustc_middle::ty::{self, Instance, InstanceDef, ParamEnv, Ty, TyCtxt};
use rustc_session::config::OptLevel;
use rustc_session::config::{DebugInfo, OptLevel};
use rustc_span::source_map::Spanned;
use rustc_span::sym;
use rustc_target::abi::FieldIdx;
@ -699,7 +699,19 @@ impl<'tcx> Inliner<'tcx> {
// Insert all of the (mapped) parts of the callee body into the caller.
caller_body.local_decls.extend(callee_body.drain_vars_and_temps());
caller_body.source_scopes.extend(&mut callee_body.source_scopes.drain(..));
caller_body.var_debug_info.append(&mut callee_body.var_debug_info);
if self
.tcx
.sess
.opts
.unstable_opts
.inline_mir_preserve_debug
.unwrap_or(self.tcx.sess.opts.debuginfo != DebugInfo::None)
{
// Note that we need to preserve these in the standard library so that
// people working on rust can build with or without debuginfo while
// still getting consistent results from the mir-opt tests.
caller_body.var_debug_info.append(&mut callee_body.var_debug_info);
}
caller_body.basic_blocks_mut().extend(callee_body.basic_blocks_mut().drain(..));
caller_body[callsite.block].terminator = Some(Terminator {

View file

@ -30,7 +30,7 @@ use unescape_error_reporting::{emit_unescape_error, escaped_char};
//
// This assertion is in this crate, rather than in `rustc_lexer`, because that
// crate cannot depend on `rustc_data_structures`.
#[cfg(all(any(target_arch = "x86_64", target_arch = "aarch64"), target_pointer_width = "64"))]
#[cfg(target_pointer_width = "64")]
rustc_data_structures::static_assert_size!(rustc_lexer::Token, 12);
#[derive(Clone, Debug)]

View file

@ -454,7 +454,7 @@ fn make_token_stream(
}
// Some types are used a lot. Make sure they don't unintentionally get bigger.
#[cfg(all(any(target_arch = "x86_64", target_arch = "aarch64"), target_pointer_width = "64"))]
#[cfg(target_pointer_width = "64")]
mod size_asserts {
use super::*;
use rustc_data_structures::static_assert_size;

View file

@ -29,7 +29,7 @@ use rustc_ast::token::{self, Delimiter, Lit, LitKind, Token, TokenKind};
use rustc_ast::tokenstream::AttrTokenTree;
use rustc_ast::util::parser::AssocOp;
use rustc_ast::{
AngleBracketedArg, AngleBracketedArgs, AnonConst, AttrVec, BinOpKind, BindingAnnotation, Block,
AngleBracketedArg, AngleBracketedArgs, AnonConst, AttrVec, BinOpKind, BindingMode, Block,
BlockCheckMode, Expr, ExprKind, GenericArg, Generics, HasTokens, Item, ItemKind, Param, Pat,
PatKind, Path, PathSegment, QSelf, Ty, TyKind,
};
@ -51,7 +51,7 @@ use thin_vec::{thin_vec, ThinVec};
pub(super) fn dummy_arg(ident: Ident, guar: ErrorGuaranteed) -> Param {
let pat = P(Pat {
id: ast::DUMMY_NODE_ID,
kind: PatKind::Ident(BindingAnnotation::NONE, ident, None),
kind: PatKind::Ident(BindingMode::NONE, ident, None),
span: ident.span,
tokens: None,
});
@ -2787,7 +2787,7 @@ impl<'a> Parser<'a> {
}
_ => {}
},
PatKind::Ident(BindingAnnotation::NONE, ident, None) => {
PatKind::Ident(BindingMode::NONE, ident, None) => {
match &first_pat.kind {
PatKind::Ident(_, old_ident, _) => {
let path = PatKind::Path(

View file

@ -2712,7 +2712,7 @@ impl<'a> Parser<'a> {
match ty {
Ok(ty) => {
let ident = Ident::new(kw::Empty, this.prev_token.span);
let bm = BindingAnnotation::NONE;
let bm = BindingMode::NONE;
let pat = this.mk_pat_ident(ty.span, bm, ident);
(pat, ty)
}

View file

@ -179,7 +179,7 @@ pub struct Parser<'a> {
// This type is used a lot, e.g. it's cloned when matching many declarative macro rules with nonterminals. Make sure
// it doesn't unintentionally get bigger.
#[cfg(all(any(target_arch = "x86_64", target_arch = "aarch64"), target_pointer_width = "64"))]
#[cfg(target_pointer_width = "64")]
rustc_data_structures::static_assert_size!(Parser<'_>, 264);
/// Stores span information about a closure.

View file

@ -16,8 +16,8 @@ use rustc_ast::mut_visit::{noop_visit_pat, MutVisitor};
use rustc_ast::ptr::P;
use rustc_ast::token::{self, BinOpToken, Delimiter, Token};
use rustc_ast::{
self as ast, AttrVec, BindingAnnotation, ByRef, Expr, ExprKind, MacCall, Mutability, Pat,
PatField, PatFieldsRest, PatKind, Path, QSelf, RangeEnd, RangeSyntax,
self as ast, AttrVec, BindingMode, ByRef, Expr, ExprKind, MacCall, Mutability, Pat, PatField,
PatFieldsRest, PatKind, Path, QSelf, RangeEnd, RangeSyntax,
};
use rustc_ast_pretty::pprust;
use rustc_errors::{Applicability, Diag, PResult};
@ -486,7 +486,7 @@ impl<'a> Parser<'a> {
}
// Parse ref ident @ pat / ref mut ident @ pat
let mutbl = self.parse_mutability();
self.parse_pat_ident(BindingAnnotation(ByRef::Yes(mutbl), Mutability::Not), syntax_loc)?
self.parse_pat_ident(BindingMode(ByRef::Yes(mutbl), Mutability::Not), syntax_loc)?
} else if self.eat_keyword(kw::Box) {
self.parse_pat_box()?
} else if self.check_inline_const(0) {
@ -511,7 +511,7 @@ impl<'a> Parser<'a> {
// Parse `ident @ pat`
// This can give false positives and parse nullary enums,
// they are dealt with later in resolve.
self.parse_pat_ident(BindingAnnotation::NONE, syntax_loc)?
self.parse_pat_ident(BindingMode::NONE, syntax_loc)?
} else if self.is_start_of_pat_with_path() {
// Parse pattern starting with a path
let (qself, path) = if self.eat_lt() {
@ -766,8 +766,7 @@ impl<'a> Parser<'a> {
let mut pat = self.parse_pat_no_top_alt(Some(Expected::Identifier), None)?;
// If we don't have `mut $ident (@ pat)?`, error.
if let PatKind::Ident(BindingAnnotation(br @ ByRef::No, m @ Mutability::Not), ..) =
&mut pat.kind
if let PatKind::Ident(BindingMode(br @ ByRef::No, m @ Mutability::Not), ..) = &mut pat.kind
{
// Don't recurse into the subpattern.
// `mut` on the outer binding doesn't affect the inner bindings.
@ -779,8 +778,7 @@ impl<'a> Parser<'a> {
self.ban_mut_general_pat(mut_span, &pat, changed_any_binding);
}
if matches!(pat.kind, PatKind::Ident(BindingAnnotation(ByRef::Yes(_), Mutability::Mut), ..))
{
if matches!(pat.kind, PatKind::Ident(BindingMode(ByRef::Yes(_), Mutability::Mut), ..)) {
self.psess.gated_spans.gate(sym::mut_ref, pat.span);
}
Ok(pat.into_inner().kind)
@ -792,7 +790,7 @@ impl<'a> Parser<'a> {
struct AddMut(bool);
impl MutVisitor for AddMut {
fn visit_pat(&mut self, pat: &mut P<Pat>) {
if let PatKind::Ident(BindingAnnotation(ByRef::No, m @ Mutability::Not), ..) =
if let PatKind::Ident(BindingMode(ByRef::No, m @ Mutability::Not), ..) =
&mut pat.kind
{
self.0 = true;
@ -1025,7 +1023,7 @@ impl<'a> Parser<'a> {
/// error message when parsing mistakes like `ref foo(a, b)`.
fn parse_pat_ident(
&mut self,
binding_annotation: BindingAnnotation,
binding_annotation: BindingMode,
syntax_loc: Option<PatternLocation>,
) -> PResult<'a, PatKind> {
let ident = self.parse_ident_common(false)?;
@ -1163,7 +1161,7 @@ impl<'a> Parser<'a> {
None
};
Ok(PatKind::Ident(BindingAnnotation::NONE, Ident::new(kw::Box, box_span), sub))
Ok(PatKind::Ident(BindingMode::NONE, Ident::new(kw::Box, box_span), sub))
} else {
let pat = self.parse_pat_with_range_pat(false, None, None)?;
self.psess.gated_spans.gate(sym::box_patterns, box_span.to(self.prev_token.span));
@ -1344,7 +1342,7 @@ impl<'a> Parser<'a> {
if let Some(last) = fields.iter().last()
&& last.is_shorthand
&& let PatKind::Ident(binding, ident, None) = last.pat.kind
&& binding != BindingAnnotation::NONE
&& binding != BindingMode::NONE
&& self.token == token::Colon
// We found `ref mut? ident:`, try to parse a `name,` or `name }`.
&& let Some(name_span) = self.look_ahead(1, |t| t.is_ident().then(|| t.span))
@ -1400,7 +1398,7 @@ impl<'a> Parser<'a> {
let fieldname = self.parse_field_name()?;
hi = self.prev_token.span;
let ann = BindingAnnotation(by_ref, mutability);
let ann = BindingMode(by_ref, mutability);
let fieldpat = self.mk_pat_ident(boxed_span.to(hi), ann, fieldname);
let subpat =
if is_box { self.mk_pat(lo.to(hi), PatKind::Box(fieldpat)) } else { fieldpat };
@ -1418,7 +1416,7 @@ impl<'a> Parser<'a> {
})
}
pub(super) fn mk_pat_ident(&self, span: Span, ann: BindingAnnotation, ident: Ident) -> P<Pat> {
pub(super) fn mk_pat_ident(&self, span: Span, ann: BindingMode, ident: Ident) -> P<Pat> {
self.mk_pat(span, PatKind::Ident(ann, ident, None))
}

View file

@ -1087,7 +1087,7 @@ fn unescape_string(string: &str) -> Option<string::String> {
}
// Assert a reasonable size for `Piece`
#[cfg(all(any(target_arch = "x86_64", target_arch = "aarch64"), target_pointer_width = "64"))]
#[cfg(target_pointer_width = "64")]
rustc_index::static_assert_size!(Piece<'_>, 16);
#[cfg(test)]

View file

@ -83,8 +83,7 @@ fn check_abi(tcx: TyCtxt<'_>, def_id: LocalDefId, abi: Abi) {
fn check_no_patterns(tcx: TyCtxt<'_>, params: &[hir::Param<'_>]) {
for param in params {
match param.pat.kind {
hir::PatKind::Wild
| hir::PatKind::Binding(hir::BindingAnnotation::NONE, _, _, None) => {}
hir::PatKind::Wild | hir::PatKind::Binding(hir::BindingMode::NONE, _, _, None) => {}
_ => {
tcx.dcx().emit_err(NoPatterns { span: param.pat.span });
}

View file

@ -46,7 +46,7 @@ use diagnostics::{ElisionFnParameter, LifetimeElisionCandidate, MissingLifetime}
#[derive(Copy, Clone, Debug)]
struct BindingInfo {
span: Span,
annotation: BindingAnnotation,
annotation: BindingMode,
}
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
@ -3655,14 +3655,14 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
fn try_resolve_as_non_binding(
&mut self,
pat_src: PatternSource,
ann: BindingAnnotation,
ann: BindingMode,
ident: Ident,
has_sub: bool,
) -> Option<Res> {
// An immutable (no `mut`) by-value (no `ref`) binding pattern without
// a sub pattern (no `@ $pat`) is syntactically ambiguous as it could
// also be interpreted as a path to e.g. a constant, variant, etc.
let is_syntactic_ambiguity = !has_sub && ann == BindingAnnotation::NONE;
let is_syntactic_ambiguity = !has_sub && ann == BindingMode::NONE;
let ls_binding = self.maybe_resolve_ident_in_lexical_scope(ident, ValueNS)?;
let (res, binding) = match ls_binding {

View file

@ -1717,6 +1717,9 @@ options! {
"enable MIR inlining (default: no)"),
inline_mir_hint_threshold: Option<usize> = (None, parse_opt_number, [TRACKED],
"inlining threshold for functions with inline hint (default: 100)"),
inline_mir_preserve_debug: Option<bool> = (None, parse_opt_bool, [TRACKED],
"when MIR inlining, whether to preserve debug info for callee variables \
(default: preserve for debuginfo != None, otherwise remove)"),
inline_mir_threshold: Option<usize> = (None, parse_opt_number, [TRACKED],
"a default MIR inlining threshold (default: 50)"),
input_stats: bool = (false, parse_bool, [UNTRACKED],

View file

@ -947,7 +947,7 @@ impl FromStr for Conv {
}
// Some types are used a lot. Make sure they don't unintentionally get bigger.
#[cfg(all(any(target_arch = "x86_64", target_arch = "aarch64"), target_pointer_width = "64"))]
#[cfg(target_pointer_width = "64")]
mod size_asserts {
use super::*;
use rustc_data_structures::static_assert_size;

View file

@ -279,9 +279,9 @@ const RISCV_ALLOWED_FEATURES: &[(&str, Stability)] = &[
("d", Unstable(sym::riscv_target_feature)),
("e", Unstable(sym::riscv_target_feature)),
("f", Unstable(sym::riscv_target_feature)),
("fast-unaligned-access", Unstable(sym::riscv_target_feature)),
("m", Stable),
("relax", Unstable(sym::riscv_target_feature)),
("unaligned-scalar-mem", Unstable(sym::riscv_target_feature)),
("v", Unstable(sym::riscv_target_feature)),
("zba", Stable),
("zbb", Stable),

View file

@ -31,7 +31,7 @@
#[macro_use]
extern crate rustc_macros;
#[cfg(all(any(target_arch = "x86_64", target_arch = "aarch64"), target_pointer_width = "64"))]
#[cfg(target_pointer_width = "64")]
#[macro_use]
extern crate rustc_data_structures;
#[macro_use]

View file

@ -751,9 +751,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
// Get the local name of this closure. This can be inaccurate because
// of the possibility of reassignment, but this should be good enough.
match &kind {
hir::PatKind::Binding(hir::BindingAnnotation::NONE, _, ident, None) => {
Some(ident.name)
}
hir::PatKind::Binding(hir::BindingMode::NONE, _, ident, None) => Some(ident.name),
_ => {
err.note(msg);
None

View file

@ -72,7 +72,7 @@ pub struct PendingPredicateObligation<'tcx> {
}
// `PendingPredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger.
#[cfg(all(any(target_arch = "x86_64", target_arch = "aarch64"), target_pointer_width = "64"))]
#[cfg(target_pointer_width = "64")]
static_assert_size!(PendingPredicateObligation<'_>, 72);
impl<'tcx> FulfillmentContext<'tcx> {

View file

@ -237,7 +237,7 @@ pub fn spin_loop() {
crate::arch::riscv64::pause();
}
#[cfg(target_arch = "aarch64")]
#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec"))]
{
// SAFETY: the `cfg` attr ensures that we only execute this on aarch64 targets.
unsafe { crate::arch::aarch64::__isb(crate::arch::aarch64::SY) };

View file

@ -239,7 +239,7 @@ pub const unsafe fn from_raw_parts<'a>(ptr: *const u8, len: usize) -> &'a str {
#[must_use]
#[unstable(feature = "str_from_raw_parts", issue = "119206")]
#[rustc_const_unstable(feature = "const_str_from_raw_parts_mut", issue = "119206")]
pub const unsafe fn from_raw_parts_mut<'a>(ptr: *mut u8, len: usize) -> &'a str {
pub const unsafe fn from_raw_parts_mut<'a>(ptr: *mut u8, len: usize) -> &'a mut str {
// SAFETY: the caller must uphold the safety contract for `from_raw_parts_mut`.
unsafe { &mut *ptr::from_raw_parts_mut(ptr.cast(), len) }
}

View file

@ -8,6 +8,7 @@
#![doc(issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/")]
#![panic_runtime]
#![allow(unused_features)]
#![feature(asm_experimental_arch)]
#![feature(core_intrinsics)]
#![feature(panic_runtime)]
#![feature(std_internals)]
@ -78,7 +79,7 @@ pub unsafe fn __rust_start_panic(_payload: &mut dyn PanicPayload) -> u32 {
core::arch::asm!("int $$0x29", in("ecx") FAST_FAIL_FATAL_APP_EXIT, options(noreturn, nostack));
} else if #[cfg(all(target_arch = "arm", target_feature = "thumb-mode"))] {
core::arch::asm!(".inst 0xDEFB", in("r0") FAST_FAIL_FATAL_APP_EXIT, options(noreturn, nostack));
} else if #[cfg(target_arch = "aarch64")] {
} else if #[cfg(any(target_arch = "aarch64", target_arch = "arm64ec"))] {
core::arch::asm!("brk 0xF003", in("x0") FAST_FAIL_FATAL_APP_EXIT, options(noreturn, nostack));
} else {
core::intrinsics::abort();

View file

@ -277,6 +277,7 @@
#![feature(allocator_internals)]
#![feature(allow_internal_unsafe)]
#![feature(allow_internal_unstable)]
#![feature(asm_experimental_arch)]
#![feature(c_unwind)]
#![feature(cfg_sanitizer_cfi)]
#![feature(cfg_target_thread_local)]

View file

@ -23,6 +23,7 @@ pub const MIN_ALIGN: usize = 8;
#[cfg(any(
target_arch = "x86_64",
target_arch = "aarch64",
target_arch = "arm64ec",
target_arch = "loongarch64",
target_arch = "mips64",
target_arch = "mips64r6",

View file

@ -1,4 +1,4 @@
// Bindings generated by `windows-bindgen` 0.55.0
// Bindings generated by `windows-bindgen` 0.56.0
#![allow(non_snake_case, non_upper_case_globals, non_camel_case_types, dead_code, clippy::all)]
#[link(name = "advapi32")]
@ -345,7 +345,7 @@ extern "system" {
}
#[link(name = "kernel32")]
extern "system" {
pub fn GetSystemTimePreciseAsFileTime(lpsystemtimeasfiletime: *mut FILETIME) -> ();
pub fn GetSystemTimePreciseAsFileTime(lpsystemtimeasfiletime: *mut FILETIME);
}
#[link(name = "kernel32")]
extern "system" {
@ -1018,7 +1018,7 @@ impl Clone for CONTEXT_0_0 {
}
}
#[repr(C)]
#[cfg(target_arch = "x86_64")]
#[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))]
pub struct CONTEXT {
pub P1Home: u64,
pub P2Home: u64,
@ -1067,30 +1067,30 @@ pub struct CONTEXT {
pub LastExceptionToRip: u64,
pub LastExceptionFromRip: u64,
}
#[cfg(target_arch = "x86_64")]
#[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))]
impl Copy for CONTEXT {}
#[cfg(target_arch = "x86_64")]
#[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))]
impl Clone for CONTEXT {
fn clone(&self) -> Self {
*self
}
}
#[repr(C)]
#[cfg(target_arch = "x86_64")]
#[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))]
pub union CONTEXT_0 {
pub FltSave: XSAVE_FORMAT,
pub Anonymous: CONTEXT_0_0,
}
#[cfg(target_arch = "x86_64")]
#[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))]
impl Copy for CONTEXT_0 {}
#[cfg(target_arch = "x86_64")]
#[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))]
impl Clone for CONTEXT_0 {
fn clone(&self) -> Self {
*self
}
}
#[repr(C)]
#[cfg(target_arch = "x86_64")]
#[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))]
pub struct CONTEXT_0_0 {
pub Header: [M128A; 2],
pub Legacy: [M128A; 8],
@ -1111,9 +1111,9 @@ pub struct CONTEXT_0_0 {
pub Xmm14: M128A,
pub Xmm15: M128A,
}
#[cfg(target_arch = "x86_64")]
#[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))]
impl Copy for CONTEXT_0_0 {}
#[cfg(target_arch = "x86_64")]
#[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))]
impl Clone for CONTEXT_0_0 {
fn clone(&self) -> Self {
*self
@ -3339,7 +3339,7 @@ pub const FILE_WRITE_EA: FILE_ACCESS_RIGHTS = 16u32;
pub const FILE_WRITE_THROUGH: NTCREATEFILE_CREATE_OPTIONS = 2u32;
pub const FIONBIO: i32 = -2147195266i32;
#[repr(C)]
#[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))]
#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))]
pub struct FLOATING_SAVE_AREA {
pub ControlWord: u32,
pub StatusWord: u32,
@ -3351,9 +3351,9 @@ pub struct FLOATING_SAVE_AREA {
pub RegisterArea: [u8; 80],
pub Cr0NpxState: u32,
}
#[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))]
#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))]
impl Copy for FLOATING_SAVE_AREA {}
#[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))]
#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))]
impl Clone for FLOATING_SAVE_AREA {
fn clone(&self) -> Self {
*self
@ -4106,7 +4106,7 @@ impl Clone for WSABUF {
}
}
#[repr(C)]
#[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))]
#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))]
pub struct WSADATA {
pub wVersion: u16,
pub wHighVersion: u16,
@ -4116,9 +4116,9 @@ pub struct WSADATA {
pub szDescription: [i8; 257],
pub szSystemStatus: [i8; 129],
}
#[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))]
#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))]
impl Copy for WSADATA {}
#[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))]
#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))]
impl Clone for WSADATA {
fn clone(&self) -> Self {
*self
@ -4286,7 +4286,7 @@ pub const WSA_SECURE_HOST_NOT_FOUND: WSA_ERROR = 11032i32;
pub const WSA_WAIT_EVENT_0: WSA_ERROR = 0i32;
pub const WSA_WAIT_IO_COMPLETION: WSA_ERROR = 192i32;
#[repr(C)]
#[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))]
#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))]
pub struct XSAVE_FORMAT {
pub ControlWord: u16,
pub StatusWord: u16,
@ -4305,9 +4305,9 @@ pub struct XSAVE_FORMAT {
pub XmmRegisters: [M128A; 16],
pub Reserved4: [u8; 96],
}
#[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))]
#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))]
impl Copy for XSAVE_FORMAT {}
#[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))]
#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))]
impl Clone for XSAVE_FORMAT {
fn clone(&self) -> Self {
*self

View file

@ -332,7 +332,7 @@ pub fn abort_internal() -> ! {
core::arch::asm!("int $$0x29", in("ecx") c::FAST_FAIL_FATAL_APP_EXIT, options(noreturn, nostack));
} else if #[cfg(all(target_arch = "arm", target_feature = "thumb-mode"))] {
core::arch::asm!(".inst 0xDEFB", in("r0") c::FAST_FAIL_FATAL_APP_EXIT, options(noreturn, nostack));
} else if #[cfg(target_arch = "aarch64")] {
} else if #[cfg(any(target_arch = "aarch64", target_arch = "arm64ec"))] {
core::arch::asm!("brk 0xF003", in("x0") c::FAST_FAIL_FATAL_APP_EXIT, options(noreturn, nostack));
} else {
core::intrinsics::abort();

View file

@ -394,16 +394,13 @@ fn copy_self_contained_objects(
target_deps.push((libunwind_path, DependencyType::TargetSelfContained));
}
} else if target.contains("-wasi") {
let srcdir = builder
.wasi_root(target)
.unwrap_or_else(|| {
panic!(
"Target {:?} does not have a \"wasi-root\" key in Config.toml",
target.triple
)
})
.join("lib")
.join(target.to_string().replace("-preview1", "").replace("p2", "").replace("p1", ""));
let srcdir = builder.wasi_libdir(target).unwrap_or_else(|| {
panic!(
"Target {:?} does not have a \"wasi-root\" key in Config.toml \
or `$WASI_SDK_PATH` set",
target.triple
)
});
for &obj in &["libc.a", "crt1-command.o", "crt1-reactor.o"] {
copy_and_stamp(
builder,
@ -514,12 +511,8 @@ pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, car
}
if target.contains("-wasi") {
if let Some(p) = builder.wasi_root(target) {
let root = format!(
"native={}/lib/{}",
p.to_str().unwrap(),
target.to_string().replace("-preview1", "")
);
if let Some(dir) = builder.wasi_libdir(target) {
let root = format!("native={}", dir.to_str().unwrap());
cargo.rustflag("-L").rustflag(&root);
}
}

View file

@ -2102,6 +2102,14 @@ impl<'a> Builder<'a> {
// break when incremental compilation is enabled. So this overrides the "no inlining
// during incremental builds" heuristic for the standard library.
rustflags.arg("-Zinline-mir");
// FIXME: always pass this after the next `#[cfg(bootstrap)]` update.
if compiler.stage != 0 {
// Similarly, we need to keep debug info for functions inlined into other std functions,
// even if we're not going to output debuginfo for the crate we're currently building,
// so that it'll be available when downstream consumers of std try to use it.
rustflags.arg("-Zinline-mir-preserve-debug");
}
}
if self.config.rustc_parallel

View file

@ -1373,9 +1373,24 @@ impl Build {
self.musl_root(target).map(|root| root.join("lib"))
}
/// Returns the sysroot for the wasi target, if defined
fn wasi_root(&self, target: TargetSelection) -> Option<&Path> {
self.config.target_config.get(&target).and_then(|t| t.wasi_root.as_ref()).map(|p| &**p)
/// Returns the `lib` directory for the WASI target specified, if
/// configured.
///
/// This first consults `wasi-root` as configured in per-target
/// configuration, and failing that it assumes that `$WASI_SDK_PATH` is
/// set in the environment, and failing that `None` is returned.
fn wasi_libdir(&self, target: TargetSelection) -> Option<PathBuf> {
let configured =
self.config.target_config.get(&target).and_then(|t| t.wasi_root.as_ref()).map(|p| &**p);
if let Some(path) = configured {
return Some(path.join("lib").join(target.to_string()));
}
let mut env_root = PathBuf::from(std::env::var_os("WASI_SDK_PATH")?);
env_root.push("share");
env_root.push("wasi-sysroot");
env_root.push("lib");
env_root.push(target.to_string());
Some(env_root)
}
/// Returns `true` if this is a no-std `target`, if defined

View file

@ -47,7 +47,7 @@ fn cc2ar(cc: &Path, target: TargetSelection) -> Option<PathBuf> {
Some(PathBuf::from("ar"))
} else if target.contains("vxworks") {
Some(PathBuf::from("wr-ar"))
} else if target.contains("android") {
} else if target.contains("android") || target.contains("-wasi") {
Some(cc.parent().unwrap().join(PathBuf::from("llvm-ar")))
} else {
let parent = cc.parent().unwrap();
@ -223,6 +223,16 @@ fn default_compiler(
}
}
t if t.contains("-wasi") => {
let root = PathBuf::from(std::env::var_os("WASI_SDK_PATH")?);
let compiler = match compiler {
Language::C => format!("{t}-clang"),
Language::CPlusPlus => format!("{t}-clang++"),
};
let compiler = root.join("bin").join(compiler);
Some(compiler)
}
_ => None,
}
}

View file

@ -85,11 +85,9 @@ RUN /tmp/build-solaris-toolchain.sh sparcv9 sparcv9 solaris-sparc sun
COPY host-x86_64/dist-various-2/build-x86_64-fortanix-unknown-sgx-toolchain.sh /tmp/
RUN /tmp/build-x86_64-fortanix-unknown-sgx-toolchain.sh
COPY host-x86_64/dist-various-2/build-wasi-toolchain.sh /tmp/
RUN /tmp/build-wasi-toolchain.sh
COPY host-x86_64/dist-various-2/build-wasi-threads-toolchain.sh /tmp/
RUN /tmp/build-wasi-threads-toolchain.sh
RUN curl -L https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-22/wasi-sdk-22.0-linux.tar.gz | \
tar -xz
ENV WASI_SDK_PATH=/tmp/wasi-sdk-22.0
COPY scripts/freebsd-toolchain.sh /tmp/
RUN /tmp/freebsd-toolchain.sh i686
@ -136,9 +134,6 @@ ENV TARGETS=$TARGETS,x86_64-unknown-uefi
RUN ln -s /usr/include/x86_64-linux-gnu/asm /usr/local/include/asm
ENV RUST_CONFIGURE_ARGS --enable-extended --enable-lld --enable-llvm-bitcode-linker --disable-docs \
--set target.wasm32-wasi.wasi-root=/wasm32-wasip1 \
--set target.wasm32-wasip1.wasi-root=/wasm32-wasip1 \
--set target.wasm32-wasip1-threads.wasi-root=/wasm32-wasip1-threads \
--musl-root-armv7=/musl-armv7
ENV SCRIPT python3 ../x.py dist --host='' --target $TARGETS

View file

@ -1,24 +0,0 @@
#!/bin/sh
set -ex
# Originally from https://github.com/llvm/llvm-project/releases/download/llvmorg-16.0.4/clang+llvm-16.0.4-x86_64-linux-gnu-ubuntu-22.04.tar.xz
curl https://ci-mirrors.rust-lang.org/rustc/2023-05-17-clang%2Bllvm-16.0.4-x86_64-linux-gnu-ubuntu-22.04.tar.xz | \
tar xJf -
bin="$PWD/clang+llvm-16.0.4-x86_64-linux-gnu-ubuntu-22.04/bin"
git clone https://github.com/WebAssembly/wasi-libc
cd wasi-libc
git reset --hard ec4566beae84e54952637f0bf61bee4b4cacc087
make -j$(nproc) \
CC="$bin/clang" \
NM="$bin/llvm-nm" \
AR="$bin/llvm-ar" \
THREAD_MODEL=posix \
INSTALL_DIR=/wasm32-wasip1-threads \
install
cd ..
rm -rf wasi-libc
rm -rf clang+llvm*

View file

@ -1,23 +0,0 @@
#!/bin/sh
set -ex
# Originally from https://github.com/llvm/llvm-project/releases/download/llvmorg-16.0.4/clang+llvm-16.0.4-x86_64-linux-gnu-ubuntu-22.04.tar.xz
curl https://ci-mirrors.rust-lang.org/rustc/2023-05-17-clang%2Bllvm-16.0.4-x86_64-linux-gnu-ubuntu-22.04.tar.xz | \
tar xJf -
bin="$PWD/clang+llvm-16.0.4-x86_64-linux-gnu-ubuntu-22.04/bin"
git clone https://github.com/WebAssembly/wasi-libc
cd wasi-libc
git reset --hard ec4566beae84e54952637f0bf61bee4b4cacc087
make -j$(nproc) \
CC="$bin/clang" \
NM="$bin/llvm-nm" \
AR="$bin/llvm-ar" \
INSTALL_DIR=/wasm32-wasip1 \
install
cd ..
rm -rf wasi-libc
rm -rf clang+llvm*

View file

@ -39,14 +39,14 @@ WORKDIR /
COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh
COPY host-x86_64/dist-various-2/build-wasi-toolchain.sh /tmp/
RUN /tmp/build-wasi-toolchain.sh
RUN curl -L https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-22/wasi-sdk-22.0-linux.tar.gz | \
tar -xz
ENV WASI_SDK_PATH=/wasi-sdk-22.0
ENV RUST_CONFIGURE_ARGS \
--musl-root-x86_64=/usr/local/x86_64-linux-musl \
--set build.nodejs=/node-v18.12.0-linux-x64/bin/node \
--set rust.lld \
--set target.wasm32-wasip1.wasi-root=/wasm32-wasip1
--set rust.lld
# Some run-make tests have assertions about code size, and enabling debug
# assertions in libstd causes the binary to be much bigger than it would
@ -68,9 +68,6 @@ ENV WASM_SCRIPT python3 /checkout/x.py --stage 2 test --host='' --target $WASM_T
tests/codegen \
tests/assembly \
library/core
ENV CC_wasm32_wasip1=clang-11 \
CFLAGS_wasm32_wasip1="--sysroot /wasm32-wasip1" \
AR_wasm32_wasip1=llvm-ar-11
ENV NVPTX_TARGETS=nvptx64-nvidia-cuda
ENV NVPTX_SCRIPT python3 /checkout/x.py --stage 2 test --host='' --target $NVPTX_TARGETS \

View file

@ -11,48 +11,69 @@ applications on AArch64 Windows 11. See <https://learn.microsoft.com/en-us/windo
## Requirements
Target only supports cross-compilation, `core` and `alloc` are supported but
`std` is not.
Builds Arm64EC static and dynamic libraries and executables which can be run on
AArch64 Windows 11 devices. Arm64EC static libraries can also be linked into
Arm64X dynamic libraries and executables.
Uses `arm64ec` as its `target_arch` - code built for Arm64EC must be compatible
with x86_64 code (e.g., same structure layouts, function signatures, etc.) but
use AArch64 intrinsics.
Only supported backend is LLVM 18 or above:
* 18.1.0 added initial support for Arm64EC.
* 18.1.2 fixed import library generation (required for `raw-dylib` support).
* 18.1.4 fixed linking issue for some intrinsics implemented in
`compiler_builtins`.
Only supported backend is LLVM 18 (or above).
### Reusing code from other architectures - x86_64 or AArch64?
Arm64EC uses `arm64ec` as its `target_arch`, but it is possible to reuse
existing architecture-specific code in most cases. The best mental model for
deciding which architecture to reuse is to is to think of Arm64EC as an x86_64
process that happens to use the AArch64 instruction set (with some caveats) and
has a completely custom ABI.
To put this in practice:
* Arm64EC interacts with the operating system, other processes and other DLLs as
x86_64.
- For example, [in `backtrace`](https://github.com/rust-lang/backtrace-rs/commit/ef39a7d7da58b4cae8c8f3fc67a8300fd8d2d0d9)
we use the x86_64 versions of `CONTEXT` and `RtlVirtualUnwind`.
- If you are configuring a search path to find DLLs (e.g., to load plugins or
addons into your application), you should use the same path as the x86_64
version of your application, not the AArch64 path (since Arm64EC (i.e.,
x86_64) processes cannot load native AArch64 DLLs).
* Arm64EC uses AArch64 intrinsics.
- For example, <https://github.com/rust-lang/portable-simd/commit/ca4033f49b1f6019561b8b161b4097b4a07f2e1b>
and <https://github.com/rust-lang/stdarch/commit/166ef7ba22b6a1d908d4b29a36e68ceca324808a>.
* Assembly for AArch64 might be reusable for Arm64EC, but there are many
caveats. For full details see [Microsoft's documentation on the Arm64EC ABI](https://learn.microsoft.com/en-us/windows/arm/arm64ec-abi)
but in brief:
- Arm64EC uses a subset of AArch64 registers.
- Arm64EC uses a different name mangling scheme than AArch64.
- Arm64EC requires entry and exit thunks be generated for some functions.
- Indirect calls must be done via a call checker.
- Control Flow Guard and stack checks use different functions than AArch64.
## Building the target
You can build Rust with support for the targets by adding it to the `target`
list in `config.toml` and disabling `std`:
list in `config.toml`:
```toml
[build]
target = [ "arm64ec-pc-windows-msvc" ]
[target.arm64ec-pc-windows-msvc]
no-std = true
```
## Building Rust programs
Rust does not yet ship pre-compiled artifacts for this target. To compile for
this target, you will either need to build Rust with the target enabled (see
"Building the target" above), or build your own copy of `core` by using
`build-std` or similar.
"Building the target" above), or build your own copy using `build-std` or
similar.
## Testing
Tests can be run on AArch64 Windows 11 devices.
Since this is a `no_std` target, the Rust test suite is not supported.
## Cross-compilation toolchains and C code
C code can be built using the Arm64-targetting MSVC toolchain.
C code can be built using the Arm64-targetting MSVC or Clang toolchain.
To compile:

View file

@ -73,19 +73,21 @@ be used instead.
## Building the target
To build this target a compiled version of [`wasi-libc`] is required to be
present at build time. This can be installed through
[`wasi-sdk`](https://github.com/WebAssembly/wasi-sdk) as well. This is the
configured with:
To build this target first acquire a copy of
[`wasi-sdk`](https://github.com/WebAssembly/wasi-sdk/). At this time version 22
is the minimum needed.
```toml
[target.wasm32-wasip1]
wasi-root = ".../wasi-libc/sysroot"
Next configure the `WASI_SDK_PATH` environment variable to point to where this
is installed. For example:
```text
export WASI_SDK_PATH=/path/to/wasi-sdk-22.0
```
Additionally users will need to enable LLD when building Rust from source as
LLVM's `wasm-ld` driver for LLD is required when linking WebAssembly code
together.
Next be sure to enable LLD when building Rust from source as LLVM's `wasm-ld`
driver for LLD is required when linking WebAssembly code together. Rust's build
system will automatically pick up any necessary binaries and programs from
`WASI_SDK_PATH`.
## Building Rust programs
@ -112,8 +114,10 @@ This target can be cross-compiled from any hosts.
## Testing
Currently the WASI target is not tested in rust-lang/rust CI. This means that
tests in the repository are not guaranteed to pass. This is theoretically
possibly by installing a standalone WebAssembly runtime and using it as a
"runner" for all tests, but there are various failures that will need to be
waded through to adjust tests to work on the WASI target.
This target is tested in rust-lang/rust CI on all merges. A subset of tests are
run in the `test-various` builder such as the UI tests and libcore tests. This
can be tested locally, for example, with:
```text
./x.py test --target wasm32-wasip1 tests/ui
```

View file

@ -22,9 +22,34 @@ This target is cross-compiled. The target supports `std` fully.
## Platform requirements
The WebAssembly runtime should support the wasi preview 2 API set.
The WebAssembly runtime should support the wasi preview 2 API set. Runtimes also
are required to support components since this target outputs a component as
opposed to a core wasm module. As of the time of this writing Wasmtime 17 and
above is able to run this target natively with no extra flags.
This target is not a stable target. This means that there are only a few engines
which implement wasi preview 2, for example:
## Building the target
* Wasmtime - `-W component-model`
To build this target first acquire a copy of
[`wasi-sdk`](https://github.com/WebAssembly/wasi-sdk/). At this time version 22
is the minimum needed.
Next configure the `WASI_SDK_PATH` environment variable to point to where this
is installed. For example:
```text
export WASI_SDK_PATH=/path/to/wasi-sdk-22.0
```
Next be sure to enable LLD when building Rust from source as LLVM's `wasm-ld`
driver for LLD is required when linking WebAssembly code together. Rust's build
system will automatically pick up any necessary binaries and programs from
`WASI_SDK_PATH`.
## Testing
This target is not tested in CI at this time. Locally it can be tested with a
`wasmtime` binary in `PATH` like so:
```text
./x.py test --target wasm32-wasip2 tests/ui
```

View file

@ -2567,7 +2567,7 @@ pub(crate) enum TypeBindingKind {
}
// Some nodes are used a lot. Make sure they don't unintentionally get bigger.
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
#[cfg(target_pointer_width = "64")]
mod size_asserts {
use super::*;
use rustc_data_structures::static_assert_size;

View file

@ -346,16 +346,28 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
{
let desc =
short_markdown_summary(&item.doc_value(), &item.link_names(self.cache));
// For searching purposes, a re-export is a duplicate if:
//
// - It's either an inline, or a true re-export
// - It's got the same name
// - Both of them have the same exact path
let defid = (match &*item.kind {
&clean::ItemKind::ImportItem(ref import) => import.source.did,
_ => None,
})
.or_else(|| item.item_id.as_def_id());
// In case this is a field from a tuple struct, we don't add it into
// the search index because its name is something like "0", which is
// not useful for rustdoc search.
self.cache.search_index.push(IndexItem {
ty,
defid,
name: s,
path: join_with_double_colon(path),
desc,
parent,
parent_idx: None,
exact_path: None,
impl_id: if let Some(ParentStackItem::Impl { item_id, .. }) =
self.cache.parent_stack.last()
{

View file

@ -78,8 +78,10 @@ pub(crate) struct Context<'tcx> {
}
// `Context` is cloned a lot, so we don't want the size to grow unexpectedly.
#[cfg(all(not(windows), target_arch = "x86_64", target_pointer_width = "64"))]
#[cfg(all(not(windows), target_pointer_width = "64"))]
rustc_data_structures::static_assert_size!(Context<'_>, 160);
#[cfg(all(windows, target_pointer_width = "64"))]
rustc_data_structures::static_assert_size!(Context<'_>, 168);
/// Shared mutable state used in [`Context`] and elsewhere.
pub(crate) struct SharedContext<'tcx> {

View file

@ -111,11 +111,13 @@ pub(crate) enum RenderMode {
#[derive(Debug)]
pub(crate) struct IndexItem {
pub(crate) ty: ItemType,
pub(crate) defid: Option<DefId>,
pub(crate) name: Symbol,
pub(crate) path: String,
pub(crate) desc: String,
pub(crate) parent: Option<DefId>,
pub(crate) parent_idx: Option<isize>,
pub(crate) exact_path: Option<String>,
pub(crate) impl_id: Option<DefId>,
pub(crate) search_type: Option<IndexItemFunctionType>,
pub(crate) aliases: Box<[Symbol]>,

View file

@ -59,10 +59,13 @@ pub(crate) fn build_index<'tcx>(
cache: &mut Cache,
tcx: TyCtxt<'tcx>,
) -> SerializedSearchIndex {
// Maps from ID to position in the `crate_paths` array.
let mut itemid_to_pathid = FxHashMap::default();
let mut primitives = FxHashMap::default();
let mut associated_types = FxHashMap::default();
let mut crate_paths = vec![];
// item type, display path, re-exported internal path
let mut crate_paths: Vec<(ItemType, Vec<Symbol>, Option<Vec<Symbol>>)> = vec![];
// Attach all orphan items to the type's definition if the type
// has since been learned.
@ -72,11 +75,13 @@ pub(crate) fn build_index<'tcx>(
let desc = short_markdown_summary(&item.doc_value(), &item.link_names(cache));
cache.search_index.push(IndexItem {
ty: item.type_(),
defid: item.item_id.as_def_id(),
name: item.name.unwrap(),
path: join_with_double_colon(&fqp[..fqp.len() - 1]),
desc,
parent: Some(parent),
parent_idx: None,
exact_path: None,
impl_id,
search_type: get_function_type_for_search(
item,
@ -126,9 +131,10 @@ pub(crate) fn build_index<'tcx>(
map: &mut FxHashMap<F, isize>,
itemid: F,
lastpathid: &mut isize,
crate_paths: &mut Vec<(ItemType, Vec<Symbol>)>,
crate_paths: &mut Vec<(ItemType, Vec<Symbol>, Option<Vec<Symbol>>)>,
item_type: ItemType,
path: &[Symbol],
exact_path: Option<&[Symbol]>,
) -> RenderTypeId {
match map.entry(itemid) {
Entry::Occupied(entry) => RenderTypeId::Index(*entry.get()),
@ -136,7 +142,11 @@ pub(crate) fn build_index<'tcx>(
let pathid = *lastpathid;
entry.insert(pathid);
*lastpathid += 1;
crate_paths.push((item_type, path.to_vec()));
crate_paths.push((
item_type,
path.to_vec(),
exact_path.map(|path| path.to_vec()),
));
RenderTypeId::Index(pathid)
}
}
@ -149,14 +159,24 @@ pub(crate) fn build_index<'tcx>(
primitives: &mut FxHashMap<Symbol, isize>,
associated_types: &mut FxHashMap<Symbol, isize>,
lastpathid: &mut isize,
crate_paths: &mut Vec<(ItemType, Vec<Symbol>)>,
crate_paths: &mut Vec<(ItemType, Vec<Symbol>, Option<Vec<Symbol>>)>,
) -> Option<RenderTypeId> {
let Cache { ref paths, ref external_paths, .. } = *cache;
let Cache { ref paths, ref external_paths, ref exact_paths, .. } = *cache;
match id {
RenderTypeId::DefId(defid) => {
if let Some(&(ref fqp, item_type)) =
paths.get(&defid).or_else(|| external_paths.get(&defid))
{
let exact_fqp = exact_paths
.get(&defid)
.or_else(|| external_paths.get(&defid).map(|&(ref fqp, _)| fqp))
// Re-exports only count if the name is exactly the same.
// This is a size optimization, since it means we only need
// to store the name once (and the path is re-used for everything
// exported from this same module). It's also likely to Do
// What I Mean, since if a re-export changes the name, it might
// also be a change in semantic meaning.
.filter(|fqp| fqp.last() == fqp.last());
Some(insert_into_map(
itemid_to_pathid,
ItemId::DefId(defid),
@ -164,6 +184,7 @@ pub(crate) fn build_index<'tcx>(
crate_paths,
item_type,
fqp,
exact_fqp.map(|x| &x[..]).filter(|exact_fqp| exact_fqp != fqp),
))
} else {
None
@ -178,6 +199,7 @@ pub(crate) fn build_index<'tcx>(
crate_paths,
ItemType::Primitive,
&[sym],
None,
))
}
RenderTypeId::Index(_) => Some(id),
@ -188,6 +210,7 @@ pub(crate) fn build_index<'tcx>(
crate_paths,
ItemType::AssocType,
&[sym],
None,
)),
}
}
@ -199,7 +222,7 @@ pub(crate) fn build_index<'tcx>(
primitives: &mut FxHashMap<Symbol, isize>,
associated_types: &mut FxHashMap<Symbol, isize>,
lastpathid: &mut isize,
crate_paths: &mut Vec<(ItemType, Vec<Symbol>)>,
crate_paths: &mut Vec<(ItemType, Vec<Symbol>, Option<Vec<Symbol>>)>,
) {
if let Some(generics) = &mut ty.generics {
for item in generics {
@ -296,7 +319,7 @@ pub(crate) fn build_index<'tcx>(
}
}
let Cache { ref paths, .. } = *cache;
let Cache { ref paths, ref exact_paths, ref external_paths, .. } = *cache;
// Then, on parent modules
let crate_items: Vec<&IndexItem> = search_index
@ -311,7 +334,13 @@ pub(crate) fn build_index<'tcx>(
lastpathid += 1;
if let Some(&(ref fqp, short)) = paths.get(&defid) {
crate_paths.push((short, fqp.clone()));
let exact_fqp = exact_paths
.get(&defid)
.or_else(|| external_paths.get(&defid).map(|&(ref fqp, _)| fqp))
.filter(|exact_fqp| {
exact_fqp.last() == Some(&item.name) && *exact_fqp != fqp
});
crate_paths.push((short, fqp.clone(), exact_fqp.cloned()));
Some(pathid)
} else {
None
@ -319,6 +348,42 @@ pub(crate) fn build_index<'tcx>(
}
});
if let Some(defid) = item.defid
&& item.parent_idx.is_none()
{
// If this is a re-export, retain the original path.
// Associated items don't use this.
// Their parent carries the exact fqp instead.
let exact_fqp = exact_paths
.get(&defid)
.or_else(|| external_paths.get(&defid).map(|&(ref fqp, _)| fqp));
item.exact_path = exact_fqp.and_then(|fqp| {
// Re-exports only count if the name is exactly the same.
// This is a size optimization, since it means we only need
// to store the name once (and the path is re-used for everything
// exported from this same module). It's also likely to Do
// What I Mean, since if a re-export changes the name, it might
// also be a change in semantic meaning.
if fqp.last() != Some(&item.name) {
return None;
}
let path =
if item.ty == ItemType::Macro && tcx.has_attr(defid, sym::macro_export) {
// `#[macro_export]` always exports to the crate root.
tcx.crate_name(defid.krate).to_string()
} else {
if fqp.len() < 2 {
return None;
}
join_with_double_colon(&fqp[..fqp.len() - 1])
};
if path == item.path {
return None;
}
Some(path)
});
}
// Omit the parent path if it is same to that of the prior item.
if lastpath == &item.path {
item.path.clear();
@ -356,7 +421,7 @@ pub(crate) fn build_index<'tcx>(
struct CrateData<'a> {
items: Vec<&'a IndexItem>,
paths: Vec<(ItemType, Vec<Symbol>)>,
paths: Vec<(ItemType, Vec<Symbol>, Option<Vec<Symbol>>)>,
// The String is alias name and the vec is the list of the elements with this alias.
//
// To be noted: the `usize` elements are indexes to `items`.
@ -374,6 +439,7 @@ pub(crate) fn build_index<'tcx>(
ty: ItemType,
name: Symbol,
path: Option<usize>,
exact_path: Option<usize>,
}
impl Serialize for Paths {
@ -387,6 +453,10 @@ pub(crate) fn build_index<'tcx>(
if let Some(ref path) = self.path {
seq.serialize_element(path)?;
}
if let Some(ref path) = self.exact_path {
assert!(self.path.is_some());
seq.serialize_element(path)?;
}
seq.end()
}
}
@ -409,14 +479,39 @@ pub(crate) fn build_index<'tcx>(
mod_paths.insert(&item.path, index);
}
let mut paths = Vec::with_capacity(self.paths.len());
for (ty, path) in &self.paths {
for (ty, path, exact) in &self.paths {
if path.len() < 2 {
paths.push(Paths { ty: *ty, name: path[0], path: None });
paths.push(Paths { ty: *ty, name: path[0], path: None, exact_path: None });
continue;
}
let full_path = join_with_double_colon(&path[..path.len() - 1]);
let full_exact_path = exact
.as_ref()
.filter(|exact| exact.last() == path.last() && exact.len() >= 2)
.map(|exact| join_with_double_colon(&exact[..exact.len() - 1]));
let exact_path = extra_paths.len() + self.items.len();
let exact_path = full_exact_path.as_ref().map(|full_exact_path| match extra_paths
.entry(full_exact_path.clone())
{
Entry::Occupied(entry) => *entry.get(),
Entry::Vacant(entry) => {
if let Some(index) = mod_paths.get(&full_exact_path) {
return *index;
}
entry.insert(exact_path);
if !revert_extra_paths.contains_key(&exact_path) {
revert_extra_paths.insert(exact_path, full_exact_path.clone());
}
exact_path
}
});
if let Some(index) = mod_paths.get(&full_path) {
paths.push(Paths { ty: *ty, name: *path.last().unwrap(), path: Some(*index) });
paths.push(Paths {
ty: *ty,
name: *path.last().unwrap(),
path: Some(*index),
exact_path,
});
continue;
}
// It means it comes from an external crate so the item and its path will be
@ -424,28 +519,54 @@ pub(crate) fn build_index<'tcx>(
//
// `index` is put after the last `mod_paths`
let index = extra_paths.len() + self.items.len();
if !revert_extra_paths.contains_key(&index) {
revert_extra_paths.insert(index, full_path.clone());
}
match extra_paths.entry(full_path) {
match extra_paths.entry(full_path.clone()) {
Entry::Occupied(entry) => {
paths.push(Paths {
ty: *ty,
name: *path.last().unwrap(),
path: Some(*entry.get()),
exact_path,
});
}
Entry::Vacant(entry) => {
entry.insert(index);
if !revert_extra_paths.contains_key(&index) {
revert_extra_paths.insert(index, full_path);
}
paths.push(Paths {
ty: *ty,
name: *path.last().unwrap(),
path: Some(index),
exact_path,
});
}
}
}
// Direct exports use adjacent arrays for the current crate's items,
// but re-exported exact paths don't.
let mut re_exports = Vec::new();
for (item_index, item) in self.items.iter().enumerate() {
if let Some(exact_path) = item.exact_path.as_ref() {
if let Some(path_index) = mod_paths.get(&exact_path) {
re_exports.push((item_index, *path_index));
} else {
let path_index = extra_paths.len() + self.items.len();
let path_index = match extra_paths.entry(exact_path.clone()) {
Entry::Occupied(entry) => *entry.get(),
Entry::Vacant(entry) => {
entry.insert(path_index);
if !revert_extra_paths.contains_key(&path_index) {
revert_extra_paths.insert(path_index, exact_path.clone());
}
path_index
}
};
re_exports.push((item_index, path_index));
}
}
}
let mut names = Vec::with_capacity(self.items.len());
let mut types = String::with_capacity(self.items.len());
let mut full_paths = Vec::with_capacity(self.items.len());
@ -501,6 +622,7 @@ pub(crate) fn build_index<'tcx>(
crate_data.serialize_field("f", &functions)?;
crate_data.serialize_field("D", &self.desc_index)?;
crate_data.serialize_field("p", &paths)?;
crate_data.serialize_field("r", &re_exports)?;
crate_data.serialize_field("b", &self.associated_item_disambiguators)?;
crate_data.serialize_field("c", &bitmap_to_string(&deprecated))?;
crate_data.serialize_field("e", &bitmap_to_string(&self.empty_desc))?;

View file

@ -1627,24 +1627,27 @@ a.tooltip:hover::after {
color: var(--copy-path-button-color);
background: var(--main-background-color);
height: 34px;
width: 33px;
margin-left: 10px;
padding: 0;
padding-left: 2px;
border: 0;
width: 33px;
line-height: 0;
font-size: 0;
}
#copy-path:before {
#copy-path::before {
filter: var(--copy-path-img-filter);
content: url('clipboard-24048e6d87f63d07.svg');
width: 19px;
height: 18px;
}
#copy-path:hover:before {
#copy-path:hover::before {
filter: var(--copy-path-img-hover-filter);
}
#copy-path.clicked::before {
/* Checkmark <https://www.svgrepo.com/svg/335033/checkmark> */
content: url('data:image/svg+xml,<svg viewBox="-1 -1 23 23" xmlns="http://www.w3.org/2000/svg" \
fill="black" height="18px">\
<g><path d="M9 19.414l-6.707-6.707 1.414-1.414L9 16.586 20.293 5.293l1.414 1.414"></path>\
</g></svg>');
}
@keyframes rotating {
from {

View file

@ -239,20 +239,27 @@ let FunctionType;
* `doc` contains the description of the crate.
*
* `p` is a list of path/type pairs. It is used for parents and function parameters.
* The first item is the type, the second is the name, the third is the visible path (if any) and
* the fourth is the canonical path used for deduplication (if any).
*
* `r` is the canonical path used for deduplication of re-exported items.
* It is not used for associated items like methods (that's the fourth element
* of `p`) but is used for modules items like free functions.
*
* `c` is an array of item indices that are deprecated.
* @typedef {{
* doc: string,
* a: Object,
* n: Array<string>,
* t: String,
* t: string,
* d: Array<string>,
* q: Array<[Number, string]>,
* i: Array<Number>,
* q: Array<[number, string]>,
* i: Array<number>,
* f: string,
* p: Array<Object>,
* b: Array<[Number, String]>,
* c: Array<Number>
* p: Array<[number, string] | [number, string, number] | [number, string, number, number]>,
* b: Array<[number, String]>,
* c: Array<number>,
* r: Array<[number, number]>,
* }}
*/
let RawSearchIndexCrate;

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