diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs index c8ec5deb92c43..372b4e820f72d 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs @@ -22,7 +22,10 @@ pub(crate) fn expand_deriving_partial_eq( path: path_std!(marker::StructuralPartialEq), skip_path_as_bound: true, // crucial! needs_copy_as_bound_if_packed: false, - additional_bounds: Vec::new(), + // The `StructuralPartialEq` impl must have the *same* bounds as the `PartialEq` impl, + // or it will apply in situations where it should not, such as in the bug + // . + additional_bounds: vec![ty::Ty::Path(path_std!(cmp::PartialEq))], // We really don't support unions, but that's already checked by the impl generated below; // a second check here would lead to redundant error messages. supports_unions: true, diff --git a/compiler/rustc_codegen_ssa/src/back/archive.rs b/compiler/rustc_codegen_ssa/src/back/archive.rs index b5d5893941ef2..bdf346d8e69d2 100644 --- a/compiler/rustc_codegen_ssa/src/back/archive.rs +++ b/compiler/rustc_codegen_ssa/src/back/archive.rs @@ -1,3 +1,4 @@ +use std::borrow::Cow; use std::env; use std::error::Error; use std::ffi::OsString; @@ -22,7 +23,7 @@ use tracing::trace; use super::metadata::{create_compressed_metadata_file, search_for_section}; use super::rmeta_link; -use super::symbol_edit::apply_hide; +use super::symbol_edit::{apply_edits, collect_internal_names}; use crate::common; // Public for ArchiveBuilderBuilder::extract_bundled_libs pub use crate::errors::ExtractBundledLibsError; @@ -314,12 +315,18 @@ pub enum AddArchiveKind<'a> { Other, } +pub struct ArchiveSymbols { + pub exported: FxHashSet, + pub rename_suffix: Option, + pub hide: bool, +} + pub trait ArchiveBuilder { fn add_file(&mut self, path: &Path, kind: ArchiveEntryKind); fn add_archive(&mut self, archive: &Path, kind: AddArchiveKind<'_>) -> io::Result<()>; - fn build(self: Box, output: &Path, exported_symbols: Option>) -> bool; + fn build(self: Box, output: &Path, symbols: Option) -> bool; } fn target_archive_format_to_object_kind(format: &str) -> Option { @@ -534,9 +541,9 @@ impl<'a> ArchiveBuilder for ArArchiveBuilder<'a> { /// Combine the provided files, rlibs, and native libraries into a single /// `Archive`. - fn build(self: Box, output: &Path, exported_symbols: Option>) -> bool { + fn build(self: Box, output: &Path, symbols: Option) -> bool { let sess = self.sess; - match self.build_inner(output, exported_symbols) { + match self.build_inner(output, symbols) { Ok(any_members) => any_members, Err(error) => { sess.dcx().emit_fatal(ArchiveBuildFailure { path: output.to_owned(), error }) @@ -546,11 +553,7 @@ impl<'a> ArchiveBuilder for ArArchiveBuilder<'a> { } impl<'a> ArArchiveBuilder<'a> { - fn build_inner( - self, - output: &Path, - exported_symbols: Option>, - ) -> io::Result { + fn build_inner(self, output: &Path, symbols: Option) -> io::Result { let archive_kind = match &*self.sess.target.archive_format { "gnu" => ArchiveKind::Gnu, "bsd" => ArchiveKind::Bsd, @@ -562,6 +565,39 @@ impl<'a> ArArchiveBuilder<'a> { } }; + // Collect all internally-defined symbol names across every Rust object file. + // This set is needed because rename must also apply to *undefined* references + // (cross-object calls within the staticlib), but we cannot use `!exported.contains(name)` + // alone — that would also match external C symbols like `malloc` which must not be renamed. + let rename = if let Some(sym) = &symbols + && let Some(rename_suffix) = sym.rename_suffix.as_deref() + { + let mut names = FxHashSet::default(); + for (_, entry) in &self.entries { + if entry.kind != ArchiveEntryKind::RustObj { + continue; + } + match &entry.source { + ArchiveEntrySource::Archive { archive_index, file_range } => { + let src_archive = &self.src_archives[*archive_index]; + let start = file_range.0 as usize; + let end = start + file_range.1 as usize; + if let Some(data) = src_archive.1.get(start..end) { + collect_internal_names(data, &sym.exported, &mut names); + } + } + ArchiveEntrySource::File(file) => { + if let Ok(data) = fs::read(file) { + collect_internal_names(&data, &sym.exported, &mut names); + } + } + } + } + Some((names, rename_suffix)) + } else { + None + }; + let mut entries = Vec::new(); for (entry_name, entry) in self.entries { @@ -588,9 +624,9 @@ impl<'a> ArArchiveBuilder<'a> { }; if entry.kind == ArchiveEntryKind::RustObj - && let Some(exported) = &exported_symbols + && let Some(sym) = &symbols { - Box::new(apply_hide(data, exported)) + Box::new(apply_edits(data, &sym.exported, sym.hide, rename.as_ref())) } else { Box::new(data) } @@ -602,9 +638,13 @@ impl<'a> ArArchiveBuilder<'a> { ) .map_err(|err| io_error_context("failed to map object file", err))?; if entry.kind == ArchiveEntryKind::RustObj - && let Some(exported) = &exported_symbols + && let Some(sym) = &symbols { - Box::new(apply_hide(&mmap, exported)) + let edited = apply_edits(&mmap, &sym.exported, sym.hide, rename.as_ref()); + match edited { + Cow::Borrowed(_) => Box::new(mmap) as Box>, + Cow::Owned(v) => Box::new(v), + } } else { Box::new(mmap) as Box> } diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index c68220aea78f7..102f0a33df721 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -47,13 +47,15 @@ use rustc_session::{Session, filesearch}; use rustc_span::Symbol; use rustc_target::spec::crt_objects::CrtObjects; use rustc_target::spec::{ - BinaryFormat, Cc, CfgAbi, Env, LinkOutputKind, LinkSelfContainedComponents, + Arch, BinaryFormat, Cc, CfgAbi, Env, LinkOutputKind, LinkSelfContainedComponents, LinkSelfContainedDefault, LinkerFeatures, LinkerFlavor, LinkerFlavorCli, Lld, Os, RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo, }; use tracing::{debug, info, warn}; -use super::archive::{AddArchiveKind, ArchiveBuilder, ArchiveBuilderBuilder, ArchiveEntryKind}; +use super::archive::{ + AddArchiveKind, ArchiveBuilder, ArchiveBuilderBuilder, ArchiveEntryKind, ArchiveSymbols, +}; use super::command::Command; use super::linker::{self, Linker}; use super::metadata::{MetadataPosition, create_wrapper_file}; @@ -566,11 +568,21 @@ fn link_staticlib( sess.dcx().emit_fatal(e); } - let exported_symbols = if sess.opts.unstable_opts.staticlib_hide_internal_symbols { + let hide = sess.opts.unstable_opts.staticlib_hide_internal_symbols; + let rename = sess.opts.unstable_opts.staticlib_rename_internal_symbols; + + let exported_symbols = if hide || rename { if !matches!(sess.target.binary_format, BinaryFormat::Elf | BinaryFormat::MachO) { - sess.dcx().emit_warn(errors::StaticlibHideInternalSymbolsUnsupported { - binary_format: sess.target.archive_format.to_string(), - }); + if hide { + sess.dcx().emit_warn(errors::StaticlibHideInternalSymbolsUnsupported { + binary_format: sess.target.archive_format.to_string(), + }); + } + if rename { + sess.dcx().emit_warn(errors::StaticlibRenameInternalSymbolsUnsupported { + binary_format: sess.target.archive_format.to_string(), + }); + } None } else { crate_info @@ -581,7 +593,14 @@ fn link_staticlib( } else { None }; - ab.build(out_filename, exported_symbols); + + let symbols = exported_symbols.map(|exported| ArchiveSymbols { + exported, + rename_suffix: rename.then(|| crate_info.symbol_rename_suffix.clone()), + hide, + }); + + ab.build(out_filename, symbols); let crates = crate_info.used_crates.iter(); @@ -2394,6 +2413,69 @@ fn add_rpath_args( } } +fn strip_numeric_suffix<'a>(base: &'a str, suffix: impl AsRef, fallback: &'a str) -> &'a str { + if suffix.as_ref().parse::().is_ok() { base } else { fallback } +} + +fn undecorate_c_symbol<'a>( + name: &'a str, + sess: &Session, + kind: SymbolExportKind, +) -> Option<&'a str> { + match sess.target.binary_format { + BinaryFormat::MachO => { + // Mach-O: strip the leading underscore that all external symbols have. + // The Darwin linker's export_symbols will add it back. + name.strip_prefix('_') + } + BinaryFormat::Coff => { + // MSVC C++ mangled names start with '?' and use a completely different + // decorating scheme that includes '@@' as structural delimiters. + // They must not be subjected to C calling-convention undecoration. + if name.starts_with('?') { + return Some(name); + } + Some(match sess.target.arch { + Arch::X86 => { + // COFF 32-bit: strip calling-convention decorations. + if let Some(rest) = name.strip_prefix('@') { + // fastcall: @foo@N -> foo + rest.rsplit_once('@') + .map(|(base, suffix)| strip_numeric_suffix(base, suffix, name)) + .unwrap_or(name) + } else if let Some(stripped) = name.strip_prefix('_') { + if let Some((base, suffix)) = stripped.rsplit_once('@') { + // stdcall: _foo@N -> foo + strip_numeric_suffix(base, suffix, stripped) + } else { + // cdecl: _foo -> foo + stripped + } + } else { + // vectorcall: foo@@N -> foo + name.rsplit_once("@@") + .map(|(base, suffix)| strip_numeric_suffix(base, suffix, name)) + .unwrap_or(name) + } + } + Arch::X86_64 => { + // COFF 64-bit: vectorcall mangling (foo@@N -> foo) also applies on x86_64. + name.rsplit_once("@@") + .map(|(base, suffix)| strip_numeric_suffix(base, suffix, name)) + .unwrap_or(name) + } + Arch::Arm64EC if kind == SymbolExportKind::Text => { + // Arm64EC: `#` prefix distinguishes ARM64EC text symbols from x64 thunks. + name.strip_prefix('#').unwrap_or(name) + } + _ => name, + }) + } + // ELF: no decoration + _ => Some(name), + } +} + fn add_c_staticlib_symbols( sess: &Session, lib: &NativeLib, @@ -2435,7 +2517,14 @@ fn add_c_staticlib_symbols( } for symbol in object.symbols() { - if symbol.scope() != object::SymbolScope::Dynamic { + // The `object` crate returns `Dynamic` for ELF/Mach-O global symbols, + // but always returns `Linkage` for COFF external symbols. + // Accept both for COFF (Windows and UEFI). + let scope = symbol.scope(); + if scope != object::SymbolScope::Dynamic + && !(sess.target.binary_format == BinaryFormat::Coff + && scope == object::SymbolScope::Linkage) + { continue; } @@ -2450,9 +2539,10 @@ fn add_c_staticlib_symbols( _ => continue, }; - // FIXME:The symbol mangle rules are slightly different in Windows(32-bit) and Apple. - // Need to be resolved. - out.push((name.to_string(), export_kind)); + let Some(undecorated) = undecorate_c_symbol(name, sess, export_kind) else { + continue; + }; + out.push((undecorated.to_string(), export_kind)); } } diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_edit.rs b/compiler/rustc_codegen_ssa/src/back/symbol_edit.rs index 19ecb3d92d209..ef8008216187a 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_edit.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_edit.rs @@ -1,42 +1,170 @@ -// We use the `object` crate for the read-only pass over ELF/Mach-O object files -// because its `Sym`/`Nlist` traits provide clean access to symbol properties without -// manual byte parsing. However, `object` does not expose mutable views into the data, -// so we cannot use it to modify symbol fields in place. Instead, the read-only pass -// collects byte-level patches (offset + new value), and the write pass -// (`apply_patches`) applies them to a copy of the byte buffer without any ELF/Mach-O -// parsing — similar to how linker relocations work. +//! Binary-level symbol editing for staticlib post-processing. +//! +//! - **Hide**: sets STV_HIDDEN (ELF) or N_PEXT (Mach-O) on non-exported symbols. +//! - **Rename**: appends a vendor-specific suffix to non-exported symbol names by +//! rebuilding the string table. +use std::borrow::Cow; use std::mem; -use object::read::elf::Sym as _; +use object::read::elf::{SectionHeader as _, Sym as _}; use object::read::macho::Nlist; use object::{Endianness, elf, macho}; -use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -/// A byte-level patch collected in the read-only pass and applied in the write pass. struct Patch { offset: usize, value: u8, } -/// Apply a list of byte patches to `data`, returning the (possibly modified) bytes. -fn apply_patches(data: &[u8], patches: &[Patch]) -> Vec { - let mut buf = data.to_vec(); - for p in patches { - buf[p.offset] = p.value; +struct RenameEntry { + name_field_offset: usize, + name: String, +} + +pub(super) fn apply_edits<'a>( + data: &'a [u8], + exported: &FxHashSet, + hide: bool, + rename: Option<&(FxHashSet, &str)>, +) -> Cow<'a, [u8]> { + let result = match object::File::parse(data).ok() { + Some(object::File::Elf64(_)) => elf_edit_impl::>( + data, + exported, + hide, + rename, + mem::offset_of!(elf::Sym64, st_other), + ), + Some(object::File::Elf32(_)) => elf_edit_impl::>( + data, + exported, + hide, + rename, + mem::offset_of!(elf::Sym32, st_other), + ), + Some(object::File::MachO64(_)) => macho_edit_impl::>( + data, + exported, + hide, + rename, + mem::offset_of!(macho::Nlist64, n_type), + ), + Some(object::File::MachO32(_)) => macho_edit_impl::>( + data, + exported, + hide, + rename, + mem::offset_of!(macho::Nlist32, n_type), + ), + _ => None, + }; + match result { + Some(v) => Cow::Owned(v), + None => Cow::Borrowed(data), + } +} + +pub(super) fn collect_internal_names( + data: &[u8], + exported: &FxHashSet, + out: &mut FxHashSet, +) { + let Ok(file) = object::File::parse(data) else { return }; + match file { + object::File::Elf64(_) => { + elf_collect_impl::>(data, exported, out) + } + object::File::Elf32(_) => { + elf_collect_impl::>(data, exported, out) + } + object::File::MachO64(_) => { + macho_collect_impl::>(data, exported, out) + } + object::File::MachO32(_) => { + macho_collect_impl::>(data, exported, out) + } + _ => {} + } +} + +fn elf_collect_impl>( + data: &[u8], + exported: &FxHashSet, + out: &mut FxHashSet, +) where + u64: From, +{ + let Ok(header) = Elf::parse(data) else { return }; + let Ok(endian) = header.endian() else { return }; + let Ok(sections) = header.sections(endian, data) else { return }; + let Ok(symtab) = sections.symbols(endian, data, elf::SHT_SYMTAB) else { return }; + let strings = symtab.strings(); + + for sym in symtab.iter() { + let binding = sym.st_bind(); + if binding != elf::STB_GLOBAL && binding != elf::STB_WEAK { + continue; + } + if sym.is_undefined(endian) { + continue; + } + let Ok(name_bytes) = sym.name(endian, strings) else { continue }; + let Ok(name) = str::from_utf8(name_bytes) else { continue }; + if !exported.contains(name) { + out.insert(name.to_string()); + } + } +} + +fn macho_collect_impl>( + data: &[u8], + exported: &FxHashSet, + out: &mut FxHashSet, +) { + let Ok(header) = Mach::parse(data, 0) else { return }; + let Ok(endian) = header.endian() else { return }; + let Ok(mut commands) = header.load_commands(endian, data, 0) else { return }; + + let symtab_cmd = loop { + let Ok(Some(cmd)) = commands.next() else { return }; + if let Ok(Some(st)) = cmd.symtab() { + break st; + } + }; + let Ok(symtab) = symtab_cmd.symbols::(endian, data) else { return }; + let strings = symtab.strings(); + + for nlist in symtab.iter() { + if nlist.is_stab() { + continue; + } + if nlist.is_undefined() { + continue; + } + if nlist.n_type() & macho::N_EXT == 0 { + continue; + } + let Ok(name_bytes) = nlist.name(endian, strings) else { continue }; + let Ok(name) = str::from_utf8(name_bytes) else { continue }; + let name = name.strip_prefix('_').unwrap_or(name); + if !exported.contains(name) { + out.insert(name.to_string()); + } } - buf } // --------------------------------------------------------------------------- -// ELF hide – read-only pass uses `object` crate, write pass uses `Patch` list +// ELF: single-pass collection + apply // --------------------------------------------------------------------------- -fn elf_hide_patches_impl<'data, Elf: object::read::elf::FileHeader>( - data: &'data [u8], - st_other_offset: usize, +fn elf_edit_impl>( + data: &[u8], exported: &FxHashSet, -) -> Option> + hide: bool, + rename: Option<&(FxHashSet, &str)>, + st_other_offset: usize, +) -> Option> where u64: From, { @@ -44,113 +172,314 @@ where let endian = header.endian().ok()?; let sections = header.sections(endian, data).ok()?; let symtab = sections.symbols(endian, data, elf::SHT_SYMTAB).ok()?; - let data_ptr = data.as_ptr() as usize; let strings = symtab.strings(); + let mut patches = Vec::new(); + let mut renames = Vec::new(); for sym in symtab.iter() { let binding = sym.st_bind(); if binding != elf::STB_GLOBAL && binding != elf::STB_WEAK { continue; } - if sym.is_undefined(endian) { - continue; - } let Ok(name_bytes) = sym.name(endian, strings) else { continue }; let Ok(name) = str::from_utf8(name_bytes) else { continue }; - if !exported.contains(name) { - let sym_addr = sym as *const Elf::Sym as usize; + + let sym_addr = sym as *const Elf::Sym as usize; + + if hide && !sym.is_undefined(endian) && !exported.contains(name) { let offset = sym_addr - data_ptr + st_other_offset; let new_vis = (sym.st_other() & !0x03) | elf::STV_HIDDEN; patches.push(Patch { offset, value: new_vis }); } + if let Some((rename_set, _)) = rename { + if rename_set.contains(name) { + renames.push(RenameEntry { + name_field_offset: sym_addr - data_ptr, + name: name.to_string(), + }); + } + } + } + + if patches.is_empty() && renames.is_empty() { + return None; } - Some(patches) + let mut result = data.to_vec(); + for p in &patches { + result[p.offset] = p.value; + } + + if !renames.is_empty() { + let suffix = rename.unwrap().1; + if let Some(renamed) = + elf_rebuild_strtab::(&result, &renames, suffix, §ions, header, endian) + { + result = renamed; + } + } + + Some(result) +} + +fn elf_rebuild_strtab>( + data: &[u8], + renames: &[RenameEntry], + suffix: &str, + sections: &object::read::elf::SectionTable<'_, Elf>, + header: &Elf, + endian: Endianness, +) -> Option> +where + u64: From, +{ + let mut strtab_si: Option = None; + for section in sections.iter() { + if section.sh_type(endian) == elf::SHT_SYMTAB { + strtab_si = Some(section.sh_link(endian) as usize); + break; + } + } + let strtab_si = strtab_si?; + + let e_shoff = u64::from(header.e_shoff(endian)) as usize; + let e_shentsize = mem::size_of::(); + let e_shnum = sections.len(); + + let strtab_section = sections.section(object::SectionIndex(strtab_si)).ok()?; + let old_strtab_offset = u64::from(strtab_section.sh_offset(endian)) as usize; + let old_strtab_size = u64::from(strtab_section.sh_size(endian)) as usize; + let old_strtab = data.get(old_strtab_offset..old_strtab_offset + old_strtab_size)?; + + let (new_strtab, rename_map) = build_renamed_strtab(old_strtab, renames, suffix); + + let is_64 = mem::size_of::() == 8; + let new_strtab_file_off = data.len(); + let new_strtab_size = new_strtab.len(); + let new_e_shoff_raw = new_strtab_file_off + new_strtab_size; + let new_e_shoff = (new_e_shoff_raw + 7) & !7; + let padding = new_e_shoff - new_e_shoff_raw; + let section_headers_size = e_shentsize * e_shnum; + + let result_size = new_e_shoff + section_headers_size; + let mut result = Vec::with_capacity(result_size); + result.extend_from_slice(data); + result.extend_from_slice(&new_strtab); + result.resize(result.len() + padding, 0); + let sh_data = data.get(e_shoff..e_shoff + section_headers_size)?; + result.extend_from_slice(sh_data); + + if is_64 { + write_u64_at( + &mut result, + mem::offset_of!(elf::FileHeader64, e_shoff), + new_e_shoff as u64, + endian, + ); + } else { + write_u32_at( + &mut result, + mem::offset_of!(elf::FileHeader32, e_shoff), + new_e_shoff as u32, + endian, + ); + } + + let new_strtab_shdr_offset = new_e_shoff + strtab_si * e_shentsize; + + if is_64 { + let sh_offset_field = mem::offset_of!(elf::SectionHeader64, sh_offset); + let sh_size_field = mem::offset_of!(elf::SectionHeader64, sh_size); + write_u64_at( + &mut result, + new_strtab_shdr_offset + sh_offset_field, + new_strtab_file_off as u64, + endian, + ); + write_u64_at( + &mut result, + new_strtab_shdr_offset + sh_size_field, + new_strtab_size as u64, + endian, + ); + } else { + let sh_offset_field = mem::offset_of!(elf::SectionHeader32, sh_offset); + let sh_size_field = mem::offset_of!(elf::SectionHeader32, sh_size); + write_u32_at( + &mut result, + new_strtab_shdr_offset + sh_offset_field, + new_strtab_file_off as u32, + endian, + ); + write_u32_at( + &mut result, + new_strtab_shdr_offset + sh_size_field, + new_strtab_size as u32, + endian, + ); + } + + for entry in renames { + let new_st_name = rename_map[&entry.name]; + write_u32_at(&mut result, entry.name_field_offset, new_st_name, endian); + } + + Some(result) } // --------------------------------------------------------------------------- -// Mach-O hide – same architecture: read-only pass via `object`, write via patches +// Mach-O: single-pass collection + apply // --------------------------------------------------------------------------- -fn macho_hide_patches_impl<'data, Mach: object::read::macho::MachHeader>( - data: &'data [u8], - n_type_offset: usize, +fn macho_edit_impl>( + data: &[u8], exported: &FxHashSet, -) -> Option> { + hide: bool, + rename: Option<&(FxHashSet, &str)>, + n_type_offset: usize, +) -> Option> { let header = Mach::parse(data, 0).ok()?; let endian = header.endian().ok()?; let mut commands = header.load_commands(endian, data, 0).ok()?; - let symtab_cmd = loop { + let (symtab_cmd, symtab_cmd_offset) = loop { let cmd = commands.next().ok()??; if let Some(st) = cmd.symtab().ok().flatten() { - break st; + break (st, cmd.raw_data().as_ptr() as usize - data.as_ptr() as usize); } }; + let symtab: object::read::macho::SymbolTable<'_, Mach, &_> = symtab_cmd.symbols(endian, data).ok()?; - let data_ptr = data.as_ptr() as usize; let strings = symtab.strings(); + let mut patches = Vec::new(); + let mut renames = Vec::new(); for nlist in symtab.iter() { if nlist.is_stab() { continue; } - if nlist.is_undefined() { - continue; - } if nlist.n_type() & macho::N_EXT == 0 { continue; } let Ok(name_bytes) = nlist.name(endian, strings) else { continue }; - let Ok(name) = str::from_utf8(name_bytes) else { continue }; - let name = name.strip_prefix('_').unwrap_or(name); - if !exported.contains(name) { - let nlist_addr = nlist as *const Mach::Nlist as usize; + let Ok(raw_name) = str::from_utf8(name_bytes) else { continue }; + let name = raw_name.strip_prefix('_').unwrap_or(raw_name); + + let nlist_addr = nlist as *const Mach::Nlist as usize; + + if hide && !nlist.is_undefined() && !exported.contains(name) { let offset = nlist_addr - data_ptr + n_type_offset; patches.push(Patch { offset, value: nlist.n_type() | macho::N_PEXT }); } + if let Some((rename_set, _)) = rename { + if rename_set.contains(name) { + renames.push(RenameEntry { + name_field_offset: nlist_addr - data_ptr, + name: raw_name.to_string(), + }); + } + } + } + + if patches.is_empty() && renames.is_empty() { + return None; } - Some(patches) + let mut result = data.to_vec(); + for p in &patches { + result[p.offset] = p.value; + } + + if !renames.is_empty() { + let suffix = rename.unwrap().1; + if let Some(renamed) = + macho_rebuild_strtab(&result, &renames, suffix, &symtab_cmd, symtab_cmd_offset, endian) + { + result = renamed; + } + } + + Some(result) +} + +fn macho_rebuild_strtab( + data: &[u8], + renames: &[RenameEntry], + suffix: &str, + symtab_cmd: &macho::SymtabCommand, + symtab_cmd_offset: usize, + endian: Endianness, +) -> Option> { + let old_stroff = symtab_cmd.stroff.get(endian) as usize; + let old_strsize = symtab_cmd.strsize.get(endian) as usize; + let old_strtab = data.get(old_stroff..old_stroff + old_strsize)?; + + let (new_strtab, rename_map) = build_renamed_strtab(old_strtab, renames, suffix); + + let new_strtab_file_off = data.len(); + let new_strtab_size = new_strtab.len(); + + let mut result = Vec::with_capacity(data.len() + new_strtab_size); + result.extend_from_slice(data); + result.extend_from_slice(&new_strtab); + + let stroff_off = mem::offset_of!(macho::SymtabCommand, stroff); + let strsize_off = mem::offset_of!(macho::SymtabCommand, strsize); + write_u32_at(&mut result, symtab_cmd_offset + stroff_off, new_strtab_file_off as u32, endian); + write_u32_at(&mut result, symtab_cmd_offset + strsize_off, new_strtab_size as u32, endian); + + for entry in renames { + let new_strx = rename_map[&entry.name]; + write_u32_at(&mut result, entry.name_field_offset, new_strx, endian); + } + + Some(result) } // --------------------------------------------------------------------------- -// Unified dispatch: top-level detection via `object::File::parse` +// Shared helpers // --------------------------------------------------------------------------- -fn hide_patches(data: &[u8], exported: &FxHashSet) -> Option> { - let file = object::File::parse(data).ok()?; - match file { - object::File::Elf64(_) => elf_hide_patches_impl::>( - data, - mem::offset_of!(elf::Sym64, st_other), - exported, - ), - object::File::Elf32(_) => elf_hide_patches_impl::>( - data, - mem::offset_of!(elf::Sym32, st_other), - exported, - ), - object::File::MachO64(_) => macho_hide_patches_impl::>( - data, - mem::offset_of!(macho::Nlist64, n_type), - exported, - ), - object::File::MachO32(_) => macho_hide_patches_impl::>( - data, - mem::offset_of!(macho::Nlist32, n_type), - exported, - ), - _ => None, +fn build_renamed_strtab( + old_strtab: &[u8], + renames: &[RenameEntry], + suffix: &str, +) -> (Vec, FxHashMap) { + let mut new_strtab = old_strtab.to_vec(); + let mut rename_map: FxHashMap = FxHashMap::default(); + + let mut sorted_names: Vec<&str> = renames.iter().map(|r| r.name.as_str()).collect(); + sorted_names.sort(); + sorted_names.dedup(); + + for name in &sorted_names { + let new_offset = new_strtab.len() as u32; + new_strtab.extend_from_slice(name.as_bytes()); + new_strtab.extend_from_slice(suffix.as_bytes()); + new_strtab.push(0); + rename_map.insert(name.to_string(), new_offset); } + + (new_strtab, rename_map) } -pub(super) fn apply_hide(data: &[u8], exported: &FxHashSet) -> Vec { - let patches = hide_patches(data, exported).unwrap_or_default(); - apply_patches(data, &patches) +fn write_u32_at(buf: &mut [u8], offset: usize, value: u32, endian: Endianness) { + let bytes = match endian { + Endianness::Little => value.to_le_bytes(), + Endianness::Big => value.to_be_bytes(), + }; + buf[offset..offset + 4].copy_from_slice(&bytes); +} + +fn write_u64_at(buf: &mut [u8], offset: usize, value: u64, endian: Endianness) { + let bytes = match endian { + Endianness::Little => value.to_le_bytes(), + Endianness::Big => value.to_be_bytes(), + }; + buf[offset..offset + 8].copy_from_slice(&bytes); } diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index c14d4aec48c35..2a5e421282f4e 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -962,6 +962,7 @@ impl CrateInfo { natvis_debugger_visualizers: Default::default(), lint_level_specs: CodegenLintLevelSpecs::from_tcx(tcx), metadata_symbol: exported_symbols::metadata_symbol_name(tcx), + symbol_rename_suffix: format!(".rs{:x}", tcx.stable_crate_id(LOCAL_CRATE)), each_linked_rlib_file_for_lto: Default::default(), exported_symbols_for_lto: Default::default(), }; diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index b634c0f7b6e7d..1fe52c34e89f4 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -701,6 +701,14 @@ pub(crate) struct StaticlibHideInternalSymbolsUnsupported { pub binary_format: String, } +#[derive(Diagnostic)] +#[diag( + "-Zstaticlib-rename-internal-symbols only supports ELF and Mach-O targets, but the target uses `{$binary_format}`" +)] +pub(crate) struct StaticlibRenameInternalSymbolsUnsupported { + pub binary_format: String, +} + #[derive(Diagnostic)] #[diag("entry symbol `main` declared multiple times")] #[help( diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index 616397dd77545..10ae8a9ee0b38 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -263,6 +263,7 @@ pub struct CrateInfo { pub natvis_debugger_visualizers: BTreeSet, pub lint_level_specs: CodegenLintLevelSpecs, pub metadata_symbol: String, + pub symbol_rename_suffix: String, pub each_linked_rlib_file_for_lto: Vec, pub exported_symbols_for_lto: Vec, } diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index d792e3d126f5d..deb8ca12b059d 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -43,7 +43,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // If this is storing a &Freeze reference with a retag, record that it's not // possible to perform writes through the stored pointer. let flags = if let ty::Ref(_, pointee_ty, Mutability::Not) = - operand.ty(self.mir, self.cx.tcx()).kind() + cg_operand.layout.ty.kind() && with_retag.yes() && pointee_ty.is_freeze(self.cx.tcx(), self.cx.typing_env()) { diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 917360ab8119e..ba938eb91a4aa 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -24,7 +24,7 @@ use rustc_middle::ty::{ TypeVisitable, TypeVisitableExt, Unnormalized, fold_regions, }; use rustc_session::lint::builtin::UNINHABITED_STATIC; -use rustc_span::sym; +use rustc_span::{DesugaringKind, sym}; use rustc_target::spec::{AbiMap, AbiMapping}; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::traits; @@ -2117,7 +2117,9 @@ fn check_type_alias_type_params_are_used<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalD // * check for emptiness to detect lone user-written `?Sized` bounds // * compare the param span to the pred span to detect lone user-written `Sized` bounds let has_explicit_bounds = bounded_params.is_empty() - || (*bounded_params).get(¶m.index).is_some_and(|&&pred_sp| pred_sp != span); + || (*bounded_params).get(¶m.index).is_some_and(|&&pred_sp| { + !pred_sp.is_desugaring(DesugaringKind::DefaultBound { def: param.def_id }) + }); let const_param_help = !has_explicit_bounds; let mut diag = tcx.dcx().create_err(diagnostics::UnusedGenericParameter { diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs index 4409f2c068eb8..7603f11b7ebef 100644 --- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs +++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs @@ -58,14 +58,16 @@ fn associated_type_bounds<'tcx>( &mut bounds, item_ty, hir_bounds, - ImpliedBoundsContext::AssociatedTypeOrImplTrait, + &[], + ImpliedBoundsContext::AssociatedType(assoc_item_def_id), span, ); icx.lowerer().add_default_traits( &mut bounds, item_ty, hir_bounds, - ImpliedBoundsContext::AssociatedTypeOrImplTrait, + &[], + ImpliedBoundsContext::AssociatedType(assoc_item_def_id), span, ); @@ -384,14 +386,16 @@ fn opaque_type_bounds<'tcx>( &mut bounds, item_ty, hir_bounds, - ImpliedBoundsContext::AssociatedTypeOrImplTrait, + &[], + ImpliedBoundsContext::ImplTrait, span, ); icx.lowerer().add_default_traits( &mut bounds, item_ty, hir_bounds, - ImpliedBoundsContext::AssociatedTypeOrImplTrait, + &[], + ImpliedBoundsContext::ImplTrait, span, ); } diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index db22b57ad22a6..6e6b6602f3a74 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -200,6 +200,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen &mut bounds, tcx.types.self_param, self_bounds, + &[], ImpliedBoundsContext::TraitDef(def_id), span, ); @@ -207,6 +208,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen &mut bounds, tcx.types.self_param, self_bounds, + &[], ImpliedBoundsContext::TraitDef(def_id), span, ); @@ -239,14 +241,16 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen &mut bounds, param_ty, &[], - ImpliedBoundsContext::TyParam(param.def_id, hir_generics.predicates), + hir_generics.predicates, + ImpliedBoundsContext::TyParam(param.def_id), param.span, ); icx.lowerer().add_default_traits( &mut bounds, param_ty, &[], - ImpliedBoundsContext::TyParam(param.def_id, hir_generics.predicates), + hir_generics.predicates, + ImpliedBoundsContext::TyParam(param.def_id), param.span, ); trace!(?bounds); @@ -692,6 +696,7 @@ pub(super) fn implied_predicates_with_filter<'tcx>( &mut bounds, self_param_ty, superbounds, + &[], ImpliedBoundsContext::TraitDef(trait_def_id), item.span, ); @@ -699,6 +704,7 @@ pub(super) fn implied_predicates_with_filter<'tcx>( &mut bounds, self_param_ty, superbounds, + &[], ImpliedBoundsContext::TraitDef(trait_def_id), item.span, ); @@ -994,14 +1000,16 @@ impl<'tcx> ItemCtxt<'tcx> { &mut bounds, param_ty, &[], - ImpliedBoundsContext::TyParam(param.def_id, hir_generics.predicates), + hir_generics.predicates, + ImpliedBoundsContext::TyParam(param.def_id), param.span, ); self.lowerer().add_default_traits( &mut bounds, param_ty, &[], - ImpliedBoundsContext::TyParam(param.def_id, hir_generics.predicates), + hir_generics.predicates, + ImpliedBoundsContext::TyParam(param.def_id), param.span, ); } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index 9d6c647329aa0..74d5447b03e80 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -12,7 +12,7 @@ use rustc_middle::ty::{ self as ty, IsSuggestable, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, Upcast, }; -use rustc_span::{ErrorGuaranteed, Ident, Span, kw}; +use rustc_span::{DesugaringKind, ErrorGuaranteed, Ident, Span, kw}; use rustc_trait_selection::traits; use tracing::{debug, instrument}; @@ -25,17 +25,17 @@ use crate::hir_ty_lowering::{ #[derive(Debug, Default)] struct CollectedBound { /// `Trait` - positive: bool, + positive: Option, /// `?Trait` - maybe: bool, + maybe: Option, /// `!Trait` - negative: bool, + negative: Option, } impl CollectedBound { /// Returns `true` if any of `Trait`, `?Trait` or `!Trait` were encountered. fn any(&self) -> bool { - self.positive || self.maybe || self.negative + self.positive.is_some() || self.maybe.is_some() || self.negative.is_some() } } @@ -59,7 +59,8 @@ impl CollectedSizednessBounds { fn search_bounds_for<'tcx>( hir_bounds: &'tcx [hir::GenericBound<'tcx>], - context: ImpliedBoundsContext<'tcx>, + where_bounds: &'tcx [hir::WherePredicate<'tcx>], + context: ImpliedBoundsContext, mut f: impl FnMut(&'tcx PolyTraitRef<'tcx>), ) { let mut search_bounds = |hir_bounds: &'tcx [hir::GenericBound<'tcx>]| { @@ -73,8 +74,8 @@ fn search_bounds_for<'tcx>( }; search_bounds(hir_bounds); - if let ImpliedBoundsContext::TyParam(self_ty, where_clause) = context { - for clause in where_clause { + if let ImpliedBoundsContext::TyParam(self_ty) = context { + for clause in where_bounds { if let hir::WherePredicateKind::BoundPredicate(pred) = clause.kind && pred.is_param_bound(self_ty.to_def_id()) { @@ -86,19 +87,20 @@ fn search_bounds_for<'tcx>( fn collect_bounds<'a, 'tcx>( hir_bounds: &'a [hir::GenericBound<'tcx>], - context: ImpliedBoundsContext<'tcx>, + where_bounds: &'tcx [hir::WherePredicate<'tcx>], + context: ImpliedBoundsContext, target_did: DefId, ) -> CollectedBound { let mut collect_into = CollectedBound::default(); - search_bounds_for(hir_bounds, context, |ptr| { + search_bounds_for(hir_bounds, where_bounds, context, |ptr| { if !matches!(ptr.trait_ref.path.res, Res::Def(DefKind::Trait, did) if did == target_did) { return; } match ptr.modifiers.polarity { - hir::BoundPolarity::Maybe(_) => collect_into.maybe = true, - hir::BoundPolarity::Negative(_) => collect_into.negative = true, - hir::BoundPolarity::Positive => collect_into.positive = true, + hir::BoundPolarity::Maybe(_) => collect_into.maybe = Some(ptr.span), + hir::BoundPolarity::Negative(_) => collect_into.negative = Some(ptr.span), + hir::BoundPolarity::Positive => collect_into.positive = Some(ptr.span), } }); collect_into @@ -107,17 +109,18 @@ fn collect_bounds<'a, 'tcx>( fn collect_sizedness_bounds<'tcx>( tcx: TyCtxt<'tcx>, hir_bounds: &'tcx [hir::GenericBound<'tcx>], - context: ImpliedBoundsContext<'tcx>, + where_bounds: &'tcx [hir::WherePredicate<'tcx>], + context: ImpliedBoundsContext, span: Span, ) -> CollectedSizednessBounds { let sized_did = tcx.require_lang_item(hir::LangItem::Sized, span); - let sized = collect_bounds(hir_bounds, context, sized_did); + let sized = collect_bounds(hir_bounds, where_bounds, context, sized_did); let meta_sized_did = tcx.require_lang_item(hir::LangItem::MetaSized, span); - let meta_sized = collect_bounds(hir_bounds, context, meta_sized_did); + let meta_sized = collect_bounds(hir_bounds, where_bounds, context, meta_sized_did); let pointee_sized_did = tcx.require_lang_item(hir::LangItem::PointeeSized, span); - let pointee_sized = collect_bounds(hir_bounds, context, pointee_sized_did); + let pointee_sized = collect_bounds(hir_bounds, where_bounds, context, pointee_sized_did); CollectedSizednessBounds { sized, meta_sized, pointee_sized } } @@ -150,7 +153,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { bounds: &mut Vec<(ty::Clause<'tcx>, Span)>, self_ty: Ty<'tcx>, hir_bounds: &'tcx [hir::GenericBound<'tcx>], - context: ImpliedBoundsContext<'tcx>, + where_bounds: &'tcx [hir::WherePredicate<'tcx>], + context: ImpliedBoundsContext, span: Span, ) { let tcx = self.tcx(); @@ -177,13 +181,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { return; } } - ImpliedBoundsContext::TyParam(..) | ImpliedBoundsContext::AssociatedTypeOrImplTrait => { - } + ImpliedBoundsContext::TyParam(..) + | ImpliedBoundsContext::AssociatedType(..) + | ImpliedBoundsContext::TraitObject + | ImpliedBoundsContext::TraitAscription + | ImpliedBoundsContext::ImplTrait => {} } - - let collected = collect_sizedness_bounds(tcx, hir_bounds, context, span); - if (collected.sized.maybe || collected.sized.negative) - && !collected.sized.positive + let collected = collect_sizedness_bounds(tcx, hir_bounds, where_bounds, context, span); + if let Some(span) = collected.sized.maybe.or(collected.sized.negative) + && collected.sized.positive.is_none() && !collected.meta_sized.any() && !collected.pointee_sized.any() { @@ -191,6 +197,21 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // other explicit ones) - this can happen for trait aliases as well as bounds. add_trait_bound(tcx, bounds, self_ty, meta_sized_did, span); } else if !collected.any() { + let span = match context { + ImpliedBoundsContext::TraitDef(def) + | ImpliedBoundsContext::TyParam(def) + | ImpliedBoundsContext::AssociatedType(def) => { + self.tcx().with_stable_hashing_context(|hcx| { + span.mark_with_reason( + None, + DesugaringKind::DefaultBound { def: def.into() }, + span.edition(), + hcx, + ) + }) + } + _ => span, + }; match context { ImpliedBoundsContext::TraitDef(..) => { // If there are no explicit sizedness bounds on a trait then add a default @@ -198,7 +219,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { add_trait_bound(tcx, bounds, self_ty, meta_sized_did, span); } ImpliedBoundsContext::TyParam(..) - | ImpliedBoundsContext::AssociatedTypeOrImplTrait => { + | ImpliedBoundsContext::AssociatedType(..) + | ImpliedBoundsContext::TraitObject + | ImpliedBoundsContext::TraitAscription + | ImpliedBoundsContext::ImplTrait => { // If there are no explicit sizedness bounds on a parameter then add a default // `Sized` bound. let sized_did = tcx.require_lang_item(hir::LangItem::Sized, span); @@ -213,11 +237,20 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { bounds: &mut Vec<(ty::Clause<'tcx>, Span)>, self_ty: Ty<'tcx>, hir_bounds: &[hir::GenericBound<'tcx>], - context: ImpliedBoundsContext<'tcx>, + where_bounds: &'tcx [hir::WherePredicate<'tcx>], + context: ImpliedBoundsContext, span: Span, ) { self.tcx().default_traits().iter().for_each(|default_trait| { - self.add_default_trait(*default_trait, bounds, self_ty, hir_bounds, context, span); + self.add_default_trait( + *default_trait, + bounds, + self_ty, + hir_bounds, + where_bounds, + context, + span, + ); }); } @@ -230,7 +263,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { bounds: &mut Vec<(ty::Clause<'tcx>, Span)>, self_ty: Ty<'tcx>, hir_bounds: &[hir::GenericBound<'tcx>], - context: ImpliedBoundsContext<'tcx>, + where_bounds: &'tcx [hir::WherePredicate<'tcx>], + context: ImpliedBoundsContext, span: Span, ) { let tcx = self.tcx(); @@ -244,7 +278,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } if let Some(trait_did) = tcx.lang_items().get(trait_) - && self.should_add_default_traits(trait_did, hir_bounds, context) + && self.should_add_default_traits(trait_did, hir_bounds, where_bounds, context) { add_trait_bound(tcx, bounds, self_ty, trait_did, span); } @@ -255,9 +289,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { &self, trait_def_id: DefId, hir_bounds: &'a [hir::GenericBound<'tcx>], - context: ImpliedBoundsContext<'tcx>, + where_bounds: &'tcx [hir::WherePredicate<'tcx>], + context: ImpliedBoundsContext, ) -> bool { - let collected = collect_bounds(hir_bounds, context, trait_def_id); + let collected = collect_bounds(hir_bounds, where_bounds, context, trait_def_id); !find_attr!(self.tcx(), crate, RustcNoImplicitBounds) && !collected.any() } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs index 761af258822dd..e75e5059bc1dc 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs @@ -83,7 +83,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .iter() .map(|&trait_ref| hir::GenericBound::Trait(trait_ref)) .collect::>(), - ImpliedBoundsContext::AssociatedTypeOrImplTrait, + &[], + ImpliedBoundsContext::TraitObject, span, ); diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 7909fdbf2365e..e029a7b311fb0 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -59,14 +59,17 @@ use crate::{NoVariantNamed, check_c_variadic_abi}; /// The context in which an implied bound is being added to a item being lowered (i.e. a sizedness /// trait or a default trait) #[derive(Clone, Copy)] -pub(crate) enum ImpliedBoundsContext<'tcx> { +pub(crate) enum ImpliedBoundsContext { /// An implied bound is added to a trait definition (i.e. a new supertrait), used when adding /// a default `MetaSized` supertrait TraitDef(LocalDefId), /// An implied bound is added to a type parameter - TyParam(LocalDefId, &'tcx [hir::WherePredicate<'tcx>]), - /// An implied bound being added in any other context - AssociatedTypeOrImplTrait, + TyParam(LocalDefId), + /// Associated type bounds + AssociatedType(LocalDefId), + ImplTrait, + TraitObject, + TraitAscription, } /// A path segment that is semantically allowed to have generic arguments. @@ -3093,7 +3096,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { &mut bounds, self_ty, hir_bounds, - ImpliedBoundsContext::AssociatedTypeOrImplTrait, + &[], + ImpliedBoundsContext::TraitAscription, hir_ty.span, ); self.register_trait_ascription_bounds(bounds, hir_ty.hir_id, hir_ty.span); diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 8c9f764c0bded..7110a1edbe28b 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -34,8 +34,8 @@ use rustc_middle::ty::print::{ use rustc_middle::ty::{self, GenericArgKind, IsSuggestable, Ty, TyCtxt, TypeVisitableExt}; use rustc_span::def_id::DefIdSet; use rustc_span::{ - DUMMY_SP, ErrorGuaranteed, ExpnKind, FileName, Ident, MacroKind, Span, Symbol, edit_distance, - kw, sym, + DUMMY_SP, DesugaringKind, ErrorGuaranteed, ExpnKind, FileName, Ident, MacroKind, Span, Symbol, + edit_distance, kw, sym, }; use rustc_trait_selection::error_reporting::traits::DefIdOrName; use rustc_trait_selection::infer::InferCtxtExt; @@ -1948,8 +1948,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _ => false, } }); - for param in generics.params { - if param.span == cause_span && sized_pred { + if sized_pred && let Some(DesugaringKind::DefaultBound { def }) = cause_span.desugaring_kind() { + if let Some(param) = generics.params.iter().find(|p| p.def_id.to_def_id() == def) { let (sp, sugg) = match param.colon_span { Some(sp) => (sp.shrink_to_hi(), " ?Sized +"), None => (param.span.shrink_to_hi(), ": ?Sized"), diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 289967ade56c8..ce21a79a02dfd 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -894,6 +894,7 @@ fn test_unstable_options_tracking_hash() { tracked!(src_hash_algorithm, Some(SourceFileHashAlgorithm::Sha1)); tracked!(stack_protector, StackProtector::All); tracked!(staticlib_hide_internal_symbols, true); + tracked!(staticlib_rename_internal_symbols, true); tracked!(teach, true); tracked!(thinlto, Some(true)); tracked!(tiny_const_eval_limit, true); diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index 0324ba8723a24..1199955dc7c63 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -17,6 +17,9 @@ use rustc_middle::ty::{ }; use rustc_span::def_id::DefId; use rustc_span::{DUMMY_SP, Span}; +use rustc_trait_selection::error_reporting::traits::ambiguity::{ + CandidateSource, compute_applicable_impls_for_diagnostics, +}; use rustc_trait_selection::traits::ObligationCause; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; use tracing::{debug, instrument, trace}; @@ -232,15 +235,35 @@ impl<'tcx> ConstToPat<'tcx> { let kind = match ty.kind() { // Extremely important check for all ADTs! - // Make sure they are eligible to be used in patterns, and if not, emit an error. + // Make sure they are eligible to be used in patterns (structural), and if not, emit an + // error. ty::Adt(adt_def, _) if !self.type_marked_structural(ty) => { // This ADT cannot be used as a constant in patterns. debug!(?adt_def, ?value.ty, "ADT type in pattern is not `type_marked_structural`"); let PartialEqImplStatus { - is_derived, structural_partial_eq, non_blanket_impl, .. + is_derived, + possibly_inapplicable_structural_partial_eq, + non_blanket_impl, + possibly_inapplicable_derived_partial_eq, + has_impl, + .. } = type_has_partial_eq_impl(self.tcx, self.typing_env, ty); + + // If we have a derived PartialEq impl but it does not apply, + // then error about that instead, because `TypeNotStructural` gives advice that is + // relevant only when the problem is that `ty` does not derive `PartialEq`. + // + // Note that this is a duplicate of a check in `unevaluated_to_pat()`, + // which we would run later if we weren’t emitting an error now. + if possibly_inapplicable_derived_partial_eq && !has_impl { + let mut err = + self.tcx.dcx().create_err(TypeNotPartialEq { span: self.span, ty }); + extend_type_not_partial_eq(self.tcx, self.typing_env, ty, &mut err); + return self.mk_err(err, ty); + } + let (manual_partialeq_impl_span, manual_partialeq_impl_note) = - match (structural_partial_eq, non_blanket_impl) { + match (possibly_inapplicable_structural_partial_eq, non_blanket_impl) { (true, _) => (None, false), (_, Some(def_id)) if def_id.is_local() && !is_derived => { (Some(tcx.def_span(def_id)), false) @@ -488,8 +511,9 @@ fn extend_type_not_partial_eq<'tcx>( let PartialEqImplStatus { has_impl, is_derived, - structural_partial_eq, + possibly_inapplicable_structural_partial_eq: structural_partial_eq, non_blanket_impl, + possibly_inapplicable_derived_partial_eq: _, } = type_has_partial_eq_impl(self.tcx, self.typing_env, ty); match (has_impl, is_derived, structural_partial_eq, non_blanket_impl) { (_, _, true, _) => {} @@ -558,10 +582,20 @@ fn extend_type_not_partial_eq<'tcx>( #[derive(Debug)] struct PartialEqImplStatus { + /// There is a `PartialEq` impl that applies to the type. has_impl: bool, + + /// The `PartialEq` impl is `#[automatically_derived]`. is_derived: bool, - structural_partial_eq: bool, + /// The `DefId` of the same impl that `is_derived` refers to. non_blanket_impl: Option, + + /// If true, there is a `StructuralPartialEq` implementation, + /// but its bounds might not be satisfied. + possibly_inapplicable_structural_partial_eq: bool, + /// If true, there is a derived `PartialEq` implementation for the type, + /// but its bounds might not be satisfied. + possibly_inapplicable_derived_partial_eq: bool, } #[instrument(level = "trace", skip(tcx), ret)] @@ -580,23 +614,6 @@ fn type_has_partial_eq_impl<'tcx>( let structural_partial_eq_trait_id = tcx.require_lang_item(hir::LangItem::StructuralPeq, DUMMY_SP); - let partial_eq_obligation = Obligation::new( - tcx, - ObligationCause::dummy(), - param_env, - ty::TraitRef::new(tcx, partial_eq_trait_id, [ty, ty]), - ); - - let mut automatically_derived = false; - let mut structural_peq = false; - let mut impl_def_id = None; - for def_id in tcx.non_blanket_impls_for_ty(partial_eq_trait_id, ty) { - automatically_derived = find_attr!(tcx, def_id, AutomaticallyDerived); - impl_def_id = Some(def_id); - } - for _ in tcx.non_blanket_impls_for_ty(structural_partial_eq_trait_id, ty) { - structural_peq = true; - } // This *could* accept a type that isn't actually `PartialEq`, because region bounds get // ignored. However that should be pretty much impossible since consts that do not depend on // generics can only mention the `'static` lifetime, and how would one have a type that's @@ -607,10 +624,60 @@ fn type_has_partial_eq_impl<'tcx>( // that patterns can only do things that the code could also do without patterns, but it is // needed for backwards compatibility. The actual pattern matching compares primitive values, // `PartialEq::eq` never gets invoked, so there's no risk of us running non-const code. + let has_impl = { + let obligation = Obligation::new( + tcx, + ObligationCause::dummy(), + param_env, + ty::TraitRef::new(tcx, partial_eq_trait_id, [ty, ty]), + ); + infcx.predicate_must_hold_modulo_regions(&obligation) + }; + + // Determine whether there are is a derived `PartialEq` implementation, whether or not its + // bounds are met. + let possibly_inapplicable_derived_partial_eq = { + let obligation = Obligation::new( + tcx, + ObligationCause::dummy(), + param_env, + ty::Binder::dummy(ty::TraitRef::new(tcx, partial_eq_trait_id, [ty, ty])), + ); + compute_applicable_impls_for_diagnostics(&infcx, &obligation, true).iter().any( + |candidate_source| { + matches!( + candidate_source, + &CandidateSource::DefId(def_id) + if find_attr!(tcx, def_id, AutomaticallyDerived) + ) + }, + ) + }; + + let possibly_inapplicable_structural_partial_eq = { + let obligation = Obligation::new( + tcx, + ObligationCause::dummy(), + param_env, + ty::Binder::dummy(ty::TraitRef::new(tcx, structural_partial_eq_trait_id, [ty])), + ); + compute_applicable_impls_for_diagnostics(&infcx, &obligation, true) + .iter() + .any(|candidate_source| matches!(candidate_source, CandidateSource::DefId(_))) + }; + + let mut automatically_derived = false; + let mut impl_def_id = None; + for def_id in tcx.non_blanket_impls_for_ty(partial_eq_trait_id, ty) { + automatically_derived = find_attr!(tcx, def_id, AutomaticallyDerived); + impl_def_id = Some(def_id); + } + PartialEqImplStatus { - has_impl: infcx.predicate_must_hold_modulo_regions(&partial_eq_obligation), + has_impl, is_derived: automatically_derived, - structural_partial_eq: structural_peq, + possibly_inapplicable_structural_partial_eq, non_blanket_impl: impl_def_id, + possibly_inapplicable_derived_partial_eq, } } diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 1dba13ce9b4bc..089a9322e6a3c 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -2481,6 +2481,14 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M ); } + if unstable_opts.staticlib_rename_internal_symbols + && !crate_types.contains(&CrateType::StaticLib) + { + early_dcx.early_warn( + "-Zstaticlib-rename-internal-symbols has no effect without `--crate-type staticlib`", + ); + } + let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(early_dcx, matches); if !unstable_opts.unstable_options && json_timings { diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 75f9f73dee948..2f9fa09c322bb 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -2713,7 +2713,9 @@ written to standard error output)"), staticlib_allow_rdylib_deps: bool = (false, parse_bool, [TRACKED], "allow staticlibs to have rust dylib dependencies"), staticlib_hide_internal_symbols: bool = (false, parse_bool, [TRACKED], - "hide non-exported symbols in ELF static libraries by setting STV_HIDDEN"), + "hide non-exported Rust symbols when building staticlibs by setting STV_HIDDEN"), + staticlib_rename_internal_symbols: bool = (false, parse_bool, [TRACKED], + "rename non-exported Rust symbols when building staticlibs to avoid conflicts"), staticlib_prefer_dynamic: bool = (false, parse_bool, [TRACKED], "prefer dynamic linking to static linking for staticlibs (default: no)"), strict_init_checks: bool = (false, parse_bool, [TRACKED], diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index 1c742052783cd..9688978f35fec 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -926,9 +926,20 @@ impl SyntaxContext { | DesugaringKind::WhileLoop | DesugaringKind::OpaqueTy | DesugaringKind::Async + | DesugaringKind::DefaultBound { .. } | DesugaringKind::Await, ) => false, - ExpnKind::AstPass(_) | ExpnKind::Desugaring(_) => true, // well, it's "external" + ExpnKind::AstPass(_) + | ExpnKind::Desugaring( + DesugaringKind::BoundModifier + | DesugaringKind::QuestionMark + | DesugaringKind::TryBlock + | DesugaringKind::Contract + | DesugaringKind::RangeExpr + | DesugaringKind::PatTyRange + | DesugaringKind::FormatLiteral { .. } + | DesugaringKind::YeetExpr, + ) => true, // well, it's "external" ExpnKind::Macro(MacroKind::Bang, _) => { // Dummy span for the `def_site` means it's an external macro. expn_data.def_site.is_dummy() || sm.is_imported(expn_data.def_site) @@ -1225,6 +1236,13 @@ pub enum DesugaringKind { source: bool, }, RangeExpr, + /// Implicit `Sized` or `MetaSized` bounds. The actual source location points to just the + /// param or item for which the implicit bound was generated. + DefaultBound { + /// The definition this implied bound was added to. + /// So far only supports params, but may be used for super trait bounds and assoc ty bounds in the future + def: DefId, + }, } impl DesugaringKind { @@ -1247,6 +1265,7 @@ impl DesugaringKind { "expression that expanded into a format string literal" } DesugaringKind::RangeExpr => "range expression", + DesugaringKind::DefaultBound { .. } => "implied bound", } } @@ -1267,6 +1286,7 @@ impl DesugaringKind { DesugaringKind::PatTyRange => value == "PatTyRange", DesugaringKind::FormatLiteral { .. } => value == "FormatLiteral", DesugaringKind::RangeExpr => value == "RangeExpr", + DesugaringKind::DefaultBound { .. } => value == "ImpliedBound", } } } diff --git a/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs b/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs index 8b02e1235e609..ec91dbeb86ef9 100644 --- a/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs @@ -2,7 +2,7 @@ use rustc_abi::Endian; -use crate::spec::{Arch, CfgAbi, LlvmAbi, Target, TargetMetadata, TargetOptions, base}; +use crate::spec::{Arch, CfgAbi, LlvmAbi, Target, TargetMetadata, TargetOptions, base, cvs}; pub(crate) fn target() -> Target { let mut base = base::linux_musl::opts(); @@ -28,6 +28,7 @@ pub(crate) fn target() -> Target { endian: Endian::Big, mcount: "_mcount".into(), llvm_abiname: LlvmAbi::N64, + llvm_args: cvs!["-mno-check-zero-division"], ..base }, } diff --git a/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_gnuabi64.rs index 14942885c6b99..bb249d3335cf3 100644 --- a/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_gnuabi64.rs +++ b/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_gnuabi64.rs @@ -1,6 +1,6 @@ use rustc_abi::Endian; -use crate::spec::{Arch, CfgAbi, LlvmAbi, Target, TargetMetadata, TargetOptions, base}; +use crate::spec::{Arch, CfgAbi, LlvmAbi, Target, TargetMetadata, TargetOptions, base, cvs}; pub(crate) fn target() -> Target { Target { @@ -23,6 +23,7 @@ pub(crate) fn target() -> Target { max_atomic_width: Some(64), mcount: "_mcount".into(), llvm_abiname: LlvmAbi::N64, + llvm_args: cvs!["-mno-check-zero-division"], ..base::linux_gnu::opts() }, diff --git a/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_muslabi64.rs b/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_muslabi64.rs index c5336fd58fc93..c83d371692e69 100644 --- a/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_muslabi64.rs +++ b/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_muslabi64.rs @@ -1,6 +1,6 @@ use rustc_abi::Endian; -use crate::spec::{Arch, CfgAbi, LlvmAbi, Target, TargetMetadata, TargetOptions, base}; +use crate::spec::{Arch, CfgAbi, LlvmAbi, Target, TargetMetadata, TargetOptions, base, cvs}; pub(crate) fn target() -> Target { let mut base = base::linux_musl::opts(); @@ -24,6 +24,7 @@ pub(crate) fn target() -> Target { endian: Endian::Big, mcount: "_mcount".into(), llvm_abiname: LlvmAbi::N64, + llvm_args: cvs!["-mno-check-zero-division"], ..base }, } diff --git a/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_gnuabi64.rs index 665cf1d4362d9..f3ab85ecdd2d2 100644 --- a/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_gnuabi64.rs +++ b/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_gnuabi64.rs @@ -1,4 +1,4 @@ -use crate::spec::{Arch, CfgAbi, LlvmAbi, Target, TargetMetadata, TargetOptions, base}; +use crate::spec::{Arch, CfgAbi, LlvmAbi, Target, TargetMetadata, TargetOptions, base, cvs}; pub(crate) fn target() -> Target { Target { @@ -20,6 +20,7 @@ pub(crate) fn target() -> Target { max_atomic_width: Some(64), mcount: "_mcount".into(), llvm_abiname: LlvmAbi::N64, + llvm_args: cvs!["-mno-check-zero-division"], ..base::linux_gnu::opts() }, diff --git a/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_muslabi64.rs b/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_muslabi64.rs index bd237eaedc667..5685e84f140a4 100644 --- a/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_muslabi64.rs +++ b/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_muslabi64.rs @@ -1,4 +1,4 @@ -use crate::spec::{Arch, CfgAbi, LlvmAbi, Target, TargetMetadata, TargetOptions, base}; +use crate::spec::{Arch, CfgAbi, LlvmAbi, Target, TargetMetadata, TargetOptions, base, cvs}; pub(crate) fn target() -> Target { let mut base = base::linux_musl::opts(); @@ -21,6 +21,7 @@ pub(crate) fn target() -> Target { cfg_abi: CfgAbi::Abi64, mcount: "_mcount".into(), llvm_abiname: LlvmAbi::N64, + llvm_args: cvs!["-mno-check-zero-division"], ..base }, } diff --git a/compiler/rustc_target/src/spec/targets/mips_mti_none_elf.rs b/compiler/rustc_target/src/spec/targets/mips_mti_none_elf.rs index 32440cdd92e99..b75c3e880cc17 100644 --- a/compiler/rustc_target/src/spec/targets/mips_mti_none_elf.rs +++ b/compiler/rustc_target/src/spec/targets/mips_mti_none_elf.rs @@ -2,7 +2,7 @@ use rustc_abi::Endian; use crate::spec::{ Arch, Cc, LinkerFlavor, Lld, LlvmAbi, PanicStrategy, RelocModel, Target, TargetMetadata, - TargetOptions, + TargetOptions, cvs, }; pub(crate) fn target() -> Target { @@ -26,6 +26,7 @@ pub(crate) fn target() -> Target { cpu: "mips32r2".into(), llvm_abiname: LlvmAbi::O32, + llvm_args: cvs!["-mno-check-zero-division"], max_atomic_width: Some(32), features: "+mips32r2,+soft-float,+noabicalls".into(), diff --git a/compiler/rustc_target/src/spec/targets/mips_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/mips_unknown_linux_gnu.rs index 8bfa8ecf60222..a706c4b1cbdc3 100644 --- a/compiler/rustc_target/src/spec/targets/mips_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/mips_unknown_linux_gnu.rs @@ -1,6 +1,6 @@ use rustc_abi::Endian; -use crate::spec::{Arch, LlvmAbi, Target, TargetMetadata, TargetOptions, base}; +use crate::spec::{Arch, LlvmAbi, Target, TargetMetadata, TargetOptions, base, cvs}; pub(crate) fn target() -> Target { Target { @@ -19,6 +19,7 @@ pub(crate) fn target() -> Target { cpu: "mips32r2".into(), features: "+mips32r2,+fpxx,+nooddspreg".into(), llvm_abiname: LlvmAbi::O32, + llvm_args: cvs!["-mno-check-zero-division"], max_atomic_width: Some(32), mcount: "_mcount".into(), diff --git a/compiler/rustc_target/src/spec/targets/mips_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/mips_unknown_linux_musl.rs index 316e59dea88b8..7e3bebc60e9d3 100644 --- a/compiler/rustc_target/src/spec/targets/mips_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/mips_unknown_linux_musl.rs @@ -1,6 +1,6 @@ use rustc_abi::Endian; -use crate::spec::{Arch, LlvmAbi, Target, TargetMetadata, TargetOptions, base}; +use crate::spec::{Arch, LlvmAbi, Target, TargetMetadata, TargetOptions, base, cvs}; pub(crate) fn target() -> Target { let mut base = base::linux_musl::opts(); @@ -21,6 +21,7 @@ pub(crate) fn target() -> Target { options: TargetOptions { endian: Endian::Big, llvm_abiname: LlvmAbi::O32, + llvm_args: cvs!["-mno-check-zero-division"], mcount: "_mcount".into(), ..base }, diff --git a/compiler/rustc_target/src/spec/targets/mips_unknown_linux_uclibc.rs b/compiler/rustc_target/src/spec/targets/mips_unknown_linux_uclibc.rs index b03dec5b5b6e8..d26a8c162e85e 100644 --- a/compiler/rustc_target/src/spec/targets/mips_unknown_linux_uclibc.rs +++ b/compiler/rustc_target/src/spec/targets/mips_unknown_linux_uclibc.rs @@ -1,6 +1,6 @@ use rustc_abi::Endian; -use crate::spec::{Arch, LlvmAbi, Target, TargetMetadata, TargetOptions, base}; +use crate::spec::{Arch, LlvmAbi, Target, TargetMetadata, TargetOptions, base, cvs}; pub(crate) fn target() -> Target { Target { @@ -19,6 +19,7 @@ pub(crate) fn target() -> Target { cpu: "mips32r2".into(), features: "+mips32r2,+soft-float".into(), llvm_abiname: LlvmAbi::O32, + llvm_args: cvs!["-mno-check-zero-division"], max_atomic_width: Some(32), mcount: "_mcount".into(), diff --git a/compiler/rustc_target/src/spec/targets/mipsel_mti_none_elf.rs b/compiler/rustc_target/src/spec/targets/mipsel_mti_none_elf.rs index ce50cedef99ff..c702dbc6c8243 100644 --- a/compiler/rustc_target/src/spec/targets/mipsel_mti_none_elf.rs +++ b/compiler/rustc_target/src/spec/targets/mipsel_mti_none_elf.rs @@ -2,7 +2,7 @@ use rustc_abi::Endian; use crate::spec::{ Arch, Cc, LinkerFlavor, Lld, LlvmAbi, PanicStrategy, RelocModel, Target, TargetMetadata, - TargetOptions, + TargetOptions, cvs, }; pub(crate) fn target() -> Target { @@ -26,6 +26,7 @@ pub(crate) fn target() -> Target { cpu: "mips32r2".into(), llvm_abiname: LlvmAbi::O32, + llvm_args: cvs!["-mno-check-zero-division"], max_atomic_width: Some(32), features: "+mips32r2,+soft-float,+noabicalls".into(), diff --git a/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_gnu.rs index 0541e0e9b2c5d..085f36c70a633 100644 --- a/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_gnu.rs @@ -1,4 +1,4 @@ -use crate::spec::{Arch, LlvmAbi, Target, TargetMetadata, TargetOptions, base}; +use crate::spec::{Arch, LlvmAbi, Target, TargetMetadata, TargetOptions, base, cvs}; pub(crate) fn target() -> Target { Target { @@ -17,6 +17,7 @@ pub(crate) fn target() -> Target { cpu: "mips32r2".into(), features: "+mips32r2,+fpxx,+nooddspreg".into(), llvm_abiname: LlvmAbi::O32, + llvm_args: cvs!["-mno-check-zero-division"], max_atomic_width: Some(32), mcount: "_mcount".into(), diff --git a/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_musl.rs index 5d0136a6699a7..c94f2fd87e589 100644 --- a/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_musl.rs @@ -1,4 +1,4 @@ -use crate::spec::{Arch, LlvmAbi, Target, TargetMetadata, TargetOptions, base}; +use crate::spec::{Arch, LlvmAbi, Target, TargetMetadata, TargetOptions, base, cvs}; pub(crate) fn target() -> Target { let mut base = base::linux_musl::opts(); @@ -16,6 +16,11 @@ pub(crate) fn target() -> Target { pointer_width: 32, data_layout: "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".into(), arch: Arch::Mips, - options: TargetOptions { llvm_abiname: LlvmAbi::O32, mcount: "_mcount".into(), ..base }, + options: TargetOptions { + llvm_abiname: LlvmAbi::O32, + llvm_args: cvs!["-mno-check-zero-division"], + mcount: "_mcount".into(), + ..base + }, } } diff --git a/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_uclibc.rs b/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_uclibc.rs index 0add21bfc9c65..7b93f0e0ce433 100644 --- a/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_uclibc.rs +++ b/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_uclibc.rs @@ -1,4 +1,4 @@ -use crate::spec::{Arch, LlvmAbi, Target, TargetMetadata, TargetOptions, base}; +use crate::spec::{Arch, LlvmAbi, Target, TargetMetadata, TargetOptions, base, cvs}; pub(crate) fn target() -> Target { Target { @@ -17,6 +17,7 @@ pub(crate) fn target() -> Target { cpu: "mips32r2".into(), features: "+mips32r2,+soft-float".into(), llvm_abiname: LlvmAbi::O32, + llvm_args: cvs!["-mno-check-zero-division"], max_atomic_width: Some(32), mcount: "_mcount".into(), diff --git a/compiler/rustc_target/src/spec/targets/mipsel_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/mipsel_unknown_netbsd.rs index 5395c15ad5813..f765409eb6d9c 100644 --- a/compiler/rustc_target/src/spec/targets/mipsel_unknown_netbsd.rs +++ b/compiler/rustc_target/src/spec/targets/mipsel_unknown_netbsd.rs @@ -1,6 +1,6 @@ use rustc_abi::Endian; -use crate::spec::{Arch, LlvmAbi, Target, TargetMetadata, TargetOptions, base}; +use crate::spec::{Arch, LlvmAbi, Target, TargetMetadata, TargetOptions, base, cvs}; pub(crate) fn target() -> Target { let mut base = base::netbsd::opts(); @@ -21,6 +21,7 @@ pub(crate) fn target() -> Target { options: TargetOptions { features: "+soft-float".into(), llvm_abiname: LlvmAbi::O32, + llvm_args: cvs!["-mno-check-zero-division"], mcount: "__mcount".into(), endian: Endian::Little, ..base diff --git a/compiler/rustc_target/src/spec/targets/mipsel_unknown_none.rs b/compiler/rustc_target/src/spec/targets/mipsel_unknown_none.rs index 0e184c8348016..e99092a5c6c27 100644 --- a/compiler/rustc_target/src/spec/targets/mipsel_unknown_none.rs +++ b/compiler/rustc_target/src/spec/targets/mipsel_unknown_none.rs @@ -4,7 +4,7 @@ use crate::spec::{ Arch, Cc, LinkerFlavor, Lld, LlvmAbi, PanicStrategy, RelocModel, Target, TargetMetadata, - TargetOptions, + TargetOptions, cvs, }; pub(crate) fn target() -> Target { @@ -25,6 +25,7 @@ pub(crate) fn target() -> Target { cpu: "mips32r2".into(), features: "+mips32r2,+soft-float,+noabicalls".into(), llvm_abiname: LlvmAbi::O32, + llvm_args: cvs!["-mno-check-zero-division"], max_atomic_width: Some(32), linker: Some("rust-lld".into()), panic_strategy: PanicStrategy::Abort, diff --git a/compiler/rustc_target/src/spec/targets/mipsisa32r6_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/mipsisa32r6_unknown_linux_gnu.rs index 80916500a4310..276d25432b6cb 100644 --- a/compiler/rustc_target/src/spec/targets/mipsisa32r6_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/mipsisa32r6_unknown_linux_gnu.rs @@ -1,6 +1,6 @@ use rustc_abi::Endian; -use crate::spec::{Arch, LlvmAbi, Target, TargetMetadata, TargetOptions, base}; +use crate::spec::{Arch, LlvmAbi, Target, TargetMetadata, TargetOptions, base, cvs}; pub(crate) fn target() -> Target { Target { @@ -19,6 +19,7 @@ pub(crate) fn target() -> Target { cpu: "mips32r6".into(), features: "+mips32r6".into(), llvm_abiname: LlvmAbi::O32, + llvm_args: cvs!["-mno-check-zero-division"], max_atomic_width: Some(32), mcount: "_mcount".into(), diff --git a/compiler/rustc_target/src/spec/targets/mipsisa32r6el_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/mipsisa32r6el_unknown_linux_gnu.rs index 87db5a2828729..0de12904d9e02 100644 --- a/compiler/rustc_target/src/spec/targets/mipsisa32r6el_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/mipsisa32r6el_unknown_linux_gnu.rs @@ -1,4 +1,4 @@ -use crate::spec::{Arch, LlvmAbi, Target, TargetMetadata, TargetOptions, base}; +use crate::spec::{Arch, LlvmAbi, Target, TargetMetadata, TargetOptions, base, cvs}; pub(crate) fn target() -> Target { Target { @@ -17,6 +17,7 @@ pub(crate) fn target() -> Target { cpu: "mips32r6".into(), features: "+mips32r6".into(), llvm_abiname: LlvmAbi::O32, + llvm_args: cvs!["-mno-check-zero-division"], max_atomic_width: Some(32), mcount: "_mcount".into(), diff --git a/compiler/rustc_target/src/spec/targets/mipsisa64r6_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/targets/mipsisa64r6_unknown_linux_gnuabi64.rs index 8e66407470a25..88e3ab6d9fc39 100644 --- a/compiler/rustc_target/src/spec/targets/mipsisa64r6_unknown_linux_gnuabi64.rs +++ b/compiler/rustc_target/src/spec/targets/mipsisa64r6_unknown_linux_gnuabi64.rs @@ -1,6 +1,6 @@ use rustc_abi::Endian; -use crate::spec::{Arch, CfgAbi, LlvmAbi, Target, TargetMetadata, TargetOptions, base}; +use crate::spec::{Arch, CfgAbi, LlvmAbi, Target, TargetMetadata, TargetOptions, base, cvs}; pub(crate) fn target() -> Target { Target { @@ -23,6 +23,7 @@ pub(crate) fn target() -> Target { max_atomic_width: Some(64), mcount: "_mcount".into(), llvm_abiname: LlvmAbi::N64, + llvm_args: cvs!["-mno-check-zero-division"], ..base::linux_gnu::opts() }, diff --git a/compiler/rustc_target/src/spec/targets/mipsisa64r6el_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/targets/mipsisa64r6el_unknown_linux_gnuabi64.rs index 5523f4470bd57..01046de7aa14b 100644 --- a/compiler/rustc_target/src/spec/targets/mipsisa64r6el_unknown_linux_gnuabi64.rs +++ b/compiler/rustc_target/src/spec/targets/mipsisa64r6el_unknown_linux_gnuabi64.rs @@ -1,4 +1,4 @@ -use crate::spec::{Arch, CfgAbi, LlvmAbi, Target, TargetMetadata, TargetOptions, base}; +use crate::spec::{Arch, CfgAbi, LlvmAbi, Target, TargetMetadata, TargetOptions, base, cvs}; pub(crate) fn target() -> Target { Target { @@ -20,6 +20,7 @@ pub(crate) fn target() -> Target { max_atomic_width: Some(64), mcount: "_mcount".into(), llvm_abiname: LlvmAbi::N64, + llvm_args: cvs!["-mno-check-zero-division"], ..base::linux_gnu::opts() }, diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs index ad9ac989c6c7f..99594d68e7428 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs @@ -296,7 +296,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let obligation = Obligation::new(tcx, ObligationCause::dummy(), param_env, ty::Binder::dummy(trait_ref)); - let applicable_impls = compute_applicable_impls_for_diagnostics(self.infcx, &obligation); + let applicable_impls = + compute_applicable_impls_for_diagnostics(self.infcx, &obligation, false); for candidate in applicable_impls { let impl_def_id = match candidate { diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs index 31bd3b32e76d8..e4a2aaff86aed 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs @@ -332,7 +332,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { leading_ellipsis, ); - self.tcx().dcx().create_err(TraitPlaceholderMismatch { + let mut err = self.tcx().dcx().create_err(TraitPlaceholderMismatch { span, satisfy_span, where_span, @@ -340,7 +340,46 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { def_id, trait_def_id: self.tcx().def_path_str(trait_def_id), actual_impl_expl_notes, - }) + }); + + let mut current_code = cause.code(); + let mut coroutine_def_id = None; + + loop { + match current_code { + ObligationCauseCode::MatchImpl(inner_cause, _) => { + current_code = inner_cause.code(); + } + ObligationCauseCode::BuiltinDerived(derived) => { + let self_ty = derived.parent_trait_pred.skip_binder().self_ty(); + + if let ty::Coroutine(def_id, _) | ty::CoroutineWitness(def_id, _) = + self_ty.kind() + { + coroutine_def_id = Some(*def_id); + break; + } + + current_code = &derived.parent_code; + } + _ => break, + } + } + + if let Some(def_id) = coroutine_def_id { + if self.tcx().trait_is_auto(trait_def_id) { + let c_span = self.tcx().def_span(def_id); + let descr = self.tcx().def_descr(def_id); + let trait_name = self.tcx().def_path_str(trait_def_id); + + err.span_label( + c_span, + format!("this {descr} captures a value whose type is not `{trait_name}`"), + ); + } + } + + err } /// Add notes with details about the expected and actual trait refs, with attention to cases diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs index 318808ffc69d9..ead68eddf2b9d 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs @@ -32,6 +32,7 @@ pub enum CandidateSource { pub fn compute_applicable_impls_for_diagnostics<'tcx>( infcx: &InferCtxt<'tcx>, obligation: &PolyTraitObligation<'tcx>, + ignore_predicates_of_impls: bool, ) -> Vec { let tcx = infcx.tcx; let param_env = obligation.param_env; @@ -71,26 +72,28 @@ pub fn compute_applicable_impls_for_diagnostics<'tcx>( _ => return false, } - let obligations = tcx - .predicates_of(impl_def_id) - .instantiate(tcx, impl_args) - .into_iter() - .map(|(predicate, _)| { - Obligation::new( - tcx, - ObligationCause::dummy(), - param_env, - predicate.skip_norm_wip(), - ) - }) - // Kinda hacky, but let's just throw away obligations that overflow. - // This may reduce the accuracy of this check (if the obligation guides - // inference or it actually resulted in error after others are processed) - // ... but this is diagnostics code. - .filter(|obligation| { - infcx.next_trait_solver() || infcx.evaluate_obligation(obligation).is_ok() - }); - ocx.register_obligations(obligations); + if !ignore_predicates_of_impls { + let obligations = tcx + .predicates_of(impl_def_id) + .instantiate(tcx, impl_args) + .into_iter() + .map(|(predicate, _)| { + Obligation::new( + tcx, + ObligationCause::dummy(), + param_env, + predicate.skip_norm_wip(), + ) + }) + // Kinda hacky, but let's just throw away obligations that overflow. + // This may reduce the accuracy of this check (if the obligation guides + // inference or it actually resulted in error after others are processed) + // ... but this is diagnostics code. + .filter(|obligation| { + infcx.next_trait_solver() || infcx.evaluate_obligation(obligation).is_ok() + }); + ocx.register_obligations(obligations); + } ocx.try_evaluate_obligations().is_empty() }) @@ -306,6 +309,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let mut ambiguities = compute_applicable_impls_for_diagnostics( self.infcx, &obligation.with(self.tcx, trait_pred), + false, ); let has_non_region_infer = trait_pred .skip_binder() 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 0849215c13404..c3f4a09b2d431 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -3571,7 +3571,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } let mut a = "a"; - let mut this = "this bound"; + let mut this = "this bound".to_owned(); let mut note = None; let mut help = None; if let ty::PredicateKind::Clause(clause) = predicate.kind().skip_binder() { @@ -3598,16 +3598,14 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { tcx.visible_parent_map(()).get(&def_id).is_some() }; if tcx.is_lang_item(def_id, LangItem::Sized) { - // Check if this is an implicit bound, even in foreign crates. - if tcx - .generics_of(item_def_id) - .own_params - .iter() - .any(|param| tcx.def_span(param.def_id) == span) + if let Some(DesugaringKind::DefaultBound { def }) = + span.desugaring_kind() { a = "an implicit `Sized`"; - this = - "the implicit `Sized` requirement on this type parameter"; + this = format!( + "the implicit `Sized` requirement on this {}", + tcx.def_kind(def).descr(def) + ); } if let Some(hir::Node::TraitItem(hir::TraitItem { generics, @@ -4217,12 +4215,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // implicit, mention it as such. if let Some(pred) = predicate.as_trait_clause() && self.tcx.is_lang_item(pred.def_id(), LangItem::Sized) - && self - .tcx - .generics_of(data.impl_or_alias_def_id) - .own_params - .iter() - .any(|param| self.tcx.def_span(param.def_id) == data.span) + && let Some(DesugaringKind::DefaultBound { .. }) = + data.span.desugaring_kind() { spans.push_span_label( data.span, @@ -5912,7 +5906,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let sized_trait = self.tcx.lang_items().sized_trait(); debug!(?generics.params); debug!(?generics.predicates); - let Some(param) = generics.params.iter().find(|param| param.span == span) else { + let Some(DesugaringKind::DefaultBound { def }) = span.desugaring_kind() else { + return; + }; + let Some(param) = generics.params.iter().find(|param| param.def_id.to_def_id() == def) + else { return; }; // Check that none of the explicit trait bounds is `Sized`. Assume that an explicit diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs index b3a33b775ad10..2955aff10eb6a 100644 --- a/compiler/rustc_type_ir/src/const_kind.rs +++ b/compiler/rustc_type_ir/src/const_kind.rs @@ -9,7 +9,7 @@ use rustc_type_ir_macros::{ GenericTypeVisitable, Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic, }; -use crate::{self as ty, BoundVarIndexKind, Interner}; +use crate::{self as ty, BoundVarIndexKind, Interner, UnevaluatedConst}; /// Represents a constant in Rust. #[derive_where(Clone, Copy, Hash, PartialEq; I: Interner)] @@ -67,26 +67,6 @@ impl fmt::Debug for ConstKind { } } -/// An unevaluated (potentially generic) constant used in the type-system. -#[derive_where(Clone, Copy, Debug, Hash, PartialEq; I: Interner)] -#[derive(TypeVisitable_Generic, GenericTypeVisitable, TypeFoldable_Generic, Lift_Generic)] -#[cfg_attr( - feature = "nightly", - derive(Decodable_NoContext, Encodable_NoContext, StableHash_NoContext) -)] -pub struct UnevaluatedConst { - #[type_foldable(identity)] - #[type_visitable(ignore)] - pub kind: UnevaluatedConstKind, - pub args: I::GenericArgs, - - /// This field exists to prevent the creation of `UnevaluatedConst` without using [`UnevaluatedConst::new`]. - #[derive_where(skip(Debug))] - pub(crate) _use_unevaluated_const_new_instead: (), -} - -impl Eq for UnevaluatedConst {} - impl UnevaluatedConst { #[inline] pub fn new( @@ -103,7 +83,7 @@ impl UnevaluatedConst { }; interner.debug_assert_args_compatible(def_id, args); } - UnevaluatedConst { kind, args, _use_unevaluated_const_new_instead: () } + UnevaluatedConst { kind, args, _use_alias_new_instead: () } } pub fn type_of(self, interner: I) -> ty::Unnormalized { @@ -121,7 +101,7 @@ impl UnevaluatedConst { /// and handled in very similar ways. The documentation for AliasTyKind/etc. may be helpful when /// learning about UnevaluatedConstKind. #[derive_where(Clone, Copy, Hash, PartialEq, Debug; I: Interner)] -#[derive(GenericTypeVisitable, Lift_Generic)] +#[derive(TypeVisitable_Generic, GenericTypeVisitable, TypeFoldable_Generic, Lift_Generic)] #[cfg_attr( feature = "nightly", derive(Encodable_NoContext, Decodable_NoContext, StableHash_NoContext) diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index d9906795dfba6..82fa72825d4d4 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -52,6 +52,7 @@ mod pattern; mod predicate; mod predicate_kind; mod region_kind; +mod ty; mod ty_info; mod ty_kind; mod unnormalized; @@ -80,6 +81,7 @@ pub use predicate_kind::*; pub use region_kind::*; pub use rustc_ast_ir::{FloatTy, IntTy, Movability, Mutability, Pinnedness, UintTy}; use rustc_type_ir_macros::GenericTypeVisitable; +pub use ty::{Alias, AliasTerm, AliasTy, UnevaluatedConst}; pub use ty_info::*; pub use ty_kind::*; pub use unnormalized::Unnormalized; diff --git a/compiler/rustc_type_ir/src/predicate.rs b/compiler/rustc_type_ir/src/predicate.rs index a7f7c2fa44358..1a07010442ab4 100644 --- a/compiler/rustc_type_ir/src/predicate.rs +++ b/compiler/rustc_type_ir/src/predicate.rs @@ -9,9 +9,10 @@ use rustc_type_ir_macros::{ }; use crate::inherent::*; +use crate::ty::AliasTerm; use crate::upcast::{Upcast, UpcastFrom}; use crate::visit::TypeVisitableExt as _; -use crate::{self as ty, AliasTyKind, Interner, UnevaluatedConstKind}; +use crate::{self as ty, Alias, AliasTyKind, Interner, UnevaluatedConstKind}; /// `A: 'region` #[derive_where(Clone, Hash, PartialEq, Debug; I: Interner, A)] @@ -537,7 +538,7 @@ impl ty::Binder> { } #[derive_where(Clone, Copy, PartialEq, Eq, Hash, Debug; I: Interner)] -#[derive(Lift_Generic, TypeVisitable_Generic, GenericTypeVisitable)] +#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic, GenericTypeVisitable)] #[cfg_attr( feature = "nightly", derive(Encodable_NoContext, Decodable_NoContext, StableHash_NoContext) @@ -640,41 +641,6 @@ impl From> for AliasTermKind { } } -/// Represents the unprojected term of a projection goal. -/// -/// * For a projection, this would be `>::N<...>`. -/// * For an inherent projection, this would be `Ty::N<...>`. -/// * For an opaque type, there is no explicit syntax. -#[derive_where(Clone, Copy, Hash, PartialEq, Debug; I: Interner)] -#[derive(TypeVisitable_Generic, GenericTypeVisitable, TypeFoldable_Generic, Lift_Generic)] -#[cfg_attr( - feature = "nightly", - derive(Decodable_NoContext, Encodable_NoContext, StableHash_NoContext) -)] -pub struct AliasTerm { - /// The parameters of the associated or opaque item. - /// - /// For a projection, these are the generic parameters for the trait and the - /// GAT parameters, if there are any. - /// - /// For an inherent projection, they consist of the self type and the GAT parameters, - /// if there are any. - /// - /// For RPIT the generic parameters are for the generics of the function, - /// while for TAIT it is used for the generic parameters of the alias. - pub args: I::GenericArgs, - - #[type_foldable(identity)] - #[type_visitable(ignore)] - pub kind: AliasTermKind, - - /// This field exists to prevent the creation of `AliasTerm` without using [`AliasTerm::new_from_args`]. - #[derive_where(skip(Debug))] - _use_alias_term_new_instead: (), -} - -impl Eq for AliasTerm {} - impl AliasTerm { pub fn new_from_args( interner: I, @@ -694,7 +660,7 @@ impl AliasTerm { }; interner.debug_assert_args_compatible(def_id, args); } - AliasTerm { kind, args, _use_alias_term_new_instead: () } + AliasTerm { kind, args, _use_alias_new_instead: () } } pub fn new( @@ -724,7 +690,7 @@ impl AliasTerm { panic!("Cannot turn `{}` into `AliasTy`", kind.descr()) } }; - ty::AliasTy { kind, args: self.args, _use_alias_ty_new_instead: () } + ty::AliasTy { kind, args: self.args, _use_alias_new_instead: () } } pub fn expect_ct(self) -> ty::UnevaluatedConst { @@ -742,7 +708,7 @@ impl AliasTerm { panic!("Cannot turn `{}` into `UnevaluatedConst`", kind.descr()) } }; - ty::UnevaluatedConst { kind, args: self.args, _use_unevaluated_const_new_instead: () } + ty::UnevaluatedConst { kind, args: self.args, _use_alias_new_instead: () } } pub fn to_term(self, interner: I) -> I::Term { @@ -897,21 +863,13 @@ impl AliasTerm { impl From> for AliasTerm { fn from(ty: ty::AliasTy) -> Self { - AliasTerm { - args: ty.args, - kind: AliasTermKind::from(ty.kind), - _use_alias_term_new_instead: (), - } + AliasTerm { args: ty.args, kind: AliasTermKind::from(ty.kind), _use_alias_new_instead: () } } } impl From> for AliasTerm { fn from(ty: ty::UnevaluatedConst) -> Self { - AliasTerm { - args: ty.args, - kind: AliasTermKind::from(ty.kind), - _use_alias_term_new_instead: (), - } + AliasTerm { args: ty.args, kind: AliasTermKind::from(ty.kind), _use_alias_new_instead: () } } } @@ -990,19 +948,17 @@ impl fmt::Debug for ProjectionPredicate { /// Used by the new solver to normalize an alias. This always expects the `term` to /// be an unconstrained inference variable which is used as the output. -#[derive_where(Clone, Copy, Hash, PartialEq; I: Interner)] +#[derive_where(Clone, Copy, Hash, Eq, PartialEq; I: Interner, K)] #[derive(TypeVisitable_Generic, GenericTypeVisitable, TypeFoldable_Generic, Lift_Generic)] #[cfg_attr( feature = "nightly", derive(Decodable_NoContext, Encodable_NoContext, StableHash_NoContext) )] -pub struct NormalizesTo { - pub alias: AliasTerm, +pub struct NormalizesTo> { + pub alias: Alias, pub term: I::Term, } -impl Eq for NormalizesTo {} - impl NormalizesTo { pub fn self_ty(self) -> I::Ty { self.alias.self_ty() @@ -1017,7 +973,13 @@ impl NormalizesTo { } } -impl fmt::Debug for NormalizesTo { +impl fmt::Debug for NormalizesTo +where + // `TypeVisitable_Generic` derived on `NormalizesTo` creates a field-level + // `Alias: TypeVisitable` bound. Since `TypeVisitable: fmt::Debug`, + // that proves `Alias: fmt::Debug`, but not `K: fmt::Debug`. + Alias: fmt::Debug, +{ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "NormalizesTo({:?}, {:?})", self.alias, self.term) } diff --git a/compiler/rustc_type_ir/src/ty/alias.rs b/compiler/rustc_type_ir/src/ty/alias.rs new file mode 100644 index 0000000000000..d61c2f2ca7ff7 --- /dev/null +++ b/compiler/rustc_type_ir/src/ty/alias.rs @@ -0,0 +1,56 @@ +use derive_where::derive_where; +#[cfg(feature = "nightly")] +use rustc_macros::{Decodable_NoContext, Encodable_NoContext, StableHash_NoContext}; +use rustc_type_ir_macros::{ + GenericTypeVisitable, Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic, +}; + +use crate::predicate::AliasTermKind; +use crate::ty_kind::AliasTyKind; +use crate::{Interner, UnevaluatedConstKind}; + +/// Represents an alias of a type, constant, or other term-like item. +/// +/// * For a projection, this would be `>::N<...>`. +/// * For an inherent projection, this would be `Ty::N<...>`. +/// * For an opaque type, there is no explicit syntax. +#[derive_where(Clone, Copy, Hash, PartialEq, Debug; I: Interner, K)] +#[derive(TypeVisitable_Generic, GenericTypeVisitable, TypeFoldable_Generic, Lift_Generic)] +#[cfg_attr( + feature = "nightly", + derive(Decodable_NoContext, Encodable_NoContext, StableHash_NoContext) +)] +pub struct Alias { + pub kind: K, + + /// The parameters of the associated, opaque, or constant alias. + /// + /// For a projection, these are the generic parameters for the trait and the + /// GAT parameters, if there are any. + /// + /// For an inherent projection, they consist of the self type and the GAT parameters, + /// if there are any. + /// + /// For RPIT the generic parameters are for the generics of the function, + /// while for TAIT it is used for the generic parameters of the alias. + pub args: I::GenericArgs, + + /// This field exists to prevent the creation of `Alias` without using the relevant constructor. + #[derive_where(skip(Debug))] + #[type_visitable(ignore)] + #[type_foldable(identity)] + #[lift(identity)] + pub(crate) _use_alias_new_instead: (), +} + +impl Eq for Alias {} + +impl Alias { + pub fn kind(self, _interner: I) -> K { + self.kind + } +} + +pub type AliasTerm = Alias>; +pub type AliasTy = Alias>; +pub type UnevaluatedConst = Alias>; diff --git a/compiler/rustc_type_ir/src/ty/mod.rs b/compiler/rustc_type_ir/src/ty/mod.rs new file mode 100644 index 0000000000000..fec25193513c0 --- /dev/null +++ b/compiler/rustc_type_ir/src/ty/mod.rs @@ -0,0 +1,3 @@ +mod alias; + +pub use alias::{Alias, AliasTerm, AliasTy, UnevaluatedConst}; diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index 784a91424156f..c3d52f4a191ac 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -17,6 +17,7 @@ use rustc_type_ir_macros::{ use self::TyKind::*; pub use self::closure::*; use crate::inherent::*; +use crate::ty::AliasTy; #[cfg(feature = "nightly")] use crate::visit::TypeVisitable; use crate::{self as ty, BoundVarIndexKind, FloatTy, IntTy, Interner, UintTy}; @@ -24,7 +25,7 @@ use crate::{self as ty, BoundVarIndexKind, FloatTy, IntTy, Interner, UintTy}; mod closure; #[derive_where(Clone, Copy, Hash, PartialEq, Debug; I: Interner)] -#[derive(GenericTypeVisitable, Lift_Generic)] +#[derive(TypeVisitable_Generic, GenericTypeVisitable, TypeFoldable_Generic, Lift_Generic)] #[cfg_attr( feature = "nightly", derive(Encodable_NoContext, Decodable_NoContext, StableHash_NoContext) @@ -427,45 +428,10 @@ impl fmt::Debug for TyKind { } } -/// Represents the projection of an associated, opaque, or lazy-type-alias type. -/// -/// * For a projection, this would be `>::N<...>`. -/// * For an inherent projection, this would be `Ty::N<...>`. -/// * For an opaque type, there is no explicit syntax. -#[derive_where(Clone, Copy, Hash, PartialEq, Debug; I: Interner)] -#[derive(TypeVisitable_Generic, GenericTypeVisitable, TypeFoldable_Generic, Lift_Generic)] -#[cfg_attr( - feature = "nightly", - derive(Decodable_NoContext, Encodable_NoContext, StableHash_NoContext) -)] -pub struct AliasTy { - /// The parameters of the associated or opaque type. - /// - /// For a projection, these are the generic parameters for the trait and the - /// GAT parameters, if there are any. - /// - /// For an inherent projection, they consist of the self type and the GAT parameters, - /// if there are any. - /// - /// For RPIT the generic parameters are for the generics of the function, - /// while for TAIT it is used for the generic parameters of the alias. - pub args: I::GenericArgs, - - #[type_foldable(identity)] - #[type_visitable(ignore)] - pub kind: AliasTyKind, - - /// This field exists to prevent the creation of `AliasTy` without using [`AliasTy::new_from_args`]. - #[derive_where(skip(Debug))] - pub(crate) _use_alias_ty_new_instead: (), -} - -impl Eq for AliasTy {} - impl AliasTy { pub fn new_from_args(interner: I, kind: AliasTyKind, args: I::GenericArgs) -> AliasTy { interner.debug_assert_args_compatible(kind.def_id(), args); - AliasTy { kind, args, _use_alias_ty_new_instead: () } + AliasTy { kind, args, _use_alias_new_instead: () } } pub fn new( diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index f66dc648f809b..b0e8039263ffe 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -105,6 +105,7 @@ #![feature(const_convert)] #![feature(const_default)] #![feature(const_destruct)] +#![feature(const_drop_in_place)] #![feature(const_eval_select)] #![feature(const_heap)] #![feature(const_index)] diff --git a/library/alloc/src/raw_vec/mod.rs b/library/alloc/src/raw_vec/mod.rs index 2f7d26c7a9724..843d0346ff5de 100644 --- a/library/alloc/src/raw_vec/mod.rs +++ b/library/alloc/src/raw_vec/mod.rs @@ -417,7 +417,8 @@ impl RawVec { } } -unsafe impl<#[may_dangle] T, A: Allocator> Drop for RawVec { +#[rustc_const_unstable(feature = "const_heap", issue = "79597")] +const unsafe impl<#[may_dangle] T, A: [const] Allocator + [const] Destruct> Drop for RawVec { /// Frees the memory owned by the `RawVec` *without* trying to drop its contents. fn drop(&mut self) { // SAFETY: We are in a Drop impl, self.inner will not be used again. @@ -861,7 +862,10 @@ impl RawVecInner { } Ok(()) } +} +#[rustc_const_unstable(feature = "const_heap", issue = "79597")] +const impl RawVecInner { /// # Safety /// /// This function deallocates the owned allocation, but does not update `ptr` or `cap` to diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 3e03acab6a701..b37f865020fd9 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -79,9 +79,7 @@ use core::cmp::Ordering; use core::hash::{Hash, Hasher}; #[cfg(not(no_global_oom_handling))] use core::iter; -#[cfg(not(no_global_oom_handling))] -use core::marker::Destruct; -use core::marker::{Freeze, PhantomData}; +use core::marker::{Destruct, Freeze, PhantomData}; use core::mem::{self, Assume, ManuallyDrop, MaybeUninit, SizedTypeProperties, TransmuteFrom}; use core::ops::{self, Index, IndexMut, Range, RangeBounds}; use core::ptr::{self, NonNull}; @@ -2218,7 +2216,8 @@ impl Vec { /// [`spare_capacity_mut()`]: Vec::spare_capacity_mut #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub unsafe fn set_len(&mut self, new_len: usize) { + #[rustc_const_unstable(feature = "const_heap", issue = "79597")] + pub const unsafe fn set_len(&mut self, new_len: usize) { ub_checks::assert_unsafe_precondition!( check_library_ub, "Vec::set_len requires that new_len <= capacity()", @@ -4288,7 +4287,10 @@ impl Ord for Vec { } #[stable(feature = "rust1", since = "1.0.0")] -unsafe impl<#[may_dangle] T, A: Allocator> Drop for Vec { +#[rustc_const_unstable(feature = "const_heap", issue = "79597")] +const unsafe impl<#[may_dangle] T: [const] Destruct, A: [const] Allocator + [const] Destruct> Drop + for Vec +{ fn drop(&mut self) { unsafe { // use drop for [T] @@ -4507,7 +4509,10 @@ impl From<&str> for Vec { } #[stable(feature = "array_try_from_vec", since = "1.48.0")] -impl TryFrom> for [T; N] { +#[rustc_const_unstable(feature = "const_convert", issue = "143773")] +const impl + TryFrom> for [T; N] +{ type Error = Vec; /// Gets the entire contents of the `Vec` as an array, diff --git a/src/doc/unstable-book/src/compiler-flags/lint-rust-version.md b/src/doc/unstable-book/src/compiler-flags/lint-rust-version.md new file mode 100644 index 0000000000000..ecc0e7fba6350 --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/lint-rust-version.md @@ -0,0 +1,9 @@ +# `lint-rust-version` + +The tracking issue for this feature is: [#157574](https://github.com/rust-lang/rust/issues/157574). + +------------------------ + +This feature allows you to specify a minimum Rust version for the crate, which will affect lint +emission. If following a lint suggestion would raise the MSRV above the provided value, it should +not be emitted. diff --git a/src/doc/unstable-book/src/compiler-flags/staticlib-rename-internal-symbols.md b/src/doc/unstable-book/src/compiler-flags/staticlib-rename-internal-symbols.md new file mode 100644 index 0000000000000..f25a45ae7efc9 --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/staticlib-rename-internal-symbols.md @@ -0,0 +1,19 @@ +# `staticlib-rename-internal-symbols` + +When building a `staticlib`, this option renames all non-exported Rust-internal +symbols by appending a `_rs{hash}` suffix. This prevents symbol collisions when +multiple Rust static libraries are linked into the same final binary. + +This option only renames symbols; it does not change their visibility. +Use `-Zstaticlib-hide-internal-symbols` in addition if you also want to hide +internal symbols. + +Only symbols explicitly exported via `#[no_mangle]` or `#[export_name]` are left +unchanged. All other `GLOBAL`/`WEAK` symbols (including `pub(crate)` and `pub` +items without `#[no_mangle]`) are renamed. + +This option can only be used with `--crate-type staticlib`. Using it with +other crate types will result in a compilation warning. + +Supported on ELF targets (Linux, BSD, etc.) and Apple targets (macOS, iOS, etc.). +On unsupported targets (Windows), a warning is emitted and the flag has no effect. diff --git a/tests/assembly-llvm/mips-div-no-trap.rs b/tests/assembly-llvm/mips-div-no-trap.rs new file mode 100644 index 0000000000000..cb3d710846159 --- /dev/null +++ b/tests/assembly-llvm/mips-div-no-trap.rs @@ -0,0 +1,120 @@ +// Test that there's no conditional trap for zero divisor for all mips +// targets. Division by zero is defined as panic so the trap is redundant. +// +//@ add-minicore +//@ assembly-output: emit-asm +// +//@ revisions: mips64el-unknown-linux-gnuabi64 +//@[mips64el-unknown-linux-gnuabi64] compile-flags: --target=mips64el-unknown-linux-gnuabi64 +//@[mips64el-unknown-linux-gnuabi64] needs-llvm-components: mips +//@[mips64el-unknown-linux-gnuabi64] filecheck-flags: --check-prefix NOTRAP +//@ revisions: mips64el-unknown-linux-muslabi64 +//@[mips64el-unknown-linux-muslabi64] compile-flags: --target=mips64el-unknown-linux-muslabi64 +//@[mips64el-unknown-linux-muslabi64] needs-llvm-components: mips +//@[mips64el-unknown-linux-muslabi64] filecheck-flags: --check-prefix NOTRAP +//@ revisions: mips64-openwrt-linux-musl +//@[mips64-openwrt-linux-musl] compile-flags: --target=mips64-openwrt-linux-musl +//@[mips64-openwrt-linux-musl] needs-llvm-components: mips +//@[mips64-openwrt-linux-musl] filecheck-flags: --check-prefix NOTRAP +//@ revisions: mips64-unknown-linux-gnuabi64 +//@[mips64-unknown-linux-gnuabi64] compile-flags: --target=mips64-unknown-linux-gnuabi64 +//@[mips64-unknown-linux-gnuabi64] needs-llvm-components: mips +//@[mips64-unknown-linux-gnuabi64] filecheck-flags: --check-prefix NOTRAP +//@ revisions: mips64-unknown-linux-muslabi64 +//@[mips64-unknown-linux-muslabi64] compile-flags: --target=mips64-unknown-linux-muslabi64 +//@[mips64-unknown-linux-muslabi64] needs-llvm-components: mips +//@[mips64-unknown-linux-muslabi64] filecheck-flags: --check-prefix NOTRAP +//@ revisions: mipsel-mti-none-elf +//@[mipsel-mti-none-elf] compile-flags: --target=mipsel-mti-none-elf +//@[mipsel-mti-none-elf] needs-llvm-components: mips +//@[mipsel-mti-none-elf] filecheck-flags: --check-prefix NOTRAP +//@ revisions: mipsel-sony-psp +//@[mipsel-sony-psp] compile-flags: --target=mipsel-sony-psp +//@[mipsel-sony-psp] needs-llvm-components: mips +//@[mipsel-sony-psp] filecheck-flags: --check-prefix NOTRAP +//@ revisions: mipsel-sony-psx +//@[mipsel-sony-psx] compile-flags: --target=mipsel-sony-psx +//@[mipsel-sony-psx] needs-llvm-components: mips +//@[mipsel-sony-psx] filecheck-flags: --check-prefix NOTRAP +//@ revisions: mipsel-unknown-linux-gnu +//@[mipsel-unknown-linux-gnu] compile-flags: --target=mipsel-unknown-linux-gnu +//@[mipsel-unknown-linux-gnu] needs-llvm-components: mips +//@[mipsel-unknown-linux-gnu] filecheck-flags: --check-prefix NOTRAP +//@ revisions: mipsel-unknown-linux-musl +//@[mipsel-unknown-linux-musl] compile-flags: --target=mipsel-unknown-linux-musl +//@[mipsel-unknown-linux-musl] needs-llvm-components: mips +//@[mipsel-unknown-linux-musl] filecheck-flags: --check-prefix NOTRAP +//@ revisions: mipsel-unknown-linux-uclibc +//@[mipsel-unknown-linux-uclibc] compile-flags: --target=mipsel-unknown-linux-uclibc +//@[mipsel-unknown-linux-uclibc] needs-llvm-components: mips +//@[mipsel-unknown-linux-uclibc] filecheck-flags: --check-prefix NOTRAP +//@ revisions: mipsel-unknown-netbsd +//@[mipsel-unknown-netbsd] compile-flags: --target=mipsel-unknown-netbsd +//@[mipsel-unknown-netbsd] needs-llvm-components: mips +//@[mipsel-unknown-netbsd] filecheck-flags: --check-prefix NOTRAP +//@ revisions: mipsel-unknown-none +//@[mipsel-unknown-none] compile-flags: --target=mipsel-unknown-none +//@[mipsel-unknown-none] needs-llvm-components: mips +//@[mipsel-unknown-none] filecheck-flags: --check-prefix NOTRAP +//@ revisions: mipsisa32r6el-unknown-linux-gnu +//@[mipsisa32r6el-unknown-linux-gnu] compile-flags: --target=mipsisa32r6el-unknown-linux-gnu +//@[mipsisa32r6el-unknown-linux-gnu] needs-llvm-components: mips +//@[mipsisa32r6el-unknown-linux-gnu] filecheck-flags: --check-prefix NOTRAP +//@ revisions: mipsisa32r6-unknown-linux-gnu +//@[mipsisa32r6-unknown-linux-gnu] compile-flags: --target=mipsisa32r6-unknown-linux-gnu +//@[mipsisa32r6-unknown-linux-gnu] needs-llvm-components: mips +//@[mipsisa32r6-unknown-linux-gnu] filecheck-flags: --check-prefix NOTRAP +//@ revisions: mipsisa64r6el-unknown-linux-gnuabi64 +//@[mipsisa64r6el-unknown-linux-gnuabi64] compile-flags: --target=mipsisa64r6el-unknown-linux-gnuabi64 +//@[mipsisa64r6el-unknown-linux-gnuabi64] needs-llvm-components: mips +//@[mipsisa64r6el-unknown-linux-gnuabi64] filecheck-flags: --check-prefix NOTRAP +//@ revisions: mipsisa64r6-unknown-linux-gnuabi64 +//@[mipsisa64r6-unknown-linux-gnuabi64] compile-flags: --target=mipsisa64r6-unknown-linux-gnuabi64 +//@[mipsisa64r6-unknown-linux-gnuabi64] needs-llvm-components: mips +//@[mipsisa64r6-unknown-linux-gnuabi64] filecheck-flags: --check-prefix NOTRAP +//@ revisions: mips-mti-none-elf +//@[mips-mti-none-elf] compile-flags: --target=mips-mti-none-elf +//@[mips-mti-none-elf] needs-llvm-components: mips +//@[mips-mti-none-elf] filecheck-flags: --check-prefix NOTRAP +//@ revisions: mips-unknown-linux-gnu +//@[mips-unknown-linux-gnu] compile-flags: --target=mips-unknown-linux-gnu +//@[mips-unknown-linux-gnu] needs-llvm-components: mips +//@[mips-unknown-linux-gnu] filecheck-flags: --check-prefix NOTRAP +//@ revisions: mips-unknown-linux-musl +//@[mips-unknown-linux-musl] compile-flags: --target=mips-unknown-linux-musl +//@[mips-unknown-linux-musl] needs-llvm-components: mips +//@[mips-unknown-linux-musl] filecheck-flags: --check-prefix NOTRAP +//@ revisions: mips-unknown-linux-uclibc +//@[mips-unknown-linux-uclibc] compile-flags: --target=mips-unknown-linux-uclibc +//@[mips-unknown-linux-uclibc] needs-llvm-components: mips +//@[mips-unknown-linux-uclibc] filecheck-flags: --check-prefix NOTRAP +// +//@ revisions: TRAP +//@[TRAP] compile-flags: --target=mips64el-unknown-linux-gnuabi64 -C llvm-args=-mno-check-zero-division=0 +//@[TRAP] needs-llvm-components: mips + +#![crate_type = "lib"] +#![feature(no_core, intrinsics)] +#![no_core] + +extern crate minicore; + +#[rustc_intrinsic] +pub unsafe fn unchecked_div(x: T, y: T) -> T; + +#[rustc_intrinsic] +pub fn abort() -> !; + +// NOTRAP-NOT: teq +// TRAP: teq +#[no_mangle] +pub fn div_i32(a: i32, b: i32) -> i32 { + match a { + 0 => abort(), + -1 => match b { + -2147483648 => abort(), + _ => unsafe { unchecked_div(a, b) }, + }, + _ => unsafe { unchecked_div(a, b) }, + } +} diff --git a/tests/mir-opt/issue_99325.main.built.after.32bit.mir b/tests/mir-opt/issue_99325.main.built.after.32bit.mir index 29fdccf85aa00..14a14ffe377f2 100644 --- a/tests/mir-opt/issue_99325.main.built.after.32bit.mir +++ b/tests/mir-opt/issue_99325.main.built.after.32bit.mir @@ -2,7 +2,7 @@ | User Type Annotations | 0: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [&*b"AAAA"], user_self_ty: None }), max_universe: U0, var_kinds: [] }, span: $DIR/issue_99325.rs:13:16: 13:46, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} -| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [UnevaluatedConst { kind: Anon { def_id: DefId(0:8 ~ issue_99325[d56d]::main::{constant#1}) }, args: [], .. }], user_self_ty: None }), max_universe: U0, var_kinds: [] }, span: $DIR/issue_99325.rs:14:16: 14:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} +| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [Alias { kind: Anon { def_id: DefId(0:8 ~ issue_99325[d56d]::main::{constant#1}) }, args: [], .. }], user_self_ty: None }), max_universe: U0, var_kinds: [] }, span: $DIR/issue_99325.rs:14:16: 14:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} | fn main() -> () { let mut _0: (); diff --git a/tests/mir-opt/issue_99325.main.built.after.64bit.mir b/tests/mir-opt/issue_99325.main.built.after.64bit.mir index 29fdccf85aa00..14a14ffe377f2 100644 --- a/tests/mir-opt/issue_99325.main.built.after.64bit.mir +++ b/tests/mir-opt/issue_99325.main.built.after.64bit.mir @@ -2,7 +2,7 @@ | User Type Annotations | 0: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [&*b"AAAA"], user_self_ty: None }), max_universe: U0, var_kinds: [] }, span: $DIR/issue_99325.rs:13:16: 13:46, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} -| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [UnevaluatedConst { kind: Anon { def_id: DefId(0:8 ~ issue_99325[d56d]::main::{constant#1}) }, args: [], .. }], user_self_ty: None }), max_universe: U0, var_kinds: [] }, span: $DIR/issue_99325.rs:14:16: 14:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} +| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [Alias { kind: Anon { def_id: DefId(0:8 ~ issue_99325[d56d]::main::{constant#1}) }, args: [], .. }], user_self_ty: None }), max_universe: U0, var_kinds: [] }, span: $DIR/issue_99325.rs:14:16: 14:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} | fn main() -> () { let mut _0: (); diff --git a/tests/run-make/cdylib-export-c-library-symbols/rmake.rs b/tests/run-make/cdylib-export-c-library-symbols/rmake.rs index cb237eceedadf..a2c0796da582e 100644 --- a/tests/run-make/cdylib-export-c-library-symbols/rmake.rs +++ b/tests/run-make/cdylib-export-c-library-symbols/rmake.rs @@ -1,34 +1,48 @@ //@ ignore-nvptx64 //@ ignore-wasm //@ ignore-cross-compile -// FIXME:The symbol mangle rules are slightly different in Windows(32-bit) and Apple. -// Need to be resolved. -//@ ignore-windows -//@ ignore-apple // Reason: the compiled binary is executed -use run_make_support::{build_native_static_lib, cc, dynamic_lib_name, is_darwin, llvm_nm, rustc}; +use run_make_support::{ + cc, dynamic_lib_name, is_darwin, is_windows, llvm_ar, llvm_nm, llvm_readobj, rfs, rustc, + static_lib_name, +}; fn main() { - cc().input("foo.c").arg("-c").out_exe("foo.o").run(); - build_native_static_lib("foo"); + cc().input("foo.c").arg("-c").arg("-fno-lto").out_exe("foo.o").run(); + llvm_ar().obj_to_ar().output_input(&static_lib_name("foo"), "foo.o").run(); rustc().input("foo.rs").arg("-lstatic=foo").crate_type("cdylib").run(); - let out = llvm_nm() - .input(dynamic_lib_name("foo")) - .run() - .assert_stdout_not_contains_regex("T *my_function"); + if is_darwin() { + llvm_nm().input(dynamic_lib_name("foo")).run().assert_stdout_not_contains("T _my_function"); + } else if is_windows() { + llvm_readobj() + .arg("--coff-exports") + .input(dynamic_lib_name("foo")) + .run() + .assert_stdout_not_contains("my_function"); + } else { + llvm_nm().input(dynamic_lib_name("foo")).run().assert_stdout_not_contains("T my_function"); + } + + rfs::remove_file(dynamic_lib_name("foo")); rustc().input("foo_export.rs").arg("-lstatic:+export-symbols=foo").crate_type("cdylib").run(); if is_darwin() { - let out = llvm_nm() + llvm_nm() .input(dynamic_lib_name("foo_export")) .run() .assert_stdout_contains("T _my_function"); + } else if is_windows() { + llvm_readobj() + .arg("--coff-exports") + .input(dynamic_lib_name("foo_export")) + .run() + .assert_stdout_contains("my_function"); } else { - let out = llvm_nm() + llvm_nm() .input(dynamic_lib_name("foo_export")) .run() .assert_stdout_contains("T my_function"); diff --git a/tests/run-make/staticlib-rename-internal-symbols-macho/rmake.rs b/tests/run-make/staticlib-rename-internal-symbols-macho/rmake.rs new file mode 100644 index 0000000000000..911dadc16325d --- /dev/null +++ b/tests/run-make/staticlib-rename-internal-symbols-macho/rmake.rs @@ -0,0 +1,163 @@ +//@ only-apple +//@ ignore-cross-compile + +use std::collections::HashSet; + +use run_make_support::object::Endianness; +use run_make_support::object::macho::{MachHeader64, N_EXT, N_PEXT, N_SECT, N_STAB, N_TYPE}; +use run_make_support::object::read::archive::ArchiveFile; +use run_make_support::object::read::macho::{MachHeader as _, Nlist as _}; +use run_make_support::path_helpers::source_root; +use run_make_support::{cc, extra_c_flags, object, rfs, run, rustc, static_lib_name}; + +type MachOFileHeader64 = MachHeader64; +type SymbolTable<'data> = + run_make_support::object::read::macho::SymbolTable<'data, MachOFileHeader64>; + +const EXPORTED: &[&str] = &["my_add", "my_hash_lookup", "call_internal", "my_safe_div"]; + +fn main() { + let hide_sibling = source_root().join("tests/run-make/staticlib-hide-internal-symbols"); + let rename_sibling = source_root().join("tests/run-make/staticlib-rename-internal-symbols"); + rfs::copy(hide_sibling.join("lib.rs"), "lib.rs"); + rfs::copy(hide_sibling.join("main.c"), "main.c"); + rfs::copy(rename_sibling.join("liba.rs"), "liba.rs"); + rfs::copy(rename_sibling.join("libb.rs"), "libb.rs"); + rfs::copy(rename_sibling.join("dual_main.c"), "dual_main.c"); + + test_basic_functionality(); + test_suffix_present(); + test_dual_staticlib_linking(); +} + +fn test_basic_functionality() { + let lib_name = static_lib_name("lib"); + + rustc() + .input("lib.rs") + .crate_type("staticlib") + .arg("-Zstaticlib-rename-internal-symbols") + .opt() + .run(); + + cc().input("main.c").input(&lib_name).out_exe("main").args(extra_c_flags()).run(); + run("main"); + + rfs::remove_file(&lib_name); +} + +fn test_suffix_present() { + let lib_name = static_lib_name("lib"); + + rustc() + .input("lib.rs") + .crate_type("staticlib") + .arg("-Zstaticlib-rename-internal-symbols") + .opt() + .run(); + + let data = rfs::read(&lib_name); + check_rename_symbols(&data); + + rfs::remove_file(&lib_name); +} + +fn test_dual_staticlib_linking() { + let liba_name = static_lib_name("liba"); + let libb_name = static_lib_name("libb"); + + rustc() + .input("liba.rs") + .crate_type("staticlib") + .arg("-Zstaticlib-rename-internal-symbols") + .opt() + .run(); + + rustc() + .input("libb.rs") + .crate_type("staticlib") + .arg("-Zstaticlib-rename-internal-symbols") + .opt() + .run(); + + cc().input("dual_main.c") + .input(&liba_name) + .input(&libb_name) + .out_exe("dual_main") + .args(extra_c_flags()) + .run(); + run("dual_main"); +} + +fn check_rename_symbols(archive_data: &[u8]) { + let archive = ArchiveFile::parse(archive_data).unwrap(); + let mut found_exported = HashSet::new(); + let mut found_suffix = false; + + for member in archive.members() { + let member = member.unwrap(); + if !member.name().ends_with(b".rcgu.o") { + continue; + } + let data = member.data(archive_data).unwrap(); + + let Ok(header) = MachOFileHeader64::parse(data, 0) else { continue }; + let Ok(endian) = header.endian() else { continue }; + + let Some(symtab) = find_symtab(header, endian, data) else { continue }; + let strtab = symtab.strings(); + + for nlist in symtab.iter() { + let n_type = nlist.n_type(); + if n_type & N_STAB != 0 { + continue; + } + if n_type & N_EXT == 0 { + continue; + } + if n_type & N_TYPE != N_SECT { + continue; + } + + let Ok(name_bytes) = nlist.name(endian, strtab) else { continue }; + let Ok(name) = std::str::from_utf8(name_bytes) else { continue }; + let name = name.strip_prefix('_').unwrap_or(name); + + if EXPORTED.contains(&name) { + assert!( + !name.contains(".rs"), + "exported symbol `{name}` should not contain .rs suffix" + ); + found_exported.insert(name.to_string()); + } else { + assert!( + name.contains(".rs"), + "internal symbol `{name}` should contain .rs suffix after rename" + ); + found_suffix = true; + } + } + } + + assert!(found_suffix, "expected to find at least one renamed symbol with .rs suffix"); + for expected in EXPORTED { + assert!( + found_exported.contains(*expected), + "expected to find exported symbol `{expected}` in archive" + ); + } +} + +fn find_symtab<'data>( + header: &MachOFileHeader64, + endian: Endianness, + data: &'data [u8], +) -> Option> { + let mut commands = header.load_commands(endian, data, 0).ok()?; + while let Ok(Some(command)) = commands.next() { + if let Ok(Some(symtab_cmd)) = command.symtab() { + return symtab_cmd.symbols::(endian, data).ok(); + } + } + None +} diff --git a/tests/run-make/staticlib-rename-internal-symbols/dual_main.c b/tests/run-make/staticlib-rename-internal-symbols/dual_main.c new file mode 100644 index 0000000000000..21f4d5cae9b55 --- /dev/null +++ b/tests/run-make/staticlib-rename-internal-symbols/dual_main.c @@ -0,0 +1,14 @@ +extern int liba_process(int v); +extern int liba_answer(); +extern int libb_multiply(int a, int b); +extern int libb_greet(); + +int main() { + if (liba_answer() != 42) return 1; + if (liba_process(10) != 31) return 1; + + if (libb_multiply(6, 7) != 42) return 1; + if (libb_greet() != 99) return 1; + + return 0; +} diff --git a/tests/run-make/staticlib-rename-internal-symbols/liba.rs b/tests/run-make/staticlib-rename-internal-symbols/liba.rs new file mode 100644 index 0000000000000..ca23944df44ea --- /dev/null +++ b/tests/run-make/staticlib-rename-internal-symbols/liba.rs @@ -0,0 +1,17 @@ +#![crate_type = "staticlib"] + +mod internal { + pub fn compute(v: i32) -> i32 { + v * 3 + 1 + } +} + +#[no_mangle] +pub extern "C" fn liba_process(v: i32) -> i32 { + internal::compute(v) +} + +#[no_mangle] +pub extern "C" fn liba_answer() -> i32 { + 42 +} diff --git a/tests/run-make/staticlib-rename-internal-symbols/libb.rs b/tests/run-make/staticlib-rename-internal-symbols/libb.rs new file mode 100644 index 0000000000000..1eca8f3d254ca --- /dev/null +++ b/tests/run-make/staticlib-rename-internal-symbols/libb.rs @@ -0,0 +1,15 @@ +#![crate_type = "staticlib"] + +fn internal_multiply(a: i32, b: i32) -> i32 { + a * b +} + +#[no_mangle] +pub extern "C" fn libb_multiply(a: i32, b: i32) -> i32 { + internal_multiply(a, b) +} + +#[no_mangle] +pub extern "C" fn libb_greet() -> i32 { + 99 +} diff --git a/tests/run-make/staticlib-rename-internal-symbols/rmake.rs b/tests/run-make/staticlib-rename-internal-symbols/rmake.rs new file mode 100644 index 0000000000000..57123dba38f45 --- /dev/null +++ b/tests/run-make/staticlib-rename-internal-symbols/rmake.rs @@ -0,0 +1,165 @@ +//@ only-elf +//@ ignore-cross-compile + +use std::collections::HashSet; + +use run_make_support::object::read::archive::ArchiveFile; +use run_make_support::object::read::elf::{FileHeader as _, SectionHeader as _, Sym as _}; +use run_make_support::object::{Endianness, elf}; +use run_make_support::path_helpers::source_root; +use run_make_support::{cc, extra_c_flags, rfs, run, rustc, static_lib_name}; + +const EXPORTED: &[&str] = &["my_add", "my_hash_lookup", "call_internal", "my_safe_div"]; + +fn main() { + let sibling = source_root().join("tests/run-make/staticlib-hide-internal-symbols"); + rfs::copy(sibling.join("lib.rs"), "lib.rs"); + rfs::copy(sibling.join("main.c"), "main.c"); + + test_basic_functionality(); + test_rs_suffix_present(); + test_dual_staticlib_linking(); +} + +fn test_basic_functionality() { + let lib_name = static_lib_name("lib"); + + rustc() + .input("lib.rs") + .crate_type("staticlib") + .arg("-Zstaticlib-rename-internal-symbols") + .opt() + .run(); + + cc().input("main.c").input(&lib_name).out_exe("main").args(extra_c_flags()).run(); + run("main"); + + rfs::remove_file(&lib_name); +} + +fn test_rs_suffix_present() { + let lib_name = static_lib_name("lib"); + + rustc() + .input("lib.rs") + .crate_type("staticlib") + .arg("-Zstaticlib-rename-internal-symbols") + .opt() + .run(); + + let data = rfs::read(&lib_name); + check_rename_symbols(&data); + + rfs::remove_file(&lib_name); +} + +fn test_dual_staticlib_linking() { + let liba_name = static_lib_name("liba"); + let libb_name = static_lib_name("libb"); + + rustc() + .input("liba.rs") + .crate_type("staticlib") + .arg("-Zstaticlib-rename-internal-symbols") + .opt() + .run(); + + rustc() + .input("libb.rs") + .crate_type("staticlib") + .arg("-Zstaticlib-rename-internal-symbols") + .opt() + .run(); + + cc().input("dual_main.c") + .input(&liba_name) + .input(&libb_name) + .out_exe("dual_main") + .args(extra_c_flags()) + .run(); + run("dual_main"); +} + +fn check_rename_symbols(archive_data: &[u8]) { + let archive = ArchiveFile::parse(archive_data).unwrap(); + let mut found_exported = HashSet::new(); + let mut found_rs_suffix = false; + + for member in archive.members() { + let member = member.unwrap(); + if !member.name().ends_with(b".rcgu.o") { + continue; + } + let data = member.data(archive_data).unwrap(); + + if let Ok(header) = elf::FileHeader64::::parse(data) { + check_elf_symbols(header, data, &mut found_exported, &mut found_rs_suffix); + } else if let Ok(header) = elf::FileHeader32::::parse(data) { + check_elf_symbols(header, data, &mut found_exported, &mut found_rs_suffix); + } + } + + assert!(found_rs_suffix, "expected to find at least one renamed symbol with .rs suffix"); + for expected in EXPORTED { + assert!( + found_exported.contains(*expected), + "expected to find exported symbol `{expected}` in archive" + ); + } +} + +fn check_elf_symbols>( + header: &Elf, + data: &[u8], + found_exported: &mut HashSet, + found_rs_suffix: &mut bool, +) { + let Ok(endian) = header.endian() else { return }; + let Ok(sections) = header.sections(endian, data) else { return }; + + for (si, section) in sections.enumerate() { + if section.sh_type(endian) != elf::SHT_SYMTAB { + continue; + } + let Ok(symbols) = run_make_support::object::read::elf::SymbolTable::parse( + endian, data, §ions, si, section, + ) else { + continue; + }; + let strtab = symbols.strings(); + + for symbol in symbols.symbols() { + let bind = symbol.st_bind(); + let shndx = symbol.st_shndx(endian); + + if shndx == elf::SHN_UNDEF { + continue; + } + if bind != elf::STB_GLOBAL && bind != elf::STB_WEAK { + continue; + } + + let Ok(name_bytes) = symbol.name(endian, strtab) else { continue }; + let Ok(name) = str::from_utf8(name_bytes) else { continue }; + + if EXPORTED.contains(&name) { + assert!( + !name.contains(".rs"), + "exported symbol `{name}` should not contain .rs suffix" + ); + assert_eq!( + symbol.st_visibility(), + elf::STV_DEFAULT, + "exported symbol `{name}` should be STV_DEFAULT" + ); + found_exported.insert(name.to_string()); + } else { + assert!( + name.contains(".rs"), + "internal symbol `{name}` should contain .rs suffix after rename" + ); + *found_rs_suffix = true; + } + } + } +} diff --git a/tests/ui/associated-types/issue-63593.current.stderr b/tests/ui/associated-types/issue-63593.current.stderr index 76fdefeb4e521..4fd7489dca019 100644 --- a/tests/ui/associated-types/issue-63593.current.stderr +++ b/tests/ui/associated-types/issue-63593.current.stderr @@ -4,11 +4,11 @@ error[E0277]: the size for values of type `Self` cannot be known at compilation LL | type This = Self; | ^^^^ doesn't have a size known at compile-time | -note: required by a bound in `MyTrait::This` +note: required by an implicit `Sized` bound in `MyTrait::This` --> $DIR/issue-63593.rs:13:5 | LL | type This = Self; - | ^^^^^^^^^^^^^^^^^ required by this bound in `MyTrait::This` + | ^^^^^^^^^^^^^^^^^ required by the implicit `Sized` requirement on this associated type in `MyTrait::This` help: consider further restricting `Self` | LL | trait MyTrait: Sized { diff --git a/tests/ui/associated-types/issue-63593.next.stderr b/tests/ui/associated-types/issue-63593.next.stderr index 76fdefeb4e521..4fd7489dca019 100644 --- a/tests/ui/associated-types/issue-63593.next.stderr +++ b/tests/ui/associated-types/issue-63593.next.stderr @@ -4,11 +4,11 @@ error[E0277]: the size for values of type `Self` cannot be known at compilation LL | type This = Self; | ^^^^ doesn't have a size known at compile-time | -note: required by a bound in `MyTrait::This` +note: required by an implicit `Sized` bound in `MyTrait::This` --> $DIR/issue-63593.rs:13:5 | LL | type This = Self; - | ^^^^^^^^^^^^^^^^^ required by this bound in `MyTrait::This` + | ^^^^^^^^^^^^^^^^^ required by the implicit `Sized` requirement on this associated type in `MyTrait::This` help: consider further restricting `Self` | LL | trait MyTrait: Sized { diff --git a/tests/ui/async-await/coroutine-auto-trait-span-issue-155880.rs b/tests/ui/async-await/coroutine-auto-trait-span-issue-155880.rs new file mode 100644 index 0000000000000..8bc8ef550ad5a --- /dev/null +++ b/tests/ui/async-await/coroutine-auto-trait-span-issue-155880.rs @@ -0,0 +1,30 @@ +//@ edition: 2021 +// Regression test for + +trait Trait { + type Assoc<'a> + where + Self: 'a; +} + +impl Trait for T { + type Assoc<'a> = () + where + Self: 'a; +} + +async fn inner<'a, T: Trait + 'a>(_: T, x: T::Assoc<'a>) -> T::Assoc<'a> { + std::future::ready(x).await +} + +async fn outer<'a>() { + let x = 1u32; + inner(&x, ()).await; +} + +fn is_send(_: T) {} + +fn main() { + is_send(outer()) + //~^ ERROR implementation of `Send` is not general enough +} diff --git a/tests/ui/async-await/coroutine-auto-trait-span-issue-155880.stderr b/tests/ui/async-await/coroutine-auto-trait-span-issue-155880.stderr new file mode 100644 index 0000000000000..3048cc1d9c1c3 --- /dev/null +++ b/tests/ui/async-await/coroutine-auto-trait-span-issue-155880.stderr @@ -0,0 +1,17 @@ +error: implementation of `Send` is not general enough + --> $DIR/coroutine-auto-trait-span-issue-155880.rs:28:5 + | +LL | async fn inner<'a, T: Trait + 'a>(_: T, x: T::Assoc<'a>) -> T::Assoc<'a> { + | __________________________________________________________________________- +LL | | std::future::ready(x).await +LL | | } + | |_- this async fn captures a value whose type is not `Send` +... +LL | is_send(outer()) + | ^^^^^^^^^^^^^^^^ implementation of `Send` is not general enough + | + = note: `Send` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`... + = note: ...but `Send` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` + +error: aborting due to 1 previous error + diff --git a/tests/ui/async-await/higher-ranked-auto-trait-11.assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-11.assumptions.stderr index d39843f628c46..331a8c0540307 100644 --- a/tests/ui/async-await/higher-ranked-auto-trait-11.assumptions.stderr +++ b/tests/ui/async-await/higher-ranked-auto-trait-11.assumptions.stderr @@ -11,7 +11,10 @@ error: implementation of `Send` is not general enough --> $DIR/higher-ranked-auto-trait-11.rs:27:9 | LL | Box::pin(async move { >::foo().await }) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Send` is not general enough + | ^^^^^^^^^----------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | | + | | this async block captures a value whose type is not `Send` + | implementation of `Send` is not general enough | = note: `Send` would have to be implemented for the type `>::Future`, for any lifetime `'0`... = note: ...but `Send` is actually implemented for the type `>::Future`, for some specific lifetime `'1` diff --git a/tests/ui/async-await/higher-ranked-auto-trait-11.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-11.no_assumptions.stderr index d39843f628c46..331a8c0540307 100644 --- a/tests/ui/async-await/higher-ranked-auto-trait-11.no_assumptions.stderr +++ b/tests/ui/async-await/higher-ranked-auto-trait-11.no_assumptions.stderr @@ -11,7 +11,10 @@ error: implementation of `Send` is not general enough --> $DIR/higher-ranked-auto-trait-11.rs:27:9 | LL | Box::pin(async move { >::foo().await }) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Send` is not general enough + | ^^^^^^^^^----------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | | + | | this async block captures a value whose type is not `Send` + | implementation of `Send` is not general enough | = note: `Send` would have to be implemented for the type `>::Future`, for any lifetime `'0`... = note: ...but `Send` is actually implemented for the type `>::Future`, for some specific lifetime `'1` diff --git a/tests/ui/async-await/return-type-notation/issue-110963-early.no_assumptions.stderr b/tests/ui/async-await/return-type-notation/issue-110963-early.no_assumptions.stderr index bb43636492409..6b434ecca0109 100644 --- a/tests/ui/async-await/return-type-notation/issue-110963-early.no_assumptions.stderr +++ b/tests/ui/async-await/return-type-notation/issue-110963-early.no_assumptions.stderr @@ -1,7 +1,10 @@ error: implementation of `Send` is not general enough --> $DIR/issue-110963-early.rs:17:5 | -LL | / spawn(async move { +LL | spawn(async move { + | ^ ---------- this async block captures a value whose type is not `Send` + | _____| + | | LL | | let mut hc = hc; LL | | if !hc.check().await { LL | | log_health_check_failure().await; @@ -15,7 +18,10 @@ LL | | }); error: implementation of `Send` is not general enough --> $DIR/issue-110963-early.rs:17:5 | -LL | / spawn(async move { +LL | spawn(async move { + | ^ ---------- this async block captures a value whose type is not `Send` + | _____| + | | LL | | let mut hc = hc; LL | | if !hc.check().await { LL | | log_health_check_failure().await; diff --git a/tests/ui/attributes/dump-preds.stderr b/tests/ui/attributes/dump-preds.stderr index 12d9308431734..b4be76450c6a9 100644 --- a/tests/ui/attributes/dump-preds.stderr +++ b/tests/ui/attributes/dump-preds.stderr @@ -33,7 +33,7 @@ error: rustc_dump_item_bounds LL | type Assoc: std::ops::Deref | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: Binder { value: ProjectionPredicate(AliasTerm { args: [Alias(AliasTy { args: [Self/#0, T/#1, P/#2], kind: Projection { def_id: DefId(..) }, .. })], kind: ProjectionTy { def_id: DefId(..) }, .. }, Term::Ty(())), bound_vars: [] } + = note: Binder { value: ProjectionPredicate(Alias { kind: ProjectionTy { def_id: DefId(..) }, args: [Alias(Alias { kind: Projection { def_id: DefId(..) }, args: [Self/#0, T/#1, P/#2], .. })], .. }, Term::Ty(())), bound_vars: [] } = note: Binder { value: TraitPredicate(<>::Assoc

as std::ops::Deref>, polarity:Positive), bound_vars: [] } = note: Binder { value: TraitPredicate(<>::Assoc

as std::marker::Sized>, polarity:Positive), bound_vars: [] } diff --git a/tests/ui/box/into-boxed-slice-fail.stderr b/tests/ui/box/into-boxed-slice-fail.stderr index f102f666dc276..2d57c4b75e751 100644 --- a/tests/ui/box/into-boxed-slice-fail.stderr +++ b/tests/ui/box/into-boxed-slice-fail.stderr @@ -7,7 +7,7 @@ LL | let _ = Box::into_boxed_slice(boxed_slice); | required by a bound introduced by this call | = help: the trait `Sized` is not implemented for `[u8]` -note: required by a bound in `Box::::into_boxed_slice` +note: required by an implicit `Sized` bound in `Box::::into_boxed_slice` --> $SRC_DIR/alloc/src/boxed.rs:LL:COL error[E0277]: the size for values of type `[u8]` cannot be known at compilation time @@ -28,7 +28,7 @@ LL | let _ = Box::into_boxed_slice(boxed_trait); | required by a bound introduced by this call | = help: the trait `Sized` is not implemented for `dyn Debug` -note: required by a bound in `Box::::into_boxed_slice` +note: required by an implicit `Sized` bound in `Box::::into_boxed_slice` --> $SRC_DIR/alloc/src/boxed.rs:LL:COL error[E0277]: the size for values of type `dyn Debug` cannot be known at compilation time diff --git a/tests/ui/closures/unsized_value_move.stderr b/tests/ui/closures/unsized_value_move.stderr index a9a26a42d1675..4c7273c3a0060 100644 --- a/tests/ui/closures/unsized_value_move.stderr +++ b/tests/ui/closures/unsized_value_move.stderr @@ -7,7 +7,7 @@ LL | (|| Box::new(*(&[0][..])))(); | required by a bound introduced by this call | = help: the trait `Sized` is not implemented for `[{integer}]` -note: required by a bound in `Box::::new` +note: required by an implicit `Sized` bound in `Box::::new` --> $SRC_DIR/alloc/src/boxed.rs:LL:COL help: references are always `Sized`, even if they point to unsized data; consider not dereferencing the expression | diff --git a/tests/ui/coherence/deep-bad-copy-reason.rs b/tests/ui/coherence/deep-bad-copy-reason.rs index f1c2698bad5cc..dbc33c009e542 100644 --- a/tests/ui/coherence/deep-bad-copy-reason.rs +++ b/tests/ui/coherence/deep-bad-copy-reason.rs @@ -14,6 +14,7 @@ pub struct ListS { pub struct Interned<'a, T>(&'a T); //~^ NOTE: required by an implicit `Sized` //~| NOTE: required by the implicit `Sized` +//~| NOTE: in this expansion of desugaring of implied bound impl<'a, T> Clone for Interned<'a, T> { fn clone(&self) -> Self { diff --git a/tests/ui/coherence/deep-bad-copy-reason.stderr b/tests/ui/coherence/deep-bad-copy-reason.stderr index 534f26c39c2d4..131796a6c05b0 100644 --- a/tests/ui/coherence/deep-bad-copy-reason.stderr +++ b/tests/ui/coherence/deep-bad-copy-reason.stderr @@ -1,5 +1,5 @@ error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/deep-bad-copy-reason.rs:38:24 + --> $DIR/deep-bad-copy-reason.rs:39:24 | LL | pub struct List<'tcx, T>(Interned<'tcx, ListS>); | ------------------------ this field does not implement `Copy` @@ -8,13 +8,13 @@ LL | impl<'tcx, T> Copy for List<'tcx, T> {} | ^^^^^^^^^^^^^ | note: the `Copy` impl for `Interned<'tcx, ListS>` requires that `OpaqueListContents: Sized` - --> $DIR/deep-bad-copy-reason.rs:26:26 + --> $DIR/deep-bad-copy-reason.rs:27:26 | LL | pub struct List<'tcx, T>(Interned<'tcx, ListS>); | ^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the size for values of type `OpaqueListContents` cannot be known at compilation time - --> $DIR/deep-bad-copy-reason.rs:26:26 + --> $DIR/deep-bad-copy-reason.rs:27:26 | LL | pub struct List<'tcx, T>(Interned<'tcx, ListS>); | ^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time diff --git a/tests/ui/coherence/occurs-check/associated-type.next.stderr b/tests/ui/coherence/occurs-check/associated-type.next.stderr index 38fb75483f3b3..d68808010bead 100644 --- a/tests/ui/coherence/occurs-check/associated-type.next.stderr +++ b/tests/ui/coherence/occurs-check/associated-type.next.stderr @@ -1,5 +1,5 @@ - WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTerm { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1))], kind: ProjectionTy { def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }, .. } - WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTerm { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1))], kind: ProjectionTy { def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }, .. } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: Alias { kind: ProjectionTy { def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }, args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1))], .. } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: Alias { kind: ProjectionTy { def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }, args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1))], .. } error[E0119]: conflicting implementations of trait `Overlap fn(&'a (), ())>` for type `for<'a> fn(&'a (), ())` --> $DIR/associated-type.rs:32:1 | diff --git a/tests/ui/coherence/occurs-check/associated-type.old.stderr b/tests/ui/coherence/occurs-check/associated-type.old.stderr index 1dac3ecea2687..0472f93cae32f 100644 --- a/tests/ui/coherence/occurs-check/associated-type.old.stderr +++ b/tests/ui/coherence/occurs-check/associated-type.old.stderr @@ -1,5 +1,5 @@ - WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTerm { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1))], kind: ProjectionTy { def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }, .. } - WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTerm { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1))], kind: ProjectionTy { def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }, .. } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: Alias { kind: ProjectionTy { def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }, args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1))], .. } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: Alias { kind: ProjectionTy { def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }, args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1))], .. } error[E0119]: conflicting implementations of trait `Overlap fn(&'a (), ())>` for type `for<'a> fn(&'a (), ())` --> $DIR/associated-type.rs:32:1 | diff --git a/tests/ui/const-generics/unused-type-param-suggestion.rs b/tests/ui/const-generics/unused-type-param-suggestion.rs index b8ae4f6b56b70..917dc972eb737 100644 --- a/tests/ui/const-generics/unused-type-param-suggestion.rs +++ b/tests/ui/const-generics/unused-type-param-suggestion.rs @@ -1,4 +1,4 @@ -#![crate_type="lib"] +#![crate_type = "lib"] struct S; //~^ ERROR type parameter `N` is never used @@ -25,4 +25,3 @@ type C = (); type D = (); //~^ ERROR type parameter `N` is never used //~| HELP consider removing `N` -//~| HELP if you intended `N` to be a const parameter diff --git a/tests/ui/const-generics/unused-type-param-suggestion.stderr b/tests/ui/const-generics/unused-type-param-suggestion.stderr index a7aa477ab31a5..67b704d8bc725 100644 --- a/tests/ui/const-generics/unused-type-param-suggestion.stderr +++ b/tests/ui/const-generics/unused-type-param-suggestion.stderr @@ -47,7 +47,6 @@ LL | type D = (); | ^ unused type parameter | = help: consider removing `N` or referring to it in the body of the type alias - = help: if you intended `N` to be a const parameter, use `const N: /* Type */` instead error: aborting due to 6 previous errors diff --git a/tests/ui/consts/bad-array-size-in-type-err.stderr b/tests/ui/consts/bad-array-size-in-type-err.stderr index 84e16f8d931ea..13b0b6c4f4a65 100644 --- a/tests/ui/consts/bad-array-size-in-type-err.stderr +++ b/tests/ui/consts/bad-array-size-in-type-err.stderr @@ -57,6 +57,10 @@ LL | pub const fn i(_: Wrap) {} | ^ - value is dropped here | | | the destructor for this type cannot be evaluated in constant functions + | + = note: see issue #133214 for more information + = help: add `#![feature(const_destruct)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: aborting due to 7 previous errors diff --git a/tests/ui/consts/const-eval/issue-65394.stock.stderr b/tests/ui/consts/const-eval/issue-65394.stock.stderr index f33593862a763..514d454df3dc0 100644 --- a/tests/ui/consts/const-eval/issue-65394.stock.stderr +++ b/tests/ui/consts/const-eval/issue-65394.stock.stderr @@ -6,6 +6,10 @@ LL | let mut x = Vec::::new(); ... LL | }; | - value is dropped here + | + = note: see issue #133214 for more information + = help: add `#![feature(const_destruct)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: aborting due to 1 previous error diff --git a/tests/ui/consts/const-eval/livedrop.stderr b/tests/ui/consts/const-eval/livedrop.stderr index 1add814060370..b090e35f07e3f 100644 --- a/tests/ui/consts/const-eval/livedrop.stderr +++ b/tests/ui/consts/const-eval/livedrop.stderr @@ -6,6 +6,10 @@ LL | let mut always_returned = None; ... LL | always_returned = never_returned; | --------------- value is dropped here + | + = note: see issue #133214 for more information + = help: add `#![feature(const_destruct)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: aborting due to 1 previous error diff --git a/tests/ui/consts/const_in_pattern/derive-and-manual-partialeq-issue-147714.rs b/tests/ui/consts/const_in_pattern/derive-and-manual-partialeq-issue-147714.rs new file mode 100644 index 0000000000000..493023f6bdb0e --- /dev/null +++ b/tests/ui/consts/const_in_pattern/derive-and-manual-partialeq-issue-147714.rs @@ -0,0 +1,31 @@ +// `derive(PartialEq)`, which also implements `StructuralPartialEq`, must not allow the latter impl +// to be used with other non-derived implementations of `PartialEq`. +// +// Test case by theemathas from . + +#[allow(dead_code)] +#[derive(PartialEq)] +enum Thing { + A(T), + B, +} + +struct Incomparable; + +// This impl does not obey StructuralPartialEq's rules. +impl PartialEq for Thing { + fn eq(&self, _: &Self) -> bool { + panic!() + } +} + +// This constant does not obey StructuralPartialEq's rules, so it should not +// implement StructuralPartialEq. +const X: Thing = Thing::B; + +fn main() { + if let X = X { + //~^ ERROR constant of non-structural type `Thing` in a pattern + println!("equal"); + } +} diff --git a/tests/ui/consts/const_in_pattern/derive-and-manual-partialeq-issue-147714.stderr b/tests/ui/consts/const_in_pattern/derive-and-manual-partialeq-issue-147714.stderr new file mode 100644 index 0000000000000..52497e23df04d --- /dev/null +++ b/tests/ui/consts/const_in_pattern/derive-and-manual-partialeq-issue-147714.stderr @@ -0,0 +1,20 @@ +error: constant of non-structural type `Thing` in a pattern + --> $DIR/derive-and-manual-partialeq-issue-147714.rs:27:12 + | +LL | enum Thing { + | ------------- `Thing` must be annotated with `#[derive(PartialEq)]` to be usable in patterns +... +LL | const X: Thing = Thing::B; + | ---------------------------- constant defined here +... +LL | if let X = X { + | ^ constant of non-structural type + | +help: if `Thing` manually implemented `PartialEq`, you could check for equality instead of pattern matching + | +LL - if let X = X { +LL + if X == X { + | + +error: aborting due to 1 previous error + diff --git a/tests/ui/consts/const_in_pattern/issue-65466.rs b/tests/ui/consts/const_in_pattern/issue-65466.rs index 82838657b02f5..dba8e7a92163a 100644 --- a/tests/ui/consts/const_in_pattern/issue-65466.rs +++ b/tests/ui/consts/const_in_pattern/issue-65466.rs @@ -11,7 +11,7 @@ const C: &[O] = &[O::None]; fn main() { let x = O::None; match &[x][..] { - C => (), //~ ERROR constant of non-structural type `&[O]` in a pattern + C => (), //~ ERROR constant of non-structural type `O` in a pattern _ => (), } } diff --git a/tests/ui/consts/const_in_pattern/issue-65466.stderr b/tests/ui/consts/const_in_pattern/issue-65466.stderr index 511a38bbc00d8..29c49223f044a 100644 --- a/tests/ui/consts/const_in_pattern/issue-65466.stderr +++ b/tests/ui/consts/const_in_pattern/issue-65466.stderr @@ -1,4 +1,4 @@ -error: constant of non-structural type `&[O]` in a pattern +error: constant of non-structural type `O` in a pattern --> $DIR/issue-65466.rs:14:9 | LL | struct B; diff --git a/tests/ui/consts/control-flow/drop-fail.precise.stderr b/tests/ui/consts/control-flow/drop-fail.precise.stderr index 32afc51c3ee34..6f07d2329615b 100644 --- a/tests/ui/consts/control-flow/drop-fail.precise.stderr +++ b/tests/ui/consts/control-flow/drop-fail.precise.stderr @@ -1,14 +1,14 @@ -error[E0493]: destructor of `Option>` cannot be evaluated at compile-time - --> $DIR/drop-fail.rs:9:9 +error[E0493]: destructor of `Option` cannot be evaluated at compile-time + --> $DIR/drop-fail.rs:16:9 | -LL | let x = Some(Vec::new()); +LL | let x = Some(NotConstDestruct); | ^ the destructor for this type cannot be evaluated in constants ... LL | }; | - value is dropped here -error[E0493]: destructor of `Option>` cannot be evaluated at compile-time - --> $DIR/drop-fail.rs:40:9 +error[E0493]: destructor of `Option` cannot be evaluated at compile-time + --> $DIR/drop-fail.rs:47:9 | LL | let mut tmp = None; | ^^^^^^^ the destructor for this type cannot be evaluated in constants diff --git a/tests/ui/consts/control-flow/drop-fail.rs b/tests/ui/consts/control-flow/drop-fail.rs index 2b73e37b23d03..3593e5af26b00 100644 --- a/tests/ui/consts/control-flow/drop-fail.rs +++ b/tests/ui/consts/control-flow/drop-fail.rs @@ -3,10 +3,17 @@ #![feature(const_destruct)] #![cfg_attr(precise, feature(const_precise_live_drops))] + +struct NotConstDestruct; + +impl Drop for NotConstDestruct { + fn drop(&mut self) {} +} + // `x` is *not* always moved into the final value and may be dropped inside the initializer. -const _: Option> = { - let y: Option> = None; - let x = Some(Vec::new()); +const _: Option = { + let y: Option = None; + let x = Some(NotConstDestruct); //[stock,precise]~^ ERROR destructor of if true { @@ -18,16 +25,16 @@ const _: Option> = { // We only clear `NeedsDrop` if a local is moved from in entirely. This is a shortcoming of the // existing analysis. -const _: Vec = { - let vec_tuple = (Vec::new(),); +const _: NotConstDestruct = { + let vec_tuple = (NotConstDestruct,); //[stock]~^ ERROR destructor of vec_tuple.0 }; // This applies to single-field enum variants as well. -const _: Vec = { - let x: Result<_, Vec> = Ok(Vec::new()); +const _: NotConstDestruct = { + let x: Result<_, NotConstDestruct> = Ok(NotConstDestruct); //[stock]~^ ERROR destructor of match x { @@ -35,8 +42,8 @@ const _: Vec = { } }; -const _: Option> = { - let mut some = Some(Vec::new()); +const _: Option = { + let mut some = Some(NotConstDestruct); let mut tmp = None; //[stock,precise]~^ ERROR destructor of diff --git a/tests/ui/consts/control-flow/drop-fail.stock.stderr b/tests/ui/consts/control-flow/drop-fail.stock.stderr index 8fe60fd736765..3caef5810939c 100644 --- a/tests/ui/consts/control-flow/drop-fail.stock.stderr +++ b/tests/ui/consts/control-flow/drop-fail.stock.stderr @@ -1,32 +1,32 @@ -error[E0493]: destructor of `Option>` cannot be evaluated at compile-time - --> $DIR/drop-fail.rs:9:9 +error[E0493]: destructor of `Option` cannot be evaluated at compile-time + --> $DIR/drop-fail.rs:16:9 | -LL | let x = Some(Vec::new()); +LL | let x = Some(NotConstDestruct); | ^ the destructor for this type cannot be evaluated in constants ... LL | }; | - value is dropped here -error[E0493]: destructor of `(Vec,)` cannot be evaluated at compile-time - --> $DIR/drop-fail.rs:22:9 +error[E0493]: destructor of `(NotConstDestruct,)` cannot be evaluated at compile-time + --> $DIR/drop-fail.rs:29:9 | -LL | let vec_tuple = (Vec::new(),); +LL | let vec_tuple = (NotConstDestruct,); | ^^^^^^^^^ the destructor for this type cannot be evaluated in constants ... LL | }; | - value is dropped here -error[E0493]: destructor of `Result, Vec>` cannot be evaluated at compile-time - --> $DIR/drop-fail.rs:30:9 +error[E0493]: destructor of `Result` cannot be evaluated at compile-time + --> $DIR/drop-fail.rs:37:9 | -LL | let x: Result<_, Vec> = Ok(Vec::new()); +LL | let x: Result<_, NotConstDestruct> = Ok(NotConstDestruct); | ^ the destructor for this type cannot be evaluated in constants ... LL | }; | - value is dropped here -error[E0493]: destructor of `Option>` cannot be evaluated at compile-time - --> $DIR/drop-fail.rs:40:9 +error[E0493]: destructor of `Option` cannot be evaluated at compile-time + --> $DIR/drop-fail.rs:47:9 | LL | let mut tmp = None; | ^^^^^^^ the destructor for this type cannot be evaluated in constants diff --git a/tests/ui/consts/miri_unleashed/assoc_const.rs b/tests/ui/consts/miri_unleashed/assoc_const.rs index 812207ee80900..753a53077e086 100644 --- a/tests/ui/consts/miri_unleashed/assoc_const.rs +++ b/tests/ui/consts/miri_unleashed/assoc_const.rs @@ -4,6 +4,13 @@ // a test demonstrating why we do need to run static const qualification on associated constants // instead of just checking the final constant + +struct NotConstDestruct; + +impl Drop for NotConstDestruct { + fn drop(&mut self) {} +} + trait Foo { const X: T; } @@ -15,18 +22,18 @@ trait Bar> { impl Foo for () { const X: u32 = 42; } -impl Foo> for String { - const X: Vec = Vec::new(); +impl Foo for NotConstDestruct { + const X: NotConstDestruct = NotConstDestruct; } impl Bar for () {} -impl Bar, String> for String {} +impl Bar for NotConstDestruct {} fn main() { // this is fine, but would have been forbidden by the static checks on `F` let x = <() as Bar>::F; // this test only causes errors due to the line below, so post-monomorphization - let y = , String>>::F; + let y = >::F; } //~? WARN skipping const checks diff --git a/tests/ui/consts/miri_unleashed/assoc_const.stderr b/tests/ui/consts/miri_unleashed/assoc_const.stderr index 0b276c8d70705..29f371373aef9 100644 --- a/tests/ui/consts/miri_unleashed/assoc_const.stderr +++ b/tests/ui/consts/miri_unleashed/assoc_const.stderr @@ -1,32 +1,32 @@ -error[E0080]: calling non-const function ` as Drop>::drop` - --> $DIR/assoc_const.rs:12:31 +error[E0080]: calling non-const function `::drop` + --> $DIR/assoc_const.rs:19:31 | LL | const F: u32 = (U::X, 42).1; - | ^ evaluation of `, std::string::String>>::F` failed inside this call + | ^ evaluation of `>::F` failed inside this call | -note: inside `std::ptr::drop_glue::<(Vec, u32)> - shim(Some((Vec, u32)))` +note: inside `std::ptr::drop_glue::<(NotConstDestruct, u32)> - shim(Some((NotConstDestruct, u32)))` --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL -note: inside `std::ptr::drop_glue::> - shim(Some(Vec))` +note: inside `std::ptr::drop_glue:: - shim(Some(NotConstDestruct))` --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL note: erroneous constant encountered - --> $DIR/assoc_const.rs:29:13 + --> $DIR/assoc_const.rs:36:13 | -LL | let y = , String>>::F; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let y = >::F; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: erroneous constant encountered - --> $DIR/assoc_const.rs:29:13 + --> $DIR/assoc_const.rs:36:13 | -LL | let y = , String>>::F; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let y = >::F; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: skipping const checks | help: skipping check that does not even have a feature gate - --> $DIR/assoc_const.rs:12:20 + --> $DIR/assoc_const.rs:19:20 | LL | const F: u32 = (U::X, 42).1; | ^^^^^^^^^^ diff --git a/tests/ui/consts/miri_unleashed/drop.rs b/tests/ui/consts/miri_unleashed/drop.rs index 0edd3a03c5996..dc7d3f5aa243e 100644 --- a/tests/ui/consts/miri_unleashed/drop.rs +++ b/tests/ui/consts/miri_unleashed/drop.rs @@ -2,20 +2,26 @@ use std::mem::ManuallyDrop; + +struct NotConstDestruct; + +impl Drop for NotConstDestruct { + fn drop(&mut self) {} +} + fn main() {} static TEST_OK: () = { - let v: Vec = Vec::new(); + let v: NotConstDestruct = NotConstDestruct; let _v = ManuallyDrop::new(v); }; // Make sure we catch executing bad drop functions. // The actual error is tested by the error-pattern above. static TEST_BAD: () = { - let _v: Vec = Vec::new(); -}; -//~^ NOTE failed inside this call -//~| ERROR calling non-const function ` as Drop>::drop` -//~| NOTE inside `std::ptr::drop_glue::> - shim(Some(Vec))` + let _v: NotConstDestruct = NotConstDestruct; +}; //~ NOTE failed inside this call + //~| ERROR calling non-const function `::drop` + //~| NOTE inside `std::ptr::drop_glue:: - shim(Some(NotConstDestruct))` //~? WARN skipping const checks diff --git a/tests/ui/consts/miri_unleashed/drop.stderr b/tests/ui/consts/miri_unleashed/drop.stderr index 2dfe75c468595..6e2afda763171 100644 --- a/tests/ui/consts/miri_unleashed/drop.stderr +++ b/tests/ui/consts/miri_unleashed/drop.stderr @@ -1,18 +1,18 @@ -error[E0080]: calling non-const function ` as Drop>::drop` - --> $DIR/drop.rs:16:1 +error[E0080]: calling non-const function `::drop` + --> $DIR/drop.rs:23:1 | LL | }; | ^ evaluation of `TEST_BAD` failed inside this call | -note: inside `std::ptr::drop_glue::> - shim(Some(Vec))` +note: inside `std::ptr::drop_glue:: - shim(Some(NotConstDestruct))` --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL warning: skipping const checks | help: skipping check that does not even have a feature gate - --> $DIR/drop.rs:15:9 + --> $DIR/drop.rs:22:9 | -LL | let _v: Vec = Vec::new(); +LL | let _v: NotConstDestruct = NotConstDestruct; | ^^ error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/consts/promote-not.stderr b/tests/ui/consts/promote-not.stderr index ec552d9dd7d48..ebe2a963a74b1 100644 --- a/tests/ui/consts/promote-not.stderr +++ b/tests/ui/consts/promote-not.stderr @@ -46,6 +46,10 @@ LL | let x = &String::new(); ... LL | }; | - value is dropped here + | + = note: see issue #133214 for more information + = help: add `#![feature(const_destruct)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0716]: temporary value dropped while borrowed --> $DIR/promote-not.rs:60:33 diff --git a/tests/ui/consts/promoted_const_call3.stderr b/tests/ui/consts/promoted_const_call3.stderr index 34c833d5bb77c..22d017abe6111 100644 --- a/tests/ui/consts/promoted_const_call3.stderr +++ b/tests/ui/consts/promoted_const_call3.stderr @@ -6,6 +6,10 @@ LL | let _: &'static _ = &String::new(); LL | LL | }; | - value is dropped here + | + = note: see issue #133214 for more information + = help: add `#![feature(const_destruct)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0493]: destructor of `String` cannot be evaluated at compile-time --> $DIR/promoted_const_call3.rs:8:30 @@ -14,6 +18,10 @@ LL | let _: &'static _ = &id(&String::new()); | ^^^^^^^^^^^^^ - value is dropped here | | | the destructor for this type cannot be evaluated in constants + | + = note: see issue #133214 for more information + = help: add `#![feature(const_destruct)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0716]: temporary value dropped while borrowed --> $DIR/promoted_const_call3.rs:13:26 diff --git a/tests/ui/consts/promoted_const_call5.stderr b/tests/ui/consts/promoted_const_call5.stderr index 1b5fa4352837e..b65422e44a510 100644 --- a/tests/ui/consts/promoted_const_call5.stderr +++ b/tests/ui/consts/promoted_const_call5.stderr @@ -5,6 +5,10 @@ LL | let _: &'static _ = &id(&new_string()); | ^^^^^^^^^^^^ - value is dropped here | | | the destructor for this type cannot be evaluated in constants + | + = note: see issue #133214 for more information + = help: add `#![feature(const_destruct)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0716]: temporary value dropped while borrowed --> $DIR/promoted_const_call5.rs:31:26 diff --git a/tests/ui/consts/qualif-indirect-mutation-fail.rs b/tests/ui/consts/qualif-indirect-mutation-fail.rs index b70fca7b86430..00c9d4900f5f6 100644 --- a/tests/ui/consts/qualif-indirect-mutation-fail.rs +++ b/tests/ui/consts/qualif-indirect-mutation-fail.rs @@ -1,32 +1,38 @@ //@ compile-flags: --crate-type=lib #![feature(const_precise_live_drops)] +struct NotConstDestruct; + +impl Drop for NotConstDestruct { + fn drop(&mut self) {} +} + // Mutable borrow of a field with drop impl. pub const fn f() { - let mut a: (u32, Option) = (0, None); //~ ERROR destructor of + let mut a: (u32, Option) = (0, None); //~ ERROR destructor of let _ = &mut a.1; } // Mutable borrow of a type with drop impl. pub const A1: () = { let mut x = None; //~ ERROR destructor of - let mut y = Some(String::new()); + let mut y = Some(NotConstDestruct); let a = &mut x; let b = &mut y; std::mem::swap(a, b); std::mem::forget(y); -}; //~ ERROR calling non-const function ` as Drop>::drop` +}; //~ ERROR calling non-const function `::drop` // Mutable borrow of a type with drop impl. pub const A2: () = { let mut x = None; - let mut y = Some(String::new()); + let mut y = Some(NotConstDestruct); let a = &mut x; let b = &mut y; std::mem::swap(a, b); std::mem::forget(y); let _z = x; //~ ERROR destructor of -}; //~ ERROR calling non-const function ` as Drop>::drop` +}; //~ ERROR calling non-const function `::drop` // Shared borrow of a type that might be !Freeze and Drop. pub const fn g1() { @@ -43,19 +49,19 @@ pub const fn g2() { // Mutable raw reference to a Drop type. pub const fn address_of_mut() { - let mut x: Option = None; //~ ERROR destructor of + let mut x: Option = None; //~ ERROR destructor of &raw mut x; - let mut y: Option = None; //~ ERROR destructor of + let mut y: Option = None; //~ ERROR destructor of std::ptr::addr_of_mut!(y); } // Const raw reference to a Drop type. Conservatively assumed to allow mutation // until resolution of https://github.com/rust-lang/rust/issues/56604. pub const fn address_of_const() { - let x: Option = None; //~ ERROR destructor of + let x: Option = None; //~ ERROR destructor of &raw const x; - let y: Option = None; //~ ERROR destructor of + let y: Option = None; //~ ERROR destructor of std::ptr::addr_of!(y); } diff --git a/tests/ui/consts/qualif-indirect-mutation-fail.stderr b/tests/ui/consts/qualif-indirect-mutation-fail.stderr index 102bbe03b2efd..9bf679f8a5348 100644 --- a/tests/ui/consts/qualif-indirect-mutation-fail.stderr +++ b/tests/ui/consts/qualif-indirect-mutation-fail.stderr @@ -1,5 +1,5 @@ -error[E0493]: destructor of `Option` cannot be evaluated at compile-time - --> $DIR/qualif-indirect-mutation-fail.rs:12:9 +error[E0493]: destructor of `Option` cannot be evaluated at compile-time + --> $DIR/qualif-indirect-mutation-fail.rs:18:9 | LL | let mut x = None; | ^^^^^ the destructor for this type cannot be evaluated in constants @@ -7,51 +7,47 @@ LL | let mut x = None; LL | }; | - value is dropped here -error[E0080]: calling non-const function ` as Drop>::drop` - --> $DIR/qualif-indirect-mutation-fail.rs:18:1 +error[E0080]: calling non-const function `::drop` + --> $DIR/qualif-indirect-mutation-fail.rs:24:1 | LL | }; | ^ evaluation of `A1` failed inside this call | -note: inside `std::ptr::drop_glue::> - shim(Some(Option))` - --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL -note: inside `std::ptr::drop_glue:: - shim(Some(String))` +note: inside `std::ptr::drop_glue::> - shim(Some(Option))` --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL -note: inside `std::ptr::drop_glue::> - shim(Some(Vec))` +note: inside `std::ptr::drop_glue:: - shim(Some(NotConstDestruct))` --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL -error[E0493]: destructor of `Option` cannot be evaluated at compile-time - --> $DIR/qualif-indirect-mutation-fail.rs:28:9 +error[E0493]: destructor of `Option` cannot be evaluated at compile-time + --> $DIR/qualif-indirect-mutation-fail.rs:34:9 | LL | let _z = x; | ^^ the destructor for this type cannot be evaluated in constants LL | }; | - value is dropped here -error[E0080]: calling non-const function ` as Drop>::drop` - --> $DIR/qualif-indirect-mutation-fail.rs:29:1 +error[E0080]: calling non-const function `::drop` + --> $DIR/qualif-indirect-mutation-fail.rs:35:1 | LL | }; | ^ evaluation of `A2` failed inside this call | -note: inside `std::ptr::drop_glue::> - shim(Some(Option))` +note: inside `std::ptr::drop_glue::> - shim(Some(Option))` --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL -note: inside `std::ptr::drop_glue:: - shim(Some(String))` - --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL -note: inside `std::ptr::drop_glue::> - shim(Some(Vec))` +note: inside `std::ptr::drop_glue:: - shim(Some(NotConstDestruct))` --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL -error[E0493]: destructor of `(u32, Option)` cannot be evaluated at compile-time - --> $DIR/qualif-indirect-mutation-fail.rs:6:9 +error[E0493]: destructor of `(u32, Option)` cannot be evaluated at compile-time + --> $DIR/qualif-indirect-mutation-fail.rs:12:9 | -LL | let mut a: (u32, Option) = (0, None); +LL | let mut a: (u32, Option) = (0, None); | ^^^^^ the destructor for this type cannot be evaluated in constant functions LL | let _ = &mut a.1; LL | } | - value is dropped here error[E0493]: destructor of `Option` cannot be evaluated at compile-time - --> $DIR/qualif-indirect-mutation-fail.rs:33:9 + --> $DIR/qualif-indirect-mutation-fail.rs:39:9 | LL | let x: Option = None; | ^ the destructor for this type cannot be evaluated in constant functions @@ -60,44 +56,44 @@ LL | } | - value is dropped here error[E0493]: destructor of `Option` cannot be evaluated at compile-time - --> $DIR/qualif-indirect-mutation-fail.rs:41:9 + --> $DIR/qualif-indirect-mutation-fail.rs:47:9 | LL | let _y = x; | ^^ the destructor for this type cannot be evaluated in constant functions LL | } | - value is dropped here -error[E0493]: destructor of `Option` cannot be evaluated at compile-time - --> $DIR/qualif-indirect-mutation-fail.rs:49:9 +error[E0493]: destructor of `Option` cannot be evaluated at compile-time + --> $DIR/qualif-indirect-mutation-fail.rs:55:9 | -LL | let mut y: Option = None; +LL | let mut y: Option = None; | ^^^^^ the destructor for this type cannot be evaluated in constant functions LL | std::ptr::addr_of_mut!(y); LL | } | - value is dropped here -error[E0493]: destructor of `Option` cannot be evaluated at compile-time - --> $DIR/qualif-indirect-mutation-fail.rs:46:9 +error[E0493]: destructor of `Option` cannot be evaluated at compile-time + --> $DIR/qualif-indirect-mutation-fail.rs:52:9 | -LL | let mut x: Option = None; +LL | let mut x: Option = None; | ^^^^^ the destructor for this type cannot be evaluated in constant functions ... LL | } | - value is dropped here -error[E0493]: destructor of `Option` cannot be evaluated at compile-time - --> $DIR/qualif-indirect-mutation-fail.rs:59:9 +error[E0493]: destructor of `Option` cannot be evaluated at compile-time + --> $DIR/qualif-indirect-mutation-fail.rs:65:9 | -LL | let y: Option = None; +LL | let y: Option = None; | ^ the destructor for this type cannot be evaluated in constant functions LL | std::ptr::addr_of!(y); LL | } | - value is dropped here -error[E0493]: destructor of `Option` cannot be evaluated at compile-time - --> $DIR/qualif-indirect-mutation-fail.rs:56:9 +error[E0493]: destructor of `Option` cannot be evaluated at compile-time + --> $DIR/qualif-indirect-mutation-fail.rs:62:9 | -LL | let x: Option = None; +LL | let x: Option = None; | ^ the destructor for this type cannot be evaluated in constant functions ... LL | } diff --git a/tests/ui/coroutine/auto-trait-regions.stderr b/tests/ui/coroutine/auto-trait-regions.stderr index beb689d868d46..04acddafc414c 100644 --- a/tests/ui/coroutine/auto-trait-regions.stderr +++ b/tests/ui/coroutine/auto-trait-regions.stderr @@ -33,6 +33,9 @@ LL | let generator = #[coroutine] static move || { error: implementation of `Foo` is not general enough --> $DIR/auto-trait-regions.rs:31:5 | +LL | let generator = #[coroutine] move || { + | ------- this coroutine captures a value whose type is not `Foo` +... LL | assert_foo(generator); | ^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough | @@ -42,6 +45,9 @@ LL | assert_foo(generator); error: implementation of `Foo` is not general enough --> $DIR/auto-trait-regions.rs:51:5 | +LL | let generator = #[coroutine] move || { + | ------- this coroutine captures a value whose type is not `Foo` +... LL | assert_foo(generator); | ^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough | diff --git a/tests/ui/derives/deriving-all-codegen.stdout b/tests/ui/derives/deriving-all-codegen.stdout index 83a3bebceeb0c..320c1b5861162 100644 --- a/tests/ui/derives/deriving-all-codegen.stdout +++ b/tests/ui/derives/deriving-all-codegen.stdout @@ -786,7 +786,10 @@ impl ::core::hash::Hash } } #[automatically_derived] -impl ::core::marker::StructuralPartialEq for Generic { } +impl + ::core::marker::StructuralPartialEq for Generic where + T::A: ::core::cmp::PartialEq { +} #[automatically_derived] impl ::core::cmp::PartialEq for Generic where @@ -903,8 +906,9 @@ impl ::core::marker::StructuralPartialEq for PackedGeneric - { +impl + ::core::marker::StructuralPartialEq for PackedGeneric where + T::A: ::core::cmp::PartialEq { } #[automatically_derived] impl ::core::hash::Hash for } } #[automatically_derived] -impl ::core::marker::StructuralPartialEq for EnumGeneric { } +impl + ::core::marker::StructuralPartialEq for EnumGeneric { +} #[automatically_derived] impl ::core::cmp::PartialEq for EnumGeneric { diff --git a/tests/ui/drop/dropck-normalize-errors.nll.stderr b/tests/ui/drop/dropck-normalize-errors.nll.stderr index 39ec4033eab2f..1766f136ac4d1 100644 --- a/tests/ui/drop/dropck-normalize-errors.nll.stderr +++ b/tests/ui/drop/dropck-normalize-errors.nll.stderr @@ -47,11 +47,11 @@ note: required because it appears within the type `BDecoder` | LL | pub struct BDecoder { | ^^^^^^^^ -note: required by a bound in `Decode::Decoder` +note: required by an implicit `Sized` bound in `Decode::Decoder` --> $DIR/dropck-normalize-errors.rs:8:5 | LL | type Decoder; - | ^^^^^^^^^^^^^ required by this bound in `Decode::Decoder` + | ^^^^^^^^^^^^^ required by the implicit `Sized` requirement on this associated type in `Decode::Decoder` help: consider relaxing the implicit `Sized` restriction | LL | type Decoder: ?Sized; diff --git a/tests/ui/drop/dropck-normalize-errors.polonius.stderr b/tests/ui/drop/dropck-normalize-errors.polonius.stderr index 3d72801b34363..3a08a2268d6bc 100644 --- a/tests/ui/drop/dropck-normalize-errors.polonius.stderr +++ b/tests/ui/drop/dropck-normalize-errors.polonius.stderr @@ -47,11 +47,11 @@ note: required because it appears within the type `BDecoder` | LL | pub struct BDecoder { | ^^^^^^^^ -note: required by a bound in `Decode::Decoder` +note: required by an implicit `Sized` bound in `Decode::Decoder` --> $DIR/dropck-normalize-errors.rs:8:5 | LL | type Decoder; - | ^^^^^^^^^^^^^ required by this bound in `Decode::Decoder` + | ^^^^^^^^^^^^^ required by the implicit `Sized` requirement on this associated type in `Decode::Decoder` help: consider relaxing the implicit `Sized` restriction | LL | type Decoder: ?Sized; diff --git a/tests/ui/drop/repeat-drop-2.stderr b/tests/ui/drop/repeat-drop-2.stderr index cea7baf697664..ff2bc7fe6bf1d 100644 --- a/tests/ui/drop/repeat-drop-2.stderr +++ b/tests/ui/drop/repeat-drop-2.stderr @@ -6,6 +6,10 @@ LL | const _: [String; 0] = [String::new(); 0]; | || | |the destructor for this type cannot be evaluated in constants | value is dropped here + | + = note: see issue #133214 for more information + = help: add `#![feature(const_destruct)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0382]: use of moved value: `foo` --> $DIR/repeat-drop-2.rs:4:17 diff --git a/tests/ui/dst/dst-rvalue.stderr b/tests/ui/dst/dst-rvalue.stderr index d8c529617f75f..b452311f70a56 100644 --- a/tests/ui/dst/dst-rvalue.stderr +++ b/tests/ui/dst/dst-rvalue.stderr @@ -7,7 +7,7 @@ LL | let _x: Box = Box::new(*"hello world"); | required by a bound introduced by this call | = help: the trait `Sized` is not implemented for `str` -note: required by a bound in `Box::::new` +note: required by an implicit `Sized` bound in `Box::::new` --> $SRC_DIR/alloc/src/boxed.rs:LL:COL help: references are always `Sized`, even if they point to unsized data; consider not dereferencing the expression | @@ -24,7 +24,7 @@ LL | let _x: Box<[isize]> = Box::new(*array); | required by a bound introduced by this call | = help: the trait `Sized` is not implemented for `[isize]` -note: required by a bound in `Box::::new` +note: required by an implicit `Sized` bound in `Box::::new` --> $SRC_DIR/alloc/src/boxed.rs:LL:COL help: references are always `Sized`, even if they point to unsized data; consider not dereferencing the expression | diff --git a/tests/ui/dyn-compatibility/assoc_type_bounds_implicit_sized.stderr b/tests/ui/dyn-compatibility/assoc_type_bounds_implicit_sized.stderr index 9bb770ce43199..8092333d6d200 100644 --- a/tests/ui/dyn-compatibility/assoc_type_bounds_implicit_sized.stderr +++ b/tests/ui/dyn-compatibility/assoc_type_bounds_implicit_sized.stderr @@ -5,11 +5,11 @@ LL | type Item = dyn Trait; | ^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `(dyn Trait + 'static)` -note: required by a bound in `TraitWithAType::Item` +note: required by an implicit `Sized` bound in `TraitWithAType::Item` --> $DIR/assoc_type_bounds_implicit_sized.rs:4:5 | LL | type Item; - | ^^^^^^^^^^ required by this bound in `TraitWithAType::Item` + | ^^^^^^^^^^ required by the implicit `Sized` requirement on this associated type in `TraitWithAType::Item` help: consider relaxing the implicit `Sized` restriction | LL | type Item: ?Sized; diff --git a/tests/ui/extern/extern-types-unsized.stderr b/tests/ui/extern/extern-types-unsized.stderr index 9953e5686632a..6c1d7a7b61b3c 100644 --- a/tests/ui/extern/extern-types-unsized.stderr +++ b/tests/ui/extern/extern-types-unsized.stderr @@ -67,10 +67,10 @@ LL | assert_sized::>(); | = help: the nightly-only, unstable trait `MetaSized` is not implemented for `A` note: required by a bound in `Bar` - --> $DIR/extern-types-unsized.rs:14:12 + --> $DIR/extern-types-unsized.rs:14:15 | LL | struct Bar { - | ^ required by this bound in `Bar` + | ^^^^^^ required by this bound in `Bar` error[E0277]: the size for values of type `A` cannot be known at compilation time --> $DIR/extern-types-unsized.rs:32:20 @@ -102,10 +102,10 @@ LL | assert_sized::>>(); | = help: the nightly-only, unstable trait `MetaSized` is not implemented for `A` note: required by a bound in `Bar` - --> $DIR/extern-types-unsized.rs:14:12 + --> $DIR/extern-types-unsized.rs:14:15 | LL | struct Bar { - | ^ required by this bound in `Bar` + | ^^^^^^ required by this bound in `Bar` error: aborting due to 6 previous errors diff --git a/tests/ui/generic-associated-types/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.stderr b/tests/ui/generic-associated-types/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.stderr index 674e28829073f..7bef897e032d1 100644 --- a/tests/ui/generic-associated-types/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.stderr +++ b/tests/ui/generic-associated-types/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.stderr @@ -5,11 +5,11 @@ LL | type Pointer = dyn Deref; | ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `(dyn Deref + 'static)` -note: required by a bound in `PointerFamily::Pointer` +note: required by an implicit `Sized` bound in `PointerFamily::Pointer` --> $DIR/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.rs:4:5 | LL | type Pointer: Deref; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `PointerFamily::Pointer` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by the implicit `Sized` requirement on this associated type in `PointerFamily::Pointer` help: consider relaxing the implicit `Sized` restriction | LL | type Pointer: Deref + ?Sized; diff --git a/tests/ui/generic-associated-types/issue-74816.current.stderr b/tests/ui/generic-associated-types/issue-74816.current.stderr index 335486c6538c1..79aeaa79b4f19 100644 --- a/tests/ui/generic-associated-types/issue-74816.current.stderr +++ b/tests/ui/generic-associated-types/issue-74816.current.stderr @@ -20,11 +20,11 @@ error[E0277]: the size for values of type `Self` cannot be known at compilation LL | type Associated: Trait1 = Self; | ^^^^ doesn't have a size known at compile-time | -note: required by a bound in `Trait2::Associated` +note: required by an implicit `Sized` bound in `Trait2::Associated` --> $DIR/issue-74816.rs:12:5 | LL | type Associated: Trait1 = Self; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Trait2::Associated` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by the implicit `Sized` requirement on this associated type in `Trait2::Associated` help: consider further restricting `Self` | LL | trait Trait2: Sized { diff --git a/tests/ui/generic-associated-types/issue-74816.next.stderr b/tests/ui/generic-associated-types/issue-74816.next.stderr index 335486c6538c1..79aeaa79b4f19 100644 --- a/tests/ui/generic-associated-types/issue-74816.next.stderr +++ b/tests/ui/generic-associated-types/issue-74816.next.stderr @@ -20,11 +20,11 @@ error[E0277]: the size for values of type `Self` cannot be known at compilation LL | type Associated: Trait1 = Self; | ^^^^ doesn't have a size known at compile-time | -note: required by a bound in `Trait2::Associated` +note: required by an implicit `Sized` bound in `Trait2::Associated` --> $DIR/issue-74816.rs:12:5 | LL | type Associated: Trait1 = Self; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Trait2::Associated` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by the implicit `Sized` requirement on this associated type in `Trait2::Associated` help: consider further restricting `Self` | LL | trait Trait2: Sized { diff --git a/tests/ui/generics/ssa-rval-monomorphization-issue-157922.rs b/tests/ui/generics/ssa-rval-monomorphization-issue-157922.rs new file mode 100644 index 0000000000000..f7ebc58e5400a --- /dev/null +++ b/tests/ui/generics/ssa-rval-monomorphization-issue-157922.rs @@ -0,0 +1,25 @@ +//@ build-pass +// (codegen test) +// +// Ensure that the "freeze" check on stores works correctly in generic functions. +// Regression test for [#157922](https://github.com/rust-lang/rust/issues/157922). + +pub trait Field { + type Value; +} + +pub struct S; + +impl Field for S

{ + type Value = (); +} + +pub struct Foo(F::Value); + +fn f(a: &Foo>) { + let _f = if 1 > 0 { a } else { a }; +} + +pub fn main() { + f(&Foo::>(())); +} diff --git a/tests/ui/higher-ranked/structually-relate-aliases.stderr b/tests/ui/higher-ranked/structually-relate-aliases.stderr index 4649aac47cdbf..8996bf11b3721 100644 --- a/tests/ui/higher-ranked/structually-relate-aliases.stderr +++ b/tests/ui/higher-ranked/structually-relate-aliases.stderr @@ -1,4 +1,4 @@ - WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTerm { args: [?1t, '^0.Named(DefId(0:15 ~ structually_relate_aliases[de75]::{impl#1}::'a))], kind: ProjectionTy { def_id: DefId(0:5 ~ structually_relate_aliases[de75]::ToUnit::Unit) }, .. } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: Alias { kind: ProjectionTy { def_id: DefId(0:5 ~ structually_relate_aliases[de75]::ToUnit::Unit) }, args: [?1t, '^0.Named(DefId(0:15 ~ structually_relate_aliases[de75]::{impl#1}::'a))], .. } error[E0277]: the trait bound `for<'a> T: ToUnit<'a>` is not satisfied --> $DIR/structually-relate-aliases.rs:13:36 | diff --git a/tests/ui/impl-trait/in-trait/refine-resolution-errors.stderr b/tests/ui/impl-trait/in-trait/refine-resolution-errors.stderr index af71e52b87d71..8b730d9535d0a 100644 --- a/tests/ui/impl-trait/in-trait/refine-resolution-errors.stderr +++ b/tests/ui/impl-trait/in-trait/refine-resolution-errors.stderr @@ -13,11 +13,11 @@ LL | LL | type Assoc = T; | ^ doesn't have a size known at compile-time | -note: required by a bound in `Mirror::Assoc` +note: required by an implicit `Sized` bound in `Mirror::Assoc` --> $DIR/refine-resolution-errors.rs:7:5 | LL | type Assoc; - | ^^^^^^^^^^^ required by this bound in `Mirror::Assoc` + | ^^^^^^^^^^^ required by the implicit `Sized` requirement on this associated type in `Mirror::Assoc` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - impl Mirror for () { diff --git a/tests/ui/linking/staticlib-rename-internal-symbols-wrong-crate-type.rs b/tests/ui/linking/staticlib-rename-internal-symbols-wrong-crate-type.rs new file mode 100644 index 0000000000000..684bdbda6969b --- /dev/null +++ b/tests/ui/linking/staticlib-rename-internal-symbols-wrong-crate-type.rs @@ -0,0 +1,8 @@ +//@ check-pass +//@ compile-flags: -Zstaticlib-rename-internal-symbols --crate-type bin + +#![feature(no_core)] +#![no_core] +#![no_main] + +//~? WARN has no effect without `--crate-type staticlib` diff --git a/tests/ui/linking/staticlib-rename-internal-symbols-wrong-crate-type.stderr b/tests/ui/linking/staticlib-rename-internal-symbols-wrong-crate-type.stderr new file mode 100644 index 0000000000000..d4095ede81a34 --- /dev/null +++ b/tests/ui/linking/staticlib-rename-internal-symbols-wrong-crate-type.stderr @@ -0,0 +1,2 @@ +warning: -Zstaticlib-rename-internal-symbols has no effect without `--crate-type staticlib` + diff --git a/tests/ui/mir/drop-elaboration-after-borrowck-error.stderr b/tests/ui/mir/drop-elaboration-after-borrowck-error.stderr index 22d05fa4ddab0..a3b8b97b3ac0c 100644 --- a/tests/ui/mir/drop-elaboration-after-borrowck-error.stderr +++ b/tests/ui/mir/drop-elaboration-after-borrowck-error.stderr @@ -6,6 +6,10 @@ LL | a[0] = String::new(); | | | the destructor for this type cannot be evaluated in statics | value is dropped here + | + = note: see issue #133214 for more information + = help: add `#![feature(const_destruct)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0493]: destructor of `[String; 1]` cannot be evaluated at compile-time --> $DIR/drop-elaboration-after-borrowck-error.rs:5:9 @@ -15,6 +19,10 @@ LL | let a: [String; 1]; ... LL | }; | - value is dropped here + | + = note: see issue #133214 for more information + = help: add `#![feature(const_destruct)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0493]: destructor of `T` cannot be evaluated at compile-time --> $DIR/drop-elaboration-after-borrowck-error.rs:17:9 diff --git a/tests/ui/offset-of/inside-array-length.stderr b/tests/ui/offset-of/inside-array-length.stderr index fd47e6c8b6805..4b2a50acf82cb 100644 --- a/tests/ui/offset-of/inside-array-length.stderr +++ b/tests/ui/offset-of/inside-array-length.stderr @@ -37,7 +37,7 @@ LL | fn foo<'a, T: 'a>(_: [(); std::mem::offset_of!((T,), 0)]) {} = note: ...which requires caching mir of `foo::{constant#0}` for CTFE... = note: ...which requires elaborating drops for `foo::{constant#0}`... = note: ...which requires borrow-checking `foo::{constant#0}`... - = note: ...which requires normalizing `Binder { value: ConstEvaluatable(UnevaluatedConst { kind: Anon { def_id: DefId(0:7 ~ inside_array_length[07d6]::foo::{constant#0}) }, args: ['^c_1, T/#1], .. }), bound_vars: [] }`... + = note: ...which requires normalizing `Binder { value: ConstEvaluatable(Alias { kind: Anon { def_id: DefId(0:7 ~ inside_array_length[07d6]::foo::{constant#0}) }, args: ['^c_1, T/#1], .. }), bound_vars: [] }`... = note: ...which again requires evaluating type-level constant, completing the cycle = note: cycle used when normalizing `inside_array_length::::foo::{constant#0}` = note: for more information, see and diff --git a/tests/ui/sized-hierarchy/overflow.current.stderr b/tests/ui/sized-hierarchy/overflow.current.stderr index da58a6d2f7bf6..9853be2a7f8e0 100644 --- a/tests/ui/sized-hierarchy/overflow.current.stderr +++ b/tests/ui/sized-hierarchy/overflow.current.stderr @@ -8,9 +8,9 @@ note: required for `Box` to implement `ParseTokens` --> $DIR/overflow.rs:13:31 | LL | impl ParseTokens for Box { - | - ^^^^^^^^^^^ ^^^^^^ - | | - | unsatisfied trait bound introduced here + | ------ ^^^^^^^^^^^ ^^^^^^ + | | + | unsatisfied trait bound introduced here = note: 1 redundant requirement hidden = note: required for `Box>` to implement `ParseTokens` diff --git a/tests/ui/trait-bounds/enum-unit-variant-trait-bound.stderr b/tests/ui/trait-bounds/enum-unit-variant-trait-bound.stderr index 9a3bcaa0c4aa4..7402129cddeac 100644 --- a/tests/ui/trait-bounds/enum-unit-variant-trait-bound.stderr +++ b/tests/ui/trait-bounds/enum-unit-variant-trait-bound.stderr @@ -5,7 +5,7 @@ LL | let _ = Option::<[u8]>::None; | ^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[u8]` -note: required by a bound in `None` +note: required by an implicit `Sized` bound in `None` --> $SRC_DIR/core/src/option.rs:LL:COL error: aborting due to 1 previous error diff --git a/tests/ui/trait-bounds/suggest-maybe-sized-bound.stderr b/tests/ui/trait-bounds/suggest-maybe-sized-bound.stderr index b459ad47e067a..63d3b01f27a2e 100644 --- a/tests/ui/trait-bounds/suggest-maybe-sized-bound.stderr +++ b/tests/ui/trait-bounds/suggest-maybe-sized-bound.stderr @@ -22,11 +22,11 @@ LL | type P = [u8]; | ^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[u8]` -note: required by a bound in `main::Trait::P` +note: required by an implicit `Sized` bound in `main::Trait::P` --> $DIR/suggest-maybe-sized-bound.rs:13:9 | LL | type P; - | ^^^^^^^^^^ required by this bound in `Trait::P` + | ^^^^^^^^^^ required by the implicit `Sized` requirement on this associated type in `Trait::P` help: consider relaxing the implicit `Sized` restriction | LL | type P: ?Sized; diff --git a/tests/ui/traits/const-traits/const-closure-with-indestructible-indestructible.next.stderr b/tests/ui/traits/const-traits/const-closure-with-indestructible-indestructible.next.stderr index 8b5c4f59fbdee..62d9091c50b10 100644 --- a/tests/ui/traits/const-traits/const-closure-with-indestructible-indestructible.next.stderr +++ b/tests/ui/traits/const-traits/const-closure-with-indestructible-indestructible.next.stderr @@ -1,20 +1,20 @@ -error[E0277]: the trait bound `Vec: const Destruct` is not satisfied - --> $DIR/const-closure-with-indestructible-indestructible.rs:10:16 +error[E0277]: the trait bound `NotConstDestruct: const Destruct` is not satisfied + --> $DIR/const-closure-with-indestructible-indestructible.rs:18:16 | LL | i_need(const || { | _________------_^ | | | | | required by a bound introduced by this call LL | | -LL | | let y = v; +LL | | let y = n; LL | | }) | |_________^ | note: required by a bound in `i_need` - --> $DIR/const-closure-with-indestructible-indestructible.rs:5:20 + --> $DIR/const-closure-with-indestructible-indestructible.rs:13:20 | -LL | const fn i_need(x: F) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `i_need` +LL | const fn i_need(x: F) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `i_need` error: aborting due to 1 previous error diff --git a/tests/ui/traits/const-traits/const-closure-with-indestructible-indestructible.old.stderr b/tests/ui/traits/const-traits/const-closure-with-indestructible-indestructible.old.stderr index 8b5c4f59fbdee..62d9091c50b10 100644 --- a/tests/ui/traits/const-traits/const-closure-with-indestructible-indestructible.old.stderr +++ b/tests/ui/traits/const-traits/const-closure-with-indestructible-indestructible.old.stderr @@ -1,20 +1,20 @@ -error[E0277]: the trait bound `Vec: const Destruct` is not satisfied - --> $DIR/const-closure-with-indestructible-indestructible.rs:10:16 +error[E0277]: the trait bound `NotConstDestruct: const Destruct` is not satisfied + --> $DIR/const-closure-with-indestructible-indestructible.rs:18:16 | LL | i_need(const || { | _________------_^ | | | | | required by a bound introduced by this call LL | | -LL | | let y = v; +LL | | let y = n; LL | | }) | |_________^ | note: required by a bound in `i_need` - --> $DIR/const-closure-with-indestructible-indestructible.rs:5:20 + --> $DIR/const-closure-with-indestructible-indestructible.rs:13:20 | -LL | const fn i_need(x: F) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `i_need` +LL | const fn i_need(x: F) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `i_need` error: aborting due to 1 previous error diff --git a/tests/ui/traits/const-traits/const-closure-with-indestructible-indestructible.rs b/tests/ui/traits/const-traits/const-closure-with-indestructible-indestructible.rs index d26260dd2d078..c6dcd119347d4 100644 --- a/tests/ui/traits/const-traits/const-closure-with-indestructible-indestructible.rs +++ b/tests/ui/traits/const-traits/const-closure-with-indestructible-indestructible.rs @@ -2,14 +2,22 @@ //@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver #![feature(const_trait_impl, const_closures, const_destruct)] -const fn i_need(x: F) {} + + +struct NotConstDestruct; + +impl Drop for NotConstDestruct { + fn drop(&mut self) {} +} + +const fn i_need(x: F) {} fn main() { const { - let v = Vec::::new(); + let n = NotConstDestruct; i_need(const || { //~^ ERROR the trait bound - let y = v; + let y = n; }) }; } diff --git a/tests/ui/traits/cycle-cache-err-60010.stderr b/tests/ui/traits/cycle-cache-err-60010.stderr index 9665d5badf599..605ef34e5d2b8 100644 --- a/tests/ui/traits/cycle-cache-err-60010.stderr +++ b/tests/ui/traits/cycle-cache-err-60010.stderr @@ -80,11 +80,11 @@ note: required because it appears within the type `SalsaStorage` | LL | struct SalsaStorage { | ^^^^^^^^^^^^ -note: required by a bound in `Database::Storage` +note: required by an implicit `Sized` bound in `Database::Storage` --> $DIR/cycle-cache-err-60010.rs:7:5 | LL | type Storage; - | ^^^^^^^^^^^^^ required by this bound in `Database::Storage` + | ^^^^^^^^^^^^^ required by the implicit `Sized` requirement on this associated type in `Database::Storage` help: consider relaxing the implicit `Sized` restriction | LL | type Storage: ?Sized; diff --git a/tests/ui/traits/next-solver/issue-118950-root-region.stderr b/tests/ui/traits/next-solver/issue-118950-root-region.stderr index 32adbb491bee7..eac8b6e11bf1b 100644 --- a/tests/ui/traits/next-solver/issue-118950-root-region.stderr +++ b/tests/ui/traits/next-solver/issue-118950-root-region.stderr @@ -16,7 +16,7 @@ help: this trait has no implementations, consider adding one LL | trait ToUnit<'a> { | ^^^^^^^^^^^^^^^^ - WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTerm { args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a)), ?1t], kind: FreeTy { def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) }, .. } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: Alias { kind: FreeTy { def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) }, args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a)), ?1t], .. } error: aborting due to 2 previous errors Some errors have detailed explanations: E0277, E0425. diff --git a/tests/ui/traits/normalize/unconstrained-projection-normalization-2.current.stderr b/tests/ui/traits/normalize/unconstrained-projection-normalization-2.current.stderr index e8742e7f09902..3ec07397ec148 100644 --- a/tests/ui/traits/normalize/unconstrained-projection-normalization-2.current.stderr +++ b/tests/ui/traits/normalize/unconstrained-projection-normalization-2.current.stderr @@ -22,11 +22,11 @@ LL | LL | type Assoc = T; | ^ doesn't have a size known at compile-time | -note: required by a bound in `Every::Assoc` +note: required by an implicit `Sized` bound in `Every::Assoc` --> $DIR/unconstrained-projection-normalization-2.rs:12:5 | LL | type Assoc; - | ^^^^^^^^^^^ required by this bound in `Every::Assoc` + | ^^^^^^^^^^^ required by the implicit `Sized` requirement on this associated type in `Every::Assoc` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - impl Every for Thing { diff --git a/tests/ui/traits/normalize/unconstrained-projection-normalization-2.next.stderr b/tests/ui/traits/normalize/unconstrained-projection-normalization-2.next.stderr index e8742e7f09902..3ec07397ec148 100644 --- a/tests/ui/traits/normalize/unconstrained-projection-normalization-2.next.stderr +++ b/tests/ui/traits/normalize/unconstrained-projection-normalization-2.next.stderr @@ -22,11 +22,11 @@ LL | LL | type Assoc = T; | ^ doesn't have a size known at compile-time | -note: required by a bound in `Every::Assoc` +note: required by an implicit `Sized` bound in `Every::Assoc` --> $DIR/unconstrained-projection-normalization-2.rs:12:5 | LL | type Assoc; - | ^^^^^^^^^^^ required by this bound in `Every::Assoc` + | ^^^^^^^^^^^ required by the implicit `Sized` requirement on this associated type in `Every::Assoc` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - impl Every for Thing { diff --git a/tests/ui/traits/normalize/unconstrained-projection-normalization.current.stderr b/tests/ui/traits/normalize/unconstrained-projection-normalization.current.stderr index 6e908df0aba2d..73bf568d8aec0 100644 --- a/tests/ui/traits/normalize/unconstrained-projection-normalization.current.stderr +++ b/tests/ui/traits/normalize/unconstrained-projection-normalization.current.stderr @@ -22,11 +22,11 @@ LL | LL | type Assoc = T; | ^ doesn't have a size known at compile-time | -note: required by a bound in `Every::Assoc` +note: required by an implicit `Sized` bound in `Every::Assoc` --> $DIR/unconstrained-projection-normalization.rs:11:5 | LL | type Assoc; - | ^^^^^^^^^^^ required by this bound in `Every::Assoc` + | ^^^^^^^^^^^ required by the implicit `Sized` requirement on this associated type in `Every::Assoc` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - impl Every for Thing { diff --git a/tests/ui/traits/normalize/unconstrained-projection-normalization.next.stderr b/tests/ui/traits/normalize/unconstrained-projection-normalization.next.stderr index 6e908df0aba2d..73bf568d8aec0 100644 --- a/tests/ui/traits/normalize/unconstrained-projection-normalization.next.stderr +++ b/tests/ui/traits/normalize/unconstrained-projection-normalization.next.stderr @@ -22,11 +22,11 @@ LL | LL | type Assoc = T; | ^ doesn't have a size known at compile-time | -note: required by a bound in `Every::Assoc` +note: required by an implicit `Sized` bound in `Every::Assoc` --> $DIR/unconstrained-projection-normalization.rs:11:5 | LL | type Assoc; - | ^^^^^^^^^^^ required by this bound in `Every::Assoc` + | ^^^^^^^^^^^ required by the implicit `Sized` requirement on this associated type in `Every::Assoc` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - impl Every for Thing {