diff options
Diffstat (limited to 'compiler')
120 files changed, 846 insertions, 666 deletions
diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs index 300bfa101c6..9c073130827 100644 --- a/compiler/rustc_ast_lowering/src/delegation.rs +++ b/compiler/rustc_ast_lowering/src/delegation.rs @@ -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 { diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 7af3945d3f9..f6065259d8d 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -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), diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index a353c79f12d..837cb805700 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -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) { diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 3ceb8e0711a..5ab99fbac86 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -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 { diff --git a/compiler/rustc_borrowck/src/def_use.rs b/compiler/rustc_borrowck/src/def_use.rs index 1f0b0981c8f..e07d7dd309a 100644 --- a/compiler/rustc_borrowck/src/def_use.rs +++ b/compiler/rustc_borrowck/src/def_use.rs @@ -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) | diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 30dd45d847c..a529df76bcb 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -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, diff --git a/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs b/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs index f090da031a0..a57041cd04c 100644 --- a/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs +++ b/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs @@ -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, diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index a2669da1b04..6983cda6ddf 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -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(..) diff --git a/compiler/rustc_builtin_macros/src/cfg_accessible.rs b/compiler/rustc_builtin_macros/src/cfg_accessible.rs index 006b6aa823f..3d3bd3aea05 100644 --- a/compiler/rustc_builtin_macros/src/cfg_accessible.rs +++ b/compiler/rustc_builtin_macros/src/cfg_accessible.rs @@ -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, diff --git a/compiler/rustc_builtin_macros/src/derive.rs b/compiler/rustc_builtin_macros/src/derive.rs index 57bddf0ab60..e8704bc2f63 100644 --- a/compiler/rustc_builtin_macros/src/derive.rs +++ b/compiler/rustc_builtin_macros/src/derive.rs @@ -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, diff --git a/compiler/rustc_builtin_macros/src/util.rs b/compiler/rustc_builtin_macros/src/util.rs index 73cc8ff547d..0bcd5aef28b 100644 --- a/compiler/rustc_builtin_macros/src/util.rs +++ b/compiler/rustc_builtin_macros/src/util.rs @@ -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, diff --git a/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs b/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs index e603ac566f4..ccbd5a78485 100644 --- a/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs +++ b/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs @@ -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)] diff --git a/compiler/rustc_codegen_cranelift/src/analyze.rs b/compiler/rustc_codegen_cranelift/src/analyze.rs index c5762638a6b..72380f50385 100644 --- a/compiler/rustc_codegen_cranelift/src/analyze.rs +++ b/compiler/rustc_codegen_cranelift/src/analyze.rs @@ -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; } _ => {} diff --git a/compiler/rustc_codegen_cranelift/src/archive.rs b/compiler/rustc_codegen_cranelift/src/archive.rs index 5eedab4f2cb..c7725e49c94 100644 --- a/compiler/rustc_codegen_cranelift/src/archive.rs +++ b/compiler/rustc_codegen_cranelift/src/archive.rs @@ -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(), - )); - } - } - } } diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index 9bc7b57c537..f1d885bf1bc 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -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_); diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index 21930fa2ddb..f737af25b62 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -12,7 +12,6 @@ #![warn(unused_lifetimes)] // tidy-alphabetical-end -extern crate ar_archive_writer; extern crate jobserver; #[macro_use] extern crate rustc_middle; diff --git a/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs b/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs index 9f096e90220..dcfa34cb729 100644 --- a/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs +++ b/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs @@ -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)] diff --git a/compiler/rustc_codegen_llvm/Cargo.toml b/compiler/rustc_codegen_llvm/Cargo.toml index dad4722d620..a93baf88413 100644 --- a/compiler/rustc_codegen_llvm/Cargo.toml +++ b/compiler/rustc_codegen_llvm/Cargo.toml @@ -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" } diff --git a/compiler/rustc_codegen_llvm/messages.ftl b/compiler/rustc_codegen_llvm/messages.ftl index 267da9325c3..df2198df14b 100644 --- a/compiler/rustc_codegen_llvm/messages.ftl +++ b/compiler/rustc_codegen_llvm/messages.ftl @@ -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} diff --git a/compiler/rustc_codegen_llvm/src/back/archive.rs b/compiler/rustc_codegen_llvm/src/back/archive.rs index 2120fc1815c..c0ec4f86b4d 100644 --- a/compiler/rustc_codegen_llvm/src/back/archive.rs +++ b/compiler/rustc_codegen_llvm/src/back/archive.rs @@ -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. diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index dd3f39ecead..1fd9f9e8116 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -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); diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index 7e53d32ce8c..e0ec9cdca56 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -40,13 +40,6 @@ pub(crate) enum PossibleFeature<'a> { } #[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> { #[primary_span] diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index f5558723d11..abfe38d4c0c 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -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 diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml index 6e1c323cbd0..e3033b332ca 100644 --- a/compiler/rustc_codegen_ssa/Cargo.toml +++ b/compiler/rustc_codegen_ssa/Cargo.toml @@ -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] diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl index 80f25d42a08..8a6a2acd87d 100644 --- a/compiler/rustc_codegen_ssa/messages.ftl +++ b/compiler/rustc_codegen_ssa/messages.ftl @@ -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 = diff --git a/compiler/rustc_codegen_ssa/src/back/archive.rs b/compiler/rustc_codegen_ssa/src/back/archive.rs index 8eb44d12016..38a440a707a 100644 --- a/compiler/rustc_codegen_ssa/src/back/archive.rs +++ b/compiler/rustc_codegen_ssa/src/back/archive.rs @@ -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, diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index 94bf0ab34e2..573a8cf7cbe 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -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, +} diff --git a/compiler/rustc_codegen_ssa/src/mir/analyze.rs b/compiler/rustc_codegen_ssa/src/mir/analyze.rs index 6794365c9be..c8cf341628c 100644 --- a/compiler/rustc_codegen_ssa/src/mir/analyze.rs +++ b/compiler/rustc_codegen_ssa/src/mir/analyze.rs @@ -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; diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 3c2c29ac7f7..d94c6f8ddce 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -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(..) | // (*) diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs index 32a9247bcc7..86a5afa65ba 100644 --- a/compiler/rustc_const_eval/src/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/check_consts/check.rs @@ -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), diff --git a/compiler/rustc_const_eval/src/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/check_consts/qualifs.rs index c0f2d113c7e..c566dc7fa84 100644 --- a/compiler/rustc_const_eval/src/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/check_consts/qualifs.rs @@ -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; diff --git a/compiler/rustc_const_eval/src/check_consts/resolver.rs b/compiler/rustc_const_eval/src/check_consts/resolver.rs index ea3a5264357..681184f7fbc 100644 --- a/compiler/rustc_const_eval/src/check_consts/resolver.rs +++ b/compiler/rustc_const_eval/src/check_consts/resolver.rs @@ -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) { diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index aaee6f6d247..70cfba1922c 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -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; diff --git a/compiler/rustc_error_codes/src/error_codes/E0745.md b/compiler/rustc_error_codes/src/error_codes/E0745.md index 23ee7af30f4..32b28f3de94 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0745.md +++ b/compiler/rustc_error_codes/src/error_codes/E0745.md @@ -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! diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index f6bf9f5e89f..b0d3fecbb47 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -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| { diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 37679e17b90..cb6b13282a2 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -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); diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index 03b40e28f8b..7838abca9b8 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -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. diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 24f691ea7fa..14e353f13ca 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -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)), diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 33e8432596b..6c7125b75db 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -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); diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index dd501f8417e..a54596e3088 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -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, _, _) => { diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 2e778fd3759..0135cdf1e90 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -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); diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 4b45ced30c5..c2b2f08132e 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -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), _ => { diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index d3b928fc17c..bdf2914fc50 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -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) diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 91fa066ec6a..f75954c9edf 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -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() => { diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index e11d3c9c48b..ae0c70d2326 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -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); }) diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 089cee2fa0d..cff21173f79 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -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, diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index 7cd97166ed1..03a76d44cc9 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -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(|_| { diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index d53df251a15..9b34c59f1f1 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -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); diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 3b71e2f19b1..b3cf73bac1a 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -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( diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 54bf73a40dd..cb7a07116ce 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -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 => (), } } diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index c731b03a875..56d77c9d1d0 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -4971,7 +4971,6 @@ declare_lint! { /// ### Example /// /// ```rust - /// #![feature(unsafe_attributes)] /// #![warn(unsafe_attr_outside_unsafe)] /// /// #[no_mangle] diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index edab6b5ebde..0f85998204c 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -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)); + + // 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; + } - 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, + // 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, .. }), diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index fa521ab9f2f..596d9f07737 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -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)) { diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index f2d87814130..efdc0c710ba 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -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); + } } } } diff --git a/compiler/rustc_middle/src/mir/statement.rs b/compiler/rustc_middle/src/mir/statement.rs index 3009ca8d809..bc7dfa6205e 100644 --- a/compiler/rustc_middle/src/mir/statement.rs +++ b/compiler/rustc_middle/src/mir/statement.rs @@ -423,7 +423,7 @@ impl<'tcx> Rvalue<'tcx> { | Rvalue::Repeat(_, _) | Rvalue::Ref(_, _, _) | Rvalue::ThreadLocalRef(_) - | Rvalue::AddressOf(_, _) + | Rvalue::RawPtr(_, _) | Rvalue::Len(_) | Rvalue::Cast( CastKind::IntToInt diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 1119ff6ff3d..51b4154ddab 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -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`. /// diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs index 1075344dc00..8d57d0d8654 100644 --- a/compiler/rustc_middle/src/mir/tcx.rs +++ b/compiler/rustc_middle/src/mir/tcx.rs @@ -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) } diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 3921176873c..bfb129495ce 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -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) ) } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 92c8d265c09..75166624f95 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -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 diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index f2ea32275f9..aca1390935e 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -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, }, diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs index f1988810437..e246ecebbec 100644 --- a/compiler/rustc_middle/src/thir/visit.rs +++ b/compiler/rustc_middle/src/thir/visit.rs @@ -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]) diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 56ddf146636..319fb7ef03b 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -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 diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index b9bf17cbb5c..045c8ad39be 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -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`, diff --git a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs index 56896d945e5..0b13ceb574d 100644 --- a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs +++ b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs @@ -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)?))) diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs index b80d9de70c8..07784982631 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs @@ -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 { .. } diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs index 379d2140c09..0c9571da3cf 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs @@ -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 { .. } diff --git a/compiler/rustc_mir_build/src/build/expr/category.rs b/compiler/rustc_mir_build/src/build/expr/category.rs index e07ba6b6e93..e0349e3e3f6 100644 --- a/compiler/rustc_mir_build/src/build/expr/category.rs +++ b/compiler/rustc_mir_build/src/build/expr/category.rs @@ -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)), diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index 01b32b8e05e..1c805ed20cc 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -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() } diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 9b85ad0ad08..e4e5844d2ef 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -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 diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index d4de5fac96e..2cbaed2cc62 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -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) }, diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs index 6120b1453cf..5b5f97cb514 100644 --- a/compiler/rustc_mir_build/src/thir/cx/mod.rs +++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs @@ -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) } diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 85b9dacb129..bc1acd51c69 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -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 { .. } diff --git a/compiler/rustc_mir_build/src/thir/print.rs b/compiler/rustc_mir_build/src/thir/print.rs index 2d4b39e7b08..ce7774f5948 100644 --- a/compiler/rustc_mir_build/src/thir/print.rs +++ b/compiler/rustc_mir_build/src/thir/print.rs @@ -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); diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs index 2ec3b53bc98..d7e738b8829 100644 --- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs +++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs @@ -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(), diff --git a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs index 885fdd0d58b..e8e78fb8a89 100644 --- a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs +++ b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs @@ -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); diff --git a/compiler/rustc_mir_dataflow/src/impls/initialized.rs b/compiler/rustc_mir_dataflow/src/impls/initialized.rs index 7822fb17f72..ddfd0739358 100644 --- a/compiler/rustc_mir_dataflow/src/impls/initialized.rs +++ b/compiler/rustc_mir_dataflow/src/impls/initialized.rs @@ -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| { diff --git a/compiler/rustc_mir_dataflow/src/impls/liveness.rs b/compiler/rustc_mir_dataflow/src/impls/liveness.rs index 48bdb131601..24a4b32ceb7 100644 --- a/compiler/rustc_mir_dataflow/src/impls/liveness.rs +++ b/compiler/rustc_mir_dataflow/src/impls/liveness.rs @@ -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 diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs index 86091379f5a..14390723ba4 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs @@ -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( diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index 139fd592f69..2b20a35b61e 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -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 } diff --git a/compiler/rustc_mir_transform/src/add_retag.rs b/compiler/rustc_mir_transform/src/add_retag.rs index 16977a63c59..12a68790374 100644 --- a/compiler/rustc_mir_transform/src/add_retag.rs +++ b/compiler/rustc_mir_transform/src/add_retag.rs @@ -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. diff --git a/compiler/rustc_mir_transform/src/check_alignment.rs b/compiler/rustc_mir_transform/src/check_alignment.rs index a1dbd7dc50e..5dfdcfc8b94 100644 --- a/compiler/rustc_mir_transform/src/check_alignment.rs +++ b/compiler/rustc_mir_transform/src/check_alignment.rs @@ -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 diff --git a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs index 370e930b740..71af099199e 100644 --- a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs +++ b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs @@ -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. diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs index 054cdbc6bad..ed924761892 100644 --- a/compiler/rustc_mir_transform/src/dest_prop.rs +++ b/compiler/rustc_mir_transform/src/dest_prop.rs @@ -576,7 +576,7 @@ impl WriteInfo { Rvalue::ThreadLocalRef(_) | Rvalue::NullaryOp(_, _) | Rvalue::Ref(_, _, _) - | Rvalue::AddressOf(_, _) + | Rvalue::RawPtr(_, _) | Rvalue::Len(_) | Rvalue::Discriminant(_) | Rvalue::CopyForDeref(_) => (), diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index e16911d79c3..90e3ba26a43 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -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)); } diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs index 1589653968c..3ec553d0ba0 100644 --- a/compiler/rustc_mir_transform/src/instsimplify.rs +++ b/compiler/rustc_mir_transform/src/instsimplify.rs @@ -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; diff --git a/compiler/rustc_mir_transform/src/known_panics_lint.rs b/compiler/rustc_mir_transform/src/known_panics_lint.rs index 7202cc2d042..7eed47cf239 100644 --- a/compiler/rustc_mir_transform/src/known_panics_lint.rs +++ b/compiler/rustc_mir_transform/src/known_panics_lint.rs @@ -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; } diff --git a/compiler/rustc_mir_transform/src/large_enums.rs b/compiler/rustc_mir_transform/src/large_enums.rs index e407929c9a7..cbc3169f2f1 100644 --- a/compiler/rustc_mir_transform/src/large_enums.rs +++ b/compiler/rustc_mir_transform/src/large_enums.rs @@ -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), ))), }; diff --git a/compiler/rustc_mir_transform/src/promote_consts.rs b/compiler/rustc_mir_transform/src/promote_consts.rs index 48a3266ae6f..6e84914ef97 100644 --- a/compiler/rustc_mir_transform/src/promote_consts.rs +++ b/compiler/rustc_mir_transform/src/promote_consts.rs @@ -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() diff --git a/compiler/rustc_mir_transform/src/ref_prop.rs b/compiler/rustc_mir_transform/src/ref_prop.rs index 76e65099e90..973a191d786 100644 --- a/compiler/rustc_mir_transform/src/ref_prop.rs +++ b/compiler/rustc_mir_transform/src/ref_prop.rs @@ -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) diff --git a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs index ea4f5fca59e..9c3f903e0ea 100644 --- a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs +++ b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs @@ -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 diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs index 5bbe3bb747f..4fe8cf6213f 100644 --- a/compiler/rustc_mir_transform/src/simplify.rs +++ b/compiler/rustc_mir_transform/src/simplify.rs @@ -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()]; diff --git a/compiler/rustc_mir_transform/src/ssa.rs b/compiler/rustc_mir_transform/src/ssa.rs index fb870425f6e..76591f52625 100644 --- a/compiler/rustc_mir_transform/src/ssa.rs +++ b/compiler/rustc_mir_transform/src/ssa.rs @@ -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; } diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index 491ae1c0d08..36908036796 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -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(_) => {} } diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index 3d06017fcf3..6391ff901cb 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs @@ -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) diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index e0917ba43e4..422206ebbce 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -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?` diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs index a64c00f3b6c..fce41bd90be 100644 --- a/compiler/rustc_parse/src/validate_attr.rs +++ b/compiler/rustc_parse/src/validate_attr.rs @@ -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); } } diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 0318d34fb73..dfc726efeb9 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -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 diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index bd157d1d619..e3c2999142f 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -189,6 +189,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { [sym::collapse_debuginfo, ..] => self.check_collapse_debuginfo(attr, span, target), [sym::must_not_suspend, ..] => self.check_must_not_suspend(attr, span, target), [sym::must_use, ..] => self.check_must_use(hir_id, attr, target), + [sym::may_dangle, ..] => self.check_may_dangle(hir_id, attr), [sym::rustc_pass_by_value, ..] => self.check_pass_by_value(attr, span, target), [sym::rustc_allow_incoherent_impl, ..] => { self.check_allow_incoherent_impl(attr, span, target) @@ -243,6 +244,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { [sym::coroutine, ..] => { self.check_coroutine(attr, target); } + [sym::linkage, ..] => self.check_linkage(attr, span, target), [ // ok sym::allow @@ -254,9 +256,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | sym::cfg_attr // need to be fixed | sym::cfi_encoding // FIXME(cfi_encoding) - | sym::may_dangle // FIXME(dropck_eyepatch) | sym::pointee // FIXME(derive_smart_pointer) - | sym::linkage // FIXME(linkage) | sym::omit_gdb_pretty_printer_section // FIXME(omit_gdb_pretty_printer_section) | sym::used // handled elsewhere to restrict to static items | sym::repr // handled elsewhere to restrict to type decls items @@ -1363,7 +1363,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - /// Checks if `#[must_not_suspend]` is applied to a function. + /// Checks if `#[must_not_suspend]` is applied to a struct, enum, union, or trait. fn check_must_not_suspend(&self, attr: &Attribute, span: Span, target: Target) { match target { Target::Struct | Target::Enum | Target::Union | Target::Trait => {} @@ -1373,6 +1373,27 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } + /// Checks if `#[may_dangle]` is applied to a lifetime or type generic parameter in `Drop` impl. + fn check_may_dangle(&self, hir_id: HirId, attr: &Attribute) { + if let hir::Node::GenericParam(param) = self.tcx.hir_node(hir_id) + && matches!( + param.kind, + hir::GenericParamKind::Lifetime { .. } | hir::GenericParamKind::Type { .. } + ) + && matches!(param.source, hir::GenericParamSource::Generics) + && let parent_hir_id = self.tcx.parent_hir_id(hir_id) + && let hir::Node::Item(item) = self.tcx.hir_node(parent_hir_id) + && let hir::ItemKind::Impl(impl_) = item.kind + && let Some(trait_) = impl_.of_trait + && let Some(def_id) = trait_.trait_def_id() + && self.tcx.is_lang_item(def_id, hir::LangItem::Drop) + { + return; + } + + self.dcx().emit_err(errors::InvalidMayDangle { attr_span: attr.span }); + } + /// Checks if `#[cold]` is applied to a non-function. fn check_cold(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) { match target { @@ -2347,6 +2368,19 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } } + + fn check_linkage(&self, attr: &Attribute, span: Span, target: Target) { + match target { + Target::Fn + | Target::Method(..) + | Target::Static + | Target::ForeignStatic + | Target::ForeignFn => {} + _ => { + self.dcx().emit_err(errors::Linkage { attr_span: attr.span, span }); + } + } + } } impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> { diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 36dfc40e762..ee7d097e5d3 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -644,6 +644,15 @@ pub struct CoroutineOnNonClosure { } #[derive(Diagnostic)] +#[diag(passes_linkage)] +pub struct Linkage { + #[primary_span] + pub attr_span: Span, + #[label] + pub span: Span, +} + +#[derive(Diagnostic)] #[diag(passes_empty_confusables)] pub(crate) struct EmptyConfusables { #[primary_span] @@ -728,6 +737,13 @@ pub struct NonExportedMacroInvalidAttrs { pub attr_span: Span, } +#[derive(Diagnostic)] +#[diag(passes_may_dangle)] +pub struct InvalidMayDangle { + #[primary_span] + pub attr_span: Span, +} + #[derive(LintDiagnostic)] #[diag(passes_unused_duplicate)] pub struct UnusedDuplicate { diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs index 3f1be87a73f..71b0ebb0e21 100644 --- a/compiler/rustc_passes/src/lang_items.rs +++ b/compiler/rustc_passes/src/lang_items.rs @@ -130,7 +130,7 @@ impl<'ast, 'tcx> LanguageItemCollector<'ast, 'tcx> { if first_defined_span.is_none() { orig_crate_name = self.tcx.crate_name(original_def_id.krate); if let Some(ExternCrate { dependency_of: inner_dependency_of, .. }) = - self.tcx.extern_crate(original_def_id) + self.tcx.extern_crate(original_def_id.krate) { orig_dependency_of = self.tcx.crate_name(*inner_dependency_of); } @@ -139,7 +139,7 @@ impl<'ast, 'tcx> LanguageItemCollector<'ast, 'tcx> { let duplicate = if item_span.is_some() { Duplicate::Plain } else { - match self.tcx.extern_crate(item_def_id) { + match self.tcx.extern_crate(item_def_id.krate) { Some(ExternCrate { dependency_of: inner_dependency_of, .. }) => { dependency_of = self.tcx.crate_name(*inner_dependency_of); Duplicate::CrateDepends diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index b9e700c1938..c064b2bd6c1 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -702,11 +702,17 @@ macro_rules! define_queries { let name = stringify!($name); $crate::plumbing::create_query_frame(tcx, rustc_middle::query::descs::$name, key, kind, name) }; - tcx.query_system.states.$name.try_collect_active_jobs( + let res = tcx.query_system.states.$name.try_collect_active_jobs( tcx, make_query, qmap, - ).unwrap(); + ); + // this can be called during unwinding, and the function has a `try_`-prefix, so + // don't `unwrap()` here, just manually check for `None` and do best-effort error + // reporting. + if res.is_none() { + tracing::warn!("Failed to collect active jobs for query with name `{}`!", stringify!($name)); + } } pub fn alloc_self_profile_query_strings<'tcx>(tcx: TyCtxt<'tcx>, string_cache: &mut QueryKeyStringCache) { diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index 8ef680cdb6c..6dbd6e89fe9 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -181,8 +181,15 @@ where cache.complete(key, result, dep_node_index); let job = { - let mut lock = state.active.lock_shard_by_value(&key); - lock.remove(&key).unwrap().expect_job() + let val = { + // don't keep the lock during the `unwrap()` of the retrieved value, or we taint the + // underlying shard. + // since unwinding also wants to look at this map, this can also prevent a double + // panic. + let mut lock = state.active.lock_shard_by_value(&key); + lock.remove(&key) + }; + val.unwrap().expect_job() }; job.signal_complete(); diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs index da705e6f959..c442ca861d3 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs @@ -174,7 +174,7 @@ impl<'tcx> Stable<'tcx> for mir::Rvalue<'tcx> { ThreadLocalRef(def_id) => { stable_mir::mir::Rvalue::ThreadLocalRef(tables.crate_item(*def_id)) } - AddressOf(mutability, place) => { + RawPtr(mutability, place) => { stable_mir::mir::Rvalue::AddressOf(mutability.stable(tables), place.stable(tables)) } Len(place) => stable_mir::mir::Rvalue::Len(place.stable(tables)), diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs index 5bfc528dffc..25e4d70945b 100644 --- a/compiler/rustc_target/src/abi/call/mod.rs +++ b/compiler/rustc_target/src/abi/call/mod.rs @@ -642,7 +642,7 @@ impl<'a, Ty> ArgAbi<'a, Ty> { pub fn make_indirect(&mut self) { match self.mode { PassMode::Direct(_) | PassMode::Pair(_, _) => { - self.mode = Self::indirect_pass_mode(&self.layout); + self.make_indirect_force(); } PassMode::Indirect { attrs: _, meta_attrs: _, on_stack: false } => { // already indirect @@ -652,6 +652,11 @@ impl<'a, Ty> ArgAbi<'a, Ty> { } } + /// Same as make_indirect, but doesn't check the current `PassMode`. + pub fn make_indirect_force(&mut self) { + self.mode = Self::indirect_pass_mode(&self.layout); + } + /// Pass this argument indirectly, by placing it at a fixed stack offset. /// This corresponds to the `byval` LLVM argument attribute. /// This is only valid for sized arguments. @@ -871,10 +876,10 @@ impl<'a, Ty> FnAbi<'a, Ty> { } "x86_64" => match abi { spec::abi::Abi::SysV64 { .. } => x86_64::compute_abi_info(cx, self), - spec::abi::Abi::Win64 { .. } => x86_win64::compute_abi_info(self), + spec::abi::Abi::Win64 { .. } => x86_win64::compute_abi_info(cx, self), _ => { if cx.target_spec().is_like_windows { - x86_win64::compute_abi_info(self) + x86_win64::compute_abi_info(cx, self) } else { x86_64::compute_abi_info(cx, self) } @@ -898,7 +903,7 @@ impl<'a, Ty> FnAbi<'a, Ty> { "csky" => csky::compute_abi_info(self), "mips" | "mips32r6" => mips::compute_abi_info(cx, self), "mips64" | "mips64r6" => mips64::compute_abi_info(cx, self), - "powerpc" => powerpc::compute_abi_info(self), + "powerpc" => powerpc::compute_abi_info(cx, self), "powerpc64" => powerpc64::compute_abi_info(cx, self), "s390x" => s390x::compute_abi_info(cx, self), "msp430" => msp430::compute_abi_info(self), diff --git a/compiler/rustc_target/src/abi/call/powerpc.rs b/compiler/rustc_target/src/abi/call/powerpc.rs index 70c32db0a87..cb80d64c943 100644 --- a/compiler/rustc_target/src/abi/call/powerpc.rs +++ b/compiler/rustc_target/src/abi/call/powerpc.rs @@ -1,4 +1,5 @@ use crate::abi::call::{ArgAbi, FnAbi}; +use crate::spec::HasTargetSpec; fn classify_ret<Ty>(ret: &mut ArgAbi<'_, Ty>) { if ret.layout.is_aggregate() { @@ -8,7 +9,17 @@ fn classify_ret<Ty>(ret: &mut ArgAbi<'_, Ty>) { } } -fn classify_arg<Ty>(arg: &mut ArgAbi<'_, Ty>) { +fn classify_arg<Ty>(cx: &impl HasTargetSpec, arg: &mut ArgAbi<'_, Ty>) { + if arg.is_ignore() { + // powerpc-unknown-linux-{gnu,musl,uclibc} doesn't ignore ZSTs. + if cx.target_spec().os == "linux" + && matches!(&*cx.target_spec().env, "gnu" | "musl" | "uclibc") + && arg.layout.is_zst() + { + arg.make_indirect_force(); + } + return; + } if arg.layout.is_aggregate() { arg.make_indirect(); } else { @@ -16,15 +27,12 @@ fn classify_arg<Ty>(arg: &mut ArgAbi<'_, Ty>) { } } -pub fn compute_abi_info<Ty>(fn_abi: &mut FnAbi<'_, Ty>) { +pub fn compute_abi_info<Ty>(cx: &impl HasTargetSpec, fn_abi: &mut FnAbi<'_, Ty>) { if !fn_abi.ret.is_ignore() { classify_ret(&mut fn_abi.ret); } for arg in fn_abi.args.iter_mut() { - if arg.is_ignore() { - continue; - } - classify_arg(arg); + classify_arg(cx, arg); } } diff --git a/compiler/rustc_target/src/abi/call/s390x.rs b/compiler/rustc_target/src/abi/call/s390x.rs index 1a2191082d5..7dcbb3e4a9e 100644 --- a/compiler/rustc_target/src/abi/call/s390x.rs +++ b/compiler/rustc_target/src/abi/call/s390x.rs @@ -3,6 +3,7 @@ use crate::abi::call::{ArgAbi, FnAbi, Reg}; use crate::abi::{HasDataLayout, TyAbiInterface}; +use crate::spec::HasTargetSpec; fn classify_ret<Ty>(ret: &mut ArgAbi<'_, Ty>) { if !ret.layout.is_aggregate() && ret.layout.size.bits() <= 64 { @@ -15,12 +16,22 @@ fn classify_ret<Ty>(ret: &mut ArgAbi<'_, Ty>) { fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) where Ty: TyAbiInterface<'a, C> + Copy, - C: HasDataLayout, + C: HasDataLayout + HasTargetSpec, { if !arg.layout.is_sized() { // Not touching this... return; } + if arg.is_ignore() { + // s390x-unknown-linux-{gnu,musl,uclibc} doesn't ignore ZSTs. + if cx.target_spec().os == "linux" + && matches!(&*cx.target_spec().env, "gnu" | "musl" | "uclibc") + && arg.layout.is_zst() + { + arg.make_indirect_force(); + } + return; + } if !arg.layout.is_aggregate() && arg.layout.size.bits() <= 64 { arg.extend_integer_width_to(64); return; @@ -46,16 +57,13 @@ where pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) where Ty: TyAbiInterface<'a, C> + Copy, - C: HasDataLayout, + C: HasDataLayout + HasTargetSpec, { if !fn_abi.ret.is_ignore() { classify_ret(&mut fn_abi.ret); } for arg in fn_abi.args.iter_mut() { - if arg.is_ignore() { - continue; - } classify_arg(cx, arg); } } diff --git a/compiler/rustc_target/src/abi/call/sparc64.rs b/compiler/rustc_target/src/abi/call/sparc64.rs index c0952130e04..3b2bf9b3187 100644 --- a/compiler/rustc_target/src/abi/call/sparc64.rs +++ b/compiler/rustc_target/src/abi/call/sparc64.rs @@ -4,6 +4,7 @@ use crate::abi::call::{ ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, CastTarget, FnAbi, Reg, Uniform, }; use crate::abi::{self, HasDataLayout, Scalar, Size, TyAbiInterface, TyAndLayout}; +use crate::spec::HasTargetSpec; #[derive(Clone, Debug)] pub struct Sdata { @@ -211,7 +212,7 @@ where pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) where Ty: TyAbiInterface<'a, C> + Copy, - C: HasDataLayout, + C: HasDataLayout + HasTargetSpec, { if !fn_abi.ret.is_ignore() { classify_arg(cx, &mut fn_abi.ret, Size::from_bytes(32)); @@ -219,7 +220,14 @@ where for arg in fn_abi.args.iter_mut() { if arg.is_ignore() { - continue; + // sparc64-unknown-linux-{gnu,musl,uclibc} doesn't ignore ZSTs. + if cx.target_spec().os == "linux" + && matches!(&*cx.target_spec().env, "gnu" | "musl" | "uclibc") + && arg.layout.is_zst() + { + arg.make_indirect_force(); + } + return; } classify_arg(cx, arg, Size::from_bytes(16)); } diff --git a/compiler/rustc_target/src/abi/call/x86_win64.rs b/compiler/rustc_target/src/abi/call/x86_win64.rs index 4e19460bd28..6ca01cf84ea 100644 --- a/compiler/rustc_target/src/abi/call/x86_win64.rs +++ b/compiler/rustc_target/src/abi/call/x86_win64.rs @@ -1,9 +1,10 @@ use crate::abi::call::{ArgAbi, FnAbi, Reg}; use crate::abi::{Abi, Float, Primitive}; +use crate::spec::HasTargetSpec; // Win64 ABI: https://docs.microsoft.com/en-us/cpp/build/parameter-passing -pub fn compute_abi_info<Ty>(fn_abi: &mut FnAbi<'_, Ty>) { +pub fn compute_abi_info<Ty>(cx: &impl HasTargetSpec, fn_abi: &mut FnAbi<'_, Ty>) { let fixup = |a: &mut ArgAbi<'_, Ty>| { match a.layout.abi { Abi::Uninhabited | Abi::Aggregate { sized: false } => {} @@ -37,6 +38,13 @@ pub fn compute_abi_info<Ty>(fn_abi: &mut FnAbi<'_, Ty>) { } for arg in fn_abi.args.iter_mut() { if arg.is_ignore() { + // x86_64-pc-windows-gnu doesn't ignore ZSTs. + if cx.target_spec().os == "windows" + && cx.target_spec().env == "gnu" + && arg.layout.is_zst() + { + arg.make_indirect_force(); + } continue; } fixup(arg); diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs index 85c40ec60c4..32c2367d5bf 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs @@ -10,7 +10,7 @@ pub fn target() -> Target { llvm_target: mac_catalyst_llvm_target(arch).into(), metadata: crate::spec::TargetMetadata { description: Some("Apple Catalyst on ARM64".into()), - tier: Some(3), + tier: Some(2), host_tools: Some(false), std: Some(true), }, diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs index d3ba17cf027..c23a20ff084 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs @@ -10,7 +10,7 @@ pub fn target() -> Target { llvm_target: mac_catalyst_llvm_target(arch).into(), metadata: crate::spec::TargetMetadata { description: Some("Apple Catalyst on x86_64".into()), - tier: Some(3), + tier: Some(2), host_tools: Some(false), std: Some(true), }, diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 326a0e4e35c..d1cc630bc9a 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -1668,7 +1668,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let name = self.tcx.crate_name(trait_def_id.krate); let spans: Vec<_> = [trait_def_id, found_type] .into_iter() - .filter_map(|def_id| self.tcx.extern_crate(def_id)) + .filter_map(|def_id| self.tcx.extern_crate(def_id.krate)) .map(|data| { let dependency = if data.dependency_of == LOCAL_CRATE { "direct dependency of the current crate".to_string() @@ -1689,11 +1689,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { err.highlighted_span_help( span, vec![ - StringPart::normal("you have ".to_string()), + StringPart::normal("there are ".to_string()), StringPart::highlighted("multiple different versions".to_string()), StringPart::normal(" of crate `".to_string()), StringPart::highlighted(format!("{name}")), - StringPart::normal("` in your dependency graph".to_string()), + StringPart::normal("` the your dependency graph".to_string()), ], ); let candidates = if impl_candidates.is_empty() { @@ -2729,6 +2729,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(ref sig, _), .. }) | Node::TraitItem(&hir::TraitItem { kind: hir::TraitItemKind::Fn(ref sig, _), .. + }) + | Node::ForeignItem(&hir::ForeignItem { + kind: hir::ForeignItemKind::Fn(ref sig, _, _), + .. }) => ( sig.span, None, diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index d0f76f0d50e..a962be54c3d 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -4610,6 +4610,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { }) } + // For E0277 when use `?` operator, suggest adding + // a suitable return type in `FnSig`, and a default + // return value at the end of the function's body. pub(super) fn suggest_add_result_as_return_type( &self, obligation: &PredicateObligation<'tcx>, @@ -4620,19 +4623,47 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { return; } + // Only suggest for local function and associated method, + // because this suggest adding both return type in + // the `FnSig` and a default return value in the body, so it + // is not suitable for foreign function without a local body, + // and neighter for trait method which may be also implemented + // in other place, so shouldn't change it's FnSig. + fn choose_suggest_items<'tcx, 'hir>( + tcx: TyCtxt<'tcx>, + node: hir::Node<'hir>, + ) -> Option<(&'hir hir::FnDecl<'hir>, hir::BodyId)> { + match node { + hir::Node::Item(item) if let hir::ItemKind::Fn(sig, _, body_id) = item.kind => { + Some((sig.decl, body_id)) + } + hir::Node::ImplItem(item) + if let hir::ImplItemKind::Fn(sig, body_id) = item.kind => + { + let parent = tcx.parent_hir_node(item.hir_id()); + if let hir::Node::Item(item) = parent + && let hir::ItemKind::Impl(imp) = item.kind + && imp.of_trait.is_none() + { + return Some((sig.decl, body_id)); + } + None + } + _ => None, + } + } + let node = self.tcx.hir_node_by_def_id(obligation.cause.body_id); - if let hir::Node::Item(item) = node - && let hir::ItemKind::Fn(sig, _, body_id) = item.kind - && let hir::FnRetTy::DefaultReturn(ret_span) = sig.decl.output + if let Some((fn_decl, body_id)) = choose_suggest_items(self.tcx, node) + && let hir::FnRetTy::DefaultReturn(ret_span) = fn_decl.output && self.tcx.is_diagnostic_item(sym::FromResidual, trait_pred.def_id()) && trait_pred.skip_binder().trait_ref.args.type_at(0).is_unit() && let ty::Adt(def, _) = trait_pred.skip_binder().trait_ref.args.type_at(1).kind() && self.tcx.is_diagnostic_item(sym::Result, def.did()) { - let body = self.tcx.hir().body(body_id); let mut sugg_spans = vec![(ret_span, " -> Result<(), Box<dyn std::error::Error>>".to_string())]; - + let body = self.tcx.hir().body(body_id); if let hir::ExprKind::Block(b, _) = body.value.kind && b.expr.is_none() { diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index 247b6e4823c..cb96db5f7a2 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -333,14 +333,14 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx> return Ok(constant); } - let constant = constant.try_super_fold_with(self)?; - debug!(?constant, ?self.param_env); - Ok(crate::traits::with_replaced_escaping_bound_vars( + let constant = crate::traits::with_replaced_escaping_bound_vars( self.infcx, &mut self.universes, constant, |constant| constant.normalize(self.infcx.tcx, self.param_env), - )) + ); + debug!(?constant, ?self.param_env); + constant.try_super_fold_with(self) } #[inline] diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 0d7ceca4301..f19cd19c99a 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -17,8 +17,7 @@ use rustc_infer::infer::{DefineOpaqueTypes, HigherRankedType, InferOk}; use rustc_infer::traits::ObligationCauseCode; use rustc_middle::traits::{BuiltinImplSource, SignatureMismatchData}; use rustc_middle::ty::{ - self, GenericArgs, GenericArgsRef, GenericParamDefKind, ToPolyTraitRef, TraitPredicate, Ty, - TyCtxt, Upcast, + self, GenericArgs, GenericArgsRef, GenericParamDefKind, ToPolyTraitRef, Ty, TyCtxt, Upcast, }; use rustc_middle::{bug, span_bug}; use rustc_span::def_id::DefId; @@ -292,90 +291,120 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, obligation: &PolyTraitObligation<'tcx>, ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> { - use rustc_transmute::{Answer, Condition}; - #[instrument(level = "debug", skip(tcx, obligation, predicate))] + use rustc_transmute::{Answer, Assume, Condition}; + + /// Generate sub-obligations for reference-to-reference transmutations. + fn reference_obligations<'tcx>( + tcx: TyCtxt<'tcx>, + obligation: &PolyTraitObligation<'tcx>, + (src_lifetime, src_ty, src_mut): (ty::Region<'tcx>, Ty<'tcx>, Mutability), + (dst_lifetime, dst_ty, dst_mut): (ty::Region<'tcx>, Ty<'tcx>, Mutability), + assume: Assume, + ) -> Vec<PredicateObligation<'tcx>> { + let make_transmute_obl = |src, dst| { + let transmute_trait = obligation.predicate.def_id(); + let assume = obligation.predicate.skip_binder().trait_ref.args.const_at(2); + let trait_ref = ty::TraitRef::new( + tcx, + transmute_trait, + [ + ty::GenericArg::from(dst), + ty::GenericArg::from(src), + ty::GenericArg::from(assume), + ], + ); + Obligation::with_depth( + tcx, + obligation.cause.clone(), + obligation.recursion_depth + 1, + obligation.param_env, + obligation.predicate.rebind(trait_ref), + ) + }; + + let make_freeze_obl = |ty| { + let trait_ref = ty::TraitRef::new( + tcx, + tcx.require_lang_item(LangItem::Freeze, None), + [ty::GenericArg::from(ty)], + ); + Obligation::with_depth( + tcx, + obligation.cause.clone(), + obligation.recursion_depth + 1, + obligation.param_env, + trait_ref, + ) + }; + + let make_outlives_obl = |target, region| { + let outlives = ty::OutlivesPredicate(target, region); + Obligation::with_depth( + tcx, + obligation.cause.clone(), + obligation.recursion_depth + 1, + obligation.param_env, + obligation.predicate.rebind(outlives), + ) + }; + + // Given a transmutation from `&'a (mut) Src` and `&'dst (mut) Dst`, + // it is always the case that `Src` must be transmutable into `Dst`, + // and that that `'src` must outlive `'dst`. + let mut obls = vec![make_transmute_obl(src_ty, dst_ty)]; + if !assume.lifetimes { + obls.push(make_outlives_obl(src_lifetime, dst_lifetime)); + } + + // Given a transmutation from `&Src`, both `Src` and `Dst` must be + // `Freeze`, otherwise, using the transmuted value could lead to + // data races. + if src_mut == Mutability::Not { + obls.extend([make_freeze_obl(src_ty), make_freeze_obl(dst_ty)]) + } + + // Given a transmutation into `&'dst mut Dst`, it also must be the + // case that `Dst` is transmutable into `Src`. For example, + // transmuting bool -> u8 is OK as long as you can't update that u8 + // to be > 1, because you could later transmute the u8 back to a + // bool and get undefined behavior. It also must be the case that + // `'dst` lives exactly as long as `'src`. + if dst_mut == Mutability::Mut { + obls.push(make_transmute_obl(dst_ty, src_ty)); + if !assume.lifetimes { + obls.push(make_outlives_obl(dst_lifetime, src_lifetime)); + } + } + + obls + } + + /// Flatten the `Condition` tree into a conjunction of obligations. + #[instrument(level = "debug", skip(tcx, obligation))] fn flatten_answer_tree<'tcx>( tcx: TyCtxt<'tcx>, obligation: &PolyTraitObligation<'tcx>, - predicate: TraitPredicate<'tcx>, cond: Condition<rustc_transmute::layout::rustc::Ref<'tcx>>, + assume: Assume, ) -> Vec<PredicateObligation<'tcx>> { match cond { // FIXME(bryangarza): Add separate `IfAny` case, instead of treating as `IfAll` // Not possible until the trait solver supports disjunctions of obligations Condition::IfAll(conds) | Condition::IfAny(conds) => conds .into_iter() - .flat_map(|cond| flatten_answer_tree(tcx, obligation, predicate, cond)) + .flat_map(|cond| flatten_answer_tree(tcx, obligation, cond, assume)) .collect(), - Condition::IfTransmutable { src, dst } => { - let transmute_trait = obligation.predicate.def_id(); - let assume_const = predicate.trait_ref.args.const_at(2); - let make_transmute_obl = |from_ty, to_ty| { - let trait_ref = ty::TraitRef::new( - tcx, - transmute_trait, - [ - ty::GenericArg::from(to_ty), - ty::GenericArg::from(from_ty), - ty::GenericArg::from(assume_const), - ], - ); - Obligation::with_depth( - tcx, - obligation.cause.clone(), - obligation.recursion_depth + 1, - obligation.param_env, - trait_ref, - ) - }; - - let make_freeze_obl = |ty| { - let trait_ref = ty::TraitRef::new( - tcx, - tcx.require_lang_item(LangItem::Freeze, None), - [ty::GenericArg::from(ty)], - ); - Obligation::with_depth( - tcx, - obligation.cause.clone(), - obligation.recursion_depth + 1, - obligation.param_env, - trait_ref, - ) - }; - - let mut obls = vec![]; - - // If the source is a shared reference, it must be `Freeze`; - // otherwise, transmuting could lead to data races. - if src.mutability == Mutability::Not { - obls.extend([make_freeze_obl(src.ty), make_freeze_obl(dst.ty)]) - } - - // If Dst is mutable, check bidirectionally. - // For example, transmuting bool -> u8 is OK as long as you can't update that u8 - // to be > 1, because you could later transmute the u8 back to a bool and get UB. - match dst.mutability { - Mutability::Not => obls.push(make_transmute_obl(src.ty, dst.ty)), - Mutability::Mut => obls.extend([ - make_transmute_obl(src.ty, dst.ty), - make_transmute_obl(dst.ty, src.ty), - ]), - } - - obls - } + Condition::IfTransmutable { src, dst } => reference_obligations( + tcx, + obligation, + (src.lifetime, src.ty, src.mutability), + (dst.lifetime, dst.ty, dst.mutability), + assume, + ), } } - // We erase regions here because transmutability calls layout queries, - // which does not handle inference regions and doesn't particularly - // care about other regions. Erasing late-bound regions is equivalent - // to instantiating the binder with placeholders then erasing those - // placeholder regions. - let predicate = self - .tcx() - .erase_regions(self.tcx().instantiate_bound_regions_with_erased(obligation.predicate)); + let predicate = obligation.predicate.skip_binder(); let Some(assume) = rustc_transmute::Assume::from_const( self.infcx.tcx, @@ -387,6 +416,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let dst = predicate.trait_ref.args.type_at(0); let src = predicate.trait_ref.args.type_at(1); + debug!(?src, ?dst); let mut transmute_env = rustc_transmute::TransmuteTypeEnv::new(self.infcx); let maybe_transmutable = transmute_env.is_transmutable( @@ -397,7 +427,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let fully_flattened = match maybe_transmutable { Answer::No(_) => Err(Unimplemented)?, - Answer::If(cond) => flatten_answer_tree(self.tcx(), obligation, predicate, cond), + Answer::If(cond) => flatten_answer_tree(self.tcx(), obligation, cond, assume), Answer::Yes => vec![], }; diff --git a/compiler/rustc_transmute/src/layout/mod.rs b/compiler/rustc_transmute/src/layout/mod.rs index bbf155581f9..1cf9e0b9b70 100644 --- a/compiler/rustc_transmute/src/layout/mod.rs +++ b/compiler/rustc_transmute/src/layout/mod.rs @@ -63,7 +63,9 @@ pub mod rustc { use std::fmt::{self, Write}; use rustc_middle::mir::Mutability; - use rustc_middle::ty::{self, Ty}; + use rustc_middle::ty::layout::{LayoutCx, LayoutError}; + use rustc_middle::ty::{self, Ty, TyCtxt}; + use rustc_target::abi::Layout; /// A reference in the layout. #[derive(Debug, Hash, Eq, PartialEq, Clone, Copy)] @@ -120,4 +122,13 @@ pub mod rustc { self != &Self::Primitive } } + + pub(crate) fn layout_of<'tcx>( + cx: LayoutCx<'tcx, TyCtxt<'tcx>>, + ty: Ty<'tcx>, + ) -> Result<Layout<'tcx>, &'tcx LayoutError<'tcx>> { + use rustc_middle::ty::layout::LayoutOf; + let ty = cx.tcx.erase_regions(ty); + cx.layout_of(ty).map(|tl| tl.layout) + } } diff --git a/compiler/rustc_transmute/src/layout/tree.rs b/compiler/rustc_transmute/src/layout/tree.rs index 5c25f913ffe..7c73f74e629 100644 --- a/compiler/rustc_transmute/src/layout/tree.rs +++ b/compiler/rustc_transmute/src/layout/tree.rs @@ -171,10 +171,12 @@ where #[cfg(feature = "rustc")] pub(crate) mod rustc { - use rustc_middle::ty::layout::{HasTyCtxt, LayoutCx, LayoutError, LayoutOf}; + use rustc_middle::ty::layout::{HasTyCtxt, LayoutCx, LayoutError}; use rustc_middle::ty::{self, AdtDef, AdtKind, List, ScalarInt, Ty, TyCtxt, TypeVisitableExt}; use rustc_span::ErrorGuaranteed; - use rustc_target::abi::{FieldsShape, Size, TyAndLayout, Variants}; + use rustc_target::abi::{ + FieldIdx, FieldsShape, Layout, Size, TyAndLayout, VariantIdx, Variants, + }; use super::Tree; use crate::layout::rustc::{Def, Ref}; @@ -202,20 +204,18 @@ pub(crate) mod rustc { } impl<'tcx> Tree<Def<'tcx>, Ref<'tcx>> { - pub fn from_ty( - ty_and_layout: TyAndLayout<'tcx, Ty<'tcx>>, - cx: LayoutCx<'tcx, TyCtxt<'tcx>>, - ) -> Result<Self, Err> { + pub fn from_ty(ty: Ty<'tcx>, cx: LayoutCx<'tcx, TyCtxt<'tcx>>) -> Result<Self, Err> { use rustc_target::abi::HasDataLayout; + let layout = ty_layout(cx, ty); - if let Err(e) = ty_and_layout.ty.error_reported() { + if let Err(e) = ty.error_reported() { return Err(Err::TypeError(e)); } let target = cx.tcx.data_layout(); let pointer_size = target.pointer_size; - match ty_and_layout.ty.kind() { + match ty.kind() { ty::Bool => Ok(Self::bool()), ty::Float(nty) => { @@ -233,32 +233,30 @@ pub(crate) mod rustc { Ok(Self::number(width as _)) } - ty::Tuple(members) => Self::from_tuple(ty_and_layout, members, cx), + ty::Tuple(members) => Self::from_tuple((ty, layout), members, cx), ty::Array(inner_ty, len) => { - let FieldsShape::Array { stride, count } = &ty_and_layout.fields else { + let FieldsShape::Array { stride, count } = &layout.fields else { return Err(Err::NotYetSupported); }; - let inner_ty_and_layout = cx.layout_of(*inner_ty)?; - assert_eq!(*stride, inner_ty_and_layout.size); - let elt = Tree::from_ty(inner_ty_and_layout, cx)?; + let inner_layout = ty_layout(cx, *inner_ty); + assert_eq!(*stride, inner_layout.size); + let elt = Tree::from_ty(*inner_ty, cx)?; Ok(std::iter::repeat(elt) .take(*count as usize) .fold(Tree::unit(), |tree, elt| tree.then(elt))) } - ty::Adt(adt_def, _args_ref) if !ty_and_layout.ty.is_box() => { - match adt_def.adt_kind() { - AdtKind::Struct => Self::from_struct(ty_and_layout, *adt_def, cx), - AdtKind::Enum => Self::from_enum(ty_and_layout, *adt_def, cx), - AdtKind::Union => Self::from_union(ty_and_layout, *adt_def, cx), - } - } + ty::Adt(adt_def, _args_ref) if !ty.is_box() => match adt_def.adt_kind() { + AdtKind::Struct => Self::from_struct((ty, layout), *adt_def, cx), + AdtKind::Enum => Self::from_enum((ty, layout), *adt_def, cx), + AdtKind::Union => Self::from_union((ty, layout), *adt_def, cx), + }, ty::Ref(lifetime, ty, mutability) => { - let ty_and_layout = cx.layout_of(*ty)?; - let align = ty_and_layout.align.abi.bytes_usize(); - let size = ty_and_layout.size.bytes_usize(); + let layout = ty_layout(cx, *ty); + let align = layout.align.abi.bytes_usize(); + let size = layout.size.bytes_usize(); Ok(Tree::Ref(Ref { lifetime: *lifetime, ty: *ty, @@ -274,21 +272,20 @@ pub(crate) mod rustc { /// Constructs a `Tree` from a tuple. fn from_tuple( - ty_and_layout: TyAndLayout<'tcx, Ty<'tcx>>, + (ty, layout): (Ty<'tcx>, Layout<'tcx>), members: &'tcx List<Ty<'tcx>>, cx: LayoutCx<'tcx, TyCtxt<'tcx>>, ) -> Result<Self, Err> { - match &ty_and_layout.fields { + match &layout.fields { FieldsShape::Primitive => { assert_eq!(members.len(), 1); let inner_ty = members[0]; - let inner_ty_and_layout = cx.layout_of(inner_ty)?; - assert_eq!(ty_and_layout.layout, inner_ty_and_layout.layout); - Self::from_ty(inner_ty_and_layout, cx) + let inner_layout = ty_layout(cx, inner_ty); + Self::from_ty(inner_ty, cx) } FieldsShape::Arbitrary { offsets, .. } => { assert_eq!(offsets.len(), members.len()); - Self::from_variant(Def::Primitive, None, ty_and_layout, ty_and_layout.size, cx) + Self::from_variant(Def::Primitive, None, (ty, layout), layout.size, cx) } FieldsShape::Array { .. } | FieldsShape::Union(_) => Err(Err::NotYetSupported), } @@ -300,13 +297,13 @@ pub(crate) mod rustc { /// /// Panics if `def` is not a struct definition. fn from_struct( - ty_and_layout: TyAndLayout<'tcx, Ty<'tcx>>, + (ty, layout): (Ty<'tcx>, Layout<'tcx>), def: AdtDef<'tcx>, cx: LayoutCx<'tcx, TyCtxt<'tcx>>, ) -> Result<Self, Err> { assert!(def.is_struct()); let def = Def::Adt(def); - Self::from_variant(def, None, ty_and_layout, ty_and_layout.size, cx) + Self::from_variant(def, None, (ty, layout), layout.size, cx) } /// Constructs a `Tree` from an enum. @@ -315,19 +312,18 @@ pub(crate) mod rustc { /// /// Panics if `def` is not an enum definition. fn from_enum( - ty_and_layout: TyAndLayout<'tcx, Ty<'tcx>>, + (ty, layout): (Ty<'tcx>, Layout<'tcx>), def: AdtDef<'tcx>, cx: LayoutCx<'tcx, TyCtxt<'tcx>>, ) -> Result<Self, Err> { assert!(def.is_enum()); - let layout = ty_and_layout.layout; // Computes the variant of a given index. let layout_of_variant = |index| { - let tag = cx.tcx.tag_for_variant((ty_and_layout.ty, index)); + let tag = cx.tcx.tag_for_variant((cx.tcx.erase_regions(ty), index)); let variant_def = Def::Variant(def.variant(index)); - let variant_ty_and_layout = ty_and_layout.for_variant(&cx, index); - Self::from_variant(variant_def, tag, variant_ty_and_layout, layout.size, cx) + let variant_layout = ty_variant(cx, (ty, layout), index); + Self::from_variant(variant_def, tag, (ty, variant_layout), layout.size, cx) }; // We consider three kinds of enums, each demanding a different @@ -385,21 +381,20 @@ pub(crate) mod rustc { fn from_variant( def: Def<'tcx>, tag: Option<ScalarInt>, - ty_and_layout: TyAndLayout<'tcx, Ty<'tcx>>, + (ty, layout): (Ty<'tcx>, Layout<'tcx>), total_size: Size, cx: LayoutCx<'tcx, TyCtxt<'tcx>>, ) -> Result<Self, Err> { // This constructor does not support non-`FieldsShape::Arbitrary` // layouts. - let FieldsShape::Arbitrary { offsets, memory_index } = ty_and_layout.layout.fields() - else { + let FieldsShape::Arbitrary { offsets, memory_index } = layout.fields() else { return Err(Err::NotYetSupported); }; // When this function is invoked with enum variants, // `ty_and_layout.size` does not encompass the entire size of the // enum. We rely on `total_size` for this. - assert!(ty_and_layout.size <= total_size); + assert!(layout.size <= total_size); let mut size = Size::ZERO; let mut struct_tree = Self::def(def); @@ -412,17 +407,18 @@ pub(crate) mod rustc { // Append the fields, in memory order, to the layout. let inverse_memory_index = memory_index.invert_bijective_mapping(); - for (memory_idx, field_idx) in inverse_memory_index.iter_enumerated() { + for (memory_idx, &field_idx) in inverse_memory_index.iter_enumerated() { // Add interfield padding. - let padding_needed = offsets[*field_idx] - size; + let padding_needed = offsets[field_idx] - size; let padding = Self::padding(padding_needed.bytes_usize()); - let field_ty_and_layout = ty_and_layout.field(&cx, field_idx.as_usize()); - let field_tree = Self::from_ty(field_ty_and_layout, cx)?; + let field_ty = ty_field(cx, (ty, layout), field_idx); + let field_layout = ty_layout(cx, field_ty); + let field_tree = Self::from_ty(field_ty, cx)?; struct_tree = struct_tree.then(padding).then(field_tree); - size += padding_needed + field_ty_and_layout.size; + size += padding_needed + field_layout.size; } // Add trailing padding. @@ -457,28 +453,27 @@ pub(crate) mod rustc { /// /// Panics if `def` is not a union definition. fn from_union( - ty_and_layout: TyAndLayout<'tcx, Ty<'tcx>>, + (ty, layout): (Ty<'tcx>, Layout<'tcx>), def: AdtDef<'tcx>, cx: LayoutCx<'tcx, TyCtxt<'tcx>>, ) -> Result<Self, Err> { assert!(def.is_union()); - let union_layout = ty_and_layout.layout; - // This constructor does not support non-`FieldsShape::Union` // layouts. Fields of this shape are all placed at offset 0. - let FieldsShape::Union(fields) = union_layout.fields() else { + let FieldsShape::Union(fields) = layout.fields() else { return Err(Err::NotYetSupported); }; let fields = &def.non_enum_variant().fields; let fields = fields.iter_enumerated().try_fold( Self::uninhabited(), - |fields, (idx, ref field_def)| { + |fields, (idx, field_def)| { let field_def = Def::Field(field_def); - let field_ty_and_layout = ty_and_layout.field(&cx, idx.as_usize()); - let field = Self::from_ty(field_ty_and_layout, cx)?; - let trailing_padding_needed = union_layout.size - field_ty_and_layout.size; + let field_ty = ty_field(cx, (ty, layout), idx); + let field_layout = ty_layout(cx, field_ty); + let field = Self::from_ty(field_ty, cx)?; + let trailing_padding_needed = layout.size - field_layout.size; let trailing_padding = Self::padding(trailing_padding_needed.bytes_usize()); let field_and_padding = field.then(trailing_padding); Result::<Self, Err>::Ok(fields.or(field_and_padding)) @@ -488,4 +483,44 @@ pub(crate) mod rustc { Ok(Self::def(Def::Adt(def)).then(fields)) } } + + pub(crate) fn ty_layout<'tcx>(cx: LayoutCx<'tcx, TyCtxt<'tcx>>, ty: Ty<'tcx>) -> Layout<'tcx> { + crate::layout::rustc::layout_of(cx, ty).unwrap() + } + + fn ty_field<'tcx>( + cx: LayoutCx<'tcx, TyCtxt<'tcx>>, + (ty, layout): (Ty<'tcx>, Layout<'tcx>), + i: FieldIdx, + ) -> Ty<'tcx> { + match ty.kind() { + ty::Adt(def, args) => { + match layout.variants { + Variants::Single { index } => { + let field = &def.variant(index).fields[i]; + field.ty(cx.tcx, args) + } + // Discriminant field for enums (where applicable). + Variants::Multiple { tag, .. } => { + assert_eq!(i.as_usize(), 0); + ty::layout::PrimitiveExt::to_ty(&tag.primitive(), cx.tcx) + } + } + } + ty::Tuple(fields) => fields[i.as_usize()], + kind @ _ => unimplemented!( + "only a subset of `Ty::ty_and_layout_field`'s functionality is implemented. implementation needed for {:?}", + kind + ), + } + } + + fn ty_variant<'tcx>( + cx: LayoutCx<'tcx, TyCtxt<'tcx>>, + (ty, layout): (Ty<'tcx>, Layout<'tcx>), + i: VariantIdx, + ) -> Layout<'tcx> { + let ty = cx.tcx.erase_regions(ty); + TyAndLayout { ty, layout }.for_variant(&cx, i).layout + } } diff --git a/compiler/rustc_transmute/src/lib.rs b/compiler/rustc_transmute/src/lib.rs index 31664ee6c4f..bdc98bcea5e 100644 --- a/compiler/rustc_transmute/src/lib.rs +++ b/compiler/rustc_transmute/src/lib.rs @@ -9,7 +9,7 @@ pub(crate) use rustc_data_structures::fx::{FxIndexMap as Map, FxIndexSet as Set} pub mod layout; mod maybe_transmutable; -#[derive(Default)] +#[derive(Copy, Clone, Debug, Default)] pub struct Assume { pub alignment: bool, pub lifetimes: bool, diff --git a/compiler/rustc_transmute/src/maybe_transmutable/mod.rs b/compiler/rustc_transmute/src/maybe_transmutable/mod.rs index 7c66a827db9..1f3c4e3c817 100644 --- a/compiler/rustc_transmute/src/maybe_transmutable/mod.rs +++ b/compiler/rustc_transmute/src/maybe_transmutable/mod.rs @@ -30,7 +30,7 @@ where // FIXME: Nix this cfg, so we can write unit tests independently of rustc #[cfg(feature = "rustc")] mod rustc { - use rustc_middle::ty::layout::{LayoutCx, LayoutOf}; + use rustc_middle::ty::layout::LayoutCx; use rustc_middle::ty::{ParamEnv, Ty, TyCtxt}; use super::*; @@ -45,10 +45,9 @@ mod rustc { let layout_cx = LayoutCx { tcx: context, param_env: ParamEnv::reveal_all() }; let layout_of = |ty| { - layout_cx - .layout_of(ty) + crate::layout::rustc::layout_of(layout_cx, ty) .map_err(|_| Err::NotYetSupported) - .and_then(|tl| Tree::from_ty(tl, layout_cx)) + .and_then(|_| Tree::from_ty(ty, layout_cx)) }; // Convert `src` and `dst` from their rustc representations, to `Tree`-based diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index 34c426f2aa6..7e3c30f2383 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -584,7 +584,7 @@ fn fn_abi_new_uncached<'tcx>( let conv = conv_from_spec_abi(cx.tcx(), sig.abi, sig.c_variadic); let mut inputs = sig.inputs(); - let extra_args = if sig.abi == RustCall { + let extra_args = if sig.abi == SpecAbi::RustCall { assert!(!sig.c_variadic && extra_args.is_empty()); if let Some(input) = sig.inputs().last() { @@ -608,18 +608,6 @@ fn fn_abi_new_uncached<'tcx>( extra_args }; - let target = &cx.tcx.sess.target; - let target_env_gnu_like = matches!(&target.env[..], "gnu" | "musl" | "uclibc"); - let win_x64_gnu = target.os == "windows" && target.arch == "x86_64" && target.env == "gnu"; - let linux_s390x_gnu_like = - target.os == "linux" && target.arch == "s390x" && target_env_gnu_like; - let linux_sparc64_gnu_like = - target.os == "linux" && target.arch == "sparc64" && target_env_gnu_like; - let linux_powerpc_gnu_like = - target.os == "linux" && target.arch == "powerpc" && target_env_gnu_like; - use SpecAbi::*; - let rust_abi = matches!(sig.abi, RustIntrinsic | Rust | RustCall); - let is_drop_in_place = fn_def_id.is_some_and(|def_id| cx.tcx.is_lang_item(def_id, LangItem::DropInPlace)); @@ -659,18 +647,7 @@ fn fn_abi_new_uncached<'tcx>( }); if arg.layout.is_zst() { - // For some forsaken reason, x86_64-pc-windows-gnu - // doesn't ignore zero-sized struct arguments. - // The same is true for {s390x,sparc64,powerpc}-unknown-linux-{gnu,musl,uclibc}. - if is_return - || rust_abi - || (!win_x64_gnu - && !linux_s390x_gnu_like - && !linux_sparc64_gnu_like - && !linux_powerpc_gnu_like) - { - arg.mode = PassMode::Ignore; - } + arg.mode = PassMode::Ignore; } Ok(arg) diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs index 24926883523..4ded935b801 100644 --- a/compiler/rustc_ty_utils/src/consts.rs +++ b/compiler/rustc_ty_utils/src/consts.rs @@ -192,7 +192,7 @@ fn recurse_build<'tcx>( ExprKind::Borrow { arg, .. } => { let arg_node = &body.exprs[*arg]; - // Skip reborrows for now until we allow Deref/Borrow/AddressOf + // Skip reborrows for now until we allow Deref/Borrow/RawBorrow // expressions. // FIXME(generic_const_exprs): Verify/explain why this is sound if let ExprKind::Deref { arg } = arg_node.kind { @@ -202,7 +202,7 @@ fn recurse_build<'tcx>( } } // FIXME(generic_const_exprs): We may want to support these. - ExprKind::AddressOf { .. } | ExprKind::Deref { .. } => maybe_supported_error( + ExprKind::RawBorrow { .. } | ExprKind::Deref { .. } => maybe_supported_error( GenericConstantTooComplexSub::AddressAndDerefNotSupported(node.span), )?, ExprKind::Repeat { .. } | ExprKind::Array { .. } => { @@ -343,7 +343,7 @@ impl<'a, 'tcx> IsThirPolymorphic<'a, 'tcx> { | thir::ExprKind::VarRef { .. } | thir::ExprKind::UpvarRef { .. } | thir::ExprKind::Borrow { .. } - | thir::ExprKind::AddressOf { .. } + | thir::ExprKind::RawBorrow { .. } | thir::ExprKind::Break { .. } | thir::ExprKind::Continue { .. } | thir::ExprKind::Return { .. } |
