Auto merge of #3828 - rust-lang:rustup-2024-08-20, r=RalfJung
Automatic Rustup
This commit is contained in:
commit
0305cee39a
1169 changed files with 12078 additions and 10426 deletions
|
|
@ -25,3 +25,5 @@ b2d2184edea578109a48ec3d8decbee5948e8f35
|
|||
ec2cc761bc7067712ecc7734502f703fe3b024c8
|
||||
# format use declarations
|
||||
84ac80f1921afc243d71fd0caaa4f2838c294102
|
||||
# bless mir-opt tests to add `copy`
|
||||
99cb0c6bc399fb94a0ddde7e9b38e9c00d523bad
|
||||
|
|
|
|||
663
Cargo.lock
663
Cargo.lock
File diff suppressed because it is too large
Load diff
|
|
@ -1,5 +1,5 @@
|
|||
[workspace]
|
||||
resolver = "1"
|
||||
resolver = "2"
|
||||
members = [
|
||||
"compiler/rustc",
|
||||
"src/etc/test-float-parse",
|
||||
|
|
|
|||
|
|
@ -189,7 +189,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
) -> hir::FnSig<'hir> {
|
||||
let header = if let Some(local_sig_id) = sig_id.as_local() {
|
||||
match self.resolver.delegation_fn_sigs.get(&local_sig_id) {
|
||||
Some(sig) => self.lower_fn_header(sig.header),
|
||||
Some(sig) => self.lower_fn_header(sig.header, hir::Safety::Safe),
|
||||
None => self.generate_header_error(),
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -237,7 +237,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
});
|
||||
let sig = hir::FnSig {
|
||||
decl,
|
||||
header: this.lower_fn_header(*header),
|
||||
header: this.lower_fn_header(*header, hir::Safety::Safe),
|
||||
span: this.lower_span(*fn_sig_span),
|
||||
};
|
||||
hir::ItemKind::Fn(sig, generics, body_id)
|
||||
|
|
@ -668,7 +668,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
ForeignItemKind::Fn(box Fn { sig, generics, .. }) => {
|
||||
let fdec = &sig.decl;
|
||||
let itctx = ImplTraitContext::Universal;
|
||||
let (generics, (fn_dec, fn_args)) =
|
||||
let (generics, (decl, fn_args)) =
|
||||
self.lower_generics(generics, Const::No, false, i.id, itctx, |this| {
|
||||
(
|
||||
// Disallow `impl Trait` in foreign items.
|
||||
|
|
@ -682,9 +682,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
this.lower_fn_params_to_names(fdec),
|
||||
)
|
||||
});
|
||||
let safety = self.lower_safety(sig.header.safety, hir::Safety::Unsafe);
|
||||
|
||||
hir::ForeignItemKind::Fn(fn_dec, fn_args, generics, safety)
|
||||
// Unmarked safety in unsafe block defaults to unsafe.
|
||||
let header = self.lower_fn_header(sig.header, hir::Safety::Unsafe);
|
||||
|
||||
hir::ForeignItemKind::Fn(
|
||||
hir::FnSig { header, decl, span: self.lower_span(sig.span) },
|
||||
fn_args,
|
||||
generics,
|
||||
)
|
||||
}
|
||||
ForeignItemKind::Static(box StaticItem { ty, mutability, expr: _, safety }) => {
|
||||
let ty = self
|
||||
|
|
@ -1390,7 +1396,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
coroutine_kind: Option<CoroutineKind>,
|
||||
parent_constness: Const,
|
||||
) -> (&'hir hir::Generics<'hir>, hir::FnSig<'hir>) {
|
||||
let header = self.lower_fn_header(sig.header);
|
||||
let header = self.lower_fn_header(sig.header, hir::Safety::Safe);
|
||||
// Don't pass along the user-provided constness of trait associated functions; we don't want to
|
||||
// synthesize a host effect param for them. We reject `const` on them during AST validation.
|
||||
let constness =
|
||||
|
|
@ -1403,14 +1409,18 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
(generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) })
|
||||
}
|
||||
|
||||
pub(super) fn lower_fn_header(&mut self, h: FnHeader) -> hir::FnHeader {
|
||||
pub(super) fn lower_fn_header(
|
||||
&mut self,
|
||||
h: FnHeader,
|
||||
default_safety: hir::Safety,
|
||||
) -> hir::FnHeader {
|
||||
let asyncness = if let Some(CoroutineKind::Async { span, .. }) = h.coroutine_kind {
|
||||
hir::IsAsync::Async(span)
|
||||
} else {
|
||||
hir::IsAsync::NotAsync
|
||||
};
|
||||
hir::FnHeader {
|
||||
safety: self.lower_safety(h.safety, hir::Safety::Safe),
|
||||
safety: self.lower_safety(h.safety, default_safety),
|
||||
asyncness: asyncness,
|
||||
constness: self.lower_constness(h.constness),
|
||||
abi: self.lower_extern(h.ext),
|
||||
|
|
|
|||
|
|
@ -887,7 +887,7 @@ fn validate_generic_param_order(dcx: DiagCtxtHandle<'_>, generics: &[GenericPara
|
|||
|
||||
impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||
fn visit_attribute(&mut self, attr: &Attribute) {
|
||||
validate_attr::check_attr(&self.features, &self.session.psess, attr);
|
||||
validate_attr::check_attr(&self.session.psess, attr);
|
||||
}
|
||||
|
||||
fn visit_ty(&mut self, ty: &'a Ty) {
|
||||
|
|
|
|||
|
|
@ -539,7 +539,6 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
|
|||
}
|
||||
}
|
||||
gate_all!(gen_blocks, "gen blocks are experimental");
|
||||
gate_all!(raw_ref_op, "raw address of syntax is experimental");
|
||||
gate_all!(const_trait_impl, "const trait impls are experimental");
|
||||
gate_all!(
|
||||
half_open_range_patterns_in_slices,
|
||||
|
|
@ -559,7 +558,6 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
|
|||
gate_all!(mut_ref, "mutable by-reference bindings are experimental");
|
||||
gate_all!(precise_capturing, "precise captures on `impl Trait` are experimental");
|
||||
gate_all!(global_registration, "global registration is experimental");
|
||||
gate_all!(unsafe_attributes, "`#[unsafe()]` markers for attributes are experimental");
|
||||
gate_all!(return_type_notation, "return type notation is experimental");
|
||||
|
||||
if !visitor.features.never_patterns {
|
||||
|
|
|
|||
|
|
@ -55,8 +55,8 @@ pub fn categorize(context: PlaceContext) -> Option<DefUse> {
|
|||
PlaceContext::NonMutatingUse(NonMutatingUseContext::PlaceMention) |
|
||||
PlaceContext::NonUse(NonUseContext::AscribeUserTy(_)) |
|
||||
|
||||
PlaceContext::MutatingUse(MutatingUseContext::AddressOf) |
|
||||
PlaceContext::NonMutatingUse(NonMutatingUseContext::AddressOf) |
|
||||
PlaceContext::MutatingUse(MutatingUseContext::RawBorrow) |
|
||||
PlaceContext::NonMutatingUse(NonMutatingUseContext::RawBorrow) |
|
||||
PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect) |
|
||||
PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) |
|
||||
PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) |
|
||||
|
|
|
|||
|
|
@ -1242,7 +1242,7 @@ impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> {
|
|||
);
|
||||
}
|
||||
|
||||
&Rvalue::AddressOf(mutability, place) => {
|
||||
&Rvalue::RawPtr(mutability, place) => {
|
||||
let access_kind = match mutability {
|
||||
Mutability::Mut => (
|
||||
Deep,
|
||||
|
|
|
|||
|
|
@ -269,7 +269,7 @@ impl<'cx, 'tcx> LoanInvalidationsGenerator<'cx, 'tcx> {
|
|||
self.access_place(location, place, access_kind, LocalMutationIsAllowed::No);
|
||||
}
|
||||
|
||||
&Rvalue::AddressOf(mutability, place) => {
|
||||
&Rvalue::RawPtr(mutability, place) => {
|
||||
let access_kind = match mutability {
|
||||
Mutability::Mut => (
|
||||
Deep,
|
||||
|
|
|
|||
|
|
@ -756,7 +756,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
|
|||
PlaceContext::MutatingUse(_) => ty::Invariant,
|
||||
PlaceContext::NonUse(StorageDead | StorageLive | VarDebugInfo) => ty::Invariant,
|
||||
PlaceContext::NonMutatingUse(
|
||||
Inspect | Copy | Move | PlaceMention | SharedBorrow | FakeBorrow | AddressOf
|
||||
Inspect | Copy | Move | PlaceMention | SharedBorrow | FakeBorrow | RawBorrow
|
||||
| Projection,
|
||||
) => ty::Covariant,
|
||||
PlaceContext::NonUse(AscribeUserTy(variance)) => variance,
|
||||
|
|
@ -2468,7 +2468,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
self.check_operand(right, location);
|
||||
}
|
||||
|
||||
Rvalue::AddressOf(..)
|
||||
Rvalue::RawPtr(..)
|
||||
| Rvalue::ThreadLocalRef(..)
|
||||
| Rvalue::Len(..)
|
||||
| Rvalue::Discriminant(..)
|
||||
|
|
@ -2485,7 +2485,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
| Rvalue::ThreadLocalRef(_)
|
||||
| Rvalue::Repeat(..)
|
||||
| Rvalue::Ref(..)
|
||||
| Rvalue::AddressOf(..)
|
||||
| Rvalue::RawPtr(..)
|
||||
| Rvalue::Len(..)
|
||||
| Rvalue::Cast(..)
|
||||
| Rvalue::ShallowInitBox(..)
|
||||
|
|
|
|||
|
|
@ -47,7 +47,6 @@ impl MultiItemModifier for Expander {
|
|||
) -> ExpandResult<Vec<Annotatable>, Annotatable> {
|
||||
let template = AttributeTemplate { list: Some("path"), ..Default::default() };
|
||||
validate_attr::check_builtin_meta_item(
|
||||
&ecx.ecfg.features,
|
||||
&ecx.sess.psess,
|
||||
meta_item,
|
||||
ast::AttrStyle::Outer,
|
||||
|
|
|
|||
|
|
@ -38,7 +38,6 @@ impl MultiItemModifier for Expander {
|
|||
let template =
|
||||
AttributeTemplate { list: Some("Trait1, Trait2, ..."), ..Default::default() };
|
||||
validate_attr::check_builtin_meta_item(
|
||||
features,
|
||||
&sess.psess,
|
||||
meta_item,
|
||||
ast::AttrStyle::Outer,
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ pub(crate) fn check_builtin_macro_attribute(ecx: &ExtCtxt<'_>, meta_item: &MetaI
|
|||
// All the built-in macro attributes are "words" at the moment.
|
||||
let template = AttributeTemplate { word: true, ..Default::default() };
|
||||
validate_attr::check_builtin_meta_item(
|
||||
&ecx.ecfg.features,
|
||||
&ecx.sess.psess,
|
||||
meta_item,
|
||||
AttrStyle::Outer,
|
||||
|
|
|
|||
|
|
@ -6,8 +6,7 @@
|
|||
extern_types,
|
||||
naked_functions,
|
||||
thread_local,
|
||||
repr_simd,
|
||||
raw_ref_op
|
||||
repr_simd
|
||||
)]
|
||||
#![no_core]
|
||||
#![allow(dead_code, non_camel_case_types, internal_features)]
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ pub(crate) fn analyze(fx: &FunctionCx<'_, '_, '_>) -> IndexVec<Local, SsaKind> {
|
|||
for stmt in bb.statements.iter() {
|
||||
match &stmt.kind {
|
||||
Assign(place_and_rval) => match &place_and_rval.1 {
|
||||
Rvalue::Ref(_, _, place) | Rvalue::AddressOf(_, place) => {
|
||||
Rvalue::Ref(_, _, place) | Rvalue::RawPtr(_, place) => {
|
||||
flag_map[place.local] = SsaKind::NotSsa;
|
||||
}
|
||||
_ => {}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,6 @@
|
|||
use std::borrow::Borrow;
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
|
||||
use ar_archive_writer::{COFFShortExport, MachineTypes};
|
||||
use rustc_codegen_ssa::back::archive::{
|
||||
create_mingw_dll_import_lib, ArArchiveBuilder, ArchiveBuilder, ArchiveBuilderBuilder,
|
||||
DEFAULT_OBJECT_READER,
|
||||
ArArchiveBuilder, ArchiveBuilder, ArchiveBuilderBuilder, DEFAULT_OBJECT_READER,
|
||||
};
|
||||
use rustc_codegen_ssa::common::is_mingw_gnu_toolchain;
|
||||
use rustc_session::Session;
|
||||
|
||||
pub(crate) struct ArArchiveBuilderBuilder;
|
||||
|
|
@ -16,78 +9,4 @@ impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder {
|
|||
fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder + 'a> {
|
||||
Box::new(ArArchiveBuilder::new(sess, &DEFAULT_OBJECT_READER))
|
||||
}
|
||||
|
||||
fn create_dll_import_lib(
|
||||
&self,
|
||||
sess: &Session,
|
||||
lib_name: &str,
|
||||
import_name_and_ordinal_vector: Vec<(String, Option<u16>)>,
|
||||
output_path: &Path,
|
||||
) {
|
||||
if is_mingw_gnu_toolchain(&sess.target) {
|
||||
// The binutils linker used on -windows-gnu targets cannot read the import
|
||||
// libraries generated by LLVM: in our attempts, the linker produced an .EXE
|
||||
// that loaded but crashed with an AV upon calling one of the imported
|
||||
// functions. Therefore, use binutils to create the import library instead,
|
||||
// by writing a .DEF file to the temp dir and calling binutils's dlltool.
|
||||
create_mingw_dll_import_lib(
|
||||
sess,
|
||||
lib_name,
|
||||
import_name_and_ordinal_vector,
|
||||
output_path,
|
||||
);
|
||||
} else {
|
||||
let mut file =
|
||||
match fs::OpenOptions::new().write(true).create_new(true).open(&output_path) {
|
||||
Ok(file) => file,
|
||||
Err(error) => {
|
||||
sess.dcx().fatal(format!(
|
||||
"failed to create import library file `{path}`: {error}",
|
||||
path = output_path.display(),
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
let machine = match sess.target.arch.borrow() {
|
||||
"x86" => MachineTypes::I386,
|
||||
"x86_64" => MachineTypes::AMD64,
|
||||
"arm" => MachineTypes::ARMNT,
|
||||
"aarch64" => MachineTypes::ARM64,
|
||||
_ => {
|
||||
sess.dcx().fatal(format!(
|
||||
"unsupported target architecture `{arch}`",
|
||||
arch = sess.target.arch,
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
let exports = import_name_and_ordinal_vector
|
||||
.iter()
|
||||
.map(|(name, ordinal)| COFFShortExport {
|
||||
name: name.to_string(),
|
||||
ext_name: None,
|
||||
symbol_name: None,
|
||||
alias_target: None,
|
||||
ordinal: ordinal.unwrap_or(0),
|
||||
noname: ordinal.is_some(),
|
||||
data: false,
|
||||
private: false,
|
||||
constant: false,
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
if let Err(error) = ar_archive_writer::write_import_library(
|
||||
&mut file,
|
||||
lib_name,
|
||||
&exports,
|
||||
machine,
|
||||
!sess.target.is_like_msvc,
|
||||
) {
|
||||
sess.dcx().fatal(format!(
|
||||
"failed to create import library `{path}`: `{error}`",
|
||||
path = output_path.display(),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -595,7 +595,7 @@ fn codegen_stmt<'tcx>(
|
|||
let val = cplace.to_cvalue(fx);
|
||||
lval.write_cvalue(fx, val)
|
||||
}
|
||||
Rvalue::Ref(_, _, place) | Rvalue::AddressOf(_, place) => {
|
||||
Rvalue::Ref(_, _, place) | Rvalue::RawPtr(_, place) => {
|
||||
let place = codegen_place(fx, place);
|
||||
let ref_ = place.place_ref(fx, lval.layout());
|
||||
lval.write_cvalue(fx, ref_);
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@
|
|||
#![warn(unused_lifetimes)]
|
||||
// tidy-alphabetical-end
|
||||
|
||||
extern crate ar_archive_writer;
|
||||
extern crate jobserver;
|
||||
#[macro_use]
|
||||
extern crate rustc_middle;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
#![feature(
|
||||
no_core, unboxed_closures, start, lang_items, never_type, linkage,
|
||||
extern_types, thread_local, raw_ref_op
|
||||
extern_types, thread_local
|
||||
)]
|
||||
#![no_core]
|
||||
#![allow(dead_code, internal_features, non_camel_case_types)]
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ bitflags = "2.4.1"
|
|||
itertools = "0.12"
|
||||
libc = "0.2"
|
||||
measureme = "11"
|
||||
object = { version = "0.36.2", default-features = false, features = ["std", "read"] }
|
||||
object = { version = "0.36.3", default-features = false, features = ["std", "read"] }
|
||||
rustc-demangle = "0.1.21"
|
||||
rustc_ast = { path = "../rustc_ast" }
|
||||
rustc_attr = { path = "../rustc_attr" }
|
||||
|
|
|
|||
|
|
@ -5,9 +5,6 @@ codegen_llvm_dynamic_linking_with_lto =
|
|||
.note = only 'staticlib', 'bin', and 'cdylib' outputs are supported with LTO
|
||||
|
||||
|
||||
codegen_llvm_error_creating_import_library =
|
||||
Error creating import library for {$lib_name}: {$error}
|
||||
|
||||
codegen_llvm_fixed_x18_invalid_arch = the `-Zfixed-x18` flag is not supported on the `{$arch}` architecture
|
||||
|
||||
codegen_llvm_from_llvm_diag = {$message}
|
||||
|
|
|
|||
|
|
@ -5,17 +5,13 @@ use std::path::{Path, PathBuf};
|
|||
use std::{io, mem, ptr, str};
|
||||
|
||||
use rustc_codegen_ssa::back::archive::{
|
||||
create_mingw_dll_import_lib, try_extract_macho_fat_archive, ArArchiveBuilder,
|
||||
ArchiveBuildFailure, ArchiveBuilder, ArchiveBuilderBuilder, ObjectReader, UnknownArchiveKind,
|
||||
DEFAULT_OBJECT_READER,
|
||||
try_extract_macho_fat_archive, ArArchiveBuilder, ArchiveBuildFailure, ArchiveBuilder,
|
||||
ArchiveBuilderBuilder, ObjectReader, UnknownArchiveKind, DEFAULT_OBJECT_READER,
|
||||
};
|
||||
use rustc_codegen_ssa::common;
|
||||
use rustc_session::Session;
|
||||
use tracing::trace;
|
||||
|
||||
use crate::errors::ErrorCreatingImportLibrary;
|
||||
use crate::llvm::archive_ro::{ArchiveRO, Child};
|
||||
use crate::llvm::{self, ArchiveKind, LLVMMachineType, LLVMRustCOFFShortExport};
|
||||
use crate::llvm::{self, ArchiveKind};
|
||||
|
||||
/// Helper for adding many files to an archive.
|
||||
#[must_use = "must call build() to finish building the archive"]
|
||||
|
|
@ -44,18 +40,6 @@ fn is_relevant_child(c: &Child<'_>) -> bool {
|
|||
}
|
||||
}
|
||||
|
||||
/// Map machine type strings to values of LLVM's MachineTypes enum.
|
||||
fn llvm_machine_type(cpu: &str) -> LLVMMachineType {
|
||||
match cpu {
|
||||
"x86_64" => LLVMMachineType::AMD64,
|
||||
"x86" => LLVMMachineType::I386,
|
||||
"aarch64" => LLVMMachineType::ARM64,
|
||||
"arm64ec" => LLVMMachineType::ARM64EC,
|
||||
"arm" => LLVMMachineType::ARM,
|
||||
_ => panic!("unsupported cpu type {cpu}"),
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ArchiveBuilder for LlvmArchiveBuilder<'a> {
|
||||
fn add_archive(
|
||||
&mut self,
|
||||
|
|
@ -116,78 +100,6 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
|
|||
Box::new(ArArchiveBuilder::new(sess, &LLVM_OBJECT_READER))
|
||||
}
|
||||
}
|
||||
|
||||
fn create_dll_import_lib(
|
||||
&self,
|
||||
sess: &Session,
|
||||
lib_name: &str,
|
||||
import_name_and_ordinal_vector: Vec<(String, Option<u16>)>,
|
||||
output_path: &Path,
|
||||
) {
|
||||
if common::is_mingw_gnu_toolchain(&sess.target) {
|
||||
// The binutils linker used on -windows-gnu targets cannot read the import
|
||||
// libraries generated by LLVM: in our attempts, the linker produced an .EXE
|
||||
// that loaded but crashed with an AV upon calling one of the imported
|
||||
// functions. Therefore, use binutils to create the import library instead,
|
||||
// by writing a .DEF file to the temp dir and calling binutils's dlltool.
|
||||
create_mingw_dll_import_lib(
|
||||
sess,
|
||||
lib_name,
|
||||
import_name_and_ordinal_vector,
|
||||
output_path,
|
||||
);
|
||||
} else {
|
||||
// we've checked for \0 characters in the library name already
|
||||
let dll_name_z = CString::new(lib_name).unwrap();
|
||||
|
||||
let output_path_z = rustc_fs_util::path_to_c_string(&output_path);
|
||||
|
||||
trace!("invoking LLVMRustWriteImportLibrary");
|
||||
trace!(" dll_name {:#?}", dll_name_z);
|
||||
trace!(" output_path {}", output_path.display());
|
||||
trace!(
|
||||
" import names: {}",
|
||||
import_name_and_ordinal_vector
|
||||
.iter()
|
||||
.map(|(name, _ordinal)| name.clone())
|
||||
.collect::<Vec<_>>()
|
||||
.join(", "),
|
||||
);
|
||||
|
||||
// All import names are Rust identifiers and therefore cannot contain \0 characters.
|
||||
// FIXME: when support for #[link_name] is implemented, ensure that the import names
|
||||
// still don't contain any \0 characters. Also need to check that the names don't
|
||||
// contain substrings like " @" or "NONAME" that are keywords or otherwise reserved
|
||||
// in definition files.
|
||||
let cstring_import_name_and_ordinal_vector: Vec<(CString, Option<u16>)> =
|
||||
import_name_and_ordinal_vector
|
||||
.into_iter()
|
||||
.map(|(name, ordinal)| (CString::new(name).unwrap(), ordinal))
|
||||
.collect();
|
||||
|
||||
let ffi_exports: Vec<LLVMRustCOFFShortExport> = cstring_import_name_and_ordinal_vector
|
||||
.iter()
|
||||
.map(|(name_z, ordinal)| LLVMRustCOFFShortExport::new(name_z.as_ptr(), *ordinal))
|
||||
.collect();
|
||||
let result = unsafe {
|
||||
crate::llvm::LLVMRustWriteImportLibrary(
|
||||
dll_name_z.as_ptr(),
|
||||
output_path_z.as_ptr(),
|
||||
ffi_exports.as_ptr(),
|
||||
ffi_exports.len(),
|
||||
llvm_machine_type(&sess.target.arch) as u16,
|
||||
!sess.target.is_like_msvc,
|
||||
)
|
||||
};
|
||||
|
||||
if result == crate::llvm::LLVMRustResult::Failure {
|
||||
sess.dcx().emit_fatal(ErrorCreatingImportLibrary {
|
||||
lib_name,
|
||||
error: llvm::last_error().unwrap_or("unknown LLVM error".to_string()),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The object crate doesn't know how to get symbols for LLVM bitcode and COFF bigobj files.
|
||||
|
|
|
|||
|
|
@ -1000,8 +1000,10 @@ impl<'ll> CodegenCx<'ll, '_> {
|
|||
ifn!("llvm.is.constant.i64", fn(t_i64) -> i1);
|
||||
ifn!("llvm.is.constant.i128", fn(t_i128) -> i1);
|
||||
ifn!("llvm.is.constant.isize", fn(t_isize) -> i1);
|
||||
ifn!("llvm.is.constant.f16", fn(t_f16) -> i1);
|
||||
ifn!("llvm.is.constant.f32", fn(t_f32) -> i1);
|
||||
ifn!("llvm.is.constant.f64", fn(t_f64) -> i1);
|
||||
ifn!("llvm.is.constant.f128", fn(t_f128) -> i1);
|
||||
ifn!("llvm.is.constant.ptr", fn(ptr) -> i1);
|
||||
|
||||
ifn!("llvm.expect.i1", fn(i1, i1) -> i1);
|
||||
|
|
|
|||
|
|
@ -39,13 +39,6 @@ pub(crate) enum PossibleFeature<'a> {
|
|||
None,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_error_creating_import_library)]
|
||||
pub(crate) struct ErrorCreatingImportLibrary<'a> {
|
||||
pub lib_name: &'a str,
|
||||
pub error: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_symbol_already_defined)]
|
||||
pub(crate) struct SymbolAlreadyDefined<'a> {
|
||||
|
|
|
|||
|
|
@ -192,14 +192,22 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> {
|
|||
}
|
||||
sym::is_val_statically_known => {
|
||||
let intrinsic_type = args[0].layout.immediate_llvm_type(self.cx);
|
||||
match self.type_kind(intrinsic_type) {
|
||||
TypeKind::Pointer | TypeKind::Integer | TypeKind::Float | TypeKind::Double => {
|
||||
self.call_intrinsic(
|
||||
&format!("llvm.is.constant.{:?}", intrinsic_type),
|
||||
&[args[0].immediate()],
|
||||
)
|
||||
let kind = self.type_kind(intrinsic_type);
|
||||
let intrinsic_name = match kind {
|
||||
TypeKind::Pointer | TypeKind::Integer => {
|
||||
Some(format!("llvm.is.constant.{intrinsic_type:?}"))
|
||||
}
|
||||
_ => self.const_bool(false),
|
||||
// LLVM float types' intrinsic names differ from their type names.
|
||||
TypeKind::Half => Some(format!("llvm.is.constant.f16")),
|
||||
TypeKind::Float => Some(format!("llvm.is.constant.f32")),
|
||||
TypeKind::Double => Some(format!("llvm.is.constant.f64")),
|
||||
TypeKind::FP128 => Some(format!("llvm.is.constant.f128")),
|
||||
_ => None,
|
||||
};
|
||||
if let Some(intrinsic_name) = intrinsic_name {
|
||||
self.call_intrinsic(&intrinsic_name, &[args[0].immediate()])
|
||||
} else {
|
||||
self.const_bool(false)
|
||||
}
|
||||
}
|
||||
sym::unlikely => self
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ edition = "2021"
|
|||
|
||||
[dependencies]
|
||||
# tidy-alphabetical-start
|
||||
ar_archive_writer = "0.3.3"
|
||||
ar_archive_writer = "0.4.0"
|
||||
arrayvec = { version = "0.7", default-features = false }
|
||||
bitflags = "2.4.1"
|
||||
cc = "1.0.90"
|
||||
|
|
@ -41,7 +41,7 @@ tempfile = "3.2"
|
|||
thin-vec = "0.2.12"
|
||||
thorin-dwp = "0.7"
|
||||
tracing = "0.1"
|
||||
wasm-encoder = "0.210.0"
|
||||
wasm-encoder = "0.215.0"
|
||||
# tidy-alphabetical-end
|
||||
|
||||
[target.'cfg(unix)'.dependencies]
|
||||
|
|
|
|||
|
|
@ -32,6 +32,9 @@ codegen_ssa_dlltool_fail_import_library =
|
|||
codegen_ssa_error_calling_dlltool =
|
||||
Error calling dlltool '{$dlltool_path}': {$error}
|
||||
|
||||
codegen_ssa_error_creating_import_library =
|
||||
Error creating import library for {$lib_name}: {$error}
|
||||
|
||||
codegen_ssa_error_creating_remark_dir = failed to create remark directory: {$error}
|
||||
|
||||
codegen_ssa_error_writing_def_file =
|
||||
|
|
|
|||
|
|
@ -5,7 +5,9 @@ use std::fs::{self, File};
|
|||
use std::io::{self, Write};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use ar_archive_writer::{write_archive_to_stream, ArchiveKind, NewArchiveMember};
|
||||
use ar_archive_writer::{
|
||||
write_archive_to_stream, ArchiveKind, COFFShortExport, MachineTypes, NewArchiveMember,
|
||||
};
|
||||
pub use ar_archive_writer::{ObjectReader, DEFAULT_OBJECT_READER};
|
||||
use object::read::archive::ArchiveFile;
|
||||
use object::read::macho::FatArch;
|
||||
|
|
@ -14,11 +16,15 @@ use rustc_data_structures::memmap::Mmap;
|
|||
use rustc_session::Session;
|
||||
use rustc_span::symbol::Symbol;
|
||||
use tempfile::Builder as TempFileBuilder;
|
||||
use tracing::trace;
|
||||
|
||||
use super::metadata::search_for_section;
|
||||
use crate::common;
|
||||
// Re-exporting for rustc_codegen_llvm::back::archive
|
||||
pub use crate::errors::{ArchiveBuildFailure, ExtractBundledLibsError, UnknownArchiveKind};
|
||||
use crate::errors::{DlltoolFailImportLibrary, ErrorCallingDllTool, ErrorWritingDEFFile};
|
||||
use crate::errors::{
|
||||
DlltoolFailImportLibrary, ErrorCallingDllTool, ErrorCreatingImportLibrary, ErrorWritingDEFFile,
|
||||
};
|
||||
|
||||
pub trait ArchiveBuilderBuilder {
|
||||
fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder + 'a>;
|
||||
|
|
@ -34,7 +40,81 @@ pub trait ArchiveBuilderBuilder {
|
|||
lib_name: &str,
|
||||
import_name_and_ordinal_vector: Vec<(String, Option<u16>)>,
|
||||
output_path: &Path,
|
||||
);
|
||||
) {
|
||||
if common::is_mingw_gnu_toolchain(&sess.target) {
|
||||
// The binutils linker used on -windows-gnu targets cannot read the import
|
||||
// libraries generated by LLVM: in our attempts, the linker produced an .EXE
|
||||
// that loaded but crashed with an AV upon calling one of the imported
|
||||
// functions. Therefore, use binutils to create the import library instead,
|
||||
// by writing a .DEF file to the temp dir and calling binutils's dlltool.
|
||||
create_mingw_dll_import_lib(
|
||||
sess,
|
||||
lib_name,
|
||||
import_name_and_ordinal_vector,
|
||||
output_path,
|
||||
);
|
||||
} else {
|
||||
trace!("creating import library");
|
||||
trace!(" dll_name {:#?}", lib_name);
|
||||
trace!(" output_path {}", output_path.display());
|
||||
trace!(
|
||||
" import names: {}",
|
||||
import_name_and_ordinal_vector
|
||||
.iter()
|
||||
.map(|(name, _ordinal)| name.clone())
|
||||
.collect::<Vec<_>>()
|
||||
.join(", "),
|
||||
);
|
||||
|
||||
// All import names are Rust identifiers and therefore cannot contain \0 characters.
|
||||
// FIXME: when support for #[link_name] is implemented, ensure that the import names
|
||||
// still don't contain any \0 characters. Also need to check that the names don't
|
||||
// contain substrings like " @" or "NONAME" that are keywords or otherwise reserved
|
||||
// in definition files.
|
||||
|
||||
let mut file = match fs::File::create_new(&output_path) {
|
||||
Ok(file) => file,
|
||||
Err(error) => sess
|
||||
.dcx()
|
||||
.emit_fatal(ErrorCreatingImportLibrary { lib_name, error: error.to_string() }),
|
||||
};
|
||||
|
||||
let exports = import_name_and_ordinal_vector
|
||||
.iter()
|
||||
.map(|(name, ordinal)| COFFShortExport {
|
||||
name: name.to_string(),
|
||||
ext_name: None,
|
||||
symbol_name: None,
|
||||
alias_target: None,
|
||||
ordinal: ordinal.unwrap_or(0),
|
||||
noname: ordinal.is_some(),
|
||||
data: false,
|
||||
private: false,
|
||||
constant: false,
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
let machine = match &*sess.target.arch {
|
||||
"x86_64" => MachineTypes::AMD64,
|
||||
"x86" => MachineTypes::I386,
|
||||
"aarch64" => MachineTypes::ARM64,
|
||||
"arm64ec" => MachineTypes::ARM64EC,
|
||||
"arm" => MachineTypes::ARMNT,
|
||||
cpu => panic!("unsupported cpu type {cpu}"),
|
||||
};
|
||||
|
||||
if let Err(error) = ar_archive_writer::write_import_library(
|
||||
&mut file,
|
||||
lib_name,
|
||||
&exports,
|
||||
machine,
|
||||
!sess.target.is_like_msvc,
|
||||
/*comdat=*/ false,
|
||||
) {
|
||||
sess.dcx()
|
||||
.emit_fatal(ErrorCreatingImportLibrary { lib_name, error: error.to_string() });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn extract_bundled_libs<'a>(
|
||||
&'a self,
|
||||
|
|
|
|||
|
|
@ -1060,3 +1060,10 @@ pub struct CompilerBuiltinsCannotCall {
|
|||
pub caller: String,
|
||||
pub callee: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_ssa_error_creating_import_library)]
|
||||
pub(crate) struct ErrorCreatingImportLibrary<'a> {
|
||||
pub lib_name: &'a str,
|
||||
pub error: String,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -220,14 +220,14 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx>
|
|||
| MutatingUseContext::SetDiscriminant
|
||||
| MutatingUseContext::AsmOutput
|
||||
| MutatingUseContext::Borrow
|
||||
| MutatingUseContext::AddressOf
|
||||
| MutatingUseContext::RawBorrow
|
||||
| MutatingUseContext::Projection,
|
||||
)
|
||||
| PlaceContext::NonMutatingUse(
|
||||
NonMutatingUseContext::Inspect
|
||||
| NonMutatingUseContext::SharedBorrow
|
||||
| NonMutatingUseContext::FakeBorrow
|
||||
| NonMutatingUseContext::AddressOf
|
||||
| NonMutatingUseContext::RawBorrow
|
||||
| NonMutatingUseContext::Projection,
|
||||
) => {
|
||||
self.locals[local] = LocalKind::Memory;
|
||||
|
|
|
|||
|
|
@ -584,7 +584,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
mir::Rvalue::CopyForDeref(place) => {
|
||||
self.codegen_operand(bx, &mir::Operand::Copy(place))
|
||||
}
|
||||
mir::Rvalue::AddressOf(mutability, place) => {
|
||||
mir::Rvalue::RawPtr(mutability, place) => {
|
||||
let mk_ptr =
|
||||
move |tcx: TyCtxt<'tcx>, ty: Ty<'tcx>| Ty::new_ptr(tcx, ty, mutability);
|
||||
self.codegen_place_to_pointer(bx, place, mk_ptr)
|
||||
|
|
@ -813,7 +813,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
cg_value.len(bx.cx())
|
||||
}
|
||||
|
||||
/// Codegen an `Rvalue::AddressOf` or `Rvalue::Ref`
|
||||
/// Codegen an `Rvalue::RawPtr` or `Rvalue::Ref`
|
||||
fn codegen_place_to_pointer(
|
||||
&mut self,
|
||||
bx: &mut Bx,
|
||||
|
|
@ -1085,7 +1085,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
}
|
||||
mir::Rvalue::Ref(..) |
|
||||
mir::Rvalue::CopyForDeref(..) |
|
||||
mir::Rvalue::AddressOf(..) |
|
||||
mir::Rvalue::RawPtr(..) |
|
||||
mir::Rvalue::Len(..) |
|
||||
mir::Rvalue::Cast(..) | // (*)
|
||||
mir::Rvalue::ShallowInitBox(..) | // (*)
|
||||
|
|
|
|||
|
|
@ -431,13 +431,13 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
|||
return;
|
||||
}
|
||||
}
|
||||
Rvalue::AddressOf(mutbl, place) => {
|
||||
Rvalue::RawPtr(mutbl, place) => {
|
||||
if let Some(reborrowed_place_ref) = place_as_reborrow(self.tcx, self.body, place) {
|
||||
let ctx = match mutbl {
|
||||
Mutability::Not => {
|
||||
PlaceContext::NonMutatingUse(NonMutatingUseContext::AddressOf)
|
||||
PlaceContext::NonMutatingUse(NonMutatingUseContext::RawBorrow)
|
||||
}
|
||||
Mutability::Mut => PlaceContext::MutatingUse(MutatingUseContext::AddressOf),
|
||||
Mutability::Mut => PlaceContext::MutatingUse(MutatingUseContext::RawBorrow),
|
||||
};
|
||||
self.visit_local(reborrowed_place_ref.local, ctx, location);
|
||||
self.visit_projection(reborrowed_place_ref, ctx, location);
|
||||
|
|
@ -472,7 +472,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
|||
}
|
||||
|
||||
Rvalue::Ref(_, BorrowKind::Mut { .. }, place)
|
||||
| Rvalue::AddressOf(Mutability::Mut, place) => {
|
||||
| Rvalue::RawPtr(Mutability::Mut, place) => {
|
||||
// Inside mutable statics, we allow arbitrary mutable references.
|
||||
// We've allowed `static mut FOO = &mut [elements];` for a long time (the exact
|
||||
// reasons why are lost to history), and there is no reason to restrict that to
|
||||
|
|
@ -493,7 +493,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
|||
}
|
||||
|
||||
Rvalue::Ref(_, BorrowKind::Shared | BorrowKind::Fake(_), place)
|
||||
| Rvalue::AddressOf(Mutability::Not, place) => {
|
||||
| Rvalue::RawPtr(Mutability::Not, place) => {
|
||||
let borrowed_place_has_mut_interior = qualifs::in_place::<HasMutInterior, _>(
|
||||
self.ccx,
|
||||
&mut |local| self.qualifs.has_mut_interior(self.ccx, local, location),
|
||||
|
|
|
|||
|
|
@ -291,7 +291,7 @@ where
|
|||
in_operand::<Q, _>(cx, in_local, lhs) || in_operand::<Q, _>(cx, in_local, rhs)
|
||||
}
|
||||
|
||||
Rvalue::Ref(_, _, place) | Rvalue::AddressOf(_, place) => {
|
||||
Rvalue::Ref(_, _, place) | Rvalue::RawPtr(_, place) => {
|
||||
// Special-case reborrows to be more like a copy of the reference.
|
||||
if let Some((place_base, ProjectionElem::Deref)) = place.as_ref().last_projection() {
|
||||
let base_ty = place_base.ty(cx.body, cx.tcx).ty;
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ where
|
|||
}
|
||||
|
||||
fn address_of_allows_mutation(&self) -> bool {
|
||||
// Exact set of permissions granted by AddressOf is undecided. Conservatively assume that
|
||||
// Exact set of permissions granted by RawPtr is undecided. Conservatively assume that
|
||||
// it might allow mutation until resolution of #56604.
|
||||
true
|
||||
}
|
||||
|
|
@ -170,7 +170,7 @@ where
|
|||
self.super_rvalue(rvalue, location);
|
||||
|
||||
match rvalue {
|
||||
mir::Rvalue::AddressOf(_mt, borrowed_place) => {
|
||||
mir::Rvalue::RawPtr(_mt, borrowed_place) => {
|
||||
if !borrowed_place.is_indirect() && self.address_of_allows_mutation() {
|
||||
let place_ty = borrowed_place.ty(self.ccx.body, self.ccx.tcx).ty;
|
||||
if Q::in_any_value_of_ty(self.ccx, place_ty) {
|
||||
|
|
|
|||
|
|
@ -234,7 +234,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
self.write_immediate(*val, &dest)?;
|
||||
}
|
||||
|
||||
AddressOf(_, place) => {
|
||||
RawPtr(_, place) => {
|
||||
// Figure out whether this is an addr_of of an already raw place.
|
||||
let place_base_raw = if place.is_indirect_first_projection() {
|
||||
let ty = self.frame().body.local_decls[place.local].ty;
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ The address of temporary value was taken.
|
|||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0745
|
||||
# #![feature(raw_ref_op)]
|
||||
fn temp_address() {
|
||||
let ptr = &raw const 2; // error!
|
||||
}
|
||||
|
|
@ -15,7 +14,6 @@ In this example, `2` is destroyed right after the assignment, which means that
|
|||
To avoid this error, first bind the temporary to a named local variable:
|
||||
|
||||
```
|
||||
# #![feature(raw_ref_op)]
|
||||
fn temp_address() {
|
||||
let val = 2;
|
||||
let ptr = &raw const val; // ok!
|
||||
|
|
|
|||
|
|
@ -265,12 +265,7 @@ impl<'a> StripUnconfigured<'a> {
|
|||
/// is in the original source file. Gives a compiler error if the syntax of
|
||||
/// the attribute is incorrect.
|
||||
pub(crate) fn expand_cfg_attr(&self, cfg_attr: &Attribute, recursive: bool) -> Vec<Attribute> {
|
||||
validate_attr::check_attribute_safety(
|
||||
self.features.unwrap_or(&Features::default()),
|
||||
&self.sess.psess,
|
||||
AttributeSafety::Normal,
|
||||
&cfg_attr,
|
||||
);
|
||||
validate_attr::check_attribute_safety(&self.sess.psess, AttributeSafety::Normal, &cfg_attr);
|
||||
|
||||
let Some((cfg_predicate, expanded_attrs)) =
|
||||
rustc_parse::parse_cfg_attr(cfg_attr, &self.sess.psess)
|
||||
|
|
@ -395,11 +390,7 @@ impl<'a> StripUnconfigured<'a> {
|
|||
}
|
||||
};
|
||||
|
||||
validate_attr::deny_builtin_meta_unsafety(
|
||||
self.features.unwrap_or(&Features::default()),
|
||||
&self.sess.psess,
|
||||
&meta_item,
|
||||
);
|
||||
validate_attr::deny_builtin_meta_unsafety(&self.sess.psess, &meta_item);
|
||||
|
||||
(
|
||||
parse_cfg(&meta_item, self.sess).map_or(true, |meta_item| {
|
||||
|
|
|
|||
|
|
@ -1882,7 +1882,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
|
|||
let mut span: Option<Span> = None;
|
||||
while let Some(attr) = attrs.next() {
|
||||
rustc_ast_passes::feature_gate::check_attribute(attr, self.cx.sess, features);
|
||||
validate_attr::check_attr(features, &self.cx.sess.psess, attr);
|
||||
validate_attr::check_attr(&self.cx.sess.psess, attr);
|
||||
|
||||
let current_span = if let Some(sp) = span { sp.to(attr.span) } else { attr.span };
|
||||
span = Some(current_span);
|
||||
|
|
|
|||
|
|
@ -321,6 +321,8 @@ declare_features! (
|
|||
(accepted, raw_dylib, "1.71.0", Some(58713)),
|
||||
/// Allows keywords to be escaped for use as identifiers.
|
||||
(accepted, raw_identifiers, "1.30.0", Some(48589)),
|
||||
/// Allows `&raw const $place_expr` and `&raw mut $place_expr` expressions.
|
||||
(accepted, raw_ref_op, "CURRENT_RUSTC_VERSION", Some(64490)),
|
||||
/// Allows relaxing the coherence rules such that
|
||||
/// `impl<T> ForeignTrait<LocalType> for ForeignType<T>` is permitted.
|
||||
(accepted, re_rebalance_coherence, "1.41.0", Some(55437)),
|
||||
|
|
@ -392,6 +394,8 @@ declare_features! (
|
|||
(accepted, universal_impl_trait, "1.26.0", Some(34511)),
|
||||
/// Allows arbitrary delimited token streams in non-macro attributes.
|
||||
(accepted, unrestricted_attribute_tokens, "1.34.0", Some(55208)),
|
||||
/// Allows unsafe attributes.
|
||||
(accepted, unsafe_attributes, "CURRENT_RUSTC_VERSION", Some(123757)),
|
||||
/// The `unsafe_op_in_unsafe_fn` lint (allowed by default): no longer treat an unsafe function as an unsafe block.
|
||||
(accepted, unsafe_block_in_unsafe_fn, "1.52.0", Some(71668)),
|
||||
/// Allows unsafe on extern declarations and safety qualifiers over internal items.
|
||||
|
|
|
|||
|
|
@ -565,8 +565,6 @@ declare_features! (
|
|||
(unstable, precise_capturing, "1.79.0", Some(123432)),
|
||||
/// Allows macro attributes on expressions, statements and non-inline modules.
|
||||
(unstable, proc_macro_hygiene, "1.30.0", Some(54727)),
|
||||
/// Allows `&raw const $place_expr` and `&raw mut $place_expr` expressions.
|
||||
(unstable, raw_ref_op, "1.41.0", Some(64490)),
|
||||
/// Makes `&` and `&mut` patterns eat only one layer of references in Rust 2024.
|
||||
(incomplete, ref_pat_eat_one_layer_2024, "1.79.0", Some(123076)),
|
||||
/// Makes `&` and `&mut` patterns eat only one layer of references in Rust 2024—structural variant
|
||||
|
|
@ -622,8 +620,6 @@ declare_features! (
|
|||
(unstable, type_changing_struct_update, "1.58.0", Some(86555)),
|
||||
/// Allows unnamed fields of struct and union type
|
||||
(incomplete, unnamed_fields, "1.74.0", Some(49804)),
|
||||
/// Allows unsafe attributes.
|
||||
(unstable, unsafe_attributes, "1.80.0", Some(123757)),
|
||||
/// Allows const generic parameters to be defined with types that
|
||||
/// are not `Sized`, e.g. `fn foo<const N: [u8]>() {`.
|
||||
(incomplete, unsized_const_params, "CURRENT_RUSTC_VERSION", Some(95174)),
|
||||
|
|
|
|||
|
|
@ -1395,7 +1395,7 @@ pub struct LetExpr<'hir> {
|
|||
pub pat: &'hir Pat<'hir>,
|
||||
pub ty: Option<&'hir Ty<'hir>>,
|
||||
pub init: &'hir Expr<'hir>,
|
||||
/// `Recovered::Yes` when this let expressions is not in a syntanctically valid location.
|
||||
/// `Recovered::Yes` when this let expressions is not in a syntactically valid location.
|
||||
/// Used to prevent building MIR in such situations.
|
||||
pub recovered: ast::Recovered,
|
||||
}
|
||||
|
|
@ -3586,7 +3586,7 @@ impl ForeignItem<'_> {
|
|||
#[derive(Debug, Clone, Copy, HashStable_Generic)]
|
||||
pub enum ForeignItemKind<'hir> {
|
||||
/// A foreign function.
|
||||
Fn(&'hir FnDecl<'hir>, &'hir [Ident], &'hir Generics<'hir>, Safety),
|
||||
Fn(FnSig<'hir>, &'hir [Ident], &'hir Generics<'hir>),
|
||||
/// A foreign static item (`static ext: u8`).
|
||||
Static(&'hir Ty<'hir>, Mutability, Safety),
|
||||
/// A foreign type.
|
||||
|
|
@ -3645,7 +3645,10 @@ impl<'hir> OwnerNode<'hir> {
|
|||
match self {
|
||||
OwnerNode::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. })
|
||||
| OwnerNode::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. })
|
||||
| OwnerNode::Item(Item { kind: ItemKind::Fn(fn_sig, _, _), .. }) => Some(fn_sig),
|
||||
| OwnerNode::Item(Item { kind: ItemKind::Fn(fn_sig, _, _), .. })
|
||||
| OwnerNode::ForeignItem(ForeignItem {
|
||||
kind: ForeignItemKind::Fn(fn_sig, _, _), ..
|
||||
}) => Some(fn_sig),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
@ -3654,11 +3657,10 @@ impl<'hir> OwnerNode<'hir> {
|
|||
match self {
|
||||
OwnerNode::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. })
|
||||
| OwnerNode::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. })
|
||||
| OwnerNode::Item(Item { kind: ItemKind::Fn(fn_sig, _, _), .. }) => Some(fn_sig.decl),
|
||||
OwnerNode::ForeignItem(ForeignItem {
|
||||
kind: ForeignItemKind::Fn(fn_decl, _, _, _),
|
||||
..
|
||||
}) => Some(fn_decl),
|
||||
| OwnerNode::Item(Item { kind: ItemKind::Fn(fn_sig, _, _), .. })
|
||||
| OwnerNode::ForeignItem(ForeignItem {
|
||||
kind: ForeignItemKind::Fn(fn_sig, _, _), ..
|
||||
}) => Some(fn_sig.decl),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
@ -3846,11 +3848,13 @@ impl<'hir> Node<'hir> {
|
|||
match self {
|
||||
Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. })
|
||||
| Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. })
|
||||
| Node::Item(Item { kind: ItemKind::Fn(fn_sig, _, _), .. }) => Some(fn_sig.decl),
|
||||
Node::Expr(Expr { kind: ExprKind::Closure(Closure { fn_decl, .. }), .. })
|
||||
| Node::ForeignItem(ForeignItem {
|
||||
kind: ForeignItemKind::Fn(fn_decl, _, _, _), ..
|
||||
}) => Some(fn_decl),
|
||||
| Node::Item(Item { kind: ItemKind::Fn(fn_sig, _, _), .. })
|
||||
| Node::ForeignItem(ForeignItem { kind: ForeignItemKind::Fn(fn_sig, _, _), .. }) => {
|
||||
Some(fn_sig.decl)
|
||||
}
|
||||
Node::Expr(Expr { kind: ExprKind::Closure(Closure { fn_decl, .. }), .. }) => {
|
||||
Some(fn_decl)
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
@ -3874,7 +3878,10 @@ impl<'hir> Node<'hir> {
|
|||
match self {
|
||||
Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. })
|
||||
| Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. })
|
||||
| Node::Item(Item { kind: ItemKind::Fn(fn_sig, _, _), .. }) => Some(fn_sig),
|
||||
| Node::Item(Item { kind: ItemKind::Fn(fn_sig, _, _), .. })
|
||||
| Node::ForeignItem(ForeignItem { kind: ForeignItemKind::Fn(fn_sig, _, _), .. }) => {
|
||||
Some(fn_sig)
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
@ -3949,7 +3956,7 @@ impl<'hir> Node<'hir> {
|
|||
pub fn generics(self) -> Option<&'hir Generics<'hir>> {
|
||||
match self {
|
||||
Node::ForeignItem(ForeignItem {
|
||||
kind: ForeignItemKind::Fn(_, _, generics, _), ..
|
||||
kind: ForeignItemKind::Fn(_, _, generics), ..
|
||||
})
|
||||
| Node::TraitItem(TraitItem { generics, .. })
|
||||
| Node::ImplItem(ImplItem { generics, .. }) => Some(generics),
|
||||
|
|
@ -4039,8 +4046,8 @@ mod size_asserts {
|
|||
static_assert_size!(Expr<'_>, 64);
|
||||
static_assert_size!(ExprKind<'_>, 48);
|
||||
static_assert_size!(FnDecl<'_>, 40);
|
||||
static_assert_size!(ForeignItem<'_>, 72);
|
||||
static_assert_size!(ForeignItemKind<'_>, 40);
|
||||
static_assert_size!(ForeignItem<'_>, 88);
|
||||
static_assert_size!(ForeignItemKind<'_>, 56);
|
||||
static_assert_size!(GenericArg<'_>, 16);
|
||||
static_assert_size!(GenericBound<'_>, 48);
|
||||
static_assert_size!(Generics<'_>, 56);
|
||||
|
|
|
|||
|
|
@ -611,9 +611,9 @@ pub fn walk_foreign_item<'v, V: Visitor<'v>>(
|
|||
try_visit!(visitor.visit_ident(foreign_item.ident));
|
||||
|
||||
match foreign_item.kind {
|
||||
ForeignItemKind::Fn(ref function_declaration, param_names, ref generics, _) => {
|
||||
ForeignItemKind::Fn(ref sig, param_names, ref generics) => {
|
||||
try_visit!(visitor.visit_generics(generics));
|
||||
try_visit!(visitor.visit_fn_decl(function_declaration));
|
||||
try_visit!(visitor.visit_fn_decl(sig.decl));
|
||||
walk_list!(visitor, visit_ident, param_names.iter().copied());
|
||||
}
|
||||
ForeignItemKind::Static(ref typ, _, _) => {
|
||||
|
|
|
|||
|
|
@ -804,8 +804,8 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
|||
|
||||
let item = tcx.hir().foreign_item(item.id);
|
||||
match &item.kind {
|
||||
hir::ForeignItemKind::Fn(fn_decl, _, _, _) => {
|
||||
require_c_abi_if_c_variadic(tcx, fn_decl, abi, item.span);
|
||||
hir::ForeignItemKind::Fn(sig, _, _) => {
|
||||
require_c_abi_if_c_variadic(tcx, sig.decl, abi, item.span);
|
||||
}
|
||||
hir::ForeignItemKind::Static(..) => {
|
||||
check_static_inhabited(tcx, def_id);
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ fn equate_intrinsic_type<'tcx>(
|
|||
let (generics, span) = match tcx.hir_node_by_def_id(def_id) {
|
||||
hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. })
|
||||
| hir::Node::ForeignItem(hir::ForeignItem {
|
||||
kind: hir::ForeignItemKind::Fn(.., generics, _),
|
||||
kind: hir::ForeignItemKind::Fn(_, _, generics),
|
||||
..
|
||||
}) => (tcx.generics_of(def_id), generics.span),
|
||||
_ => {
|
||||
|
|
|
|||
|
|
@ -350,8 +350,8 @@ fn check_foreign_item<'tcx>(
|
|||
);
|
||||
|
||||
match item.kind {
|
||||
hir::ForeignItemKind::Fn(decl, ..) => {
|
||||
check_item_fn(tcx, def_id, item.ident, item.span, decl)
|
||||
hir::ForeignItemKind::Fn(sig, ..) => {
|
||||
check_item_fn(tcx, def_id, item.ident, item.span, sig.decl)
|
||||
}
|
||||
hir::ForeignItemKind::Static(ty, ..) => {
|
||||
check_item_type(tcx, def_id, ty.span, UnsizedHandling::AllowIfForeignTail)
|
||||
|
|
|
|||
|
|
@ -1440,11 +1440,9 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFn
|
|||
icx.lowerer().lower_fn_ty(hir_id, header.safety, header.abi, decl, Some(generics), None)
|
||||
}
|
||||
|
||||
ForeignItem(&hir::ForeignItem {
|
||||
kind: ForeignItemKind::Fn(fn_decl, _, _, safety), ..
|
||||
}) => {
|
||||
ForeignItem(&hir::ForeignItem { kind: ForeignItemKind::Fn(sig, _, _), .. }) => {
|
||||
let abi = tcx.hir().get_foreign_abi(hir_id);
|
||||
compute_sig_of_foreign_fn_decl(tcx, def_id, fn_decl, abi, safety)
|
||||
compute_sig_of_foreign_fn_decl(tcx, def_id, sig.decl, abi, sig.header.safety)
|
||||
}
|
||||
|
||||
Ctor(data) | Variant(hir::Variant { data, .. }) if data.ctor().is_some() => {
|
||||
|
|
|
|||
|
|
@ -604,7 +604,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
|
|||
|
||||
fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) {
|
||||
match item.kind {
|
||||
hir::ForeignItemKind::Fn(_, _, generics, _) => {
|
||||
hir::ForeignItemKind::Fn(_, _, generics) => {
|
||||
self.visit_early_late(item.hir_id(), generics, |this| {
|
||||
intravisit::walk_foreign_item(this, item);
|
||||
})
|
||||
|
|
|
|||
|
|
@ -352,16 +352,11 @@ impl<'a> State<'a> {
|
|||
self.maybe_print_comment(item.span.lo());
|
||||
self.print_outer_attributes(self.attrs(item.hir_id()));
|
||||
match item.kind {
|
||||
hir::ForeignItemKind::Fn(decl, arg_names, generics, safety) => {
|
||||
hir::ForeignItemKind::Fn(sig, arg_names, generics) => {
|
||||
self.head("");
|
||||
self.print_fn(
|
||||
decl,
|
||||
hir::FnHeader {
|
||||
safety,
|
||||
constness: hir::Constness::NotConst,
|
||||
abi: Abi::Rust,
|
||||
asyncness: hir::IsAsync::NotAsync,
|
||||
},
|
||||
sig.decl,
|
||||
sig.header,
|
||||
Some(item.ident.name),
|
||||
generics,
|
||||
arg_names,
|
||||
|
|
|
|||
|
|
@ -967,7 +967,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
|||
// need to special-case obtaining a raw pointer
|
||||
// from a region pointer to a vector.
|
||||
|
||||
// Coerce to a raw pointer so that we generate AddressOf in MIR.
|
||||
// Coerce to a raw pointer so that we generate RawPtr in MIR.
|
||||
let array_ptr_type = Ty::new_ptr(fcx.tcx, m_expr.ty, m_expr.mutbl);
|
||||
fcx.coerce(self.expr, self.expr_ty, array_ptr_type, AllowTwoPhase::No, None)
|
||||
.unwrap_or_else(|_| {
|
||||
|
|
|
|||
|
|
@ -1859,7 +1859,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
|
|||
};
|
||||
|
||||
// If this is due to an explicit `return`, suggest adding a return type.
|
||||
if let Some((fn_id, fn_decl, can_suggest)) = fcx.get_fn_decl(parent_id)
|
||||
if let Some((fn_id, fn_decl, can_suggest)) = fcx.get_fn_decl(block_or_return_id)
|
||||
&& !due_to_block
|
||||
{
|
||||
fcx.suggest_missing_return_type(&mut err, fn_decl, expected, found, can_suggest, fn_id);
|
||||
|
|
|
|||
|
|
@ -3448,6 +3448,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
trait_missing_method: bool,
|
||||
) {
|
||||
let mut alt_rcvr_sugg = false;
|
||||
let mut trait_in_other_version_found = false;
|
||||
if let (SelfSource::MethodCall(rcvr), false) = (source, unsatisfied_bounds) {
|
||||
debug!(
|
||||
"suggest_traits_to_import: span={:?}, item_name={:?}, rcvr_ty={:?}, rcvr={:?}",
|
||||
|
|
@ -3489,8 +3490,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// self types and rely on the suggestion to `use` the trait from
|
||||
// `suggest_valid_traits`.
|
||||
let did = Some(pick.item.container_id(self.tcx));
|
||||
let skip = skippable.contains(&did);
|
||||
if pick.autoderefs == 0 && !skip {
|
||||
if skippable.contains(&did) {
|
||||
continue;
|
||||
}
|
||||
trait_in_other_version_found = self
|
||||
.detect_and_explain_multiple_crate_versions(
|
||||
err,
|
||||
pick.item.def_id,
|
||||
rcvr.hir_id,
|
||||
*rcvr_ty,
|
||||
);
|
||||
if pick.autoderefs == 0 && !trait_in_other_version_found {
|
||||
err.span_label(
|
||||
pick.item.ident(self.tcx).span,
|
||||
format!("the method is available for `{rcvr_ty}` here"),
|
||||
|
|
@ -3675,7 +3685,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
}
|
||||
if self.suggest_valid_traits(err, item_name, valid_out_of_scope_traits, true) {
|
||||
|
||||
if let SelfSource::QPath(ty) = source
|
||||
&& !valid_out_of_scope_traits.is_empty()
|
||||
&& let hir::TyKind::Path(path) = ty.kind
|
||||
&& let hir::QPath::Resolved(_, path) = path
|
||||
&& let Some(def_id) = path.res.opt_def_id()
|
||||
&& let Some(assoc) = self
|
||||
.tcx
|
||||
.associated_items(valid_out_of_scope_traits[0])
|
||||
.filter_by_name_unhygienic(item_name.name)
|
||||
.next()
|
||||
{
|
||||
// See if the `Type::function(val)` where `function` wasn't found corresponds to a
|
||||
// `Trait` that is imported directly, but `Type` came from a different version of the
|
||||
// same crate.
|
||||
let rcvr_ty = self.tcx.type_of(def_id).instantiate_identity();
|
||||
trait_in_other_version_found = self.detect_and_explain_multiple_crate_versions(
|
||||
err,
|
||||
assoc.def_id,
|
||||
ty.hir_id,
|
||||
rcvr_ty,
|
||||
);
|
||||
}
|
||||
if !trait_in_other_version_found
|
||||
&& self.suggest_valid_traits(err, item_name, valid_out_of_scope_traits, true)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -4040,6 +4075,62 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn detect_and_explain_multiple_crate_versions(
|
||||
&self,
|
||||
err: &mut Diag<'_>,
|
||||
item_def_id: DefId,
|
||||
hir_id: hir::HirId,
|
||||
rcvr_ty: Ty<'_>,
|
||||
) -> bool {
|
||||
let hir_id = self.tcx.parent_hir_id(hir_id);
|
||||
let Some(traits) = self.tcx.in_scope_traits(hir_id) else { return false };
|
||||
if traits.is_empty() {
|
||||
return false;
|
||||
}
|
||||
let trait_def_id = self.tcx.parent(item_def_id);
|
||||
let krate = self.tcx.crate_name(trait_def_id.krate);
|
||||
let name = self.tcx.item_name(trait_def_id);
|
||||
let candidates: Vec<_> = traits
|
||||
.iter()
|
||||
.filter(|c| {
|
||||
c.def_id.krate != trait_def_id.krate
|
||||
&& self.tcx.crate_name(c.def_id.krate) == krate
|
||||
&& self.tcx.item_name(c.def_id) == name
|
||||
})
|
||||
.map(|c| (c.def_id, c.import_ids.get(0).cloned()))
|
||||
.collect();
|
||||
if candidates.is_empty() {
|
||||
return false;
|
||||
}
|
||||
let item_span = self.tcx.def_span(item_def_id);
|
||||
let msg = format!(
|
||||
"there are multiple different versions of crate `{krate}` in the dependency graph",
|
||||
);
|
||||
let trait_span = self.tcx.def_span(trait_def_id);
|
||||
let mut multi_span: MultiSpan = trait_span.into();
|
||||
multi_span.push_span_label(trait_span, format!("this is the trait that is needed"));
|
||||
let descr = self.tcx.associated_item(item_def_id).descr();
|
||||
multi_span
|
||||
.push_span_label(item_span, format!("the {descr} is available for `{rcvr_ty}` here"));
|
||||
for (def_id, import_def_id) in candidates {
|
||||
if let Some(import_def_id) = import_def_id {
|
||||
multi_span.push_span_label(
|
||||
self.tcx.def_span(import_def_id),
|
||||
format!(
|
||||
"`{name}` imported here doesn't correspond to the right version of crate \
|
||||
`{krate}`",
|
||||
),
|
||||
);
|
||||
}
|
||||
multi_span.push_span_label(
|
||||
self.tcx.def_span(def_id),
|
||||
format!("this is the trait that was imported"),
|
||||
);
|
||||
}
|
||||
err.span_note(multi_span, msg);
|
||||
true
|
||||
}
|
||||
|
||||
/// issue #102320, for `unwrap_or` with closure as argument, suggest `unwrap_or_else`
|
||||
/// FIXME: currently not working for suggesting `map_or_else`, see #102408
|
||||
pub(crate) fn suggest_else_fn_with_closure(
|
||||
|
|
|
|||
|
|
@ -1734,13 +1734,16 @@ impl<'tcx> LateLintPass<'tcx> for ImproperCTypesDeclarations {
|
|||
let abi = cx.tcx.hir().get_foreign_abi(it.hir_id());
|
||||
|
||||
match it.kind {
|
||||
hir::ForeignItemKind::Fn(decl, _, _, _) if !vis.is_internal_abi(abi) => {
|
||||
vis.check_foreign_fn(it.owner_id.def_id, decl);
|
||||
hir::ForeignItemKind::Fn(sig, _, _) => {
|
||||
if vis.is_internal_abi(abi) {
|
||||
vis.check_fn(it.owner_id.def_id, sig.decl)
|
||||
} else {
|
||||
vis.check_foreign_fn(it.owner_id.def_id, sig.decl);
|
||||
}
|
||||
}
|
||||
hir::ForeignItemKind::Static(ty, _, _) if !vis.is_internal_abi(abi) => {
|
||||
vis.check_foreign_static(it.owner_id, ty.span);
|
||||
}
|
||||
hir::ForeignItemKind::Fn(decl, _, _, _) => vis.check_fn(it.owner_id.def_id, decl),
|
||||
hir::ForeignItemKind::Static(..) | hir::ForeignItemKind::Type => (),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4971,7 +4971,6 @@ declare_lint! {
|
|||
/// ### Example
|
||||
///
|
||||
/// ```rust
|
||||
/// #![feature(unsafe_attributes)]
|
||||
/// #![warn(unsafe_attr_outside_unsafe)]
|
||||
///
|
||||
/// #[no_mangle]
|
||||
|
|
|
|||
|
|
@ -554,53 +554,43 @@ impl<'hir> Map<'hir> {
|
|||
/// }
|
||||
/// ```
|
||||
pub fn get_fn_id_for_return_block(self, id: HirId) -> Option<HirId> {
|
||||
let mut iter = self.parent_iter(id).peekable();
|
||||
let mut ignore_tail = false;
|
||||
if let Node::Expr(Expr { kind: ExprKind::Ret(_), .. }) = self.tcx.hir_node(id) {
|
||||
// When dealing with `return` statements, we don't care about climbing only tail
|
||||
// expressions.
|
||||
ignore_tail = true;
|
||||
}
|
||||
let enclosing_body_owner = self.tcx.local_def_id_to_hir_id(self.enclosing_body_owner(id));
|
||||
|
||||
let mut prev_hir_id = None;
|
||||
while let Some((hir_id, node)) = iter.next() {
|
||||
if let (Some((_, next_node)), false) = (iter.peek(), ignore_tail) {
|
||||
match next_node {
|
||||
Node::Block(Block { expr: None, .. }) => return None,
|
||||
// The current node is not the tail expression of its parent.
|
||||
Node::Block(Block { expr: Some(e), .. }) if hir_id != e.hir_id => return None,
|
||||
// Return `None` if the `id` expression is not the returned value of the enclosing body
|
||||
let mut iter = [id].into_iter().chain(self.parent_id_iter(id)).peekable();
|
||||
while let Some(cur_id) = iter.next() {
|
||||
if enclosing_body_owner == cur_id {
|
||||
break;
|
||||
}
|
||||
|
||||
// A return statement is always the value returned from the enclosing body regardless of
|
||||
// what the parent expressions are.
|
||||
if let Node::Expr(Expr { kind: ExprKind::Ret(_), .. }) = self.tcx.hir_node(cur_id) {
|
||||
break;
|
||||
}
|
||||
|
||||
// If the current expression's value doesnt get used as the parent expressions value then return `None`
|
||||
if let Some(&parent_id) = iter.peek() {
|
||||
match self.tcx.hir_node(parent_id) {
|
||||
// The current node is not the tail expression of the block expression parent expr.
|
||||
Node::Block(Block { expr: Some(e), .. }) if cur_id != e.hir_id => return None,
|
||||
Node::Block(Block { expr: Some(e), .. })
|
||||
if matches!(e.kind, ExprKind::If(_, _, None)) =>
|
||||
{
|
||||
return None;
|
||||
}
|
||||
|
||||
// The current expression's value does not pass up through these parent expressions
|
||||
Node::Block(Block { expr: None, .. })
|
||||
| Node::Expr(Expr { kind: ExprKind::Loop(..), .. })
|
||||
| Node::LetStmt(..) => return None,
|
||||
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
match node {
|
||||
Node::Item(_)
|
||||
| Node::ForeignItem(_)
|
||||
| Node::TraitItem(_)
|
||||
| Node::Expr(Expr { kind: ExprKind::Closure(_), .. })
|
||||
| Node::ImplItem(_)
|
||||
// The input node `id` must be enclosed in the method's body as opposed
|
||||
// to some other place such as its return type (fixes #114918).
|
||||
// We verify that indirectly by checking that the previous node is the
|
||||
// current node's body
|
||||
if node.body_id().map(|b| b.hir_id) == prev_hir_id => {
|
||||
return Some(hir_id)
|
||||
}
|
||||
// Ignore `return`s on the first iteration
|
||||
Node::Expr(Expr { kind: ExprKind::Loop(..) | ExprKind::Ret(..), .. })
|
||||
| Node::LetStmt(_) => {
|
||||
return None;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
prev_hir_id = Some(hir_id);
|
||||
}
|
||||
None
|
||||
|
||||
Some(enclosing_body_owner)
|
||||
}
|
||||
|
||||
/// Retrieves the `OwnerId` for `id`'s parent item, or `id` itself if no
|
||||
|
|
@ -826,6 +816,11 @@ impl<'hir> Map<'hir> {
|
|||
})
|
||||
| Node::ImplItem(ImplItem {
|
||||
kind: ImplItemKind::Fn(sig, ..), span: outer_span, ..
|
||||
})
|
||||
| Node::ForeignItem(ForeignItem {
|
||||
kind: ForeignItemKind::Fn(sig, ..),
|
||||
span: outer_span,
|
||||
..
|
||||
}) => {
|
||||
// Ensure that the returned span has the item's SyntaxContext, and not the
|
||||
// SyntaxContext of the visibility.
|
||||
|
|
@ -884,10 +879,7 @@ impl<'hir> Map<'hir> {
|
|||
},
|
||||
Node::Variant(variant) => named_span(variant.span, variant.ident, None),
|
||||
Node::ImplItem(item) => named_span(item.span, item.ident, Some(item.generics)),
|
||||
Node::ForeignItem(item) => match item.kind {
|
||||
ForeignItemKind::Fn(decl, _, _, _) => until_within(item.span, decl.output.span()),
|
||||
_ => named_span(item.span, item.ident, None),
|
||||
},
|
||||
Node::ForeignItem(item) => named_span(item.span, item.ident, None),
|
||||
Node::Ctor(_) => return self.span(self.tcx.parent_hir_id(hir_id)),
|
||||
Node::Expr(Expr {
|
||||
kind: ExprKind::Closure(Closure { fn_decl_span, .. }),
|
||||
|
|
|
|||
|
|
@ -202,7 +202,7 @@ pub fn provide(providers: &mut Providers) {
|
|||
..
|
||||
})
|
||||
| Node::ForeignItem(&ForeignItem {
|
||||
kind: ForeignItemKind::Fn(_, idents, _, _),
|
||||
kind: ForeignItemKind::Fn(_, idents, _),
|
||||
..
|
||||
}) = tcx.hir_node(tcx.local_def_id_to_hir_id(def_id))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1038,7 +1038,7 @@ impl<'tcx> Debug for Rvalue<'tcx> {
|
|||
|
||||
CopyForDeref(ref place) => write!(fmt, "deref_copy {place:#?}"),
|
||||
|
||||
AddressOf(mutability, ref place) => {
|
||||
RawPtr(mutability, ref place) => {
|
||||
write!(fmt, "&raw {mut_str} {place:?}", mut_str = mutability.ptr_str())
|
||||
}
|
||||
|
||||
|
|
@ -1159,7 +1159,7 @@ impl<'tcx> Debug for Operand<'tcx> {
|
|||
use self::Operand::*;
|
||||
match *self {
|
||||
Constant(ref a) => write!(fmt, "{a:?}"),
|
||||
Copy(ref place) => write!(fmt, "{place:?}"),
|
||||
Copy(ref place) => write!(fmt, "copy {place:?}"),
|
||||
Move(ref place) => write!(fmt, "move {place:?}"),
|
||||
}
|
||||
}
|
||||
|
|
@ -1418,21 +1418,19 @@ pub fn write_allocations<'tcx>(
|
|||
alloc.inner().provenance().ptrs().values().map(|p| p.alloc_id())
|
||||
}
|
||||
|
||||
fn alloc_ids_from_const_val(val: ConstValue<'_>) -> impl Iterator<Item = AllocId> + '_ {
|
||||
fn alloc_id_from_const_val(val: ConstValue<'_>) -> Option<AllocId> {
|
||||
match val {
|
||||
ConstValue::Scalar(interpret::Scalar::Ptr(ptr, _)) => {
|
||||
Either::Left(std::iter::once(ptr.provenance.alloc_id()))
|
||||
}
|
||||
ConstValue::Scalar(interpret::Scalar::Int { .. }) => Either::Right(std::iter::empty()),
|
||||
ConstValue::ZeroSized => Either::Right(std::iter::empty()),
|
||||
ConstValue::Scalar(interpret::Scalar::Ptr(ptr, _)) => Some(ptr.provenance.alloc_id()),
|
||||
ConstValue::Scalar(interpret::Scalar::Int { .. }) => None,
|
||||
ConstValue::ZeroSized => None,
|
||||
ConstValue::Slice { .. } => {
|
||||
// `u8`/`str` slices, shouldn't contain pointers that we want to print.
|
||||
Either::Right(std::iter::empty())
|
||||
None
|
||||
}
|
||||
ConstValue::Indirect { alloc_id, .. } => {
|
||||
// FIXME: we don't actually want to print all of these, since some are printed nicely directly as values inline in MIR.
|
||||
// Really we'd want `pretty_print_const_value` to decide which allocations to print, instead of having a separate visitor.
|
||||
Either::Left(std::iter::once(alloc_id))
|
||||
Some(alloc_id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1443,7 +1441,9 @@ pub fn write_allocations<'tcx>(
|
|||
match c.const_ {
|
||||
Const::Ty(_, _) | Const::Unevaluated(..) => {}
|
||||
Const::Val(val, _) => {
|
||||
self.0.extend(alloc_ids_from_const_val(val));
|
||||
if let Some(id) = alloc_id_from_const_val(val) {
|
||||
self.0.insert(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -423,7 +423,7 @@ impl<'tcx> Rvalue<'tcx> {
|
|||
| Rvalue::Repeat(_, _)
|
||||
| Rvalue::Ref(_, _, _)
|
||||
| Rvalue::ThreadLocalRef(_)
|
||||
| Rvalue::AddressOf(_, _)
|
||||
| Rvalue::RawPtr(_, _)
|
||||
| Rvalue::Len(_)
|
||||
| Rvalue::Cast(
|
||||
CastKind::IntToInt
|
||||
|
|
|
|||
|
|
@ -1293,14 +1293,14 @@ pub enum Rvalue<'tcx> {
|
|||
/// nature of this operation?
|
||||
ThreadLocalRef(DefId),
|
||||
|
||||
/// Creates a pointer with the indicated mutability to the place.
|
||||
/// Creates a raw pointer with the indicated mutability to the place.
|
||||
///
|
||||
/// This is generated by pointer casts like `&v as *const _` or raw address of expressions like
|
||||
/// `&raw v` or `addr_of!(v)`.
|
||||
/// This is generated by pointer casts like `&v as *const _` or raw borrow expressions like
|
||||
/// `&raw const v`.
|
||||
///
|
||||
/// Like with references, the semantics of this operation are heavily dependent on the aliasing
|
||||
/// model.
|
||||
AddressOf(Mutability, Place<'tcx>),
|
||||
RawPtr(Mutability, Place<'tcx>),
|
||||
|
||||
/// Yields the length of the place, as a `usize`.
|
||||
///
|
||||
|
|
|
|||
|
|
@ -170,7 +170,7 @@ impl<'tcx> Rvalue<'tcx> {
|
|||
let place_ty = place.ty(local_decls, tcx).ty;
|
||||
Ty::new_ref(tcx, reg, place_ty, bk.to_mutbl_lossy())
|
||||
}
|
||||
Rvalue::AddressOf(mutability, ref place) => {
|
||||
Rvalue::RawPtr(mutability, ref place) => {
|
||||
let place_ty = place.ty(local_decls, tcx).ty;
|
||||
Ty::new_ptr(tcx, place_ty, mutability)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -682,13 +682,13 @@ macro_rules! make_mir_visitor {
|
|||
);
|
||||
}
|
||||
|
||||
Rvalue::AddressOf(m, path) => {
|
||||
Rvalue::RawPtr(m, path) => {
|
||||
let ctx = match m {
|
||||
Mutability::Mut => PlaceContext::MutatingUse(
|
||||
MutatingUseContext::AddressOf
|
||||
MutatingUseContext::RawBorrow
|
||||
),
|
||||
Mutability::Not => PlaceContext::NonMutatingUse(
|
||||
NonMutatingUseContext::AddressOf
|
||||
NonMutatingUseContext::RawBorrow
|
||||
),
|
||||
};
|
||||
self.visit_place(path, ctx, location);
|
||||
|
|
@ -1299,8 +1299,8 @@ pub enum NonMutatingUseContext {
|
|||
/// FIXME: do we need to distinguish shallow and deep fake borrows? In fact, do we need to
|
||||
/// distinguish fake and normal deep borrows?
|
||||
FakeBorrow,
|
||||
/// AddressOf for *const pointer.
|
||||
AddressOf,
|
||||
/// `&raw const`.
|
||||
RawBorrow,
|
||||
/// PlaceMention statement.
|
||||
///
|
||||
/// This statement is executed as a check that the `Place` is live without reading from it,
|
||||
|
|
@ -1333,8 +1333,8 @@ pub enum MutatingUseContext {
|
|||
Drop,
|
||||
/// Mutable borrow.
|
||||
Borrow,
|
||||
/// AddressOf for *mut pointer.
|
||||
AddressOf,
|
||||
/// `&raw mut`.
|
||||
RawBorrow,
|
||||
/// Used as base for another place, e.g., `x` in `x.y`. Could potentially mutate the place.
|
||||
/// For example, the projection `x.y` is marked as a mutation in these cases:
|
||||
/// ```ignore (illustrative)
|
||||
|
|
@ -1386,8 +1386,8 @@ impl PlaceContext {
|
|||
pub fn is_address_of(&self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
PlaceContext::NonMutatingUse(NonMutatingUseContext::AddressOf)
|
||||
| PlaceContext::MutatingUse(MutatingUseContext::AddressOf)
|
||||
PlaceContext::NonMutatingUse(NonMutatingUseContext::RawBorrow)
|
||||
| PlaceContext::MutatingUse(MutatingUseContext::RawBorrow)
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1520,7 +1520,7 @@ rustc_queries! {
|
|||
separate_provide_extern
|
||||
}
|
||||
|
||||
query extern_crate(def_id: DefId) -> Option<&'tcx ExternCrate> {
|
||||
query extern_crate(def_id: CrateNum) -> Option<&'tcx ExternCrate> {
|
||||
eval_always
|
||||
desc { "getting crate's ExternCrateData" }
|
||||
separate_provide_extern
|
||||
|
|
|
|||
|
|
@ -407,7 +407,7 @@ pub enum ExprKind<'tcx> {
|
|||
arg: ExprId,
|
||||
},
|
||||
/// A `&raw [const|mut] $place_expr` raw borrow resulting in type `*[const|mut] T`.
|
||||
AddressOf {
|
||||
RawBorrow {
|
||||
mutability: hir::Mutability,
|
||||
arg: ExprId,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ pub fn walk_expr<'thir, 'tcx: 'thir, V: Visitor<'thir, 'tcx>>(
|
|||
}
|
||||
VarRef { id: _ } | UpvarRef { closure_def_id: _, var_hir_id: _ } => {}
|
||||
Borrow { arg, borrow_kind: _ } => visitor.visit_expr(&visitor.thir()[arg]),
|
||||
AddressOf { arg, mutability: _ } => visitor.visit_expr(&visitor.thir()[arg]),
|
||||
RawBorrow { arg, mutability: _ } => visitor.visit_expr(&visitor.thir()[arg]),
|
||||
Break { value, label: _ } => {
|
||||
if let Some(value) = value {
|
||||
visitor.visit_expr(&visitor.thir()[value])
|
||||
|
|
|
|||
|
|
@ -451,7 +451,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
|||
// 2. For an extern inferred from a path or an indirect crate,
|
||||
// where there is no explicit `extern crate`, we just prepend
|
||||
// the crate name.
|
||||
match self.tcx().extern_crate(def_id) {
|
||||
match self.tcx().extern_crate(cnum) {
|
||||
Some(&ExternCrate { src, dependency_of, span, .. }) => match (src, dependency_of) {
|
||||
(ExternCrateSource::Extern(def_id), LOCAL_CRATE) => {
|
||||
// NOTE(eddyb) the only reason `span` might be dummy,
|
||||
|
|
@ -3247,10 +3247,8 @@ fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, N
|
|||
let mut seen_defs: DefIdSet = Default::default();
|
||||
|
||||
for &cnum in tcx.crates(()).iter() {
|
||||
let def_id = cnum.as_def_id();
|
||||
|
||||
// Ignore crates that are not direct dependencies.
|
||||
match tcx.extern_crate(def_id) {
|
||||
match tcx.extern_crate(cnum) {
|
||||
None => continue,
|
||||
Some(extern_crate) => {
|
||||
if !extern_crate.is_direct() {
|
||||
|
|
@ -3259,7 +3257,7 @@ fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, N
|
|||
}
|
||||
}
|
||||
|
||||
queue.push(def_id);
|
||||
queue.push(cnum.as_def_id());
|
||||
}
|
||||
|
||||
// Iterate external crate defs but be mindful about visibility
|
||||
|
|
|
|||
|
|
@ -859,7 +859,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
// If `extern_crate` is `None`, then the crate was injected (e.g., by the allocator).
|
||||
// Treat that kind of crate as "indirect", since it's an implementation detail of
|
||||
// the language.
|
||||
|| self.extern_crate(key.as_def_id()).is_some_and(|e| e.is_direct())
|
||||
|| self.extern_crate(key).is_some_and(|e| e.is_direct())
|
||||
}
|
||||
|
||||
/// Whether the item has a host effect param. This is different from `TyCtxt::is_const`,
|
||||
|
|
|
|||
|
|
@ -244,8 +244,8 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
|
|||
ExprKind::Borrow { borrow_kind, arg } => Ok(
|
||||
Rvalue::Ref(self.tcx.lifetimes.re_erased, *borrow_kind, self.parse_place(*arg)?)
|
||||
),
|
||||
ExprKind::AddressOf { mutability, arg } => Ok(
|
||||
Rvalue::AddressOf(*mutability, self.parse_place(*arg)?)
|
||||
ExprKind::RawBorrow { mutability, arg } => Ok(
|
||||
Rvalue::RawPtr(*mutability, self.parse_place(*arg)?)
|
||||
),
|
||||
ExprKind::Binary { op, lhs, rhs } => Ok(
|
||||
Rvalue::BinaryOp(*op, Box::new((self.parse_operand(*lhs)?, self.parse_operand(*rhs)?)))
|
||||
|
|
|
|||
|
|
@ -542,7 +542,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
| ExprKind::PointerCoercion { .. }
|
||||
| ExprKind::Repeat { .. }
|
||||
| ExprKind::Borrow { .. }
|
||||
| ExprKind::AddressOf { .. }
|
||||
| ExprKind::RawBorrow { .. }
|
||||
| ExprKind::Match { .. }
|
||||
| ExprKind::If { .. }
|
||||
| ExprKind::Loop { .. }
|
||||
|
|
|
|||
|
|
@ -512,7 +512,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
| ExprKind::NeverToAny { .. }
|
||||
| ExprKind::Use { .. }
|
||||
| ExprKind::Borrow { .. }
|
||||
| ExprKind::AddressOf { .. }
|
||||
| ExprKind::RawBorrow { .. }
|
||||
| ExprKind::Adt { .. }
|
||||
| ExprKind::Loop { .. }
|
||||
| ExprKind::LogicalOp { .. }
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ impl Category {
|
|||
| ExprKind::Use { .. }
|
||||
| ExprKind::Adt { .. }
|
||||
| ExprKind::Borrow { .. }
|
||||
| ExprKind::AddressOf { .. }
|
||||
| ExprKind::RawBorrow { .. }
|
||||
| ExprKind::Yield { .. }
|
||||
| ExprKind::Call { .. }
|
||||
| ExprKind::InlineAsm { .. } => Some(Category::Rvalue(RvalueFunc::Into)),
|
||||
|
|
|
|||
|
|
@ -303,12 +303,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
this.cfg.push_assign(block, source_info, destination, borrow);
|
||||
block.unit()
|
||||
}
|
||||
ExprKind::AddressOf { mutability, arg } => {
|
||||
ExprKind::RawBorrow { mutability, arg } => {
|
||||
let place = match mutability {
|
||||
hir::Mutability::Not => this.as_read_only_place(block, arg),
|
||||
hir::Mutability::Mut => this.as_place(block, arg),
|
||||
};
|
||||
let address_of = Rvalue::AddressOf(mutability, unpack!(block = place));
|
||||
let address_of = Rvalue::RawPtr(mutability, unpack!(block = place));
|
||||
this.cfg.push_assign(block, source_info, destination, address_of);
|
||||
block.unit()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -397,7 +397,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
|
|||
| ExprKind::Scope { .. }
|
||||
| ExprKind::Cast { .. } => {}
|
||||
|
||||
ExprKind::AddressOf { .. }
|
||||
ExprKind::RawBorrow { .. }
|
||||
| ExprKind::Adt { .. }
|
||||
| ExprKind::Array { .. }
|
||||
| ExprKind::Binary { .. }
|
||||
|
|
@ -498,7 +498,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
}
|
||||
ExprKind::AddressOf { arg, .. } => {
|
||||
ExprKind::RawBorrow { arg, .. } => {
|
||||
if let ExprKind::Scope { value: arg, .. } = self.thir[arg].kind
|
||||
// THIR desugars UNSAFE_STATIC into *UNSAFE_STATIC_REF, where
|
||||
// UNSAFE_STATIC_REF holds the addr of the UNSAFE_STATIC, so: take two steps
|
||||
|
|
|
|||
|
|
@ -143,7 +143,7 @@ impl<'tcx> Cx<'tcx> {
|
|||
arg: self.thir.exprs.push(expr),
|
||||
},
|
||||
Adjust::Borrow(AutoBorrow::RawPtr(mutability)) => {
|
||||
ExprKind::AddressOf { mutability, arg: self.thir.exprs.push(expr) }
|
||||
ExprKind::RawBorrow { mutability, arg: self.thir.exprs.push(expr) }
|
||||
}
|
||||
Adjust::DynStar => ExprKind::Cast { source: self.thir.exprs.push(expr) },
|
||||
};
|
||||
|
|
@ -396,7 +396,7 @@ impl<'tcx> Cx<'tcx> {
|
|||
}
|
||||
|
||||
hir::ExprKind::AddrOf(hir::BorrowKind::Raw, mutability, arg) => {
|
||||
ExprKind::AddressOf { mutability, arg: self.mirror_expr(arg) }
|
||||
ExprKind::RawBorrow { mutability, arg: self.mirror_expr(arg) }
|
||||
}
|
||||
|
||||
hir::ExprKind::Block(blk, _) => ExprKind::Block { block: self.mirror_block(blk) },
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use rustc_hir as hir;
|
|||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_hir::{HirId, Node};
|
||||
use rustc_hir::HirId;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::middle::region;
|
||||
use rustc_middle::thir::*;
|
||||
|
|
@ -110,11 +110,7 @@ impl<'tcx> Cx<'tcx> {
|
|||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn pattern_from_hir(&mut self, p: &hir::Pat<'_>) -> Box<Pat<'tcx>> {
|
||||
let p = match self.tcx.hir_node(p.hir_id) {
|
||||
Node::Pat(p) => p,
|
||||
node => bug!("pattern became {:?}", node),
|
||||
};
|
||||
fn pattern_from_hir(&mut self, p: &'tcx hir::Pat<'tcx>) -> Box<Pat<'tcx>> {
|
||||
pat_from_hir(self.tcx, self.param_env, self.typeck_results(), p)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -325,7 +325,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
|
|||
Assign { .. } | AssignOp { .. } | InlineAsm { .. } | Let { .. } => true,
|
||||
|
||||
// These evaluate to a value.
|
||||
AddressOf { .. }
|
||||
RawBorrow { .. }
|
||||
| Adt { .. }
|
||||
| Array { .. }
|
||||
| Binary { .. }
|
||||
|
|
|
|||
|
|
@ -379,8 +379,8 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> {
|
|||
self.print_expr(*arg, depth_lvl + 2);
|
||||
print_indented!(self, ")", depth_lvl);
|
||||
}
|
||||
AddressOf { mutability, arg } => {
|
||||
print_indented!(self, "AddressOf {", depth_lvl);
|
||||
RawBorrow { mutability, arg } => {
|
||||
print_indented!(self, "RawBorrow {", depth_lvl);
|
||||
print_indented!(self, format!("mutability: {:?}", mutability), depth_lvl + 1);
|
||||
print_indented!(self, "arg:", depth_lvl + 1);
|
||||
self.print_expr(*arg, depth_lvl + 2);
|
||||
|
|
|
|||
|
|
@ -703,7 +703,7 @@ where
|
|||
statements: vec![
|
||||
self.assign(
|
||||
ptr,
|
||||
Rvalue::AddressOf(Mutability::Mut, tcx.mk_place_index(self.place, cur)),
|
||||
Rvalue::RawPtr(Mutability::Mut, tcx.mk_place_index(self.place, cur)),
|
||||
),
|
||||
self.assign(
|
||||
cur.into(),
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ where
|
|||
match rvalue {
|
||||
// We ignore fake borrows as these get removed after analysis and shouldn't effect
|
||||
// the layout of generators.
|
||||
Rvalue::AddressOf(_, borrowed_place)
|
||||
Rvalue::RawPtr(_, borrowed_place)
|
||||
| Rvalue::Ref(_, BorrowKind::Mut { .. } | BorrowKind::Shared, borrowed_place) => {
|
||||
if !borrowed_place.is_indirect() {
|
||||
self.trans.gen_(borrowed_place.local);
|
||||
|
|
|
|||
|
|
@ -351,7 +351,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, '_, 'tcx> {
|
|||
&& let Some((_, rvalue)) = statement.kind.as_assign()
|
||||
&& let mir::Rvalue::Ref(_, mir::BorrowKind::Mut { .. }, place)
|
||||
// FIXME: Does `&raw const foo` allow mutation? See #90413.
|
||||
| mir::Rvalue::AddressOf(_, place) = rvalue
|
||||
| mir::Rvalue::RawPtr(_, place) = rvalue
|
||||
&& let LookupResult::Exact(mpi) = self.move_data().rev_lookup.find(place.as_ref())
|
||||
{
|
||||
on_all_children_bits(self.move_data(), mpi, |child| {
|
||||
|
|
|
|||
|
|
@ -189,13 +189,13 @@ impl DefUse {
|
|||
|
||||
// All other contexts are uses...
|
||||
PlaceContext::MutatingUse(
|
||||
MutatingUseContext::AddressOf
|
||||
MutatingUseContext::RawBorrow
|
||||
| MutatingUseContext::Borrow
|
||||
| MutatingUseContext::Drop
|
||||
| MutatingUseContext::Retag,
|
||||
)
|
||||
| PlaceContext::NonMutatingUse(
|
||||
NonMutatingUseContext::AddressOf
|
||||
NonMutatingUseContext::RawBorrow
|
||||
| NonMutatingUseContext::Copy
|
||||
| NonMutatingUseContext::Inspect
|
||||
| NonMutatingUseContext::Move
|
||||
|
|
|
|||
|
|
@ -432,7 +432,7 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> {
|
|||
}
|
||||
Rvalue::CopyForDeref(..) => unreachable!(),
|
||||
Rvalue::Ref(..)
|
||||
| Rvalue::AddressOf(..)
|
||||
| Rvalue::RawPtr(..)
|
||||
| Rvalue::Discriminant(..)
|
||||
| Rvalue::Len(..)
|
||||
| Rvalue::NullaryOp(
|
||||
|
|
|
|||
|
|
@ -177,7 +177,7 @@ pub trait ValueAnalysis<'tcx> {
|
|||
match rvalue {
|
||||
Rvalue::Use(operand) => self.handle_operand(operand, state),
|
||||
Rvalue::CopyForDeref(place) => self.handle_operand(&Operand::Copy(*place), state),
|
||||
Rvalue::Ref(..) | Rvalue::AddressOf(..) => {
|
||||
Rvalue::Ref(..) | Rvalue::RawPtr(..) => {
|
||||
// We don't track such places.
|
||||
ValueOrPlace::TOP
|
||||
}
|
||||
|
|
|
|||
|
|
@ -131,9 +131,9 @@ impl<'tcx> MirPass<'tcx> for AddRetag {
|
|||
// Ptr-creating operations already do their own internal retagging, no
|
||||
// need to also add a retag statement.
|
||||
// *Except* if we are deref'ing a Box, because those get desugared to directly working
|
||||
// with the inner raw pointer! That's relevant for `AddressOf` as Miri otherwise makes it
|
||||
// with the inner raw pointer! That's relevant for `RawPtr` as Miri otherwise makes it
|
||||
// a NOP when the original pointer is already raw.
|
||||
Rvalue::AddressOf(_mutbl, place) => {
|
||||
Rvalue::RawPtr(_mutbl, place) => {
|
||||
// Using `is_box_global` here is a bit sketchy: if this code is
|
||||
// generic over the allocator, we'll not add a retag! This is a hack
|
||||
// to make Stacked Borrows compatible with custom allocator code.
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ struct PointerFinder<'tcx, 'a> {
|
|||
impl<'tcx, 'a> Visitor<'tcx> for PointerFinder<'tcx, 'a> {
|
||||
fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) {
|
||||
// We want to only check reads and writes to Places, so we specifically exclude
|
||||
// Borrows and AddressOf.
|
||||
// Borrow and RawBorrow.
|
||||
match context {
|
||||
PlaceContext::MutatingUse(
|
||||
MutatingUseContext::Store
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ impl<'tcx> Visitor<'tcx> for DeduceReadOnly {
|
|||
// This is a mutation, so mark it as such.
|
||||
true
|
||||
}
|
||||
PlaceContext::NonMutatingUse(NonMutatingUseContext::AddressOf) => {
|
||||
PlaceContext::NonMutatingUse(NonMutatingUseContext::RawBorrow) => {
|
||||
// Whether mutating though a `&raw const` is allowed is still undecided, so we
|
||||
// disable any sketchy `readonly` optimizations for now.
|
||||
// But we only need to do this if the pointer would point into the argument.
|
||||
|
|
|
|||
|
|
@ -576,7 +576,7 @@ impl WriteInfo {
|
|||
Rvalue::ThreadLocalRef(_)
|
||||
| Rvalue::NullaryOp(_, _)
|
||||
| Rvalue::Ref(_, _, _)
|
||||
| Rvalue::AddressOf(_, _)
|
||||
| Rvalue::RawPtr(_, _)
|
||||
| Rvalue::Len(_)
|
||||
| Rvalue::Discriminant(_)
|
||||
| Rvalue::CopyForDeref(_) => (),
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@
|
|||
//!
|
||||
//! # Handling of references
|
||||
//!
|
||||
//! We handle references by assigning a different "provenance" index to each Ref/AddressOf rvalue.
|
||||
//! We handle references by assigning a different "provenance" index to each Ref/RawPtr rvalue.
|
||||
//! This ensure that we do not spuriously merge borrows that should not be merged. Meanwhile, we
|
||||
//! consider all the derefs of an immutable reference to a freeze type to give the same value:
|
||||
//! ```ignore (MIR)
|
||||
|
|
@ -832,7 +832,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
|||
self.simplify_place_projection(place, location);
|
||||
return self.new_pointer(*place, AddressKind::Ref(borrow_kind));
|
||||
}
|
||||
Rvalue::AddressOf(mutbl, ref mut place) => {
|
||||
Rvalue::RawPtr(mutbl, ref mut place) => {
|
||||
self.simplify_place_projection(place, location);
|
||||
return self.new_pointer(*place, AddressKind::Address(mutbl));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -141,7 +141,7 @@ impl<'tcx> InstSimplifyContext<'tcx, '_> {
|
|||
|
||||
/// Transform `&(*a)` ==> `a`.
|
||||
fn simplify_ref_deref(&self, source_info: &SourceInfo, rvalue: &mut Rvalue<'tcx>) {
|
||||
if let Rvalue::Ref(_, _, place) | Rvalue::AddressOf(_, place) = rvalue {
|
||||
if let Rvalue::Ref(_, _, place) | Rvalue::RawPtr(_, place) = rvalue {
|
||||
if let Some((base, ProjectionElem::Deref)) = place.as_ref().last_projection() {
|
||||
if rvalue.ty(self.local_decls, self.tcx) != base.ty(self.local_decls, self.tcx).ty {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -419,8 +419,8 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
|||
}
|
||||
|
||||
// Do not try creating references (#67862)
|
||||
Rvalue::AddressOf(_, place) | Rvalue::Ref(_, _, place) => {
|
||||
trace!("skipping AddressOf | Ref for {:?}", place);
|
||||
Rvalue::RawPtr(_, place) | Rvalue::Ref(_, _, place) => {
|
||||
trace!("skipping RawPtr | Ref for {:?}", place);
|
||||
|
||||
// This may be creating mutable references or immutable references to cells.
|
||||
// If that happens, the pointed to value could be mutated via that reference.
|
||||
|
|
@ -616,7 +616,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
|||
ImmTy::from_scalar(Scalar::from_target_usize(len, self), layout).into()
|
||||
}
|
||||
|
||||
Ref(..) | AddressOf(..) => return None,
|
||||
Ref(..) | RawPtr(..) => return None,
|
||||
|
||||
NullaryOp(ref null_op, ty) => {
|
||||
let op_layout = self.use_ecx(|this| this.ecx.layout_of(ty))?;
|
||||
|
|
@ -969,9 +969,9 @@ impl<'tcx> Visitor<'tcx> for CanConstProp {
|
|||
// mutation.
|
||||
| NonMutatingUse(NonMutatingUseContext::SharedBorrow)
|
||||
| NonMutatingUse(NonMutatingUseContext::FakeBorrow)
|
||||
| NonMutatingUse(NonMutatingUseContext::AddressOf)
|
||||
| NonMutatingUse(NonMutatingUseContext::RawBorrow)
|
||||
| MutatingUse(MutatingUseContext::Borrow)
|
||||
| MutatingUse(MutatingUseContext::AddressOf) => {
|
||||
| MutatingUse(MutatingUseContext::RawBorrow) => {
|
||||
trace!("local {:?} can't be propagated because it's used: {:?}", local, context);
|
||||
self.can_const_prop[local] = ConstPropMode::NoPropagation;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -214,7 +214,7 @@ impl EnumSizeOpt {
|
|||
source_info,
|
||||
kind: StatementKind::Assign(Box::new((
|
||||
dst,
|
||||
Rvalue::AddressOf(Mutability::Mut, *lhs),
|
||||
Rvalue::RawPtr(Mutability::Mut, *lhs),
|
||||
))),
|
||||
};
|
||||
|
||||
|
|
@ -238,7 +238,7 @@ impl EnumSizeOpt {
|
|||
source_info,
|
||||
kind: StatementKind::Assign(Box::new((
|
||||
src,
|
||||
Rvalue::AddressOf(Mutability::Not, *rhs),
|
||||
Rvalue::RawPtr(Mutability::Not, *rhs),
|
||||
))),
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -551,7 +551,7 @@ impl<'tcx> Validator<'_, 'tcx> {
|
|||
self.validate_operand(rhs)?;
|
||||
}
|
||||
|
||||
Rvalue::AddressOf(_, place) => {
|
||||
Rvalue::RawPtr(_, place) => {
|
||||
// We accept `&raw *`, i.e., raw reborrows -- creating a raw pointer is
|
||||
// no problem, only using it is.
|
||||
if let Some((place_base, ProjectionElem::Deref)) = place.as_ref().last_projection()
|
||||
|
|
|
|||
|
|
@ -227,7 +227,7 @@ fn compute_replacement<'tcx>(
|
|||
}
|
||||
}
|
||||
}
|
||||
Rvalue::Ref(_, _, place) | Rvalue::AddressOf(_, place) => {
|
||||
Rvalue::Ref(_, _, place) | Rvalue::RawPtr(_, place) => {
|
||||
let mut place = *place;
|
||||
// Try to see through `place` in order to collapse reborrow chains.
|
||||
if place.projection.first() == Some(&PlaceElem::Deref)
|
||||
|
|
|
|||
|
|
@ -343,7 +343,7 @@ impl<'tcx> AsyncDestructorCtorShimBuilder<'tcx> {
|
|||
.tcx
|
||||
.mk_place_elems(&[PlaceElem::Deref, PlaceElem::Field(field, field_ty)]),
|
||||
};
|
||||
self.put_temp_rvalue(Rvalue::AddressOf(Mutability::Mut, place))
|
||||
self.put_temp_rvalue(Rvalue::RawPtr(Mutability::Mut, place))
|
||||
}
|
||||
|
||||
/// If given Self is an enum puts `to_drop: *mut FieldTy` on top of
|
||||
|
|
@ -363,7 +363,7 @@ impl<'tcx> AsyncDestructorCtorShimBuilder<'tcx> {
|
|||
PlaceElem::Field(field, field_ty),
|
||||
]),
|
||||
};
|
||||
self.put_temp_rvalue(Rvalue::AddressOf(Mutability::Mut, place))
|
||||
self.put_temp_rvalue(Rvalue::RawPtr(Mutability::Mut, place))
|
||||
}
|
||||
|
||||
/// If given Self is an enum puts `to_drop: *mut FieldTy` on top of
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ use rustc_index::{Idx, IndexSlice, IndexVec};
|
|||
use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor};
|
||||
use rustc_middle::mir::*;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_span::DUMMY_SP;
|
||||
use smallvec::SmallVec;
|
||||
|
||||
pub enum SimplifyCfg {
|
||||
|
|
@ -318,6 +319,7 @@ pub(crate) fn remove_dead_blocks(body: &mut Body<'_>) {
|
|||
let mut orig_index = 0;
|
||||
let mut used_index = 0;
|
||||
let mut kept_unreachable = None;
|
||||
let mut deduplicated_unreachable = false;
|
||||
basic_blocks.raw.retain(|bbdata| {
|
||||
let orig_bb = BasicBlock::new(orig_index);
|
||||
if !reachable.contains(orig_bb) {
|
||||
|
|
@ -330,6 +332,7 @@ pub(crate) fn remove_dead_blocks(body: &mut Body<'_>) {
|
|||
let kept_unreachable = *kept_unreachable.get_or_insert(used_bb);
|
||||
if kept_unreachable != used_bb {
|
||||
replacements[orig_index] = kept_unreachable;
|
||||
deduplicated_unreachable = true;
|
||||
orig_index += 1;
|
||||
return false;
|
||||
}
|
||||
|
|
@ -341,6 +344,14 @@ pub(crate) fn remove_dead_blocks(body: &mut Body<'_>) {
|
|||
true
|
||||
});
|
||||
|
||||
// If we deduplicated unreachable blocks we erase their source_info as we
|
||||
// can no longer attribute their code to a particular location in the
|
||||
// source.
|
||||
if deduplicated_unreachable {
|
||||
basic_blocks[kept_unreachable.unwrap()].terminator_mut().source_info =
|
||||
SourceInfo { span: DUMMY_SP, scope: OUTERMOST_SOURCE_SCOPE };
|
||||
}
|
||||
|
||||
for block in basic_blocks {
|
||||
for target in block.terminator_mut().successors_mut() {
|
||||
*target = replacements[target.index()];
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@
|
|||
//! 1/ They are only assigned-to once, either as a function parameter, or in an assign statement;
|
||||
//! 2/ This single assignment dominates all uses;
|
||||
//!
|
||||
//! As we do not track indirect assignments, a local that has its address taken (either by
|
||||
//! AddressOf or by borrowing) is considered non-SSA. However, it is UB to modify through an
|
||||
//! immutable borrow of a `Freeze` local. Those can still be considered to be SSA.
|
||||
//! As we do not track indirect assignments, a local that has its address taken (via a borrow or raw
|
||||
//! borrow operator) is considered non-SSA. However, it is UB to modify through an immutable borrow
|
||||
//! of a `Freeze` local. Those can still be considered to be SSA.
|
||||
|
||||
use rustc_data_structures::graph::dominators::Dominators;
|
||||
use rustc_index::bit_set::BitSet;
|
||||
|
|
@ -262,7 +262,7 @@ impl<'tcx> Visitor<'tcx> for SsaVisitor<'tcx, '_> {
|
|||
PlaceContext::MutatingUse(MutatingUseContext::Projection)
|
||||
| PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection) => bug!(),
|
||||
// Anything can happen with raw pointers, so remove them.
|
||||
PlaceContext::NonMutatingUse(NonMutatingUseContext::AddressOf)
|
||||
PlaceContext::NonMutatingUse(NonMutatingUseContext::RawBorrow)
|
||||
| PlaceContext::MutatingUse(_) => {
|
||||
self.assignments[local] = Set1::Many;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1345,7 +1345,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
|||
}
|
||||
Rvalue::Repeat(_, _)
|
||||
| Rvalue::ThreadLocalRef(_)
|
||||
| Rvalue::AddressOf(_, _)
|
||||
| Rvalue::RawPtr(_, _)
|
||||
| Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::UbChecks, _)
|
||||
| Rvalue::Discriminant(_) => {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use rustc_ast::token::{self, Delimiter};
|
|||
use rustc_errors::codes::*;
|
||||
use rustc_errors::{Diag, PResult};
|
||||
use rustc_span::symbol::kw;
|
||||
use rustc_span::{sym, BytePos, Span};
|
||||
use rustc_span::{BytePos, Span};
|
||||
use thin_vec::ThinVec;
|
||||
use tracing::debug;
|
||||
|
||||
|
|
@ -265,7 +265,6 @@ impl<'a> Parser<'a> {
|
|||
let is_unsafe = this.eat_keyword(kw::Unsafe);
|
||||
let unsafety = if is_unsafe {
|
||||
let unsafe_span = this.prev_token.span;
|
||||
this.psess.gated_spans.gate(sym::unsafe_attributes, unsafe_span);
|
||||
this.expect(&token::OpenDelim(Delimiter::Parenthesis))?;
|
||||
ast::Safety::Unsafe(unsafe_span)
|
||||
} else {
|
||||
|
|
@ -406,7 +405,6 @@ impl<'a> Parser<'a> {
|
|||
};
|
||||
let unsafety = if is_unsafe {
|
||||
let unsafe_span = self.prev_token.span;
|
||||
self.psess.gated_spans.gate(sym::unsafe_attributes, unsafe_span);
|
||||
self.expect(&token::OpenDelim(Delimiter::Parenthesis))?;
|
||||
|
||||
ast::Safety::Unsafe(unsafe_span)
|
||||
|
|
|
|||
|
|
@ -851,7 +851,7 @@ impl<'a> Parser<'a> {
|
|||
self.expect_and()?;
|
||||
let has_lifetime = self.token.is_lifetime() && self.look_ahead(1, |t| t != &token::Colon);
|
||||
let lifetime = has_lifetime.then(|| self.expect_lifetime()); // For recovery, see below.
|
||||
let (borrow_kind, mutbl) = self.parse_borrow_modifiers(lo);
|
||||
let (borrow_kind, mutbl) = self.parse_borrow_modifiers();
|
||||
let attrs = self.parse_outer_attributes()?;
|
||||
let expr = if self.token.is_range_separator() {
|
||||
self.parse_expr_prefix_range(attrs)
|
||||
|
|
@ -871,13 +871,12 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
|
||||
/// Parse `mut?` or `raw [ const | mut ]`.
|
||||
fn parse_borrow_modifiers(&mut self, lo: Span) -> (ast::BorrowKind, ast::Mutability) {
|
||||
fn parse_borrow_modifiers(&mut self) -> (ast::BorrowKind, ast::Mutability) {
|
||||
if self.check_keyword(kw::Raw) && self.look_ahead(1, Token::is_mutability) {
|
||||
// `raw [ const | mut ]`.
|
||||
let found_raw = self.eat_keyword(kw::Raw);
|
||||
assert!(found_raw);
|
||||
let mutability = self.parse_const_or_mut().unwrap();
|
||||
self.psess.gated_spans.gate(sym::raw_ref_op, lo.to(self.prev_token.span));
|
||||
(ast::BorrowKind::Raw, mutability)
|
||||
} else {
|
||||
// `mut?`
|
||||
|
|
|
|||
|
|
@ -7,9 +7,7 @@ use rustc_ast::{
|
|||
NestedMetaItem, Safety,
|
||||
};
|
||||
use rustc_errors::{Applicability, FatalError, PResult};
|
||||
use rustc_feature::{
|
||||
AttributeSafety, AttributeTemplate, BuiltinAttribute, Features, BUILTIN_ATTRIBUTE_MAP,
|
||||
};
|
||||
use rustc_feature::{AttributeSafety, AttributeTemplate, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
|
||||
use rustc_session::errors::report_lit_error;
|
||||
use rustc_session::lint::builtin::{ILL_FORMED_ATTRIBUTE_INPUT, UNSAFE_ATTR_OUTSIDE_UNSAFE};
|
||||
use rustc_session::lint::BuiltinLintDiag;
|
||||
|
|
@ -18,7 +16,7 @@ use rustc_span::{sym, BytePos, Span, Symbol};
|
|||
|
||||
use crate::{errors, parse_in};
|
||||
|
||||
pub fn check_attr(features: &Features, psess: &ParseSess, attr: &Attribute) {
|
||||
pub fn check_attr(psess: &ParseSess, attr: &Attribute) {
|
||||
if attr.is_doc_comment() {
|
||||
return;
|
||||
}
|
||||
|
|
@ -28,7 +26,7 @@ pub fn check_attr(features: &Features, psess: &ParseSess, attr: &Attribute) {
|
|||
|
||||
// All non-builtin attributes are considered safe
|
||||
let safety = attr_info.map(|x| x.safety).unwrap_or(AttributeSafety::Normal);
|
||||
check_attribute_safety(features, psess, safety, attr);
|
||||
check_attribute_safety(psess, safety, attr);
|
||||
|
||||
// Check input tokens for built-in and key-value attributes.
|
||||
match attr_info {
|
||||
|
|
@ -36,9 +34,9 @@ pub fn check_attr(features: &Features, psess: &ParseSess, attr: &Attribute) {
|
|||
Some(BuiltinAttribute { name, template, .. }) if *name != sym::rustc_dummy => {
|
||||
match parse_meta(psess, attr) {
|
||||
// Don't check safety again, we just did that
|
||||
Ok(meta) => check_builtin_meta_item(
|
||||
features, psess, &meta, attr.style, *name, *template, false,
|
||||
),
|
||||
Ok(meta) => {
|
||||
check_builtin_meta_item(psess, &meta, attr.style, *name, *template, false)
|
||||
}
|
||||
Err(err) => {
|
||||
err.emit();
|
||||
}
|
||||
|
|
@ -157,16 +155,7 @@ fn is_attr_template_compatible(template: &AttributeTemplate, meta: &ast::MetaIte
|
|||
}
|
||||
}
|
||||
|
||||
pub fn check_attribute_safety(
|
||||
features: &Features,
|
||||
psess: &ParseSess,
|
||||
safety: AttributeSafety,
|
||||
attr: &Attribute,
|
||||
) {
|
||||
if !features.unsafe_attributes {
|
||||
return;
|
||||
}
|
||||
|
||||
pub fn check_attribute_safety(psess: &ParseSess, safety: AttributeSafety, attr: &Attribute) {
|
||||
let attr_item = attr.get_normal_item();
|
||||
|
||||
if safety == AttributeSafety::Unsafe {
|
||||
|
|
@ -215,21 +204,18 @@ pub fn check_attribute_safety(
|
|||
|
||||
// Called by `check_builtin_meta_item` and code that manually denies
|
||||
// `unsafe(...)` in `cfg`
|
||||
pub fn deny_builtin_meta_unsafety(features: &Features, psess: &ParseSess, meta: &MetaItem) {
|
||||
pub fn deny_builtin_meta_unsafety(psess: &ParseSess, meta: &MetaItem) {
|
||||
// This only supports denying unsafety right now - making builtin attributes
|
||||
// support unsafety will requite us to thread the actual `Attribute` through
|
||||
// for the nice diagnostics.
|
||||
if features.unsafe_attributes {
|
||||
if let Safety::Unsafe(unsafe_span) = meta.unsafety {
|
||||
psess
|
||||
.dcx()
|
||||
.emit_err(errors::InvalidAttrUnsafe { span: unsafe_span, name: meta.path.clone() });
|
||||
}
|
||||
if let Safety::Unsafe(unsafe_span) = meta.unsafety {
|
||||
psess
|
||||
.dcx()
|
||||
.emit_err(errors::InvalidAttrUnsafe { span: unsafe_span, name: meta.path.clone() });
|
||||
}
|
||||
}
|
||||
|
||||
pub fn check_builtin_meta_item(
|
||||
features: &Features,
|
||||
psess: &ParseSess,
|
||||
meta: &MetaItem,
|
||||
style: ast::AttrStyle,
|
||||
|
|
@ -246,7 +232,7 @@ pub fn check_builtin_meta_item(
|
|||
}
|
||||
|
||||
if deny_unsafety {
|
||||
deny_builtin_meta_unsafety(features, psess, meta);
|
||||
deny_builtin_meta_unsafety(psess, meta);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -430,6 +430,10 @@ passes_link_section =
|
|||
.warn = {-passes_previously_accepted}
|
||||
.label = not a function or static
|
||||
|
||||
passes_linkage =
|
||||
attribute should be applied to a function or static
|
||||
.label = not a function definition or static
|
||||
|
||||
passes_macro_export =
|
||||
`#[macro_export]` only has an effect on macro definitions
|
||||
|
||||
|
|
@ -440,6 +444,9 @@ passes_macro_export_on_decl_macro =
|
|||
passes_macro_use =
|
||||
`#[{$name}]` only has an effect on `extern crate` and modules
|
||||
|
||||
passes_may_dangle =
|
||||
`#[may_dangle]` must be applied to a lifetime or type generic parameter in `Drop` impl
|
||||
|
||||
passes_maybe_string_interpolation = you might have meant to use string interpolation in this string literal
|
||||
passes_missing_const_err =
|
||||
attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
|
||||
|
|
@ -471,8 +478,8 @@ passes_multiple_start_functions =
|
|||
.previous = previous `#[start]` function here
|
||||
|
||||
passes_must_not_suspend =
|
||||
`must_not_suspend` attribute should be applied to a struct, enum, or trait
|
||||
.label = is not a struct, enum, or trait
|
||||
`must_not_suspend` attribute should be applied to a struct, enum, union, or trait
|
||||
.label = is not a struct, enum, union, or trait
|
||||
|
||||
passes_must_use_async =
|
||||
`must_use` attribute on `async` functions applies to the anonymous `Future` returned by the function, not the value within
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue