diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index b8339c74dac03..b8d54df4fb75a 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -31,7 +31,8 @@ use rustc_data_structures::tagged_ptr::Tag; use rustc_macros::{Decodable, Encodable, StableHash, Walkable}; pub use rustc_span::AttrId; use rustc_span::{ - ByteSymbol, DUMMY_SP, ErrorGuaranteed, Ident, Span, Spanned, Symbol, kw, respan, sym, + ByteSymbol, DUMMY_SP, ErrorGuaranteed, Ident, LocalExpnId, Span, Spanned, Symbol, kw, respan, + sym, }; use thin_vec::{ThinVec, thin_vec}; @@ -3906,10 +3907,10 @@ pub struct EiiImpl { pub is_default: bool, } -#[derive(Clone, Encodable, Decodable, Debug, Walkable, PartialEq, Eq)] +#[derive(Clone, Copy, Encodable, Decodable, Debug, PartialEq, Eq)] pub enum DelegationSource { Single, - List, + List(LocalExpnId), Glob, } @@ -3923,6 +3924,7 @@ pub struct Delegation { pub rename: Option, pub body: Option>, /// The item was expanded from a glob delegation item. + #[visitable(ignore)] pub source: DelegationSource, } diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 19255e55506f9..1e96d1d52f7eb 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -431,7 +431,6 @@ macro_rules! common_visitor_and_walkers { Delegation, DelegationMac, DelegationSuffixes, - DelegationSource, DelimArgs, DelimSpan, EnumDef, diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs index 68ae9e68b029a..90c7604b7babc 100644 --- a/compiler/rustc_ast_lowering/src/delegation.rs +++ b/compiler/rustc_ast_lowering/src/delegation.rs @@ -62,7 +62,7 @@ use crate::diagnostics::{ }; use crate::{ AllowReturnTypeNotation, ImplTraitContext, ImplTraitPosition, LoweringContext, ParamMode, - ResolverAstLoweringExt, index_crate, + index_crate, }; mod generics; @@ -126,7 +126,7 @@ pub(crate) fn delegations_resolutions( let delegation = ast_index[def_id].delegation().expect("processing delegations"); let span = delegation.last_segment_span(); - if let Some(info) = resolver.delegation_info(def_id) { + if let Some(info) = tcx.resolutions(()).delegation_infos.get(&def_id) { let res = info.resolution_id.map(|id| check_for_cycles(tcx, id, span).map(|_| id)); result.insert(def_id, res.flatten()); } else { @@ -143,8 +143,6 @@ pub(crate) fn delegations_resolutions( fn check_for_cycles(tcx: TyCtxt<'_>, mut def_id: DefId, span: Span) -> Result<(), ErrorGuaranteed> { let mut visited: FxHashSet = Default::default(); - let (resolver, _) = &*tcx.hir_crate(()).delayed_resolver.borrow(); - loop { visited.insert(def_id); @@ -152,7 +150,7 @@ fn check_for_cycles(tcx: TyCtxt<'_>, mut def_id: DefId, span: Span) -> Result<() // it means that we refer to another delegation as a callee, so in order to obtain // a signature DefId we obtain NodeId of the callee delegation and try to get signature from it. if let Some(local_id) = def_id.as_local() - && let Some(info) = resolver.delegation_info(local_id) + && let Some(info) = tcx.resolutions(()).delegation_infos.get(&local_id) && let Ok(id) = info.resolution_id { def_id = id; @@ -209,10 +207,11 @@ impl<'hir> LoweringContext<'_, 'hir> { let mut generics = self.uplift_delegation_generics(delegation, sig_id, is_method); - let (body_id, call_expr_id) = + let (body_id, call_expr_id, unused_target_expr) = self.lower_delegation_body(delegation, sig_id, param_count, &mut generics, span); let decl = self.lower_delegation_decl( + delegation.source, sig_id, param_count, c_variadic, @@ -220,6 +219,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &generics, delegation.id, call_expr_id, + unused_target_expr, ); let sig = self.lower_delegation_sig(sig_id, decl, span); @@ -375,6 +375,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_delegation_decl( &mut self, + source: DelegationSource, sig_id: DefId, param_count: usize, c_variadic: bool, @@ -382,6 +383,7 @@ impl<'hir> LoweringContext<'_, 'hir> { generics: &GenericsGenerationResults<'hir>, call_path_node_id: NodeId, call_expr_id: HirId, + unused_target_expr: bool, ) -> &'hir hir::FnDecl<'hir> { // The last parameter in C variadic functions is skipped in the signature, // like during regular lowering. @@ -406,6 +408,17 @@ impl<'hir> LoweringContext<'_, 'hir> { parent_args_segment_id: generics.parent.args_segment_id, self_ty_id: generics.self_ty_id, propagate_self_ty: generics.propagate_self_ty, + group_id: { + let id = match source { + DelegationSource::Single => None, + DelegationSource::List(expn_id) => Some(expn_id), + DelegationSource::Glob => { + Some(self.tcx.expn_that_defined(self.owner.def_id).expect_local()) + } + }; + + id.map(|id| (id, unused_target_expr)) + }, })), )), span, @@ -504,9 +517,10 @@ impl<'hir> LoweringContext<'_, 'hir> { param_count: usize, generics: &mut GenericsGenerationResults<'hir>, span: Span, - ) -> (BodyId, HirId) { + ) -> (BodyId, HirId, bool) { let block = delegation.body.as_deref(); let mut call_expr_id = HirId::INVALID; + let mut unused_target_expr = false; let block_id = self.lower_body(|this| { let mut parameters: Vec> = Vec::with_capacity(param_count); @@ -514,6 +528,12 @@ impl<'hir> LoweringContext<'_, 'hir> { let mut stmts: &[hir::Stmt<'hir>] = &[]; let is_method = this.is_method(sig_id, span); + let should_generate_block = this.should_generate_block(delegation, sig_id, is_method); + + // Consider non-specified target expression as generated, + // as we do not want to emit error when target expression is + // not specified. + unused_target_expr = block.is_some() && (param_count == 0 || !should_generate_block); for idx in 0..param_count { let (param, pat_node_id) = this.generate_param(is_method, idx, span); @@ -524,7 +544,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let arg = if let Some(block) = block && idx == 0 - && this.should_generate_block(delegation, sig_id, is_method) + && should_generate_block { let mut self_resolver = SelfResolver { ctxt: this, @@ -565,7 +585,7 @@ impl<'hir> LoweringContext<'_, 'hir> { debug_assert_ne!(call_expr_id, HirId::INVALID); - (block_id, call_expr_id) + (block_id, call_expr_id, unused_target_expr) } fn finalize_body_lowering( diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index a18f0c2f69548..59ac413a6eac5 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -63,7 +63,7 @@ use rustc_macros::extension; use rustc_middle::hir::{self as mid_hir}; use rustc_middle::queries::Providers; use rustc_middle::span_bug; -use rustc_middle::ty::{DelegationInfo, PerOwnerResolverData, ResolverAstLowering, TyCtxt}; +use rustc_middle::ty::{PerOwnerResolverData, ResolverAstLowering, TyCtxt}; use rustc_session::errors::add_feature_diagnostics; use rustc_span::symbol::{Ident, Symbol, kw, sym}; use rustc_span::{DUMMY_SP, DesugaringKind, Span}; @@ -307,10 +307,6 @@ impl<'tcx> ResolverAstLowering<'tcx> { self.extra_lifetime_params_map.get(&id).map_or(&[], |v| &v[..]) } - fn delegation_info(&self, id: LocalDefId) -> Option<&DelegationInfo> { - self.delegation_infos.get(&id) - } - fn owner_def_id(&self, id: NodeId) -> LocalDefId { self.owners[&id].def_id } diff --git a/compiler/rustc_codegen_ssa/src/back/archive.rs b/compiler/rustc_codegen_ssa/src/back/archive.rs index 66f9c7f8e15eb..b5d5893941ef2 100644 --- a/compiler/rustc_codegen_ssa/src/back/archive.rs +++ b/compiler/rustc_codegen_ssa/src/back/archive.rs @@ -1,18 +1,16 @@ +use std::env; use std::error::Error; use std::ffi::OsString; use std::fs::{self, File}; use std::io::{self, BufWriter, Write}; use std::path::{Path, PathBuf}; -use std::{env, mem}; use ar_archive_writer::{ ArchiveKind, COFFShortExport, MachineTypes, NewArchiveMember, write_archive_to_stream, }; pub use ar_archive_writer::{DEFAULT_OBJECT_READER, ObjectReader}; use object::read::archive::{ArchiveFile, ArchiveKind as ObjectArchiveKind}; -use object::read::elf::Sym as _; -use object::read::macho::{FatArch, Nlist}; -use object::{Endianness, elf, macho}; +use object::read::macho::FatArch; use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; use rustc_data_structures::memmap::Mmap; use rustc_fs_util::TempDirBuilder; @@ -24,6 +22,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 crate::common; // Public for ArchiveBuilderBuilder::extract_bundled_libs pub use crate::errors::ExtractBundledLibsError; @@ -671,153 +670,3 @@ impl<'a> ArArchiveBuilder<'a> { fn io_error_context(context: &str, err: io::Error) -> io::Error { io::Error::new(io::ErrorKind::Other, format!("{context}: {err}")) } - -// 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. - -/// 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; - } - buf -} - -// --------------------------------------------------------------------------- -// ELF hide – read-only pass uses `object` crate, write pass uses `Patch` list -// --------------------------------------------------------------------------- - -fn elf_hide_patches_impl<'data, Elf: object::read::elf::FileHeader>( - data: &'data [u8], - st_other_offset: usize, - exported: &FxHashSet, -) -> Option> -where - u64: From, -{ - let header = Elf::parse(data).ok()?; - 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(); - - 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 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 }); - } - } - - Some(patches) -} - -// --------------------------------------------------------------------------- -// Mach-O hide – same architecture: read-only pass via `object`, write via patches -// --------------------------------------------------------------------------- - -fn macho_hide_patches_impl<'data, Mach: object::read::macho::MachHeader>( - data: &'data [u8], - n_type_offset: usize, - exported: &FxHashSet, -) -> 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 cmd = commands.next().ok()??; - if let Some(st) = cmd.symtab().ok().flatten() { - break st; - } - }; - 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(); - - 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 offset = nlist_addr - data_ptr + n_type_offset; - patches.push(Patch { offset, value: nlist.n_type() | macho::N_PEXT }); - } - } - - Some(patches) -} - -// --------------------------------------------------------------------------- -// Unified dispatch: top-level detection via `object::File::parse` -// --------------------------------------------------------------------------- - -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 apply_hide(data: &[u8], exported: &FxHashSet) -> Vec { - let patches = hide_patches(data, exported).unwrap_or_default(); - apply_patches(data, &patches) -} diff --git a/compiler/rustc_codegen_ssa/src/back/mod.rs b/compiler/rustc_codegen_ssa/src/back/mod.rs index 17f6faa942c49..0f5050a9d7a9a 100644 --- a/compiler/rustc_codegen_ssa/src/back/mod.rs +++ b/compiler/rustc_codegen_ssa/src/back/mod.rs @@ -11,6 +11,7 @@ pub mod lto; pub mod metadata; pub mod rmeta_link; pub(crate) mod rpath; +mod symbol_edit; pub mod symbol_export; pub mod write; diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_edit.rs b/compiler/rustc_codegen_ssa/src/back/symbol_edit.rs new file mode 100644 index 0000000000000..19ecb3d92d209 --- /dev/null +++ b/compiler/rustc_codegen_ssa/src/back/symbol_edit.rs @@ -0,0 +1,156 @@ +// 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. + +use std::mem; + +use object::read::elf::Sym as _; +use object::read::macho::Nlist; +use object::{Endianness, elf, macho}; +use rustc_data_structures::fx::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; + } + buf +} + +// --------------------------------------------------------------------------- +// ELF hide – read-only pass uses `object` crate, write pass uses `Patch` list +// --------------------------------------------------------------------------- + +fn elf_hide_patches_impl<'data, Elf: object::read::elf::FileHeader>( + data: &'data [u8], + st_other_offset: usize, + exported: &FxHashSet, +) -> Option> +where + u64: From, +{ + let header = Elf::parse(data).ok()?; + 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(); + + 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 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 }); + } + } + + Some(patches) +} + +// --------------------------------------------------------------------------- +// Mach-O hide – same architecture: read-only pass via `object`, write via patches +// --------------------------------------------------------------------------- + +fn macho_hide_patches_impl<'data, Mach: object::read::macho::MachHeader>( + data: &'data [u8], + n_type_offset: usize, + exported: &FxHashSet, +) -> 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 cmd = commands.next().ok()??; + if let Some(st) = cmd.symtab().ok().flatten() { + break st; + } + }; + 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(); + + 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 offset = nlist_addr - data_ptr + n_type_offset; + patches.push(Patch { offset, value: nlist.n_type() | macho::N_PEXT }); + } + } + + Some(patches) +} + +// --------------------------------------------------------------------------- +// Unified dispatch: top-level detection via `object::File::parse` +// --------------------------------------------------------------------------- + +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, + } +} + +pub(super) fn apply_hide(data: &[u8], exported: &FxHashSet) -> Vec { + let patches = hide_patches(data, exported).unwrap_or_default(); + apply_patches(data, &patches) +} diff --git a/compiler/rustc_data_structures/src/graph/linked_graph/mod.rs b/compiler/rustc_data_structures/src/graph/linked_graph/mod.rs index 2223e85a24957..cecb051172598 100644 --- a/compiler/rustc_data_structures/src/graph/linked_graph/mod.rs +++ b/compiler/rustc_data_structures/src/graph/linked_graph/mod.rs @@ -45,17 +45,19 @@ mod tests; /// This graph implementation predates the later [graph traits](crate::graph), /// and does not implement those traits, so it has its own implementations of a /// few basic graph algorithms. +#[derive(Clone)] pub struct LinkedGraph { nodes: IndexVec>, edges: Vec>, } +#[derive(Clone)] pub struct Node { first_edge: [EdgeIndex; 2], // see module comment pub data: Option, } -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct Edge { next_edge: [EdgeIndex; 2], // see module comment source: NodeIndex, diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 55f10867c9321..c2d09da3b0e82 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -24,6 +24,7 @@ use std::io::Write; use std::num::NonZero; use std::ops::DerefMut; use std::path::{Path, PathBuf}; +use std::thread::ThreadId; use std::{assert_matches, fmt, panic}; use Level::*; @@ -297,11 +298,12 @@ impl<'a> std::ops::Deref for DiagCtxtHandle<'a> { struct DiagCtxtInner { flags: DiagCtxtFlags, - /// The error guarantees from all emitted errors. The length gives the error count. - err_guars: Vec, - /// The error guarantee from all emitted lint errors. The length gives the - /// lint error count. - lint_err_guars: Vec, + /// The error guarantees from all emitted errors, each paired with the + /// thread that emitted it. The length gives the error count. + err_guars: Vec<(ErrorGuaranteed, ThreadId)>, + /// The error guarantee from all emitted lint errors, each paired with the + /// thread that emitted it. The length gives the lint error count. + lint_err_guars: Vec<(ErrorGuaranteed, ThreadId)>, /// The delayed bugs and their error guarantees. delayed_bugs: Vec<(DelayedDiagInner, ErrorGuaranteed)>, @@ -343,7 +345,7 @@ struct DiagCtxtInner { /// `emit_stashed_diagnostics` by the time the `DiagCtxtInner` is dropped, /// otherwise an assertion failure will occur. stashed_diagnostics: - FxIndexMap)>>, + FxIndexMap, ThreadId)>>, future_breakage_diagnostics: Vec, @@ -613,7 +615,7 @@ impl<'a> DiagCtxtHandle<'a> { .stashed_diagnostics .entry(key) .or_default() - .insert(span.with_parent(None), (diag, guar)); + .insert(span.with_parent(None), (diag, guar, std::thread::current().id())); guar } @@ -623,7 +625,7 @@ impl<'a> DiagCtxtHandle<'a> { /// error. pub fn steal_non_err(self, span: Span, key: StashKey) -> Option> { // FIXME(#120456) - is `swap_remove` correct? - let (diag, guar) = self.inner.borrow_mut().stashed_diagnostics.get_mut(&key).and_then( + let (diag, guar, _) = self.inner.borrow_mut().stashed_diagnostics.get_mut(&key).and_then( |stashed_diagnostics| stashed_diagnostics.swap_remove(&span.with_parent(None)), )?; assert!(!diag.is_error()); @@ -648,7 +650,7 @@ impl<'a> DiagCtxtHandle<'a> { let err = self.inner.borrow_mut().stashed_diagnostics.get_mut(&key).and_then( |stashed_diagnostics| stashed_diagnostics.swap_remove(&span.with_parent(None)), ); - err.map(|(err, guar)| { + err.map(|(err, guar, _)| { // The use of `::` is safe because level is `Level::Error`. assert_eq!(err.level, Error); assert!(guar.is_some()); @@ -673,7 +675,7 @@ impl<'a> DiagCtxtHandle<'a> { |stashed_diagnostics| stashed_diagnostics.swap_remove(&span.with_parent(None)), ); match old_err { - Some((old_err, guar)) => { + Some((old_err, guar, _)) => { assert_eq!(old_err.level, Error); assert!(guar.is_some()); // Because `old_err` has already been counted, it can only be @@ -710,7 +712,27 @@ impl<'a> DiagCtxtHandle<'a> { + inner .stashed_diagnostics .values() - .map(|a| a.values().filter(|(_, guar)| guar.is_some()).count()) + .map(|a| a.values().filter(|(_, guar, _)| guar.is_some()).count()) + .sum::() + } + + /// The number of errors that have been emitted on the *current thread*. + /// + /// Like [`DiagCtxtHandle::err_count`], but only counts errors whose recorded + /// emitting thread is the calling thread. + pub fn err_count_on_current_thread(&self) -> usize { + let inner = self.inner.borrow(); + let current = std::thread::current().id(); + inner.err_guars.iter().filter(|(_, thread)| *thread == current).count() + + inner.lint_err_guars.iter().filter(|(_, thread)| *thread == current).count() + + inner + .stashed_diagnostics + .values() + .map(|a| { + a.values() + .filter(|(_, guar, thread)| guar.is_some() && *thread == current) + .count() + }) .sum::() } @@ -879,7 +901,8 @@ impl<'a> DiagCtxtHandle<'a> { // This `unchecked_error_guaranteed` is valid. It is where the // `ErrorGuaranteed` for unused_extern errors originates. #[allow(deprecated)] - inner.lint_err_guars.push(ErrorGuaranteed::unchecked_error_guaranteed()); + let guar = ErrorGuaranteed::unchecked_error_guaranteed(); + inner.lint_err_guars.push((guar, std::thread::current().id())); inner.panic_if_treat_err_as_bug(); } @@ -1178,7 +1201,7 @@ impl DiagCtxtInner { let mut guar = None; let has_errors = !self.err_guars.is_empty(); for (_, stashed_diagnostics) in std::mem::take(&mut self.stashed_diagnostics).into_iter() { - for (_, (diag, _guar)) in stashed_diagnostics { + for (_, (diag, _guar, _thread)) in stashed_diagnostics { if !diag.is_error() { // Unless they're forced, don't flush stashed warnings when // there are errors, to avoid causing warning overload. The @@ -1347,13 +1370,14 @@ impl DiagCtxtInner { // `ErrorGuaranteed` for errors and lint errors originates. #[allow(deprecated)] let guar = ErrorGuaranteed::unchecked_error_guaranteed(); + let thread = std::thread::current().id(); if is_lint { - self.lint_err_guars.push(guar); + self.lint_err_guars.push((guar, thread)); } else { if let Some(taint) = taint { taint.set(Some(guar)); } - self.err_guars.push(guar); + self.err_guars.push((guar, thread)); } self.panic_if_treat_err_as_bug(); Some(guar) @@ -1377,12 +1401,12 @@ impl DiagCtxtInner { } fn has_errors_excluding_lint_errors(&self) -> Option { - self.err_guars.get(0).copied().or_else(|| { - if let Some((_diag, guar)) = self + self.err_guars.get(0).map(|(guar, _)| *guar).or_else(|| { + if let Some((_diag, guar, _)) = self .stashed_diagnostics .values() .flat_map(|stashed_diagnostics| stashed_diagnostics.values()) - .find(|(diag, guar)| guar.is_some() && diag.is_lint.is_none()) + .find(|(diag, guar, _)| guar.is_some() && diag.is_lint.is_none()) { *guar } else { @@ -1392,13 +1416,15 @@ impl DiagCtxtInner { } fn has_errors(&self) -> Option { - self.err_guars.get(0).copied().or_else(|| self.lint_err_guars.get(0).copied()).or_else( - || { + self.err_guars + .get(0) + .map(|(guar, _)| *guar) + .or_else(|| self.lint_err_guars.get(0).map(|(guar, _)| *guar)) + .or_else(|| { self.stashed_diagnostics.values().find_map(|stashed_diagnostics| { - stashed_diagnostics.values().find_map(|(_, guar)| *guar) + stashed_diagnostics.values().find_map(|(_, guar, _)| *guar) }) - }, - ) + }) } fn has_errors_or_delayed_bugs(&self) -> Option { diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 9f474fbeb7650..30a77811bb389 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -32,7 +32,7 @@ use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw}; use smallvec::{SmallVec, smallvec}; use thin_vec::ThinVec; -use crate::errors; +use crate::diagnostics; use crate::expand::{self, AstFragment, Invocation}; use crate::mbe::macro_rules::ParserAnyMacro; use crate::module::DirOwnership; @@ -954,7 +954,7 @@ impl SyntaxExtension { let stability = find_attr!(attrs, Stability { stability, .. } => *stability); if let Some(sp) = find_attr!(attrs, RustcBodyStability{ span, .. } => *span) { - sess.dcx().emit_err(errors::MacroBodyStability { + sess.dcx().emit_err(diagnostics::MacroBodyStability { span: sp, head_span: sess.source_map().guess_head_span(span), }); @@ -1358,7 +1358,7 @@ impl<'a> ExtCtxt<'a> { pub fn trace_macros_diag(&mut self) { for (span, notes) in self.expansions.iter() { - let mut db = self.dcx().create_note(errors::TraceMacro { span: *span }); + let mut db = self.dcx().create_note(diagnostics::TraceMacro { span: *span }); for note in notes { db.note(note.clone()); } @@ -1401,7 +1401,7 @@ pub fn resolve_path(sess: &Session, path: impl Into, span: Span) -> PRe let callsite = span.source_callsite(); let source_map = sess.source_map(); let Some(mut base_path) = source_map.span_to_filename(callsite).into_local_path() else { - return Err(sess.dcx().create_err(errors::ResolveRelativePath { + return Err(sess.dcx().create_err(diagnostics::ResolveRelativePath { span, path: source_map .filename_for_diagnostics(&source_map.span_to_filename(callsite)) diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index 2b914a2664fe5..1289f8ed63af6 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -31,7 +31,7 @@ use rustc_session::errors::feature_err; use rustc_span::{STDLIB_STABLE_CRATES, Span, Symbol, sym}; use tracing::instrument; -use crate::errors::{ +use crate::diagnostics::{ CrateNameInCfgAttr, CrateTypeInCfgAttr, FeatureNotAllowed, FeatureRemoved, FeatureRemovedReason, InvalidCfg, RemoveExprNotSupported, }; @@ -282,7 +282,7 @@ impl<'a> StripUnconfigured<'a> { rustc_lint_defs::builtin::UNUSED_ATTRIBUTES, cfg_attr.span, ast::CRATE_NODE_ID, - crate::errors::CfgAttrNoAttributes, + crate::diagnostics::CfgAttrNoAttributes, ); } diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/diagnostics.rs similarity index 100% rename from compiler/rustc_expand/src/errors.rs rename to compiler/rustc_expand/src/diagnostics.rs diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index ac16dbc2fa387..0fd21e017ff61 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -8,9 +8,9 @@ use rustc_ast::tokenstream::TokenStream; use rustc_ast::visit::{self, AssocCtxt, Visitor, VisitorResult, try_visit, walk_list}; use rustc_ast::{ self as ast, AssocItemKind, AstNodeWrapper, AttrArgs, AttrItemKind, AttrStyle, AttrVec, - DUMMY_NODE_ID, DelegationSuffixes, EarlyParsedAttribute, ExprKind, ForeignItemKind, HasAttrs, - HasNodeId, Inline, ItemKind, MacStmtStyle, MetaItemInner, MetaItemKind, ModKind, NodeId, - PatKind, StmtKind, TyKind, token, + DUMMY_NODE_ID, DelegationSource, DelegationSuffixes, EarlyParsedAttribute, ExprKind, + ForeignItemKind, HasAttrs, HasNodeId, Inline, ItemKind, MacStmtStyle, MetaItemInner, + MetaItemKind, ModKind, NodeId, PatKind, StmtKind, TyKind, token, }; use rustc_ast_pretty::pprust; use rustc_attr_parsing::parser::AllowExprMetavar; @@ -38,7 +38,7 @@ use smallvec::SmallVec; use crate::base::*; use crate::config::{StripUnconfigured, attr_into_trace}; -use crate::errors::{ +use crate::diagnostics::{ EmptyDelegationMac, GlobDelegationOutsideImpls, GlobDelegationTraitlessQpath, IncompleteParse, RecursionLimitReached, RemoveExprNotSupported, RemoveNodeNotSupported, UnsupportedKeyValue, WrongFragmentKind, @@ -992,7 +992,12 @@ impl<'a, 'b> MacroExpander<'a, 'b> { type Node = AstNodeWrapper, ImplItemTag>; let single_delegations = build_single_delegations::( - self.cx, deleg, &item, &suffixes, item.span, true, + self.cx, + deleg, + &item, + &suffixes, + item.span, + DelegationSource::Glob, ); // `-Zmacro-stats` ignores these because they don't seem important. fragment_kind.expect_from_annotatables(single_delegations.map(|item| { @@ -2041,8 +2046,12 @@ fn build_single_delegations<'a, Node: InvocationCollectorNode>( item: &'a ast::Item, suffixes: &'a [(Ident, Option)], item_span: Span, - from_glob: bool, + source: DelegationSource, ) -> impl Iterator> + 'a { + debug_assert_ne!(source, DelegationSource::Single); + + let from_glob = source == DelegationSource::Glob; + if suffixes.is_empty() { // Report an error for now, to avoid keeping stem for resolution and // stability checks. @@ -2066,11 +2075,7 @@ fn build_single_delegations<'a, Node: InvocationCollectorNode>( ident: rename.unwrap_or(ident), rename, body: deleg.body.clone(), - source: if from_glob { - ast::DelegationSource::Glob - } else { - ast::DelegationSource::List - }, + source, })), tokens: None, } @@ -2278,7 +2283,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { UNUSED_DOC_COMMENTS, current_span, self.cx.current_expansion.lint_node_id, - crate::errors::MacroCallUnusedDocComment { span: attr.span }, + crate::diagnostics::MacroCallUnusedDocComment { span: attr.span }, ); } else if rustc_attr_parsing::is_builtin_attr(attr) && !AttributeParser::is_parsed_attribute(&attr.path()) @@ -2288,7 +2293,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { UNUSED_ATTRIBUTES, attr.span, self.cx.current_expansion.lint_node_id, - crate::errors::UnusedBuiltinAttribute { + crate::diagnostics::UnusedBuiltinAttribute { attr_name, macro_name: pprust::path_to_string(&call.path), invoc_span: call.path.span, @@ -2414,7 +2419,12 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { }; let single_delegations = build_single_delegations::( - self.cx, deleg, item, suffixes, item.span, false, + self.cx, + deleg, + item, + suffixes, + item.span, + DelegationSource::List(LocalExpnId::fresh_empty()), ); Node::flatten_outputs(single_delegations.map(|item| { let mut item = Node::from_item(item); diff --git a/compiler/rustc_expand/src/lib.rs b/compiler/rustc_expand/src/lib.rs index 5068501a0e2d1..ec55f40b6c1e0 100644 --- a/compiler/rustc_expand/src/lib.rs +++ b/compiler/rustc_expand/src/lib.rs @@ -10,7 +10,7 @@ // tidy-alphabetical-end mod build; -mod errors; +mod diagnostics; mod mbe; mod placeholders; mod proc_macro_server; diff --git a/compiler/rustc_expand/src/mbe/macro_check.rs b/compiler/rustc_expand/src/mbe/macro_check.rs index 0eae44a05e783..55645a5a66d04 100644 --- a/compiler/rustc_expand/src/mbe/macro_check.rs +++ b/compiler/rustc_expand/src/mbe/macro_check.rs @@ -114,7 +114,7 @@ use rustc_session::parse::ParseSess; use rustc_span::{ErrorGuaranteed, MacroRulesNormalizedIdent, Span, kw}; use smallvec::SmallVec; -use crate::errors; +use crate::diagnostics; use crate::mbe::{KleeneToken, TokenTree}; /// Stack represented as linked list. @@ -247,7 +247,7 @@ fn check_binders( psess, span, node_id, - errors::DuplicateMatcherBindingLint { span, prev: prev_info.span }, + diagnostics::DuplicateMatcherBindingLint { span, prev: prev_info.span }, ); } else if get_binder_info(macros, binders, name).is_none() { // 2. The meta-variable is free: This is a binder. @@ -266,11 +266,11 @@ fn check_binders( if let Some(prev_info) = get_binder_info(macros, binders, name) { // Duplicate binders at the top-level macro definition are errors. The lint is only // for nested macro definitions. - *guar = Some( - psess - .dcx() - .emit_err(errors::DuplicateMatcherBinding { span, prev: prev_info.span }), - ); + *guar = + Some(psess.dcx().emit_err(diagnostics::DuplicateMatcherBinding { + span, + prev: prev_info.span, + })); } else { binders.insert(name, BinderInfo { span, ops: ops.into() }); } @@ -578,7 +578,7 @@ fn check_ops_is_prefix( return; } } - buffer_lint(psess, span, node_id, errors::UnknownMacroVariable { name }); + buffer_lint(psess, span, node_id, diagnostics::UnknownMacroVariable { name }); } /// Returns whether `binder_ops` is a prefix of `occurrence_ops`. @@ -613,7 +613,7 @@ fn ops_is_prefix( psess, span, node_id, - errors::MetaVarStillRepeatingLint { label: binder.span, ident }, + diagnostics::MetaVarStillRepeatingLint { label: binder.span, ident }, ); return; } @@ -623,7 +623,7 @@ fn ops_is_prefix( psess, span, node_id, - errors::MetaVariableWrongOperator { + diagnostics::MetaVariableWrongOperator { binder: binder.span, occurrence: occurrence.span, }, diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 5bf50804ab1e8..1a1ef0f06963e 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -30,14 +30,14 @@ use rustc_span::hygiene::Transparency; use rustc_span::{Ident, Span, Symbol, kw, sym}; use tracing::{debug, instrument, trace, trace_span}; +use super::SequenceRepetition; use super::diagnostics::{FailedMacro, failed_to_match_macro}; use super::macro_parser::{NamedMatches, NamedParseResult}; -use super::{SequenceRepetition, diagnostics}; use crate::base::{ AttrProcMacro, BangProcMacro, DummyResult, ExpandResult, ExtCtxt, MacResult, MacroExpanderResult, SyntaxExtension, SyntaxExtensionKind, TTMacroExpander, }; -use crate::errors; +use crate::diagnostics; use crate::expand::{AstFragment, AstFragmentKind, ensure_complete_parse, parse_ast_fragment}; use crate::mbe::macro_check::check_meta_variables; use crate::mbe::macro_parser::{Error, ErrorReported, Failure, MatcherLoc, Success, TtParser}; @@ -81,7 +81,7 @@ impl<'a, 'b> ParserAnyMacro<'a, 'b> { let fragment = match parse_ast_fragment(parser, kind) { Ok(f) => f, Err(err) => { - let guar = diagnostics::emit_frag_parse_err( + let guar = super::diagnostics::emit_frag_parse_err( err, parser, snapshot, @@ -104,7 +104,7 @@ impl<'a, 'b> ParserAnyMacro<'a, 'b> { SEMICOLON_IN_EXPRESSIONS_FROM_MACROS, parser.token.span, lint_node_id, - errors::TrailingMacro { is_trailing: is_trailing_mac, name: macro_ident }, + diagnostics::TrailingMacro { is_trailing: is_trailing_mac, name: macro_ident }, ); } parser.bump(); @@ -903,9 +903,9 @@ fn check_args_parens(sess: &Session, rule_kw: Symbol, args: &tokenstream::TokenT if let tokenstream::TokenTree::Delimited(dspan, _, delim, _) = args && *delim != Delimiter::Parenthesis { - sess.dcx().emit_err(errors::MacroArgsBadDelim { + sess.dcx().emit_err(diagnostics::MacroArgsBadDelim { span: dspan.entire(), - sugg: errors::MacroArgsBadDelimSugg { open: dspan.open, close: dspan.close }, + sugg: diagnostics::MacroArgsBadDelimSugg { open: dspan.open, close: dspan.close }, rule_kw, }); } @@ -1539,7 +1539,7 @@ fn check_matcher_core<'tt>( RUST_2021_INCOMPATIBLE_OR_PATTERNS, span, ast::CRATE_NODE_ID, - errors::OrPatternsBackCompat { span, suggestion }, + diagnostics::OrPatternsBackCompat { span, suggestion }, ); } match is_in_follow(next_token, kind) { diff --git a/compiler/rustc_expand/src/mbe/metavar_expr.rs b/compiler/rustc_expand/src/mbe/metavar_expr.rs index 70d796cda11c0..a02b84204cb39 100644 --- a/compiler/rustc_expand/src/mbe/metavar_expr.rs +++ b/compiler/rustc_expand/src/mbe/metavar_expr.rs @@ -7,7 +7,7 @@ use rustc_macros::{Decodable, Encodable}; use rustc_session::parse::ParseSess; use rustc_span::{Ident, Span, Symbol, sym}; -use crate::errors; +use crate::diagnostics; pub(crate) const RAW_IDENT_ERR: &str = "`${concat(..)}` currently does not support raw identifiers"; pub(crate) const UNSUPPORTED_CONCAT_ELEM_ERR: &str = "expected identifier or string literal"; @@ -51,15 +51,18 @@ impl MetaVarExpr { Some(tt) => (Some(tt.span()), None), None => (None, Some(ident.span.shrink_to_hi())), }; - let err = - errors::MveMissingParen { ident_span: ident.span, unexpected_span, insert_span }; + let err = diagnostics::MveMissingParen { + ident_span: ident.span, + unexpected_span, + insert_span, + }; return Err(psess.dcx().create_err(err)); }; // Ensure there are no trailing tokens in the braces, e.g. `${foo() extra}` if iter.peek().is_some() { let span = iter_span(&iter).expect("checked is_some above"); - let err = errors::MveExtraTokens { + let err = diagnostics::MveExtraTokens { span, ident_span: ident.span, extra_count: iter.count(), @@ -79,7 +82,7 @@ impl MetaVarExpr { sym::index => MetaVarExpr::Index(parse_depth(&mut iter, psess, ident.span)?), sym::len => MetaVarExpr::Len(parse_depth(&mut iter, psess, ident.span)?), _ => { - let err = errors::MveUnrecognizedExpr { + let err = diagnostics::MveUnrecognizedExpr { span: ident.span, valid_expr_list: "`count`, `ignore`, `index`, `len`, and `concat`", }; @@ -129,7 +132,7 @@ fn check_trailing_tokens<'psess>( other => unreachable!("unknown MVEs should be rejected earlier (got `{other}`)"), }; - let err = errors::MveExtraTokens { + let err = diagnostics::MveExtraTokens { span: iter_span(iter).expect("checked is_none above"), ident_span: ident.span, extra_count: iter.count(), diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs index 443a17287d734..3e82a61067af4 100644 --- a/compiler/rustc_expand/src/mbe/quoted.rs +++ b/compiler/rustc_expand/src/mbe/quoted.rs @@ -9,7 +9,7 @@ use rustc_session::errors::feature_err; use rustc_span::edition::Edition; use rustc_span::{Ident, Span, kw, sym}; -use crate::errors; +use crate::diagnostics; use crate::mbe::macro_parser::count_metavar_decls; use crate::mbe::{Delimited, KleeneOp, KleeneToken, MetaVarExpr, SequenceRepetition, TokenTree}; @@ -94,7 +94,7 @@ fn parse( // Emit a missing-fragment diagnostic and return a `TokenTree` fallback so parsing can // continue. let missing_fragment_specifier = |span, add_span| { - sess.dcx().emit_err(errors::MissingFragmentSpecifier { + sess.dcx().emit_err(diagnostics::MissingFragmentSpecifier { span, add_span, valid: VALID_FRAGMENT_NAMES_MSG, @@ -163,7 +163,7 @@ fn parse( if !span.from_expansion() { edition } else { span.edition() } }; let kind = NonterminalKind::from_symbol(fragment.name, edition).unwrap_or_else(|| { - sess.dcx().emit_err(errors::InvalidFragmentSpecifier { + sess.dcx().emit_err(diagnostics::InvalidFragmentSpecifier { span, fragment, help: VALID_FRAGMENT_NAMES_MSG, @@ -299,7 +299,7 @@ fn parse_tree<'a>( _ => { let token = pprust::token_kind_to_string(&delim.as_open_token_kind()); - sess.dcx().emit_err(errors::ExpectedParenOrBrace { + sess.dcx().emit_err(diagnostics::ExpectedParenOrBrace { span: delim_span.entire(), token, }); diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index c56c5569f9a5b..34d5147606e90 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -17,7 +17,7 @@ use rustc_span::{ }; use smallvec::{SmallVec, smallvec}; -use crate::errors::{ +use crate::diagnostics::{ ConcatInvalidIdent, CountRepetitionMisplaced, InvalidIdentReason, MacroVarStillRepeating, MetaVarsDifSeqMatchers, MustRepeatOnce, MveUnrecognizedVar, NoRepeatableVar, NoSyntaxVarsExprRepeat, VarNoTypo, VarTypoSuggestionRepeatable, VarTypoSuggestionUnrepeatable, diff --git a/compiler/rustc_expand/src/module.rs b/compiler/rustc_expand/src/module.rs index d4bda53ece04b..febe5e16cf446 100644 --- a/compiler/rustc_expand/src/module.rs +++ b/compiler/rustc_expand/src/module.rs @@ -14,7 +14,7 @@ use rustc_span::{Ident, Span, sym}; use thin_vec::ThinVec; use crate::base::ModuleData; -use crate::errors::{ +use crate::diagnostics::{ ModuleCircular, ModuleFileNotFound, ModuleInBlock, ModuleInBlockName, ModuleMultipleCandidates, }; diff --git a/compiler/rustc_expand/src/proc_macro.rs b/compiler/rustc_expand/src/proc_macro.rs index 2deba79a775a6..105d2d796aa80 100644 --- a/compiler/rustc_expand/src/proc_macro.rs +++ b/compiler/rustc_expand/src/proc_macro.rs @@ -11,7 +11,7 @@ use rustc_span::profiling::SpannedEventArgRecorder; use rustc_span::{LocalExpnId, Span}; use crate::base::{self, *}; -use crate::{errors, proc_macro_server}; +use crate::{diagnostics, proc_macro_server}; fn exec_strategy(sess: &Session) -> impl pm::bridge::server::ExecutionStrategy + 'static { pm::bridge::server::MaybeCrossThread { @@ -47,9 +47,11 @@ impl base::BangProcMacro for BangProcMacro { let strategy = exec_strategy(ecx.sess); let server = proc_macro_server::Rustc::new(ecx); self.client.run1(&strategy, server, input, proc_macro_backtrace).map_err(|e| { - ecx.dcx().emit_err(errors::ProcMacroPanicked { + ecx.dcx().emit_err(diagnostics::ProcMacroPanicked { span, - message: e.into_string().map(|message| errors::ProcMacroPanickedHelp { message }), + message: e + .into_string() + .map(|message| diagnostics::ProcMacroPanickedHelp { message }), }) }) } @@ -74,11 +76,11 @@ impl base::AttrProcMacro for AttrProcMacro { let server = proc_macro_server::Rustc::new(ecx); self.client.run2(&strategy, server, annotation, annotated, proc_macro_backtrace).map_err( |e| { - ecx.dcx().emit_err(errors::CustomAttributePanicked { + ecx.dcx().emit_err(diagnostics::CustomAttributePanicked { span, message: e .into_string() - .map(|message| errors::CustomAttributePanickedHelp { message }), + .map(|message| diagnostics::CustomAttributePanickedHelp { message }), }) }, ) @@ -154,7 +156,7 @@ impl MultiItemModifier for DeriveProcMacro { // fail if there have been errors emitted if ecx.dcx().err_count() > error_count_before { - ecx.dcx().emit_err(errors::ProcMacroDeriveTokens { span }); + ecx.dcx().emit_err(diagnostics::ProcMacroDeriveTokens { span }); } ExpandResult::Ready(items) @@ -202,11 +204,11 @@ fn expand_derive_macro( let invoc_expn_data = invoc_id.expn_data(); let span = invoc_expn_data.call_site; ecx.dcx().emit_err({ - errors::ProcMacroDerivePanicked { + diagnostics::ProcMacroDerivePanicked { span, message: e .into_string() - .map(|message| errors::ProcMacroDerivePanickedHelp { message }), + .map(|message| diagnostics::ProcMacroDerivePanickedHelp { message }), } }); Err(()) diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 4041556925aae..6d50e9655f7ae 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -25,7 +25,8 @@ use rustc_index::IndexVec; use rustc_macros::{Decodable, Encodable, StableHash}; use rustc_span::def_id::LocalDefId; use rustc_span::{ - BytePos, DUMMY_SP, DesugaringKind, ErrorGuaranteed, Ident, Span, Spanned, Symbol, kw, sym, + BytePos, DUMMY_SP, DesugaringKind, ErrorGuaranteed, Ident, LocalExpnId, Span, Spanned, Symbol, + kw, sym, }; use rustc_target::asm::InlineAsmRegOrRegClass; use smallvec::SmallVec; @@ -3877,6 +3878,7 @@ pub struct DelegationInfo { pub child_args_segment_id: Option, pub self_ty_id: Option, pub propagate_self_ty: bool, + pub group_id: Option<(LocalExpnId, bool /* unused_target_expr */)>, } #[derive(Debug, Clone, Copy, PartialEq, Eq, StableHash)] diff --git a/compiler/rustc_hir_analysis/src/delegation.rs b/compiler/rustc_hir_analysis/src/delegation.rs index 4e5908c4d8885..0f0449c0aa9b3 100644 --- a/compiler/rustc_hir_analysis/src/delegation.rs +++ b/compiler/rustc_hir_analysis/src/delegation.rs @@ -5,9 +5,9 @@ use std::debug_assert_matches; use rustc_data_structures::fx::FxHashMap; +use rustc_hir::PathSegment; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::{DelegationInfo, PathSegment}; use rustc_middle::ty::{ self, EarlyBinder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, }; @@ -71,19 +71,6 @@ enum SelfPositionKind { None, } -pub fn opt_get_delegation_info( - tcx: TyCtxt<'_>, - delegation_id: LocalDefId, -) -> Option<&DelegationInfo> { - tcx.hir_node(tcx.local_def_id_to_hir_id(delegation_id)) - .fn_sig() - .and_then(|sig| sig.decl.opt_delegation_info()) -} - -fn get_delegation_info(tcx: TyCtxt<'_>, delegation_id: LocalDefId) -> &DelegationInfo { - opt_get_delegation_info(tcx, delegation_id).expect("processing delegation") -} - fn create_self_position_kind( tcx: TyCtxt<'_>, delegation_id: LocalDefId, @@ -96,7 +83,7 @@ fn create_self_position_kind( | (FnKind::AssocTrait, FnKind::Free) => SelfPositionKind::Zero, (FnKind::Free, FnKind::AssocTrait) => { - let propagate_self_ty = get_delegation_info(tcx, delegation_id).propagate_self_ty; + let propagate_self_ty = tcx.hir_delegation_info(delegation_id).propagate_self_ty; SelfPositionKind::AfterLifetimes(propagate_self_ty) } @@ -282,7 +269,7 @@ fn get_parent_and_inheritance_kind<'tcx>( } fn get_delegation_self_ty_or_err(tcx: TyCtxt<'_>, delegation_id: LocalDefId) -> Ty<'_> { - get_delegation_info(tcx, delegation_id) + tcx.hir_delegation_info(delegation_id) .self_ty_id .map(|id| { let ctx = ItemCtxt::new(tcx, delegation_id); @@ -644,7 +631,7 @@ pub(crate) fn delegation_user_specified_args<'tcx>( tcx: TyCtxt<'tcx>, delegation_id: LocalDefId, ) -> (&'tcx [ty::GenericArg<'tcx>], &'tcx [ty::GenericArg<'tcx>]) { - let info = get_delegation_info(tcx, delegation_id); + let info = tcx.hir_delegation_info(delegation_id); let get_segment = |hir_id| -> Option<(&'tcx PathSegment<'tcx>, DefId)> { let segment = tcx.hir_node(hir_id).expect_path_segment(); diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index 430e934d161cc..4711fd22d5729 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -7,7 +7,6 @@ use rustc_hir::def::{self, CtorKind, Namespace, Res}; use rustc_hir::def_id::DefId; use rustc_hir::{self as hir, HirId, LangItem, find_attr}; use rustc_hir_analysis::autoderef::Autoderef; -use rustc_hir_analysis::delegation::opt_get_delegation_info; use rustc_infer::infer::BoundRegionConversionTime; use rustc_infer::traits::{Obligation, ObligationCause, ObligationCauseCode}; use rustc_middle::ty::adjustment::{ @@ -701,7 +700,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // by comparing their hir ids (otherwise we will encounter errors in nested delegations, // see tests\ui\delegation\impl-reuse-pass.rs:237). let parent_def = self.tcx.hir_get_parent_item(call_expr.hir_id).def_id; - let Some(info) = opt_get_delegation_info(self.tcx, parent_def) else { return None }; + let Some(info) = self.tcx.hir_opt_delegation_info(parent_def) else { + return None; + }; if call_expr.hir_id != info.call_expr_id { return None; diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index d62ba9cf804eb..0553276b1053b 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -13,7 +13,6 @@ use rustc_hir::def_id::DefId; use rustc_hir::intravisit::Visitor; use rustc_hir::{Expr, ExprKind, FnRetTy, HirId, LangItem, Node, QPath, is_range_literal}; use rustc_hir_analysis::check::potentially_plural_count; -use rustc_hir_analysis::delegation::opt_get_delegation_info; use rustc_hir_analysis::hir_ty_lowering::{HirTyLowerer, ResolvedStructPath}; use rustc_index::IndexVec; use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferOk, TypeTrace}; @@ -341,7 +340,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // If we are processing first arg of delegation then we could have adjusted it // in `execute_delegation_aware_arguments_check`. - let checked_ty = opt_get_delegation_info(self.tcx, self.body_id) + let checked_ty = self + .tcx + .hir_opt_delegation_info(self.body_id) .and_then(|_| self.typeck_results.borrow().node_type_opt(provided_arg.hir_id)) .unwrap_or_else(|| self.check_expr_with_expectation(provided_arg, expectation)); @@ -902,6 +903,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Type check the pattern. Override if necessary to avoid knock-on errors. self.check_pat_top(decl.pat, decl_ty, ty_span, origin_expr, Some(decl.origin)); + if decl.ty.is_none() + && decl.init.is_none() + && !matches!(decl.pat.kind, hir::PatKind::Binding(.., None) | hir::PatKind::Wild) + { + self.register_wf_obligation( + decl_ty.into(), + decl.pat.span, + ObligationCauseCode::WellFormed(None), + ); + } let pat_ty = self.node_ty(decl.pat.hir_id); self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, pat_ty); diff --git a/compiler/rustc_incremental/src/assert_dep_graph.rs b/compiler/rustc_incremental/src/assert_dep_graph.rs index 36439160b7d20..b3f9a137817a7 100644 --- a/compiler/rustc_incremental/src/assert_dep_graph.rs +++ b/compiler/rustc_incremental/src/assert_dep_graph.rs @@ -57,8 +57,14 @@ use crate::errors; #[allow(missing_docs)] pub(crate) fn assert_dep_graph(tcx: TyCtxt<'_>) { tcx.dep_graph.with_ignore(|| { + // Clone the retained dep graph once and share it between the graph dump and the path + // checks below, rather than locking and cloning it separately for each. + let retained_dep_graph = tcx.dep_graph.retained_dep_graph(); + if tcx.sess.opts.unstable_opts.dump_dep_graph { - tcx.dep_graph.with_retained_dep_graph(dump_graph); + if let Some(graph) = &retained_dep_graph { + dump_graph(graph); + } } if !tcx.sess.opts.unstable_opts.query_dep_graph { @@ -92,7 +98,7 @@ pub(crate) fn assert_dep_graph(tcx: TyCtxt<'_>) { } // Check paths. - check_paths(tcx, &if_this_changed, &then_this_would_need); + check_paths(tcx, retained_dep_graph.as_ref(), &if_this_changed, &then_this_would_need); }) } @@ -172,30 +178,33 @@ impl<'tcx> Visitor<'tcx> for IfThisChanged<'tcx> { } } -fn check_paths<'tcx>(tcx: TyCtxt<'tcx>, if_this_changed: &Sources, then_this_would_need: &Targets) { - // Return early here so as not to construct the query, which is not cheap. +fn check_paths<'tcx>( + tcx: TyCtxt<'tcx>, + retained_dep_graph: Option<&RetainedDepGraph>, + if_this_changed: &Sources, + then_this_would_need: &Targets, +) { if if_this_changed.is_empty() { for &(target_span, _, _, _) in then_this_would_need { tcx.dcx().emit_err(errors::MissingIfThisChanged { span: target_span }); } return; } - tcx.dep_graph.with_retained_dep_graph(|query| { - for &(_, source_def_id, ref source_dep_node) in if_this_changed { - let dependents = query.transitive_predecessors(source_dep_node); - for &(target_span, ref target_pass, _, ref target_dep_node) in then_this_would_need { - if !dependents.contains(&target_dep_node) { - tcx.dcx().emit_err(errors::NoPath { - span: target_span, - source: tcx.def_path_str(source_def_id), - target: *target_pass, - }); - } else { - tcx.dcx().emit_err(errors::Ok { span: target_span }); - } + let Some(query) = retained_dep_graph else { return }; + for &(_, source_def_id, ref source_dep_node) in if_this_changed { + let dependents = query.transitive_predecessors(source_dep_node); + for &(target_span, ref target_pass, _, ref target_dep_node) in then_this_would_need { + if !dependents.contains(&target_dep_node) { + tcx.dcx().emit_err(errors::NoPath { + span: target_span, + source: tcx.def_path_str(source_def_id), + target: *target_pass, + }); + } else { + tcx.dcx().emit_err(errors::Ok { span: target_span }); } } - }); + } } fn dump_graph(graph: &RetainedDepGraph) { diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index df6f2909796ee..62cdc2ca60f34 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -1083,6 +1083,8 @@ fn run_required_analyses(tcx: TyCtxt<'_>) { // to use `hir_crate_items`. tcx.ensure_done().hir_crate_items(()); + rustc_passes::delegation::check_glob_and_list_delegations_target_expr(tcx); + let sess = tcx.sess; sess.time("misc_checking_1", || { par_fns(&mut [ diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index d18764bc6814a..cb3d1b6d67487 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -39,7 +39,7 @@ use rustc_span::{DUMMY_SP, Ident, Span, Symbol, sym}; use rustc_target::spec::{PanicStrategy, Target}; use tracing::{debug, info, trace}; -use crate::errors; +use crate::diagnostics; use crate::locator::{CrateError, CrateLocator, CratePaths, CrateRejections}; use crate::rmeta::{ CrateDep, CrateMetadata, CrateNumMap, CrateRoot, MetadataBlob, TargetModifiers, @@ -365,7 +365,7 @@ impl CStore { match (flag_local_value, flag_extern_value) { (Some(local_value), Some(extern_value)) => { - tcx.dcx().emit_err(errors::IncompatibleTargetModifiers { + tcx.dcx().emit_err(diagnostics::IncompatibleTargetModifiers { span, extern_crate, local_crate, @@ -376,7 +376,7 @@ impl CStore { }) } (None, Some(extern_value)) => { - tcx.dcx().emit_err(errors::IncompatibleTargetModifiersLMissed { + tcx.dcx().emit_err(diagnostics::IncompatibleTargetModifiersLMissed { span, extern_crate, local_crate, @@ -386,7 +386,7 @@ impl CStore { }) } (Some(local_value), None) => { - tcx.dcx().emit_err(errors::IncompatibleTargetModifiersRMissed { + tcx.dcx().emit_err(diagnostics::IncompatibleTargetModifiersRMissed { span, extern_crate, local_crate, @@ -458,7 +458,7 @@ impl CStore { pub fn report_incompatible_target_modifiers(&self, tcx: TyCtxt<'_>, krate: &Crate) { for flag_name in &tcx.sess.opts.cg.unsafe_allow_abi_mismatch { if !OptionsTargetModifiers::is_target_modifier(flag_name) { - tcx.dcx().emit_err(errors::UnknownTargetModifierUnsafeAllowed { + tcx.dcx().emit_err(diagnostics::UnknownTargetModifierUnsafeAllowed { span: krate.spans.inner_span.shrink_to_lo(), flag_name: flag_name.clone(), }); @@ -502,7 +502,7 @@ impl CStore { } *errors += 1; - tcx.dcx().emit_err(errors::MitigationLessStrictInDependency { + tcx.dcx().emit_err(diagnostics::MitigationLessStrictInDependency { span: krate.spans.inner_span.shrink_to_lo(), mitigation_name: my_mitigation.kind.to_string(), mitigation_level: my_mitigation.level.level_str().to_string(), @@ -525,7 +525,7 @@ impl CStore { if data.has_async_drops() { let extern_crate = data.name(); let local_crate = tcx.crate_name(LOCAL_CRATE); - tcx.dcx().emit_warn(errors::AsyncDropTypesInDependency { + tcx.dcx().emit_warn(diagnostics::AsyncDropTypesInDependency { span: krate.spans.inner_span.shrink_to_lo(), extern_crate, local_crate, @@ -1034,11 +1034,13 @@ impl CStore { // Sanity check the loaded crate to ensure it is indeed a panic runtime // and the panic strategy is indeed what we thought it was. if !cdata.is_panic_runtime() { - tcx.dcx().emit_err(errors::CrateNotPanicRuntime { crate_name: name }); + tcx.dcx().emit_err(diagnostics::CrateNotPanicRuntime { crate_name: name }); } if cdata.required_panic_strategy() != Some(desired_strategy) { - tcx.dcx() - .emit_err(errors::NoPanicStrategy { crate_name: name, strategy: desired_strategy }); + tcx.dcx().emit_err(diagnostics::NoPanicStrategy { + crate_name: name, + strategy: desired_strategy, + }); } self.injected_panic_runtime = Some(cnum); @@ -1074,7 +1076,7 @@ impl CStore { // Sanity check the loaded crate to ensure it is indeed a profiler runtime if !cdata.is_profiler_runtime() { - tcx.dcx().emit_err(errors::NotProfilerRuntime { crate_name: name }); + tcx.dcx().emit_err(diagnostics::NotProfilerRuntime { crate_name: name }); } } @@ -1082,8 +1084,10 @@ impl CStore { self.has_global_allocator = match &*fn_spans(krate, Symbol::intern(&global_fn_name(sym::alloc))) { [span1, span2, ..] => { - tcx.dcx() - .emit_err(errors::NoMultipleGlobalAlloc { span2: *span2, span1: *span1 }); + tcx.dcx().emit_err(diagnostics::NoMultipleGlobalAlloc { + span2: *span2, + span1: *span1, + }); true } spans => !spans.is_empty(), @@ -1091,8 +1095,10 @@ impl CStore { let alloc_error_handler = Symbol::intern(&global_fn_name(ALLOC_ERROR_HANDLER)); self.has_alloc_error_handler = match &*fn_spans(krate, alloc_error_handler) { [span1, span2, ..] => { - tcx.dcx() - .emit_err(errors::NoMultipleAllocErrorHandler { span2: *span2, span1: *span1 }); + tcx.dcx().emit_err(diagnostics::NoMultipleAllocErrorHandler { + span2: *span2, + span1: *span1, + }); true } spans => !spans.is_empty(), @@ -1130,7 +1136,7 @@ impl CStore { if data.has_global_allocator() { match global_allocator { Some(other_crate) => { - tcx.dcx().emit_err(errors::ConflictingGlobalAlloc { + tcx.dcx().emit_err(diagnostics::ConflictingGlobalAlloc { crate_name: data.name(), other_crate_name: other_crate, }); @@ -1144,7 +1150,7 @@ impl CStore { if data.has_alloc_error_handler() { match alloc_error_handler { Some(other_crate) => { - tcx.dcx().emit_err(errors::ConflictingAllocErrorHandler { + tcx.dcx().emit_err(diagnostics::ConflictingAllocErrorHandler { crate_name: data.name(), other_crate_name: other_crate, }); @@ -1164,7 +1170,7 @@ impl CStore { if !attr::contains_name(&krate.attrs, sym::default_lib_allocator) && !self.iter_crate_data().any(|(_, data)| data.has_default_lib_allocator()) { - tcx.dcx().emit_err(errors::GlobalAllocRequired); + tcx.dcx().emit_err(diagnostics::GlobalAllocRequired); } self.allocator_kind = Some(AllocatorKind::Default); } @@ -1229,7 +1235,7 @@ impl CStore { // Sanity check that the loaded crate is `#![compiler_builtins]` let cdata = self.get_crate_data(cnum); if !cdata.is_compiler_builtins() { - tcx.dcx().emit_err(errors::CrateNotCompilerBuiltins { crate_name: cdata.name() }); + tcx.dcx().emit_err(diagnostics::CrateNotCompilerBuiltins { crate_name: cdata.name() }); } } @@ -1261,7 +1267,7 @@ impl CStore { lint::builtin::UNUSED_CRATE_DEPENDENCIES, span, ast::CRATE_NODE_ID, - errors::UnusedCrateDependency { + diagnostics::UnusedCrateDependency { extern_crate: name_interned, local_crate: tcx.crate_name(LOCAL_CRATE), }, @@ -1298,7 +1304,7 @@ impl CStore { // Make a point span rather than covering the whole file let span = krate.spans.inner_span.shrink_to_lo(); - tcx.sess.dcx().emit_err(errors::WasmCAbi { span }); + tcx.sess.dcx().emit_err(diagnostics::WasmCAbi { span }); } } diff --git a/compiler/rustc_metadata/src/dependency_format.rs b/compiler/rustc_metadata/src/dependency_format.rs index 673a7444f90c0..257b2a9b03884 100644 --- a/compiler/rustc_metadata/src/dependency_format.rs +++ b/compiler/rustc_metadata/src/dependency_format.rs @@ -65,7 +65,7 @@ use rustc_target::spec::PanicStrategy; use tracing::info; use crate::creader::CStore; -use crate::errors::{ +use crate::diagnostics::{ BadPanicStrategy, CrateDepMultiple, IncompatiblePanicInDropStrategy, IncompatibleWithImmediateAbort, IncompatibleWithImmediateAbortCore, LibRequired, NonStaticCrateDep, RequiredPanicStrategy, RlibRequired, RustcLibRequired, TwoPanicRuntimes, diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/diagnostics.rs similarity index 100% rename from compiler/rustc_metadata/src/errors.rs rename to compiler/rustc_metadata/src/diagnostics.rs diff --git a/compiler/rustc_metadata/src/fs.rs b/compiler/rustc_metadata/src/fs.rs index 1eaad26ff8e80..5759b4afada7e 100644 --- a/compiler/rustc_metadata/src/fs.rs +++ b/compiler/rustc_metadata/src/fs.rs @@ -8,7 +8,7 @@ use rustc_session::Session; use rustc_session::config::{CrateType, OutFileName, OutputType}; use rustc_session::output::filename_for_metadata; -use crate::errors::{ +use crate::diagnostics::{ BinaryOutputToTty, FailedCopyToStdout, FailedCreateEncodedMetadata, FailedCreateFile, FailedCreateTempdir, FailedWriteError, }; diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs index ebaff2a2d8f97..51c56d777a751 100644 --- a/compiler/rustc_metadata/src/lib.rs +++ b/compiler/rustc_metadata/src/lib.rs @@ -21,7 +21,7 @@ mod native_libs; mod rmeta; pub mod creader; -pub mod errors; +pub mod diagnostics; pub mod fs; pub mod locator; diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index e8b78fdbea3ff..321274243a857 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -235,7 +235,7 @@ use tempfile::Builder as TempFileBuilder; use tracing::{debug, info}; use crate::creader::{Library, MetadataLoader}; -use crate::errors; +use crate::diagnostics; use crate::rmeta::{METADATA_HEADER, MetadataBlob, ProcMacroKind, rustc_version}; #[derive(Clone)] @@ -1070,28 +1070,45 @@ impl CrateError { let dcx = sess.dcx(); match self { CrateError::NonAsciiName(crate_name) => { - dcx.emit_err(errors::NonAsciiName { span, crate_name }); + dcx.emit_err(diagnostics::NonAsciiName { span, crate_name }); } CrateError::ExternLocationNotExist(crate_name, loc) => { - dcx.emit_err(errors::ExternLocationNotExist { span, crate_name, location: &loc }); + dcx.emit_err(diagnostics::ExternLocationNotExist { + span, + crate_name, + location: &loc, + }); } CrateError::ExternLocationNotFile(crate_name, loc) => { - dcx.emit_err(errors::ExternLocationNotFile { span, crate_name, location: &loc }); + dcx.emit_err(diagnostics::ExternLocationNotFile { + span, + crate_name, + location: &loc, + }); } CrateError::MultipleCandidates(crate_name, flavor, candidates) => { - dcx.emit_err(errors::MultipleCandidates { span, crate_name, flavor, candidates }); + dcx.emit_err(diagnostics::MultipleCandidates { + span, + crate_name, + flavor, + candidates, + }); } CrateError::FullMetadataNotFound(crate_name, flavor) => { - dcx.emit_err(errors::FullMetadataNotFound { span, crate_name, flavor }); + dcx.emit_err(diagnostics::FullMetadataNotFound { span, crate_name, flavor }); } CrateError::SymbolConflictsCurrent(root_name) => { - dcx.emit_err(errors::SymbolConflictsCurrent { span, crate_name: root_name }); + dcx.emit_err(diagnostics::SymbolConflictsCurrent { span, crate_name: root_name }); } CrateError::StableCrateIdCollision(crate_name0, crate_name1) => { - dcx.emit_err(errors::StableCrateIdCollision { span, crate_name0, crate_name1 }); + dcx.emit_err(diagnostics::StableCrateIdCollision { + span, + crate_name0, + crate_name1, + }); } CrateError::DlOpen(path, err) | CrateError::DlSym(path, err) => { - dcx.emit_err(errors::DlError { span, path, err }); + dcx.emit_err(diagnostics::DlError { span, path, err }); } CrateError::LocatorCombined(locator) => { let crate_name = locator.crate_name; @@ -1102,8 +1119,12 @@ impl CrateError { if !locator.crate_rejections.via_filename.is_empty() { let mismatches = locator.crate_rejections.via_filename.iter(); for CrateMismatch { path, .. } in mismatches { - dcx.emit_err(errors::CrateLocationUnknownType { span, path, crate_name }); - dcx.emit_err(errors::LibFilenameForm { + dcx.emit_err(diagnostics::CrateLocationUnknownType { + span, + path, + crate_name, + }); + dcx.emit_err(diagnostics::LibFilenameForm { span, dll_prefix: &locator.dll_prefix, dll_suffix: &locator.dll_suffix, @@ -1129,7 +1150,7 @@ impl CrateError { )); } } - dcx.emit_err(errors::NewerCrateVersion { + dcx.emit_err(diagnostics::NewerCrateVersion { span, crate_name, add_info, @@ -1145,7 +1166,7 @@ impl CrateError { path.display(), )); } - dcx.emit_err(errors::NoCrateWithTriple { + dcx.emit_err(diagnostics::NoCrateWithTriple { span, crate_name, locator_triple: locator.triple.tuple(), @@ -1161,7 +1182,7 @@ impl CrateError { path.display() )); } - dcx.emit_err(errors::FoundStaticlib { + dcx.emit_err(diagnostics::FoundStaticlib { span, crate_name, add_info, @@ -1177,7 +1198,7 @@ impl CrateError { path.display(), )); } - dcx.emit_err(errors::IncompatibleRustc { + dcx.emit_err(diagnostics::IncompatibleRustc { span, crate_name, add_info, @@ -1189,14 +1210,14 @@ impl CrateError { for CrateMismatch { path: _, got } in locator.crate_rejections.via_invalid { crate_rejections.push(got); } - dcx.emit_err(errors::InvalidMetadataFiles { + dcx.emit_err(diagnostics::InvalidMetadataFiles { span, crate_name, add_info, crate_rejections, }); } else { - let error = errors::CannotFindCrate { + let error = diagnostics::CannotFindCrate { span, crate_name, add_info, @@ -1222,7 +1243,7 @@ impl CrateError { } } CrateError::NotFound(crate_name) => { - let error = errors::CannotFindCrate { + let error = diagnostics::CannotFindCrate { span, crate_name, add_info: String::new(), diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index bfe7e01dc85e7..e467cf9bf105b 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -21,7 +21,7 @@ use rustc_span::Symbol; use rustc_span::def_id::{DefId, LOCAL_CRATE}; use rustc_target::spec::{Arch, BinaryFormat, CfgAbi, Env, LinkSelfContainedComponents, Os}; -use crate::errors; +use crate::diagnostics; /// The fallback directories are passed to linker, but not used when rustc does the search, /// because in the latter case the set of fallback directories cannot always be determined @@ -163,8 +163,9 @@ pub fn try_find_native_dynamic_library( } pub fn find_native_static_library(name: &str, verbatim: bool, sess: &Session) -> PathBuf { - try_find_native_static_library(sess, name, verbatim) - .unwrap_or_else(|| sess.dcx().emit_fatal(errors::MissingNativeLibrary::new(name, verbatim))) + try_find_native_static_library(sess, name, verbatim).unwrap_or_else(|| { + sess.dcx().emit_fatal(diagnostics::MissingNativeLibrary::new(name, verbatim)) + }) } fn find_bundled_library( @@ -241,7 +242,7 @@ impl<'tcx> Collector<'tcx> { if let Some(span) = find_attr!(self.tcx, child_item, LinkOrdinal {span, ..} => *span) { - sess.dcx().emit_err(errors::LinkOrdinalRawDylib { span }); + sess.dcx().emit_err(diagnostics::LinkOrdinalRawDylib { span }); } } @@ -277,16 +278,18 @@ impl<'tcx> Collector<'tcx> { && !self.tcx.sess.target.is_like_darwin { // Cannot check this when parsing options because the target is not yet available. - self.tcx.dcx().emit_err(errors::LibFrameworkApple); + self.tcx.dcx().emit_err(diagnostics::LibFrameworkApple); } if let Some(ref new_name) = lib.new_name { let any_duplicate = self.libs.iter().any(|n| n.name.as_str() == lib.name); if new_name.is_empty() { - self.tcx.dcx().emit_err(errors::EmptyRenamingTarget { lib_name: &lib.name }); + self.tcx + .dcx() + .emit_err(diagnostics::EmptyRenamingTarget { lib_name: &lib.name }); } else if !any_duplicate { - self.tcx.dcx().emit_err(errors::RenamingNoLink { lib_name: &lib.name }); + self.tcx.dcx().emit_err(diagnostics::RenamingNoLink { lib_name: &lib.name }); } else if !renames.insert(&lib.name) { - self.tcx.dcx().emit_err(errors::MultipleRenamings { lib_name: &lib.name }); + self.tcx.dcx().emit_err(diagnostics::MultipleRenamings { lib_name: &lib.name }); } } } @@ -312,14 +315,14 @@ impl<'tcx> Collector<'tcx> { if lib.has_modifiers() || passed_lib.has_modifiers() { match lib.foreign_module { Some(def_id) => { - self.tcx.dcx().emit_err(errors::NoLinkModOverride { + self.tcx.dcx().emit_err(diagnostics::NoLinkModOverride { span: Some(self.tcx.def_span(def_id)), }) } None => self .tcx .dcx() - .emit_err(errors::NoLinkModOverride { span: None }), + .emit_err(diagnostics::NoLinkModOverride { span: None }), }; } if passed_lib.kind != NativeLibKind::Unspecified { @@ -434,7 +437,7 @@ impl<'tcx> Collector<'tcx> { DllCallingConvention::Vectorcall(self.i686_arg_list_size(item)) } _ => { - self.tcx.dcx().emit_fatal(errors::RawDylibUnsupportedAbi { span }); + self.tcx.dcx().emit_fatal(diagnostics::RawDylibUnsupportedAbi { span }); } } } else { @@ -443,7 +446,7 @@ impl<'tcx> Collector<'tcx> { DllCallingConvention::C } _ => { - self.tcx.dcx().emit_fatal(errors::RawDylibUnsupportedAbi { span }); + self.tcx.dcx().emit_fatal(diagnostics::RawDylibUnsupportedAbi { span }); } } }; @@ -458,11 +461,11 @@ impl<'tcx> Collector<'tcx> { if self.tcx.sess.target.binary_format == BinaryFormat::Elf { let name = name.as_str(); if name.contains('\0') { - self.tcx.dcx().emit_err(errors::RawDylibMalformed { span }); + self.tcx.dcx().emit_err(diagnostics::RawDylibMalformed { span }); } else if let Some((left, right)) = name.split_once('@') && (left.is_empty() || right.is_empty() || right.contains('@')) { - self.tcx.dcx().emit_err(errors::RawDylibMalformed { span }); + self.tcx.dcx().emit_err(diagnostics::RawDylibMalformed { span }); } } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 6219c23a0c6ab..514b6a6c4c447 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -35,8 +35,8 @@ use rustc_span::{ }; use tracing::{debug, instrument, trace}; +use crate::diagnostics::{FailCreateFileEncoder, FailWriteFile}; use crate::eii::EiiMapEncodedKeyValue; -use crate::errors::{FailCreateFileEncoder, FailWriteFile}; use crate::rmeta::*; pub(super) struct EncodeContext<'a, 'tcx> { @@ -1122,6 +1122,9 @@ fn should_encode_mir( && reachable_set.contains(&def_id) && (tcx.generics_of(def_id).requires_monomorphization(tcx) || tcx.cross_crate_inlinable(def_id))); + // Comptime fns do not have optimized MIR at all. + let opt = + opt && !matches!(tcx.constness(def_id), hir::Constness::Const { always: true }); // The function has a `const` modifier or is in a `const trait`. let is_const_fn = tcx.is_const_fn(def_id.to_def_id()); (is_const_fn, opt) diff --git a/compiler/rustc_middle/src/dep_graph/graph.rs b/compiler/rustc_middle/src/dep_graph/graph.rs index b5c32a1848aeb..fa408fd3f832b 100644 --- a/compiler/rustc_middle/src/dep_graph/graph.rs +++ b/compiler/rustc_middle/src/dep_graph/graph.rs @@ -195,10 +195,12 @@ impl DepGraph { self.data.is_some() } - pub fn with_retained_dep_graph(&self, f: impl Fn(&RetainedDepGraph)) { - if let Some(data) = &self.data { - data.current.encoder.with_retained_dep_graph(f) - } + /// Returns a clone of the in-memory retained dep graph, if it is being built + /// (i.e. `-Zquery-dep-graph` is set). Cloning rather than exposing the lock keeps + /// callers from holding it while forcing queries, which would deadlock against a + /// reentrant `record` under the parallel frontend. + pub fn retained_dep_graph(&self) -> Option { + self.data.as_ref().and_then(|data| data.current.encoder.retained_dep_graph()) } pub fn assert_ignored(&self) { diff --git a/compiler/rustc_middle/src/dep_graph/retained.rs b/compiler/rustc_middle/src/dep_graph/retained.rs index 626b3b7821794..7949a47346845 100644 --- a/compiler/rustc_middle/src/dep_graph/retained.rs +++ b/compiler/rustc_middle/src/dep_graph/retained.rs @@ -9,6 +9,7 @@ use super::{DepNode, DepNodeIndex}; /// Normally, dependencies recorded during the current session are written to /// disk and then forgotten, to avoid wasting memory on information that is /// not needed when the compiler is working correctly. +#[derive(Clone)] pub struct RetainedDepGraph { pub inner: LinkedGraph, pub indices: FxHashMap, diff --git a/compiler/rustc_middle/src/dep_graph/serialized.rs b/compiler/rustc_middle/src/dep_graph/serialized.rs index 6d7f8e37e6c0a..d17721fea6503 100644 --- a/compiler/rustc_middle/src/dep_graph/serialized.rs +++ b/compiler/rustc_middle/src/dep_graph/serialized.rs @@ -636,10 +636,12 @@ impl EncoderState { // Outline the build of the full dep graph as it's typically disabled and cold. outline(move || { - // Do not ICE when a query is called from within `with_query`. - if let Some(retained_graph) = &mut retained_graph.try_lock() { - retained_graph.push(index, *node, &edges); - } + // Block on the lock rather than using `try_lock`: under the parallel frontend + // several threads record nodes concurrently, and dropping a node on lock + // contention would make the retained graph nondeterministic. Readers take a + // clone of the graph (`retained_dep_graph`) rather than holding the lock, so + // this never deadlocks against a reentrant `record`. + retained_graph.lock().push(index, *node, &edges); }); } @@ -874,10 +876,8 @@ impl GraphEncoder { GraphEncoder { status, retained_graph, profiler: sess.prof.clone() } } - pub(crate) fn with_retained_dep_graph(&self, f: impl Fn(&RetainedDepGraph)) { - if let Some(retained_graph) = &self.retained_graph { - f(&retained_graph.lock()) - } + pub(crate) fn retained_dep_graph(&self) -> Option { + self.retained_graph.as_ref().map(|retained_graph| retained_graph.lock().clone()) } /// Encodes a node that does not exists in the previous graph. diff --git a/compiler/rustc_middle/src/hir/map.rs b/compiler/rustc_middle/src/hir/map.rs index 81eae1ca142f8..333fe67ff919e 100644 --- a/compiler/rustc_middle/src/hir/map.rs +++ b/compiler/rustc_middle/src/hir/map.rs @@ -871,6 +871,14 @@ impl<'tcx> TyCtxt<'tcx> { self.opt_hir_owner_node(def_id)?.fn_decl()?.opt_delegation_sig_id() } + pub fn hir_opt_delegation_info(self, def_id: LocalDefId) -> Option<&'tcx DelegationInfo> { + self.opt_hir_owner_node(def_id)?.fn_decl()?.opt_delegation_info() + } + + pub fn hir_delegation_info(self, delegation_id: LocalDefId) -> &'tcx DelegationInfo { + self.hir_opt_delegation_info(delegation_id).expect("processing delegation") + } + #[inline] fn hir_opt_ident(self, id: HirId) -> Option { match self.hir_node(id) { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index ac82cf1981032..c59e198dc07a8 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -201,6 +201,9 @@ pub struct ResolverGlobalCtxt { pub doc_link_traits_in_scope: FxIndexMap>, pub all_macro_rules: UnordSet, pub stripped_cfg_items: Vec, + // Information about delegations which is used when handling recursive delegations + // and ensures easy access to delegation-only `LocalDefId`s. + pub delegation_infos: FxIndexMap, } #[derive(Debug)] @@ -257,13 +260,10 @@ pub struct ResolverAstLowering<'tcx> { /// Lints that were emitted by the resolver and early lints. pub lint_buffer: Steal, - // Information about delegations which is used when handling recursive delegations - pub delegation_infos: LocalDefIdMap, - pub disambiguators: LocalDefIdMap>, } -#[derive(Debug)] +#[derive(Debug, StableHash)] pub struct DelegationInfo { // `DefId` (either the resolution at delegation.id or item_id in case of a trait impl) for signature resolution, // for details see https://github.com/rust-lang/rust/issues/118212#issuecomment-2160686914 @@ -1789,6 +1789,14 @@ impl<'tcx> TyCtxt<'tcx> { | DefKind::Ctor(..) | DefKind::AnonConst | DefKind::InlineConst => self.mir_for_ctfe(def), + DefKind::Fn | DefKind::AssocFn + if matches!( + self.constness(def), + hir::Constness::Const { always: true } + ) => + { + self.mir_for_ctfe(def) + } // If the caller wants `mir_for_ctfe` of a function they should not be using // `instance_mir`, so we'll assume const fn also wants the optimized version. _ => self.optimized_mir(def), diff --git a/compiler/rustc_mir_build/src/builder/expr/into.rs b/compiler/rustc_mir_build/src/builder/expr/into.rs index a6c3d5f9fb9a7..e802b5b5c4898 100644 --- a/compiler/rustc_mir_build/src/builder/expr/into.rs +++ b/compiler/rustc_mir_build/src/builder/expr/into.rs @@ -18,7 +18,7 @@ use crate::builder::expr::category::{Category, RvalueFunc}; use crate::builder::matches::{DeclareLetBindings, Exhaustive, HasMatchGuard}; use crate::builder::scope::LintLevel; use crate::builder::{BlockAnd, BlockAndExtension, BlockFrame, Builder, NeedsTemporary}; -use crate::errors::{LoopMatchArmWithGuard, LoopMatchUnsupportedType}; +use crate::diagnostics::{LoopMatchArmWithGuard, LoopMatchUnsupportedType}; impl<'a, 'tcx> Builder<'a, 'tcx> { /// Compile `expr`, storing the result into `destination`, which diff --git a/compiler/rustc_mir_build/src/builder/mod.rs b/compiler/rustc_mir_build/src/builder/mod.rs index d158f55a3111c..c0234b718f1d0 100644 --- a/compiler/rustc_mir_build/src/builder/mod.rs +++ b/compiler/rustc_mir_build/src/builder/mod.rs @@ -44,7 +44,7 @@ use rustc_span::{Span, Symbol}; use crate::builder::expr::as_place::PlaceBuilder; use crate::builder::scope::{DropKind, LintLevel}; -use crate::errors; +use crate::diagnostics; pub(crate) fn closure_saved_names_of_captured_variables<'tcx>( tcx: TyCtxt<'tcx>, @@ -931,7 +931,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { lint::builtin::UNREACHABLE_CODE, lint_root, target_loc.span, - errors::UnreachableDueToUninhabited { + diagnostics::UnreachableDueToUninhabited { expr: target_loc.span, orig: orig_span, descr, diff --git a/compiler/rustc_mir_build/src/builder/scope.rs b/compiler/rustc_mir_build/src/builder/scope.rs index a341bef032889..84abb6ca70e70 100644 --- a/compiler/rustc_mir_build/src/builder/scope.rs +++ b/compiler/rustc_mir_build/src/builder/scope.rs @@ -99,7 +99,7 @@ use tracing::{debug, instrument}; use super::matches::BuiltMatchTree; use crate::builder::{BlockAnd, BlockAndExtension, BlockFrame, Builder, CFG}; -use crate::errors::{ +use crate::diagnostics::{ ConstContinueBadConst, ConstContinueNotMonomorphicConst, ConstContinueUnknownJumpTarget, }; @@ -924,7 +924,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { | ExprKind::NamedConst { .. } => self.as_constant(&self.thir[value]), other => { - use crate::errors::ConstContinueNotMonomorphicConstReason as Reason; + use crate::diagnostics::ConstContinueNotMonomorphicConstReason as Reason; let span = expr.span; let reason = match other { diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index f99d8934aa7fa..a5e5b9f7699b8 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -16,7 +16,7 @@ use rustc_session::lint::builtin::{DEPRECATED_SAFE_2024, UNSAFE_OP_IN_UNSAFE_FN, use rustc_span::def_id::{DefId, LocalDefId}; use rustc_span::{Span, Symbol}; -use crate::errors::*; +use crate::diagnostics::*; struct UnsafetyVisitor<'a, 'tcx> { tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/diagnostics.rs similarity index 100% rename from compiler/rustc_mir_build/src/errors.rs rename to compiler/rustc_mir_build/src/diagnostics.rs diff --git a/compiler/rustc_mir_build/src/lib.rs b/compiler/rustc_mir_build/src/lib.rs index e5516b45ee6b3..78be159b08292 100644 --- a/compiler/rustc_mir_build/src/lib.rs +++ b/compiler/rustc_mir_build/src/lib.rs @@ -11,7 +11,7 @@ mod builder; mod check_tail_calls; mod check_unsafety; -mod errors; +mod diagnostics; pub mod thir; use rustc_middle::util::Providers; diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index b32d7dce4f4d3..d8015046aab28 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -22,7 +22,7 @@ use rustc_middle::{bug, span_bug}; use rustc_span::Span; use tracing::{debug, info, instrument, trace}; -use crate::errors::*; +use crate::diagnostics::*; use crate::thir::cx::ThirBuildCx; impl<'tcx> ThirBuildCx<'tcx> { diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 8e147a44d3b75..274a9d874790e 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -27,7 +27,7 @@ use rustc_span::{Ident, Span}; use rustc_trait_selection::infer::InferCtxtExt; use tracing::instrument; -use crate::errors::*; +use crate::diagnostics::*; pub(crate) fn check_match(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGuaranteed> { let typeck_results = tcx.typeck(def_id); 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 56aeabe83898f..178f79173ea50 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 @@ -20,7 +20,7 @@ use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; use tracing::{debug, instrument, trace}; use super::PatCtxt; -use crate::errors::{ +use crate::diagnostics::{ ConstPatternDependsOnGenericParameter, CouldNotEvalConstPattern, InvalidPattern, NaNPattern, PointerPattern, SuggestEq, TypeNotPartialEq, TypeNotStructural, UnionPattern, UnsizedPattern, }; diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index d826a7ed1f30a..92cb9dd8de7ca 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -29,7 +29,7 @@ use tracing::{debug, instrument}; pub(crate) use self::check_match::check_match; use self::migration::PatMigration; -use crate::errors::*; +use crate::diagnostics::*; use crate::thir::cx::ThirBuildCx; /// Context for lowering HIR patterns to THIR patterns. diff --git a/compiler/rustc_mir_dataflow/src/errors.rs b/compiler/rustc_mir_dataflow/src/diagnostics.rs similarity index 100% rename from compiler/rustc_mir_dataflow/src/errors.rs rename to compiler/rustc_mir_dataflow/src/diagnostics.rs diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs index f29a1f361e4b1..7cec1db2a810c 100644 --- a/compiler/rustc_mir_dataflow/src/lib.rs +++ b/compiler/rustc_mir_dataflow/src/lib.rs @@ -23,8 +23,8 @@ pub use self::framework::{ use self::move_paths::MoveData; pub mod debuginfo; +mod diagnostics; mod drop_flag_effects; -mod errors; mod framework; pub mod impls; pub mod move_paths; diff --git a/compiler/rustc_mir_dataflow/src/rustc_peek.rs b/compiler/rustc_mir_dataflow/src/rustc_peek.rs index 8d16e99f751e8..4eb38569e6d48 100644 --- a/compiler/rustc_mir_dataflow/src/rustc_peek.rs +++ b/compiler/rustc_mir_dataflow/src/rustc_peek.rs @@ -5,7 +5,7 @@ use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::{Span, sym}; use tracing::{debug, info}; -use crate::errors::{ +use crate::diagnostics::{ PeekArgumentNotALocal, PeekArgumentUntracked, PeekBitNotSet, PeekMustBeNotTemporary, PeekMustBePlaceOrRefPlace, StopAfterDataFlowEndedCompilation, }; diff --git a/compiler/rustc_mir_transform/src/cross_crate_inline.rs b/compiler/rustc_mir_transform/src/cross_crate_inline.rs index 5d3827e70ffb1..13b3304fda8f2 100644 --- a/compiler/rustc_mir_transform/src/cross_crate_inline.rs +++ b/compiler/rustc_mir_transform/src/cross_crate_inline.rs @@ -1,7 +1,7 @@ use rustc_hir::attrs::InlineAttr; use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; -use rustc_hir::find_attr; +use rustc_hir::{self as hir, find_attr}; use rustc_middle::bug; use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::*; @@ -43,6 +43,12 @@ fn cross_crate_inlinable(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { return true; } + if let hir::Constness::Const { always: true } = tcx.constness(def_id) { + // Comptime functions only exist during const eval and can never be passed + // to codegen. The const eval MIR pipeline also doesn't inline anything at all. + return false; + } + // Obey source annotations first; this is important because it means we can use // #[inline(never)] to force code generation. match codegen_fn_attrs.inline { diff --git a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs index cd6395eb2e8e8..bcd43bc40d8bc 100644 --- a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs +++ b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs @@ -9,6 +9,7 @@ //! after `optimized_mir`! We check for things that are *not* guaranteed to be preserved by MIR //! transforms, such as which local variables happen to be mutated. +use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; use rustc_index::IndexVec; use rustc_middle::middle::deduced_param_attrs::{DeducedParamAttrs, UsageSummary}; @@ -205,6 +206,12 @@ pub(super) fn deduced_param_attrs<'tcx>( return &[]; } + if let hir::Constness::Const { always: true } = tcx.constness(def_id) { + // Comptime functions only exist during const eval and can never be passed + // to codegen. + return &[]; + } + // Grab the optimized MIR. Analyze it to determine which arguments have been mutated. let body: &Body<'tcx> = tcx.optimized_mir(def_id); // Arguments spread at ABI level are currently unsupported. diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index bbf190ce1a3e0..9d6803bc53e5a 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -511,7 +511,18 @@ fn inner_mir_for_ctfe(tcx: TyCtxt<'_>, def: LocalDefId) -> Body<'_> { }; let mut body = remap_mir_for_const_eval_select(tcx, body, hir::Constness::Const { always }); - pm::run_passes(tcx, &mut body, &[&ctfe_limit::CtfeLimit], None, pm::Optimizations::Allowed); + // FIXME(reflection): probably need to look at this for comptime closures + let passes: &[&dyn MirPass<'_>] = if matches!(tcx.def_kind(def), DefKind::Fn | DefKind::AssocFn) + && matches!(tcx.constness(def), hir::Constness::Const { always: true }) + { + // Need to generate mentioned items, as all functions are expected to have them, but for const + // fns we just look at the optimized MIR, which generates it. For comptime fns, there is no + // optimized MIR. + &[&ctfe_limit::CtfeLimit, &mentioned_items::MentionedItems] + } else { + &[&ctfe_limit::CtfeLimit] + }; + pm::run_passes(tcx, &mut body, passes, None, pm::Optimizations::Allowed); body } diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 9ddd33678c341..8c5a8a625ec99 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -413,7 +413,7 @@ fn collect_items_rec<'tcx>( // current step of mono items collection. // // FIXME: don't rely on global state, instead bubble up errors. Note: this is very hard to do. - let error_count = tcx.dcx().err_count(); + let error_count = tcx.dcx().err_count_on_current_thread(); // In `mentioned_items` we collect items that were mentioned in this MIR but possibly do not // need to be monomorphized. This is done to ensure that optimizing away function calls does not @@ -538,7 +538,7 @@ fn collect_items_rec<'tcx>( // Check for PMEs and emit a diagnostic if one happened. To try to show relevant edges of the // mono item graph. - if tcx.dcx().err_count() > error_count + if tcx.dcx().err_count_on_current_thread() > error_count && starting_item.node.is_generic_fn() && starting_item.node.is_user_defined() { diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index b5151cf20ab02..8a881c6f8b568 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -1092,7 +1092,7 @@ impl<'a> Parser<'a> { && (self.token.can_begin_type() || (self.token.is_reserved_ident() && !self.token.is_keyword(kw::Where)))) { - if self.token.is_keyword(kw::Dyn) { + if self.token.is_keyword(kw::Dyn) && self.token.span.edition().at_least_rust_2018() { // Account for `&dyn Trait + dyn Other`. self.bump(); self.dcx().emit_err(InvalidDynKeyword { diff --git a/compiler/rustc_passes/src/delegation.rs b/compiler/rustc_passes/src/delegation.rs new file mode 100644 index 0000000000000..5b2267efbccd8 --- /dev/null +++ b/compiler/rustc_passes/src/delegation.rs @@ -0,0 +1,32 @@ +use rustc_data_structures::fx::FxIndexMap; +use rustc_macros::Diagnostic; +use rustc_middle::ty::TyCtxt; +use rustc_span::Span; + +pub fn check_glob_and_list_delegations_target_expr(tcx: TyCtxt<'_>) { + let mut delegations_by_group_id = FxIndexMap::default(); + + for &id in tcx.resolutions(()).delegation_infos.keys() { + if let Some(info) = tcx.hir_opt_delegation_info(id) + && let Some((group_id, unused_target_expr)) = info.group_id + { + delegations_by_group_id + .entry(group_id) + .or_insert_with(|| (true, tcx.def_span(id))) + .0 &= unused_target_expr; + } + } + + for (_, (unused_target_expr, span)) in delegations_by_group_id { + if unused_target_expr { + tcx.dcx().emit_err(DelegationTargetExprDeletedEverywhere { span }); + } + } +} + +#[derive(Diagnostic)] +#[diag("unused target expression is specified for glob or list delegation")] +struct DelegationTargetExprDeletedEverywhere { + #[primary_span] + pub span: Span, +} diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs index dea57cf4eba51..b51934cab90c4 100644 --- a/compiler/rustc_passes/src/lib.rs +++ b/compiler/rustc_passes/src/lib.rs @@ -11,6 +11,7 @@ mod check_attr; mod check_export; pub mod dead; mod debugger_visualizer; +pub mod delegation; mod diagnostic_items; mod eii; pub mod entry; diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 4216d7bf030af..769466a112ff8 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1506,7 +1506,7 @@ pub struct Resolver<'ra, 'tcx> { /// Generic args to suggest for required params (e.g. `<'_>`, `<_, _>`), if any. item_required_generic_args_suggestions: FxHashMap = default::fx_hash_map(), delegation_fn_sigs: LocalDefIdMap = Default::default(), - delegation_infos: LocalDefIdMap = Default::default(), + delegation_infos: FxIndexMap, main_def: Option = None, trait_impls: FxIndexMap>, @@ -1871,6 +1871,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { doc_link_traits_in_scope: Default::default(), current_crate_outer_attr_insert_span, disambiguators: Default::default(), + delegation_infos: Default::default(), .. }; @@ -1991,6 +1992,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { doc_link_traits_in_scope: self.doc_link_traits_in_scope, all_macro_rules: self.all_macro_rules, stripped_cfg_items, + delegation_infos: self.delegation_infos, }; let ast_lowering = ty::ResolverAstLowering { partial_res_map: self.partial_res_map, @@ -1998,7 +2000,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { next_node_id: self.next_node_id, owners: self.owners, lint_buffer: Steal::new(self.lint_buffer), - delegation_infos: self.delegation_infos, disambiguators, }; ResolverOutputs { global_ctxt, ast_lowering } diff --git a/compiler/rustc_type_ir/src/predicate.rs b/compiler/rustc_type_ir/src/predicate.rs index 8de64762c30b5..a8830b80493e6 100644 --- a/compiler/rustc_type_ir/src/predicate.rs +++ b/compiler/rustc_type_ir/src/predicate.rs @@ -429,13 +429,6 @@ impl ExistentialTraitRef { /// Therefore, you must specify *some* self type to perform the conversion. /// A common choice is the trait object type itself or some kind of dummy type. pub fn with_self_ty(self, interner: I, self_ty: I::Ty) -> TraitRef { - // FIXME(#157122): This assertion was accidentally commented out in refactoring PR #53816 - // back in 2018 but nowadays it can actually trigger. Either remove this - // comment entirely if the assertion is incorrect or uncomment it and fix - // the fallout! - // otherwise the escaping vars would be captured by the binder - //debug_assert!(!self_ty.has_escaping_bound_vars()); - TraitRef::new(interner, self.def_id, [self_ty.into()].into_iter().chain(self.args.iter())) } } diff --git a/library/alloc/src/collections/btree/map/entry.rs b/library/alloc/src/collections/btree/map/entry.rs index b99fbb5e84bd6..1c2ad5c568e6a 100644 --- a/library/alloc/src/collections/btree/map/entry.rs +++ b/library/alloc/src/collections/btree/map/entry.rs @@ -165,9 +165,42 @@ impl<'a, K: Ord, V, A: Allocator + Clone> Entry<'a, K, V, A> { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn or_insert_with V>(self, default: F) -> &'a mut V { + self.or_try_insert_with(|| Result::<_, !>::Ok(default())).unwrap() + } + + /// Ensures a value is in the entry by inserting the result of a fallible default function + /// if empty, and returns a mutable reference to the value in the entry. + /// + /// This method works identically to [`or_insert_with`] except that the default function + /// should return a `Result` and, in the case of an error, the error is propagated. + /// + /// [`or_insert_with`]: Self::or_insert_with + /// + /// # Examples + /// + /// ``` + /// #![feature(try_entry)] + /// # fn main() -> Result<(), std::num::ParseIntError> { + /// use std::collections::BTreeMap; + /// + /// let mut map: BTreeMap<&str, usize> = BTreeMap::new(); + /// let value = "42"; + /// + /// map.entry("poneyland").or_try_insert_with(|| value.parse())?; + /// + /// assert_eq!(map["poneyland"], 42); + /// # Ok(()) + /// # } + /// ``` + #[inline] + #[unstable(feature = "try_entry", issue = "157354")] + pub fn or_try_insert_with Result, E>( + self, + default: F, + ) -> Result<&'a mut V, E> { match self { - Occupied(entry) => entry.into_mut(), - Vacant(entry) => entry.insert(default()), + Occupied(entry) => Ok(entry.into_mut()), + Vacant(entry) => Ok(entry.insert(default()?)), } } @@ -193,11 +226,44 @@ impl<'a, K: Ord, V, A: Allocator + Clone> Entry<'a, K, V, A> { #[inline] #[stable(feature = "or_insert_with_key", since = "1.50.0")] pub fn or_insert_with_key V>(self, default: F) -> &'a mut V { + self.or_try_insert_with_key(|k| Result::<_, !>::Ok(default(k))).into_ok() + } + + /// Ensures a value is in the entry by inserting, if empty, the result of the default function. + /// This method allows for generating key-derived values for insertion by providing the default + /// function a reference to the key that was moved during the `entry(key)` method call. + /// + /// This method works identically to [`or_insert_with_key`] except that the default function + /// should return a `Result` and, in the case of an error, the error is propagated. + /// + /// [`or_insert_with_key`]: Self::or_insert_with_key + /// + /// # Examples + /// + /// ``` + /// #![feature(try_entry)] + /// # fn main() -> Result<(), std::num::ParseIntError> { + /// use std::collections::BTreeMap; + /// + /// let mut map: BTreeMap<&str, usize> = BTreeMap::new(); + /// + /// map.entry("42").or_try_insert_with_key(|key| key.parse())?; + /// + /// assert_eq!(map["42"], 42); + /// # Ok(()) + /// # } + /// ``` + #[inline] + #[unstable(feature = "try_entry", issue = "157354")] + pub fn or_try_insert_with_key Result, E>( + self, + default: F, + ) -> Result<&'a mut V, E> { match self { - Occupied(entry) => entry.into_mut(), + Occupied(entry) => Ok(entry.into_mut()), Vacant(entry) => { - let value = default(entry.key()); - entry.insert(value) + let value = default(entry.key())?; + Ok(entry.insert(value)) } } } diff --git a/library/alloctests/lib.rs b/library/alloctests/lib.rs index db643ccb7a4e6..590f559e0d524 100644 --- a/library/alloctests/lib.rs +++ b/library/alloctests/lib.rs @@ -51,6 +51,7 @@ #![feature(trusted_random_access)] #![feature(try_reserve_kind)] #![feature(try_trait_v2)] +#![feature(unwrap_infallible)] #![feature(wtf8_internals)] // tidy-alphabetical-end // diff --git a/library/core/src/any.rs b/library/core/src/any.rs index 862f01ecbedb1..6c8cb114b9ef1 100644 --- a/library/core/src/any.rs +++ b/library/core/src/any.rs @@ -785,9 +785,8 @@ impl TypeId { /// ``` #[unstable(feature = "type_info", issue = "146922")] #[rustc_const_unstable(feature = "type_info", issue = "146922")] - pub const fn trait_info_of< - T: ptr::Pointee> + ?Sized + 'static, - >( + #[rustc_comptime] + pub fn trait_info_of> + ?Sized + 'static>( self, ) -> Option> { // SAFETY: The vtable was obtained for `T`, so it is guaranteed to be `DynMetadata`. @@ -812,7 +811,8 @@ impl TypeId { /// ``` #[unstable(feature = "type_info", issue = "146922")] #[rustc_const_unstable(feature = "type_info", issue = "146922")] - pub const fn trait_info_of_trait_type_id( + #[rustc_comptime] + pub fn trait_info_of_trait_type_id( self, trait_represented_by_type_id: TypeId, ) -> Option> { diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index 78d7314c58110..c96c2344a8cb4 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -2874,11 +2874,12 @@ pub const unsafe fn size_of_val(ptr: *const T) -> usize; pub const unsafe fn align_of_val(ptr: *const T) -> usize; #[rustc_intrinsic] +#[rustc_comptime] #[unstable(feature = "core_intrinsics", issue = "none")] /// Check if a type represented by a `TypeId` implements a trait represented by a `TypeId`. /// It can only be called at compile time, the backends do /// not implement it. If it implements the trait the dyn metadata gets returned for vtable access. -pub const fn type_id_vtable( +pub fn type_id_vtable( _id: crate::any::TypeId, _trait: crate::any::TypeId, ) -> Option> { @@ -2922,7 +2923,8 @@ pub const fn type_name() -> &'static str; #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_intrinsic] -pub const fn type_id() -> crate::any::TypeId; +#[rustc_comptime] +pub fn type_id() -> crate::any::TypeId; /// Tests (at compile-time) if two [`crate::any::TypeId`] instances identify the /// same type. This is necessary because at const-eval time the actual discriminating @@ -2944,7 +2946,8 @@ pub const fn type_id_eq(a: crate::any::TypeId, b: crate::any::TypeId) -> bool { /// The more user-friendly version of this intrinsic is [`core::any::TypeId::size`]. #[rustc_intrinsic] #[unstable(feature = "core_intrinsics", issue = "none")] -pub const fn size_of_type_id(_id: crate::any::TypeId) -> Option { +#[rustc_comptime] +pub fn size_of_type_id(_id: crate::any::TypeId) -> Option { panic!("`TypeId::size` can only be called at compile-time") } @@ -2953,7 +2956,8 @@ pub const fn size_of_type_id(_id: crate::any::TypeId) -> Option { /// The more user-friendly version of this intrinsic is [`core::any::TypeId::variants`]. #[rustc_intrinsic] #[unstable(feature = "core_intrinsics", issue = "none")] -pub const fn type_id_variants(_id: crate::any::TypeId) -> usize { +#[rustc_comptime] +pub fn type_id_variants(_id: crate::any::TypeId) -> usize { panic!("`TypeId::variants` can only be called at compile-time") } @@ -2962,7 +2966,8 @@ pub const fn type_id_variants(_id: crate::any::TypeId) -> usize { /// The more user-friendly version of this intrinsic is [`core::any::TypeId::fields`]. #[rustc_intrinsic] #[unstable(feature = "core_intrinsics", issue = "none")] -pub const fn type_id_fields(_id: crate::any::TypeId, _variant_index: usize) -> usize { +#[rustc_comptime] +pub fn type_id_fields(_id: crate::any::TypeId, _variant_index: usize) -> usize { panic!("`TypeId::fields` can only be called at compile-time") } @@ -2973,7 +2978,8 @@ pub const fn type_id_fields(_id: crate::any::TypeId, _variant_index: usize) -> u /// [`FieldRepresentingType`]: crate::field::FieldRepresentingType #[rustc_intrinsic] #[unstable(feature = "core_intrinsics", issue = "none")] -pub const fn type_id_field_representing_type( +#[rustc_comptime] +pub fn type_id_field_representing_type( _id: crate::any::TypeId, _variant_index: usize, _field_index: usize, @@ -2988,7 +2994,8 @@ pub const fn type_id_field_representing_type( /// [`FieldRepresentingType`]: crate::field::FieldRepresentingType #[rustc_intrinsic] #[unstable(feature = "core_intrinsics", issue = "none")] -pub const fn field_representing_type_actual_type_id( +#[rustc_comptime] +pub fn field_representing_type_actual_type_id( _frt_type_id: crate::any::TypeId, ) -> crate::any::TypeId { panic!("`FieldId::type_id` can only be called at compile-time") diff --git a/library/core/src/mem/type_info.rs b/library/core/src/mem/type_info.rs index 8e7e51caad1f1..9ec36561839b5 100644 --- a/library/core/src/mem/type_info.rs +++ b/library/core/src/mem/type_info.rs @@ -374,7 +374,8 @@ impl TypeId { /// ``` #[unstable(feature = "type_info", issue = "146922")] #[rustc_const_unstable(feature = "type_info", issue = "146922")] - pub const fn size(self) -> Option { + #[rustc_comptime] + pub fn size(self) -> Option { intrinsics::size_of_type_id(self) } @@ -399,7 +400,8 @@ impl TypeId { /// ``` #[unstable(feature = "type_info", issue = "146922")] #[rustc_const_unstable(feature = "type_info", issue = "146922")] - pub const fn variants(self) -> usize { + #[rustc_comptime] + pub fn variants(self) -> usize { intrinsics::type_id_variants(self) } @@ -461,7 +463,8 @@ impl TypeId { /// ``` #[unstable(feature = "type_info", issue = "146922")] #[rustc_const_unstable(feature = "type_info", issue = "146922")] - pub const fn fields(self, variant_index: usize) -> usize { + #[rustc_comptime] + pub fn fields(self, variant_index: usize) -> usize { intrinsics::type_id_fields(self, variant_index) } @@ -527,7 +530,8 @@ impl TypeId { /// ``` #[unstable(feature = "type_info", issue = "146922")] #[rustc_const_unstable(feature = "type_info", issue = "146922")] - pub const fn field(self, variant_index: usize, field_index: usize) -> FieldId { + #[rustc_comptime] + pub fn field(self, variant_index: usize, field_index: usize) -> FieldId { FieldId { frt_type_id: intrinsics::type_id_field_representing_type( self, @@ -571,7 +575,8 @@ impl FieldId { /// ``` #[unstable(feature = "type_info", issue = "146922")] #[rustc_const_unstable(feature = "type_info", issue = "146922")] - pub const fn type_id(self) -> TypeId { + #[rustc_comptime] + pub fn type_id(self) -> TypeId { intrinsics::field_representing_type_actual_type_id(self.frt_type_id) } } diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index 887efd12f550f..af03ae9a35b1c 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -2538,9 +2538,42 @@ impl<'a, K, V, A: Allocator> Entry<'a, K, V, A> { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn or_insert_with V>(self, default: F) -> &'a mut V { + self.or_try_insert_with(|| Result::<_, !>::Ok(default())).unwrap() + } + + /// Ensures a value is in the entry by inserting the result of a fallible default function + /// if empty, and returns a mutable reference to the value in the entry. + /// + /// This method works identically to [`or_insert_with`] except that the default function + /// should return a `Result` and, in the case of an error, the error is propagated. + /// + /// [`or_insert_with`]: Self::or_insert_with + /// + /// # Examples + /// + /// ``` + /// #![feature(try_entry)] + /// # fn main() -> Result<(), std::num::ParseIntError> { + /// use std::collections::HashMap; + /// + /// let mut map: HashMap<&str, usize> = HashMap::new(); + /// let value = "42"; + /// + /// map.entry("poneyland").or_try_insert_with(|| value.parse())?; + /// + /// assert_eq!(map["poneyland"], 42); + /// # Ok(()) + /// # } + /// ``` + #[inline] + #[unstable(feature = "try_entry", issue = "157354")] + pub fn or_try_insert_with Result, E>( + self, + default: F, + ) -> Result<&'a mut V, E> { match self { - Occupied(entry) => entry.into_mut(), - Vacant(entry) => entry.insert(default()), + Occupied(entry) => Ok(entry.into_mut()), + Vacant(entry) => Ok(entry.insert(default()?)), } } @@ -2565,11 +2598,44 @@ impl<'a, K, V, A: Allocator> Entry<'a, K, V, A> { #[inline] #[stable(feature = "or_insert_with_key", since = "1.50.0")] pub fn or_insert_with_key V>(self, default: F) -> &'a mut V { + self.or_try_insert_with_key(|k| Result::<_, !>::Ok(default(k))).into_ok() + } + + /// Ensures a value is in the entry by inserting, if empty, the result of the default function. + /// This method allows for generating key-derived values for insertion by providing the default + /// function a reference to the key that was moved during the `entry(key)` method call. + /// + /// This method works identically to [`or_insert_with_key`] except that the default function + /// should return a `Result` and, in the case of an error, the error is propagated. + /// + /// [`or_insert_with_key`]: Self::or_insert_with_key + /// + /// # Examples + /// + /// ``` + /// #![feature(try_entry)] + /// # fn main() -> Result<(), std::num::ParseIntError> { + /// use std::collections::HashMap; + /// + /// let mut map: HashMap<&str, usize> = HashMap::new(); + /// + /// map.entry("42").or_try_insert_with_key(|key| key.parse())?; + /// + /// assert_eq!(map["42"], 42); + /// # Ok(()) + /// # } + /// ``` + #[inline] + #[unstable(feature = "try_entry", issue = "157354")] + pub fn or_try_insert_with_key Result, E>( + self, + default: F, + ) -> Result<&'a mut V, E> { match self { - Occupied(entry) => entry.into_mut(), + Occupied(entry) => Ok(entry.into_mut()), Vacant(entry) => { - let value = default(entry.key()); - entry.insert(value) + let value = default(entry.key())?; + Ok(entry.insert(value)) } } } diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 09d81f11e0a45..ee7f108bc4e3d 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -313,6 +313,7 @@ #![feature(try_blocks)] #![feature(try_trait_v2)] #![feature(type_alias_impl_trait)] +#![feature(unwrap_infallible)] // tidy-alphabetical-end // // Library features (core): diff --git a/library/std/src/time.rs b/library/std/src/time.rs index 4dda8061a11a9..5566c497e06cb 100644 --- a/library/std/src/time.rs +++ b/library/std/src/time.rs @@ -137,9 +137,9 @@ use crate::sys::{FromInner, IntoInner, time}; /// if available, which is the case for all [tier 1] platforms. /// In practice such guarantees are – under rare circumstances – broken by hardware, virtualization /// or operating system bugs. To work around these bugs and platforms not offering monotonic clocks -/// [`duration_since`], [`elapsed`] and [`sub`] saturate to zero. In older Rust versions this -/// lead to a panic instead. [`checked_duration_since`] can be used to detect and handle situations -/// where monotonicity is violated, or `Instant`s are subtracted in the wrong order. +/// [`duration_since`], [`elapsed`] and [`sub`](#impl-Sub-for-Instant) saturate to zero. In older +/// Rust versions this lead to a panic instead. [`checked_duration_since`] can be used to detect and +/// handle situations where monotonicity is violated, or `Instant`s are subtracted in the wrong order. /// /// This workaround obscures programming errors where earlier and later instants are accidentally /// swapped. For this reason future Rust versions may reintroduce panics. diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs index c67981deda337..0948742de27a7 100644 --- a/src/bootstrap/src/core/build_steps/doc.rs +++ b/src/bootstrap/src/core/build_steps/doc.rs @@ -82,6 +82,7 @@ book!( #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct UnstableBook { + build_compiler: Compiler, target: TargetSelection, } @@ -97,11 +98,24 @@ impl Step for UnstableBook { } fn make_run(run: RunConfig<'_>) { - run.builder.ensure(UnstableBook { target: run.target }); + // Bump the stage to 2, because the unstable book requires an in-tree compiler. + // At the same time, since this step is enabled by default, we don't want `x doc` to fail + // in stage 1. + let stage = if run.builder.config.is_explicit_stage() || run.builder.top_stage >= 2 { + run.builder.top_stage + } else { + 2 + }; + + run.builder.ensure(UnstableBook { + build_compiler: prepare_doc_compiler(run.builder, run.target, stage), + target: run.target, + }); } fn run(self, builder: &Builder<'_>) { - builder.ensure(UnstableBookGen { target: self.target }); + builder + .ensure(UnstableBookGen { build_compiler: self.build_compiler, target: self.target }); builder.ensure(RustbookSrc { target: self.target, name: "unstable-book".to_owned(), @@ -1265,6 +1279,7 @@ impl Step for ErrorIndex { #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct UnstableBookGen { + build_compiler: Compiler, target: TargetSelection, } @@ -1281,11 +1296,15 @@ impl Step for UnstableBookGen { } fn make_run(run: RunConfig<'_>) { - run.builder.ensure(UnstableBookGen { target: run.target }); + run.builder.ensure(UnstableBookGen { + build_compiler: prepare_doc_compiler(run.builder, run.target, run.builder.top_stage), + target: run.target, + }); } fn run(self, builder: &Builder<'_>) { let target = self.target; + let rustc_path = builder.rustc(self.build_compiler); builder.info(&format!("Generating unstable book md files ({target})")); let out = builder.md_doc_out(target).join("unstable-book"); @@ -1295,6 +1314,7 @@ impl Step for UnstableBookGen { cmd.arg(builder.src.join("library")); cmd.arg(builder.src.join("compiler")); cmd.arg(builder.src.join("src")); + cmd.arg(rustc_path); cmd.arg(out); cmd.run(builder); diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index 618129e27b8ad..1a59e54a95cbf 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -1098,12 +1098,12 @@ mod snapshot { ctx .config("dist") .render_steps(), @r" - [build] rustc 0 -> UnstableBookGen 1 - [build] rustc 0 -> Rustbook 1 - [doc] unstable-book (book) [build] llvm [build] rustc 0 -> rustc 1 [build] rustc 1 -> std 1 + [build] rustc 0 -> UnstableBookGen 1 + [build] rustc 0 -> Rustbook 1 + [doc] unstable-book (book) [doc] book (book) [doc] book/first-edition (book) [doc] book/second-edition (book) @@ -1150,12 +1150,12 @@ mod snapshot { .path("rustc-docs") .args(&["--set", "build.compiler-docs=true"]) .render_steps(), @r" - [build] rustc 0 -> UnstableBookGen 1 - [build] rustc 0 -> Rustbook 1 - [doc] unstable-book (book) [build] llvm [build] rustc 0 -> rustc 1 [build] rustc 1 -> std 1 + [build] rustc 0 -> UnstableBookGen 1 + [build] rustc 0 -> Rustbook 1 + [doc] unstable-book (book) [doc] book (book) [doc] book/first-edition (book) [doc] book/second-edition (book) @@ -1208,15 +1208,15 @@ mod snapshot { "rust.lld=true", ]) .render_steps(), @r" - [build] rustc 0 -> UnstableBookGen 1 - [build] rustc 0 -> Rustbook 1 - [doc] unstable-book (book) [build] llvm [build] rustc 0 -> rustc 1 [build] rustc 0 -> LldWrapper 1 [build] rustc 0 -> WasmComponentLd 1 [build] rustc 0 -> LlvmBitcodeLinker 1 [build] rustc 1 -> std 1 + [build] rustc 0 -> UnstableBookGen 1 + [build] rustc 0 -> Rustbook 1 + [doc] unstable-book (book) [doc] book (book) [doc] book/first-edition (book) [doc] book/second-edition (book) @@ -1284,18 +1284,18 @@ mod snapshot { .hosts(&[&host_target()]) .targets(&[&host_target(), TEST_TRIPLE_1]) .render_steps(), @r" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 [build] rustc 0 -> UnstableBookGen 1 [build] rustc 0 -> Rustbook 1 [doc] unstable-book (book) + [build] rustc 1 -> std 1 [doc] unstable-book (book) - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 1 -> std 1 [doc] book (book) [doc] book/first-edition (book) [doc] book/second-edition (book) [doc] book/2018-edition (book) - [build] rustc 1 -> std 1 [doc] book (book) [doc] book/first-edition (book) [doc] book/second-edition (book) @@ -1360,12 +1360,13 @@ mod snapshot { .hosts(&[&host_target(), TEST_TRIPLE_1]) .targets(&[&host_target()]) .render_steps(), @r" - [build] rustc 0 -> UnstableBookGen 1 - [build] rustc 0 -> Rustbook 1 - [doc] unstable-book (book) [build] llvm [build] rustc 0 -> rustc 1 [build] rustc 1 -> std 1 + [build] rustc 0 -> UnstableBookGen 1 + [build] rustc 0 -> Rustbook 1 + [doc] unstable-book (book) + [build] rustc 1 -> std 1 [doc] book (book) [doc] book/first-edition (book) [doc] book/second-edition (book) @@ -1377,7 +1378,6 @@ mod snapshot { [build] rustc 1 -> error-index 2 [doc] rustc 1 -> error-index 2 [build] llvm - [build] rustc 1 -> std 1 [build] rustc 1 -> rustc 2 [build] rustc 1 -> error-index 2 [doc] rustc 1 -> error-index 2 @@ -1423,18 +1423,18 @@ mod snapshot { .hosts(&[&host_target(), TEST_TRIPLE_1]) .targets(&[&host_target(), TEST_TRIPLE_1]) .render_steps(), @r" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 [build] rustc 0 -> UnstableBookGen 1 [build] rustc 0 -> Rustbook 1 [doc] unstable-book (book) + [build] rustc 1 -> std 1 [doc] unstable-book (book) - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 1 -> std 1 [doc] book (book) [doc] book/first-edition (book) [doc] book/second-edition (book) [doc] book/2018-edition (book) - [build] rustc 1 -> std 1 [doc] book (book) [doc] book/first-edition (book) [doc] book/second-edition (book) @@ -1508,12 +1508,12 @@ mod snapshot { .hosts(&[]) .targets(&[TEST_TRIPLE_1]) .render_steps(), @r" - [build] rustc 0 -> UnstableBookGen 1 - [build] rustc 0 -> Rustbook 1 - [doc] unstable-book (book) [build] llvm [build] rustc 0 -> rustc 1 [build] rustc 1 -> std 1 + [build] rustc 0 -> UnstableBookGen 1 + [build] rustc 0 -> Rustbook 1 + [doc] unstable-book (book) [doc] book (book) [doc] book/first-edition (book) [doc] book/second-edition (book) @@ -1551,13 +1551,13 @@ mod snapshot { .targets(&[TEST_TRIPLE_1]) .args(&["--set", "rust.channel=nightly", "--set", "build.extended=true"]) .render_steps(), @r" - [build] rustc 0 -> UnstableBookGen 1 - [build] rustc 0 -> Rustbook 1 - [doc] unstable-book (book) [build] llvm [build] rustc 0 -> rustc 1 [build] rustc 0 -> WasmComponentLd 1 [build] rustc 1 -> std 1 + [build] rustc 0 -> UnstableBookGen 1 + [build] rustc 0 -> Rustbook 1 + [doc] unstable-book (book) [doc] book (book) [doc] book/first-edition (book) [doc] book/second-edition (book) @@ -1695,13 +1695,13 @@ mod snapshot { .config("dist") .args(&["--set", "rust.codegen-backends=['llvm', 'cranelift']"]) .render_steps(), @r" - [build] rustc 0 -> UnstableBookGen 1 - [build] rustc 0 -> Rustbook 1 - [doc] unstable-book (book) [build] llvm [build] rustc 0 -> rustc 1 [build] rustc 0 -> rustc_codegen_cranelift 1 [build] rustc 1 -> std 1 + [build] rustc 0 -> UnstableBookGen 1 + [build] rustc 0 -> Rustbook 1 + [doc] unstable-book (book) [doc] book (book) [doc] book/first-edition (book) [doc] book/second-edition (book) @@ -1778,12 +1778,12 @@ mod snapshot { .config("dist") .path("rustc-docs") .render_steps(), @r" - [build] rustc 0 -> UnstableBookGen 1 - [build] rustc 0 -> Rustbook 1 - [doc] unstable-book (book) [build] llvm [build] rustc 0 -> rustc 1 [build] rustc 1 -> std 1 + [build] rustc 0 -> UnstableBookGen 1 + [build] rustc 0 -> Rustbook 1 + [doc] unstable-book (book) [doc] book (book) [doc] book/first-edition (book) [doc] book/second-edition (book) @@ -2533,6 +2533,9 @@ mod snapshot { insta::assert_snapshot!( ctx.config("doc") .render_steps(), @r" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 [build] rustc 0 -> UnstableBookGen 1 [build] rustc 0 -> Rustbook 1 [doc] unstable-book (book) @@ -2542,14 +2545,11 @@ mod snapshot { [doc] book/2018-edition (book) [build] rustdoc 0 [doc] rustc 0 -> standalone 1 - [build] llvm - [build] rustc 0 -> rustc 1 [build] rustdoc 1 [doc] rustc 1 -> std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] [build] rustc 0 -> error-index 1 [doc] rustc 0 -> error-index 1 [doc] nomicon (book) - [build] rustc 1 -> std 1 [doc] rustc 1 -> reference (book) 2 [doc] rustdoc (book) [doc] rust-by-example (book) @@ -2901,10 +2901,10 @@ mod snapshot { }), @r" [build] llvm [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 [build] rustc 0 -> UnstableBookGen 1 [build] rustc 0 -> Rustbook 1 [doc] unstable-book (book) - [build] rustc 1 -> std 1 [doc] book (book) [doc] book/first-edition (book) [doc] book/second-edition (book) @@ -2960,10 +2960,10 @@ mod snapshot { }), @r" [build] llvm [build] rustc 0 -> rustc 1 + [build] rustc 1 -> std 1 [build] rustc 0 -> UnstableBookGen 1 [build] rustc 0 -> Rustbook 1 [doc] unstable-book (book) - [build] rustc 1 -> std 1 [doc] book (book) [doc] book/first-edition (book) [doc] book/second-edition (book) @@ -3048,10 +3048,10 @@ mod snapshot { [build] llvm [build] rustc 0 -> rustc 1 [build] rustc 0 -> WasmComponentLd 1 + [build] rustc 1 -> std 1 [build] rustc 0 -> UnstableBookGen 1 [build] rustc 0 -> Rustbook 1 [doc] unstable-book (book) - [build] rustc 1 -> std 1 [doc] book (book) [doc] book/first-edition (book) [doc] book/second-edition (book) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 7cbfb8dd11345..8bcc618be40b5 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -352,23 +352,23 @@ target | std | host | notes [`loongarch32-unknown-none-softfloat`](platform-support/loongarch-none.md) | * | | LoongArch32 Bare-metal (ILP32S ABI) [`m68k-unknown-linux-gnu`](platform-support/m68k-unknown-linux-gnu.md) | ? | | Motorola 680x0 Linux [`m68k-unknown-none-elf`](platform-support/m68k-unknown-none-elf.md) | | | Motorola 680x0 -`mips-unknown-linux-gnu` | ✓ | ✓ | MIPS Linux (kernel 4.4, glibc 2.23) -`mips-unknown-linux-musl` | ✓ | | MIPS Linux with musl 1.2.5 -`mips-unknown-linux-uclibc` | ✓ | | MIPS Linux with uClibc -[`mips64-openwrt-linux-musl`](platform-support/mips64-openwrt-linux-musl.md) | ? | | MIPS64 for OpenWrt Linux musl 1.2.5 -`mips64-unknown-linux-gnuabi64` | ✓ | ✓ | MIPS64 Linux, N64 ABI (kernel 4.4, glibc 2.23) -[`mips64-unknown-linux-muslabi64`](platform-support/mips64-unknown-linux-muslabi64.md) | ✓ | ✓ | MIPS64 Linux, N64 ABI, musl 1.2.5 -`mips64el-unknown-linux-gnuabi64` | ✓ | ✓ | MIPS64 (little endian) Linux, N64 ABI (kernel 4.4, glibc 2.23) -`mips64el-unknown-linux-muslabi64` | ✓ | | MIPS64 (little endian) Linux, N64 ABI, musl 1.2.5 -`mipsel-sony-psp` | * | | MIPS (LE) Sony PlayStation Portable (PSP) -[`mipsel-sony-psx`](platform-support/mipsel-sony-psx.md) | * | | MIPS (LE) Sony PlayStation 1 (PSX) -[`mipsel-unknown-linux-gnu`](platform-support/mipsel-unknown-linux-gnu.md) | ✓ | ✓ | MIPS (little endian) Linux (kernel 4.4, glibc 2.23) -`mipsel-unknown-linux-musl` | ✓ | | MIPS (little endian) Linux with musl 1.2.5 -`mipsel-unknown-linux-uclibc` | ✓ | | MIPS (LE) Linux with uClibc -[`mipsel-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | 32-bit MIPS (LE), requires mips32 cpu support -`mipsel-unknown-none` | * | | Bare MIPS (LE) softfloat -[`mips-mti-none-elf`](platform-support/mips-mti-none-elf.md) | * | | Bare MIPS32r2 (BE) softfloat -[`mipsel-mti-none-elf`](platform-support/mips-mti-none-elf.md) | * | | Bare MIPS32r2 (LE) softfloat +`mips-unknown-linux-gnu` | ✓ | ✓ | MIPS Linux (kernel 4.4, glibc 2.23) [^snan-inverted] +`mips-unknown-linux-musl` | ✓ | | MIPS Linux with musl 1.2.5 [^snan-inverted] +`mips-unknown-linux-uclibc` | ✓ | | MIPS Linux with uClibc [^snan-inverted] +[`mips64-openwrt-linux-musl`](platform-support/mips64-openwrt-linux-musl.md) | ? | | MIPS64 for OpenWrt Linux musl 1.2.5 [^snan-inverted] +`mips64-unknown-linux-gnuabi64` | ✓ | ✓ | MIPS64 Linux, N64 ABI (kernel 4.4, glibc 2.23) [^snan-inverted] +[`mips64-unknown-linux-muslabi64`](platform-support/mips64-unknown-linux-muslabi64.md) | ✓ | ✓ | MIPS64 Linux, N64 ABI, musl 1.2.5 [^snan-inverted] +`mips64el-unknown-linux-gnuabi64` | ✓ | ✓ | MIPS64 (little endian) Linux, N64 ABI (kernel 4.4, glibc 2.23) [^snan-inverted] +`mips64el-unknown-linux-muslabi64` | ✓ | | MIPS64 (little endian) Linux, N64 ABI, musl 1.2.5 [^snan-inverted] +`mipsel-sony-psp` | * | | MIPS (LE) Sony PlayStation Portable (PSP) [^snan-inverted] +[`mipsel-sony-psx`](platform-support/mipsel-sony-psx.md) | * | | MIPS (LE) Sony PlayStation 1 (PSX) [^snan-inverted] +[`mipsel-unknown-linux-gnu`](platform-support/mipsel-unknown-linux-gnu.md) | ✓ | ✓ | MIPS (little endian) Linux (kernel 4.4, glibc 2.23) [^snan-inverted] +`mipsel-unknown-linux-musl` | ✓ | | MIPS (little endian) Linux with musl 1.2.5 [^snan-inverted] +`mipsel-unknown-linux-uclibc` | ✓ | | MIPS (LE) Linux with uClibc [^snan-inverted] +[`mipsel-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | 32-bit MIPS (LE), requires mips32 cpu support [^snan-inverted] +`mipsel-unknown-none` | * | | Bare MIPS (LE) softfloat [^snan-inverted] +[`mips-mti-none-elf`](platform-support/mips-mti-none-elf.md) | * | | Bare MIPS32r2 (BE) softfloat [^snan-inverted] +[`mipsel-mti-none-elf`](platform-support/mips-mti-none-elf.md) | * | | Bare MIPS32r2 (LE) softfloat [^snan-inverted] [`mipsisa32r6-unknown-linux-gnu`](platform-support/mips-release-6.md) | ? | | 32-bit MIPS Release 6 Big Endian [`mipsisa32r6el-unknown-linux-gnu`](platform-support/mips-release-6.md) | ? | | 32-bit MIPS Release 6 Little Endian [`mipsisa64r6-unknown-linux-gnuabi64`](platform-support/mips-release-6.md) | ? | | 64-bit MIPS Release 6 Big Endian @@ -472,3 +472,7 @@ target | std | host | notes [runs on NVIDIA GPUs]: https://github.com/japaric-archived/nvptx#targets [the AMD GPU]: https://llvm.org/docs/AMDGPUUsage.html#processors + +[^snan-inverted]: On these targets, the treatment of floating-point NaN values is non-compliant. The bit representation for signaling NaNs is inverted compared to [what Rust expects](../std/primitive.f32.html). This means that operations that are expected to return a quiet NaN may return a signaling NaN. See [issue #68925][snan-issue]. + +[snan-issue]: https://github.com/rust-lang/rust/issues/68925 diff --git a/src/tools/unstable-book-gen/src/main.rs b/src/tools/unstable-book-gen/src/main.rs index 16550f83003dc..e50b8173e7f0f 100644 --- a/src/tools/unstable-book-gen/src/main.rs +++ b/src/tools/unstable-book-gen/src/main.rs @@ -4,12 +4,15 @@ use std::collections::BTreeSet; use std::env; use std::fs::{self, write}; use std::path::Path; +use std::process::Command; use tidy::diagnostics::RunningCheck; -use tidy::features::{Features, collect_env_vars, collect_lang_features, collect_lib_features}; +use tidy::features::{ + Feature, Features, Status, collect_env_vars, collect_lang_features, collect_lib_features, +}; use tidy::t; use tidy::unstable_book::{ - ENV_VARS_DIR, LANG_FEATURES_DIR, LIB_FEATURES_DIR, PATH_STR, + COMPILER_FLAGS_DIR, ENV_VARS_DIR, LANG_FEATURES_DIR, LIB_FEATURES_DIR, PATH_STR, collect_unstable_book_section_file_names, collect_unstable_feature_names, }; @@ -39,8 +42,15 @@ fn set_to_summary_str(set: &BTreeSet, dir: &str) -> String { .fold("".to_owned(), |s, a| s + &a + "\n") } -fn generate_summary(path: &Path, lang_features: &Features, lib_features: &Features) { - let compiler_flags = collect_unstable_book_section_file_names(&path.join("src/compiler-flags")); +fn generate_summary( + path: &Path, + lang_features: &Features, + lib_features: &Features, + compiler_flags: &Features, +) { + let compiler_flags = + &collect_unstable_book_section_file_names(&path.join("src/compiler-flags")) + | &collect_unstable_feature_names(&compiler_flags); let compiler_env_vars = collect_unstable_book_section_file_names(&path.join("src/compiler-environment-variables")); @@ -113,14 +123,47 @@ fn copy_recursive(from: &Path, to: &Path) { } } +fn collect_compiler_flags(rustc_path: impl AsRef) -> Features { + let mut rustc = Command::new(rustc_path.as_ref()); + rustc.arg("-Zhelp"); + let output = t!(rustc.output()); + let help_str = t!(String::from_utf8(output.stdout)); + let parts = help_str.split("\n -Z").collect::>(); + assert!(!parts[1..].is_empty(), "no -Z options were found"); + + let mut features = Features::new(); + for part in parts.into_iter().skip(1) { + let (name, description) = + part.split_once("--").expect("name and description should be delimited by '--'"); + let name = name.trim().trim_end_matches("=val"); + let description = description.trim(); + + features.insert( + name.replace('-', "_"), + Feature { + level: Status::Unstable, + since: None, + has_gate_test: false, + tracking_issue: None, + file: "".into(), + line: 0, + description: Some(description.to_owned()), + }, + ); + } + features +} + fn main() { let library_path_str = env::args_os().nth(1).expect("library/ path required"); let compiler_path_str = env::args_os().nth(2).expect("compiler/ path required"); let src_path_str = env::args_os().nth(3).expect("src/ path required"); - let dest_path_str = env::args_os().nth(4).expect("destination path required"); + let rustc_path_str = env::args_os().nth(4).expect("rustc path required"); + let dest_path_str = env::args_os().nth(5).expect("destination path required"); let library_path = Path::new(&library_path_str); let compiler_path = Path::new(&compiler_path_str); let src_path = Path::new(&src_path_str); + let rustc_path = Path::new(&rustc_path_str); let dest_path = Path::new(&dest_path_str); let lang_features = collect_lang_features(compiler_path, &mut RunningCheck::new_noop()); @@ -129,6 +172,7 @@ fn main() { .filter(|&(ref name, _)| !lang_features.contains_key(name)) .collect(); let env_vars = collect_env_vars(compiler_path); + let compiler_flags = collect_compiler_flags(rustc_path); let doc_src_path = src_path.join(PATH_STR); @@ -144,9 +188,14 @@ fn main() { &dest_path.join(LIB_FEATURES_DIR), &lib_features, ); + generate_feature_files( + &doc_src_path.join(COMPILER_FLAGS_DIR), + &dest_path.join(COMPILER_FLAGS_DIR), + &compiler_flags, + ); generate_env_files(&doc_src_path.join(ENV_VARS_DIR), &dest_path.join(ENV_VARS_DIR), &env_vars); copy_recursive(&doc_src_path, &dest_path); - generate_summary(&dest_path, &lang_features, &lib_features); + generate_summary(&dest_path, &lang_features, &lib_features, &compiler_flags); } diff --git a/tests/ui/abi/simd-abi-checks-avx.rs b/tests/ui/abi/simd-abi-checks-avx.rs index c68ba2fb5f890..7432381d15b72 100644 --- a/tests/ui/abi/simd-abi-checks-avx.rs +++ b/tests/ui/abi/simd-abi-checks-avx.rs @@ -1,7 +1,7 @@ //@ only-x86_64 //@ build-fail //@ compile-flags: -C target-feature=-avx -//@ ignore-parallel-frontend post-monomorphization errors + #![feature(portable_simd)] #![feature(simd_ffi)] #![allow(improper_ctypes_definitions)] diff --git a/tests/ui/consts/const-eval/index-out-of-bounds-never-type.rs b/tests/ui/consts/const-eval/index-out-of-bounds-never-type.rs index dbe507e3cd137..6777bee050a16 100644 --- a/tests/ui/consts/const-eval/index-out-of-bounds-never-type.rs +++ b/tests/ui/consts/const-eval/index-out-of-bounds-never-type.rs @@ -1,5 +1,5 @@ //@ build-fail -//@ ignore-parallel-frontend post-monomorphization errors + // Regression test for #66975 #![warn(unconditional_panic)] #![feature(never_type)] diff --git a/tests/ui/consts/const-eval/issue-50814-2.rs b/tests/ui/consts/const-eval/issue-50814-2.rs index 34a200e2887b9..1b917a0916da3 100644 --- a/tests/ui/consts/const-eval/issue-50814-2.rs +++ b/tests/ui/consts/const-eval/issue-50814-2.rs @@ -2,7 +2,7 @@ //@ revisions: normal mir-opt //@ [mir-opt]compile-flags: -Zmir-opt-level=4 //@ dont-require-annotations: NOTE -//@ ignore-parallel-frontend post-monomorphization errors + trait C { const BOO: usize; } diff --git a/tests/ui/consts/const-eval/issue-50814.rs b/tests/ui/consts/const-eval/issue-50814.rs index 3901a2c0c9316..011f065ad814b 100644 --- a/tests/ui/consts/const-eval/issue-50814.rs +++ b/tests/ui/consts/const-eval/issue-50814.rs @@ -1,6 +1,6 @@ //@ build-fail //@ dont-require-annotations: NOTE -//@ ignore-parallel-frontend post-monomorphization errors + trait Unsigned { const MAX: u8; } diff --git a/tests/ui/consts/mono-reachable-invalid-const.rs b/tests/ui/consts/mono-reachable-invalid-const.rs index 3d76e4a65a4e2..aba41dabe71f9 100644 --- a/tests/ui/consts/mono-reachable-invalid-const.rs +++ b/tests/ui/consts/mono-reachable-invalid-const.rs @@ -1,5 +1,5 @@ //@ build-fail -//@ ignore-parallel-frontend post-monomorphization errors + struct Bar; impl Bar { diff --git a/tests/ui/consts/required-consts/collect-in-called-fn.rs b/tests/ui/consts/required-consts/collect-in-called-fn.rs index d07c0927a16a9..2045b8266c792 100644 --- a/tests/ui/consts/required-consts/collect-in-called-fn.rs +++ b/tests/ui/consts/required-consts/collect-in-called-fn.rs @@ -4,7 +4,7 @@ //@[opt] compile-flags: -O //! Make sure we detect erroneous constants post-monomorphization even when they are unused. This is //! crucial, people rely on it for soundness. (https://github.com/rust-lang/rust/issues/112090) -//@ ignore-parallel-frontend post-monomorphization errors + struct Fail(T); impl Fail { const C: () = panic!(); //~ERROR evaluation panicked: explicit panic diff --git a/tests/ui/consts/required-consts/collect-in-dead-closure.rs b/tests/ui/consts/required-consts/collect-in-dead-closure.rs index 825336e9d3ef3..5f8b6bbb174c4 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-closure.rs +++ b/tests/ui/consts/required-consts/collect-in-dead-closure.rs @@ -3,7 +3,7 @@ //@[noopt] compile-flags: -Copt-level=0 //@[opt] compile-flags: -O //! This fails without optimizations, so it should also fail with optimizations. -//@ ignore-parallel-frontend post-monomorphization errors + struct Fail(T); impl Fail { const C: () = panic!(); //~ERROR evaluation panicked: explicit panic diff --git a/tests/ui/consts/required-consts/collect-in-dead-drop.rs b/tests/ui/consts/required-consts/collect-in-dead-drop.rs index fa9b8730c11c9..f7293d162df7b 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-drop.rs +++ b/tests/ui/consts/required-consts/collect-in-dead-drop.rs @@ -3,7 +3,7 @@ //@[noopt] compile-flags: -Copt-level=0 //@[opt] compile-flags: -O //! This fails without optimizations, so it should also fail with optimizations. -//@ ignore-parallel-frontend post-monomorphization errors + struct Fail(T); impl Fail { const C: () = panic!(); //~ERROR evaluation panicked: explicit panic diff --git a/tests/ui/consts/required-consts/collect-in-dead-fn-behind-assoc-type.rs b/tests/ui/consts/required-consts/collect-in-dead-fn-behind-assoc-type.rs index a76481b673132..e6be9f56cb7a0 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-fn-behind-assoc-type.rs +++ b/tests/ui/consts/required-consts/collect-in-dead-fn-behind-assoc-type.rs @@ -4,7 +4,7 @@ //@[noopt] compile-flags: -Copt-level=0 //@[opt] compile-flags: -O //! This fails without optimizations, so it should also fail with optimizations. -//@ ignore-parallel-frontend post-monomorphization errors + struct Fail(T); impl Fail { const C: () = panic!(); //~ERROR evaluation panicked: explicit panic diff --git a/tests/ui/consts/required-consts/collect-in-dead-fn-behind-generic.rs b/tests/ui/consts/required-consts/collect-in-dead-fn-behind-generic.rs index 4fe05db34d78e..a86902af52677 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-fn-behind-generic.rs +++ b/tests/ui/consts/required-consts/collect-in-dead-fn-behind-generic.rs @@ -3,7 +3,7 @@ //@[noopt] compile-flags: -Copt-level=0 //@[opt] compile-flags: -O //! This fails without optimizations, so it should also fail with optimizations. -//@ ignore-parallel-frontend post-monomorphization errors + struct Fail(T); impl Fail { const C: () = panic!(); //~ERROR evaluation panicked: explicit panic diff --git a/tests/ui/consts/required-consts/collect-in-dead-fn-behind-opaque-type.rs b/tests/ui/consts/required-consts/collect-in-dead-fn-behind-opaque-type.rs index a6132ef1fe07e..4cdb27413540f 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-fn-behind-opaque-type.rs +++ b/tests/ui/consts/required-consts/collect-in-dead-fn-behind-opaque-type.rs @@ -4,7 +4,7 @@ //@[opt] compile-flags: -O //! This fails without optimizations, so it should also fail with optimizations. #![feature(type_alias_impl_trait)] -//@ ignore-parallel-frontend post-monomorphization errors + mod m { struct Fail(T); impl Fail { diff --git a/tests/ui/consts/required-consts/collect-in-dead-fn.rs b/tests/ui/consts/required-consts/collect-in-dead-fn.rs index f4627323249d4..0c4795801068d 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-fn.rs +++ b/tests/ui/consts/required-consts/collect-in-dead-fn.rs @@ -3,7 +3,7 @@ //@[noopt] compile-flags: -Copt-level=0 //@[opt] compile-flags: -O //! This fails without optimizations, so it should also fail with optimizations. -//@ ignore-parallel-frontend post-monomorphization errors + struct Fail(T); impl Fail { const C: () = panic!(); //~ERROR evaluation panicked: explicit panic diff --git a/tests/ui/consts/required-consts/collect-in-dead-fnptr-in-const.rs b/tests/ui/consts/required-consts/collect-in-dead-fnptr-in-const.rs index 8808a4e26f0cb..04544cb413984 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-fnptr-in-const.rs +++ b/tests/ui/consts/required-consts/collect-in-dead-fnptr-in-const.rs @@ -3,7 +3,7 @@ //@[noopt] compile-flags: -Copt-level=0 //@[opt] compile-flags: -O //! This fails without optimizations, so it should also fail with optimizations. -//@ ignore-parallel-frontend post-monomorphization errors + struct Late(T); impl Late { const FAIL: () = panic!(); //~ERROR evaluation panicked: explicit panic diff --git a/tests/ui/consts/required-consts/collect-in-dead-fnptr.rs b/tests/ui/consts/required-consts/collect-in-dead-fnptr.rs index 1a9b99f9868f6..4cdb50f4385a1 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-fnptr.rs +++ b/tests/ui/consts/required-consts/collect-in-dead-fnptr.rs @@ -3,7 +3,7 @@ //@[noopt] compile-flags: -Copt-level=0 //@[opt] compile-flags: -O //! This fails without optimizations, so it should also fail with optimizations. -//@ ignore-parallel-frontend post-monomorphization errors + struct Fail(T); impl Fail { const C: () = panic!(); //~ERROR evaluation panicked: explicit panic diff --git a/tests/ui/consts/required-consts/collect-in-dead-forget.rs b/tests/ui/consts/required-consts/collect-in-dead-forget.rs index bc717edbe73ee..7586004116c36 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-forget.rs +++ b/tests/ui/consts/required-consts/collect-in-dead-forget.rs @@ -3,7 +3,7 @@ //@[noopt] compile-flags: -Copt-level=0 //@[opt] compile-flags: -O //! This passes without optimizations, so it can (and should) also pass with optimizations. -//@ ignore-parallel-frontend post-monomorphization errors + struct Fail(T); impl Fail { const C: () = panic!(); diff --git a/tests/ui/consts/required-consts/collect-in-dead-move.rs b/tests/ui/consts/required-consts/collect-in-dead-move.rs index 05491136e8d5e..4e2d959db32c7 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-move.rs +++ b/tests/ui/consts/required-consts/collect-in-dead-move.rs @@ -3,7 +3,7 @@ //@[noopt] compile-flags: -Copt-level=0 //@[opt] compile-flags: -O //! This fails without optimizations, so it should also fail with optimizations. -//@ ignore-parallel-frontend post-monomorphization errors + struct Fail(T); impl Fail { const C: () = panic!(); //~ERROR evaluation panicked: explicit panic diff --git a/tests/ui/consts/required-consts/collect-in-dead-vtable.rs b/tests/ui/consts/required-consts/collect-in-dead-vtable.rs index 1ca52064a3fdd..d4ad730837730 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-vtable.rs +++ b/tests/ui/consts/required-consts/collect-in-dead-vtable.rs @@ -3,7 +3,7 @@ //@[noopt] compile-flags: -Copt-level=0 //@[opt] compile-flags: -O //! This fails without optimizations, so it should also fail with optimizations. -//@ ignore-parallel-frontend post-monomorphization errors + struct Fail(T); impl Fail { const C: () = panic!(); //~ERROR evaluation panicked: explicit panic diff --git a/tests/ui/consts/required-consts/collect-in-promoted-const.rs b/tests/ui/consts/required-consts/collect-in-promoted-const.rs index 415f22fd05dda..c475720938697 100644 --- a/tests/ui/consts/required-consts/collect-in-promoted-const.rs +++ b/tests/ui/consts/required-consts/collect-in-promoted-const.rs @@ -3,7 +3,7 @@ //@[noopt] compile-flags: -Copt-level=0 //@[opt] compile-flags: -O //! Make sure we error on erroneous consts even if they get promoted. -//@ ignore-parallel-frontend post-monomorphization errors + struct Fail(T); impl Fail { const C: () = panic!(); //~ERROR evaluation panicked: explicit panic diff --git a/tests/ui/consts/required-consts/interpret-in-const-called-fn.rs b/tests/ui/consts/required-consts/interpret-in-const-called-fn.rs index 2d63c620a0384..9309457e22a46 100644 --- a/tests/ui/consts/required-consts/interpret-in-const-called-fn.rs +++ b/tests/ui/consts/required-consts/interpret-in-const-called-fn.rs @@ -2,7 +2,7 @@ //@[noopt] compile-flags: -Copt-level=0 //@[opt] compile-flags: -O //! Make sure we error on erroneous consts even if they are unused. -//@ ignore-parallel-frontend post-monomorphization errors + struct Fail(T); impl Fail { const C: () = panic!(); //~ERROR explicit panic diff --git a/tests/ui/consts/required-consts/interpret-in-promoted.rs b/tests/ui/consts/required-consts/interpret-in-promoted.rs index cbb1a309006c5..b223e6d16aa12 100644 --- a/tests/ui/consts/required-consts/interpret-in-promoted.rs +++ b/tests/ui/consts/required-consts/interpret-in-promoted.rs @@ -2,7 +2,7 @@ //@[noopt] compile-flags: -Copt-level=0 //@[opt] compile-flags: -O //@ dont-require-annotations: NOTE -//@ ignore-parallel-frontend post-monomorphization errors + //! Make sure we evaluate const fn calls even if they get promoted and their result ignored. const unsafe fn ub() { diff --git a/tests/ui/consts/required-consts/interpret-in-static.rs b/tests/ui/consts/required-consts/interpret-in-static.rs index edc7b1d01fd6c..19ad6be1c9fa7 100644 --- a/tests/ui/consts/required-consts/interpret-in-static.rs +++ b/tests/ui/consts/required-consts/interpret-in-static.rs @@ -2,7 +2,7 @@ //@[noopt] compile-flags: -Copt-level=0 //@[opt] compile-flags: -O //! Make sure we error on erroneous consts even if they are unused. -//@ ignore-parallel-frontend post-monomorphization errors + struct Fail(T); impl Fail { const C: () = panic!(); //~ERROR explicit panic diff --git a/tests/ui/delegation/self-coercion-static-free.rs b/tests/ui/delegation/self-coercion-static-free.rs index 2aeb5bd404991..408b29a12cde0 100644 --- a/tests/ui/delegation/self-coercion-static-free.rs +++ b/tests/ui/delegation/self-coercion-static-free.rs @@ -23,6 +23,7 @@ impl Trait for S { //~^ ERROR: mismatched types //~| ERROR: mismatched types //~| ERROR: mismatched types + //~| ERROR: unused target expression is specified for glob or list delegation let _ = self; S::static_self() } @@ -35,6 +36,7 @@ impl Trait for S1 { //~^ ERROR: mismatched types //~| ERROR: mismatched types //~| ERROR: mismatched types + //~| ERROR: unused target expression is specified for glob or list delegation let _ = self; S1::static_self() } diff --git a/tests/ui/delegation/self-coercion-static-free.stderr b/tests/ui/delegation/self-coercion-static-free.stderr index b61ec58ee715c..870bd6bf3073b 100644 --- a/tests/ui/delegation/self-coercion-static-free.stderr +++ b/tests/ui/delegation/self-coercion-static-free.stderr @@ -1,3 +1,15 @@ +error: unused target expression is specified for glob or list delegation + --> $DIR/self-coercion-static-free.rs:22:26 + | +LL | reuse ::{static_value, static_mut_ref, static_ref} { + | ^^^^^^^^^^^^ + +error: unused target expression is specified for glob or list delegation + --> $DIR/self-coercion-static-free.rs:35:26 + | +LL | reuse ::{static_value, static_mut_ref, static_ref} { + | ^^^^^^^^^^^^ + error[E0308]: mismatched types --> $DIR/self-coercion-static-free.rs:22:26 | @@ -48,7 +60,7 @@ LL | fn static_ref(_: &Self) -> i32 { 3 } | ^^^^^^^^^^ -------- error[E0308]: mismatched types - --> $DIR/self-coercion-static-free.rs:34:26 + --> $DIR/self-coercion-static-free.rs:35:26 | LL | reuse ::{static_value, static_mut_ref, static_ref} { | ^^^^^^^^^^^^ @@ -63,7 +75,7 @@ LL | fn static_value(_: Self) -> i32 { 1 } | ^^^^^^^^^^^^ ------- error[E0308]: mismatched types - --> $DIR/self-coercion-static-free.rs:34:40 + --> $DIR/self-coercion-static-free.rs:35:40 | LL | reuse ::{static_value, static_mut_ref, static_ref} { | ^^^^^^^^^^^^^^ @@ -80,7 +92,7 @@ LL | fn static_mut_ref(_: &mut Self) -> i32 { 2 } | ^^^^^^^^^^^^^^ ------------ error[E0308]: mismatched types - --> $DIR/self-coercion-static-free.rs:34:56 + --> $DIR/self-coercion-static-free.rs:35:56 | LL | reuse ::{static_value, static_mut_ref, static_ref} { | ^^^^^^^^^^ @@ -97,7 +109,7 @@ LL | fn static_ref(_: &Self) -> i32 { 3 } | ^^^^^^^^^^ -------- error[E0308]: mismatched types - --> $DIR/self-coercion-static-free.rs:50:43 + --> $DIR/self-coercion-static-free.rs:52:43 | LL | reuse to_reuse::{value, mut_ref, r#ref} { F } | ------- ^ expected `&mut _`, found `F` @@ -107,7 +119,7 @@ LL | reuse to_reuse::{value, mut_ref, r#ref} { F } = note: expected mutable reference `&mut _` found struct `F` note: function defined here - --> $DIR/self-coercion-static-free.rs:46:12 + --> $DIR/self-coercion-static-free.rs:48:12 | LL | pub fn mut_ref(_: &mut impl Trait) -> i32 { 2 } | ^^^^^^^ ------------------ @@ -117,7 +129,7 @@ LL | reuse to_reuse::{value, mut_ref, r#ref} { &mut F } | ++++ error[E0308]: mismatched types - --> $DIR/self-coercion-static-free.rs:50:43 + --> $DIR/self-coercion-static-free.rs:52:43 | LL | reuse to_reuse::{value, mut_ref, r#ref} { F } | ----- ^ expected `&_`, found `F` @@ -127,7 +139,7 @@ LL | reuse to_reuse::{value, mut_ref, r#ref} { F } = note: expected reference `&_` found struct `F` note: function defined here - --> $DIR/self-coercion-static-free.rs:47:12 + --> $DIR/self-coercion-static-free.rs:49:12 | LL | pub fn r#ref(_: &impl Trait) -> i32 { 3 } | ^^^^^ -------------- @@ -136,6 +148,6 @@ help: consider borrowing here LL | reuse to_reuse::{value, mut_ref, r#ref} { &F } | + -error: aborting due to 8 previous errors +error: aborting due to 10 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/delegation/unused-target-expr-in-glob-or-list.rs b/tests/ui/delegation/unused-target-expr-in-glob-or-list.rs new file mode 100644 index 0000000000000..72f82390b62be --- /dev/null +++ b/tests/ui/delegation/unused-target-expr-in-glob-or-list.rs @@ -0,0 +1,208 @@ +#![feature(fn_delegation)] + +pub trait Trait: Sized { + fn static_self() -> F { F } + fn static_self2() -> F { F } + + fn static_value(_: F) -> i32 { 1 } + fn static_mut_ref(_: &mut F) -> i32 { 2 } + fn static_ref(_: &F) -> i32 { 3 } +} + +#[derive(Default, Eq, PartialEq, Debug)] +pub struct F; +impl Trait for F {} + +struct S(F); +impl Trait for S { + reuse ::* { self.0 } + //~^ ERROR: unused target expression is specified for glob or list delegation +} + +struct S1(F); +impl S1 { + reuse ::* { self.0 } + //~^ ERROR: unused target expression is specified for glob or list delegation +} + +struct S2(F); +impl Trait for S2 { + reuse ::{static_self} { self.0 } + //~^ ERROR: unused target expression is specified for glob or list delegation +} + +struct S3(F); +impl Trait for S3 { + reuse ::{static_self, static_value} { self.0 } + //~^ ERROR: unused target expression is specified for glob or list delegation +} + +struct S4(F); +impl Trait for S4 { + reuse ::{static_self, static_value, static_mut_ref, static_ref} { self.0 } + //~^ ERROR: unused target expression is specified for glob or list delegation +} + +struct S5(F); +impl Trait for S5 { + reuse ::{static_self, static_value, static_mut_ref, static_ref} { } + //~^ ERROR: unused target expression is specified for glob or list delegation +} + +struct S6(F); +impl Trait for S6 { + // Error about unused target expression is not emitted when error delegation is generated. + reuse UnresolvedTrait::* { self.0 } + //~^ ERROR: cannot find type `UnresolvedTrait` in this scope +} + +struct S7(F); +impl Trait for S7 { + reuse ::*; +} + +struct S8(F); +impl Trait for S8 { + reuse ::{static_self, static_self2} { { F } } + //~^ ERROR: unused target expression is specified for glob or list delegation +} + +struct S9; +impl S9 { + reuse ::{static_self, static_self2} { { F } } + //~^ ERROR: unused target expression is specified for glob or list delegation + + reuse ::{static_value, static_mut_ref, static_ref} { } + //~^ ERROR: unused target expression is specified for glob or list delegation +} + +trait Trait2 { + reuse ::{static_self, static_self2} { { F } } + //~^ ERROR: unused target expression is specified for glob or list delegation + + reuse ::{static_value, static_mut_ref} { } + //~^ ERROR: unused target expression is specified for glob or list delegation + + reuse ::{static_ref}; +} + +mod free_to_trait1 { + use super::{F, Trait}; + + reuse ::{static_self, static_self2} { { F } } + //~^ ERROR: unused target expression is specified for glob or list delegation + + reuse ::{static_value, static_mut_ref} { } + //~^ ERROR: unused target expression is specified for glob or list delegation + + reuse ::{static_ref}; +} + +mod macros { + use super::*; + + macro_rules! delegation { + () => { + impl Trait for S { + reuse ::static_self { self.0 } + //~^ ERROR: delegation's target expression is specified for function with no params + //~| ERROR: mismatched types + //~| ERROR: this function takes 0 arguments but 1 argument was supplied + //~| ERROR: method `static_self` has an incompatible type for trait + reuse ::static_value { self.0 } + //~^ ERROR: no field `0` on type `F` + reuse ::static_mut_ref { self.0 } + //~^ ERROR: no field `0` on type `&mut F` + reuse ::static_ref { self.0 } + //~^ ERROR: no field `0` on type `&F` + } + }; + } + + struct S(F); + delegation!(); + + macro_rules! delegation2 { + () => { + reuse ::static_self { self.0 } + //~^ ERROR: delegation's target expression is specified for function with no params + //~| ERROR: mismatched types + //~| ERROR: this function takes 0 arguments but 1 argument was supplied + //~| ERROR: method `static_self` has an incompatible type for trait + reuse ::static_value { self.0 } + //~^ ERROR: no field `0` on type `F` + reuse ::static_mut_ref { self.0 } + //~^ ERROR: no field `0` on type `&mut F` + reuse ::static_ref { self.0 } + //~^ ERROR: no field `0` on type `&F` + }; + } + + struct S1(F); + impl Trait for S1 { + delegation2!(); + } +} + +mod free_list { + mod to_reuse { + pub fn value() -> i32 { 1 } + pub fn mut_ref() -> i32 { 2 } + pub fn r#ref() -> i32 { 3 } + } + + reuse to_reuse::{value, mut_ref, r#ref} { () } + //~^ ERROR: this function takes 0 arguments but 1 argument was supplied + //~| ERROR: this function takes 0 arguments but 1 argument was supplied + //~| ERROR: this function takes 0 arguments but 1 argument was supplied + //~| ERROR: mismatched types + //~| ERROR: mismatched types + //~| ERROR: mismatched types + //~| ERROR: delegation's target expression is specified for function with no params + //~| ERROR: delegation's target expression is specified for function with no params + //~| ERROR: delegation's target expression is specified for function with no params + + reuse to_reuse::{value as value2} { } + //~^ ERROR: this function takes 0 arguments but 1 argument was supplied + //~| ERROR: mismatched types + //~| ERROR: delegation's target expression is specified for function with no params +} + +mod to_free { + trait Trait { + fn value() -> i32 { 1 } + fn mut_ref() -> i32 { 2 } + fn r#ref() -> i32 { 3 } + } + + mod to_reuse { + pub fn value() -> i32 { 1 } + pub fn mut_ref() -> i32 { 2 } + pub fn r#ref() -> i32 { 3 } + } + + struct F; + impl Trait for F {} + + struct S(F); + impl Trait for S { + reuse to_reuse::{value, mut_ref, r#ref} { () } + //~^ ERROR: unused target expression is specified for glob or list delegation + } + + struct S2; + impl S2 { + reuse to_reuse::{value, mut_ref, r#ref} { 1 + 1 } + //~^ ERROR: this function takes 0 arguments but 1 argument was supplied + //~| ERROR: this function takes 0 arguments but 1 argument was supplied + //~| ERROR: this function takes 0 arguments but 1 argument was supplied + //~| ERROR: mismatched types + //~| ERROR: mismatched types + //~| ERROR: mismatched types + //~| ERROR: delegation's target expression is specified for function with no params + //~| ERROR: delegation's target expression is specified for function with no params + //~| ERROR: delegation's target expression is specified for function with no params + } +} + +fn main() {} diff --git a/tests/ui/delegation/unused-target-expr-in-glob-or-list.stderr b/tests/ui/delegation/unused-target-expr-in-glob-or-list.stderr new file mode 100644 index 0000000000000..65091ac8b5d49 --- /dev/null +++ b/tests/ui/delegation/unused-target-expr-in-glob-or-list.stderr @@ -0,0 +1,569 @@ +error[E0433]: cannot find type `UnresolvedTrait` in this scope + --> $DIR/unused-target-expr-in-glob-or-list.rs:55:11 + | +LL | reuse UnresolvedTrait::* { self.0 } + | ^^^^^^^^^^^^^^^ use of undeclared type `UnresolvedTrait` + +error: delegation's target expression is specified for function with no params + --> $DIR/unused-target-expr-in-glob-or-list.rs:154:45 + | +LL | reuse to_reuse::{value, mut_ref, r#ref} { () } + | ^^^^^^ + +error: delegation's target expression is specified for function with no params + --> $DIR/unused-target-expr-in-glob-or-list.rs:154:45 + | +LL | reuse to_reuse::{value, mut_ref, r#ref} { () } + | ^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: delegation's target expression is specified for function with no params + --> $DIR/unused-target-expr-in-glob-or-list.rs:154:45 + | +LL | reuse to_reuse::{value, mut_ref, r#ref} { () } + | ^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: delegation's target expression is specified for function with no params + --> $DIR/unused-target-expr-in-glob-or-list.rs:165:39 + | +LL | reuse to_reuse::{value as value2} { } + | ^^^ + +error: delegation's target expression is specified for function with no params + --> $DIR/unused-target-expr-in-glob-or-list.rs:195:49 + | +LL | reuse to_reuse::{value, mut_ref, r#ref} { 1 + 1 } + | ^^^^^^^^^ + +error: delegation's target expression is specified for function with no params + --> $DIR/unused-target-expr-in-glob-or-list.rs:195:49 + | +LL | reuse to_reuse::{value, mut_ref, r#ref} { 1 + 1 } + | ^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: delegation's target expression is specified for function with no params + --> $DIR/unused-target-expr-in-glob-or-list.rs:195:49 + | +LL | reuse to_reuse::{value, mut_ref, r#ref} { 1 + 1 } + | ^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: delegation's target expression is specified for function with no params + --> $DIR/unused-target-expr-in-glob-or-list.rs:107:49 + | +LL | reuse ::static_self { self.0 } + | ^^^^^^^^^^ +... +LL | delegation!(); + | ------------- in this macro invocation + | + = note: this error originates in the macro `delegation` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: delegation's target expression is specified for function with no params + --> $DIR/unused-target-expr-in-glob-or-list.rs:127:45 + | +LL | reuse ::static_self { self.0 } + | ^^^^^^^^^^ +... +LL | delegation2!(); + | -------------- in this macro invocation + | + = note: this error originates in the macro `delegation2` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: unused target expression is specified for glob or list delegation + --> $DIR/unused-target-expr-in-glob-or-list.rs:18:25 + | +LL | reuse ::* { self.0 } + | ^ + +error: unused target expression is specified for glob or list delegation + --> $DIR/unused-target-expr-in-glob-or-list.rs:24:25 + | +LL | reuse ::* { self.0 } + | ^ + +error: unused target expression is specified for glob or list delegation + --> $DIR/unused-target-expr-in-glob-or-list.rs:30:26 + | +LL | reuse ::{static_self} { self.0 } + | ^^^^^^^^^^^ + +error: unused target expression is specified for glob or list delegation + --> $DIR/unused-target-expr-in-glob-or-list.rs:36:26 + | +LL | reuse ::{static_self, static_value} { self.0 } + | ^^^^^^^^^^^ + +error: unused target expression is specified for glob or list delegation + --> $DIR/unused-target-expr-in-glob-or-list.rs:42:26 + | +LL | reuse ::{static_self, static_value, static_mut_ref, static_ref} { self.0 } + | ^^^^^^^^^^^ + +error: unused target expression is specified for glob or list delegation + --> $DIR/unused-target-expr-in-glob-or-list.rs:48:26 + | +LL | reuse ::{static_self, static_value, static_mut_ref, static_ref} { } + | ^^^^^^^^^^^ + +error: unused target expression is specified for glob or list delegation + --> $DIR/unused-target-expr-in-glob-or-list.rs:66:26 + | +LL | reuse ::{static_self, static_self2} { { F } } + | ^^^^^^^^^^^ + +error: unused target expression is specified for glob or list delegation + --> $DIR/unused-target-expr-in-glob-or-list.rs:72:26 + | +LL | reuse ::{static_self, static_self2} { { F } } + | ^^^^^^^^^^^ + +error: unused target expression is specified for glob or list delegation + --> $DIR/unused-target-expr-in-glob-or-list.rs:75:26 + | +LL | reuse ::{static_value, static_mut_ref, static_ref} { } + | ^^^^^^^^^^^^ + +error: unused target expression is specified for glob or list delegation + --> $DIR/unused-target-expr-in-glob-or-list.rs:80:26 + | +LL | reuse ::{static_self, static_self2} { { F } } + | ^^^^^^^^^^^ + +error: unused target expression is specified for glob or list delegation + --> $DIR/unused-target-expr-in-glob-or-list.rs:83:26 + | +LL | reuse ::{static_value, static_mut_ref} { } + | ^^^^^^^^^^^^ + +error: unused target expression is specified for glob or list delegation + --> $DIR/unused-target-expr-in-glob-or-list.rs:92:26 + | +LL | reuse ::{static_self, static_self2} { { F } } + | ^^^^^^^^^^^ + +error: unused target expression is specified for glob or list delegation + --> $DIR/unused-target-expr-in-glob-or-list.rs:95:26 + | +LL | reuse ::{static_value, static_mut_ref} { } + | ^^^^^^^^^^^^ + +error: unused target expression is specified for glob or list delegation + --> $DIR/unused-target-expr-in-glob-or-list.rs:189:26 + | +LL | reuse to_reuse::{value, mut_ref, r#ref} { () } + | ^^^^^ + +error[E0053]: method `static_self` has an incompatible type for trait + --> $DIR/unused-target-expr-in-glob-or-list.rs:107:37 + | +LL | reuse ::static_self { self.0 } + | ^^^^^^^^^^^ expected `F`, found `()` +... +LL | delegation!(); + | ------------- in this macro invocation + | +note: type in trait + --> $DIR/unused-target-expr-in-glob-or-list.rs:4:25 + | +LL | fn static_self() -> F { F } + | ^ + = note: expected signature `fn() -> F` + found signature `fn() -> ()` + = note: this error originates in the macro `delegation` (in Nightly builds, run with -Z macro-backtrace for more info) +help: change the output type to match the trait + | +LL - reuse ::static_self { self.0 } +LL + reuse :: -> F { self.0 } + | + +error[E0053]: method `static_self` has an incompatible type for trait + --> $DIR/unused-target-expr-in-glob-or-list.rs:127:33 + | +LL | reuse ::static_self { self.0 } + | ^^^^^^^^^^^ expected `F`, found `()` +... +LL | delegation2!(); + | -------------- in this macro invocation + | +note: type in trait + --> $DIR/unused-target-expr-in-glob-or-list.rs:4:25 + | +LL | fn static_self() -> F { F } + | ^ + = note: expected signature `fn() -> F` + found signature `fn() -> ()` + = note: this error originates in the macro `delegation2` (in Nightly builds, run with -Z macro-backtrace for more info) +help: change the output type to match the trait + | +LL - reuse ::static_self { self.0 } +LL + reuse :: -> F { self.0 } + | + +error[E0061]: this function takes 0 arguments but 1 argument was supplied + --> $DIR/unused-target-expr-in-glob-or-list.rs:107:37 + | +LL | reuse ::static_self { self.0 } + | ^^^^^^^^^^^ ---------- unexpected argument +... +LL | delegation!(); + | ------------- in this macro invocation + | +note: associated function defined here + --> $DIR/unused-target-expr-in-glob-or-list.rs:4:8 + | +LL | fn static_self() -> F { F } + | ^^^^^^^^^^^ + = note: this error originates in the macro `delegation` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> $DIR/unused-target-expr-in-glob-or-list.rs:107:37 + | +LL | reuse ::static_self { self.0 } + | ^^^^^^^^^^^- help: consider using a semicolon here: `;` + | | + | expected `()`, found `F` + | expected `()` because of default return type +... +LL | delegation!(); + | ------------- in this macro invocation + | + = note: this error originates in the macro `delegation` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0609]: no field `0` on type `F` + --> $DIR/unused-target-expr-in-glob-or-list.rs:112:57 + | +LL | reuse ::static_value { self.0 } + | ^ unknown field +... +LL | delegation!(); + | ------------- in this macro invocation + | + = note: this error originates in the macro `delegation` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0609]: no field `0` on type `&mut F` + --> $DIR/unused-target-expr-in-glob-or-list.rs:114:59 + | +LL | reuse ::static_mut_ref { self.0 } + | ^ unknown field +... +LL | delegation!(); + | ------------- in this macro invocation + | + = note: this error originates in the macro `delegation` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0609]: no field `0` on type `&F` + --> $DIR/unused-target-expr-in-glob-or-list.rs:116:55 + | +LL | reuse ::static_ref { self.0 } + | ^ unknown field +... +LL | delegation!(); + | ------------- in this macro invocation + | + = note: this error originates in the macro `delegation` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0061]: this function takes 0 arguments but 1 argument was supplied + --> $DIR/unused-target-expr-in-glob-or-list.rs:127:33 + | +LL | reuse ::static_self { self.0 } + | ^^^^^^^^^^^ ---------- unexpected argument +... +LL | delegation2!(); + | -------------- in this macro invocation + | +note: associated function defined here + --> $DIR/unused-target-expr-in-glob-or-list.rs:4:8 + | +LL | fn static_self() -> F { F } + | ^^^^^^^^^^^ + = note: this error originates in the macro `delegation2` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> $DIR/unused-target-expr-in-glob-or-list.rs:127:33 + | +LL | reuse ::static_self { self.0 } + | ^^^^^^^^^^^- help: consider using a semicolon here: `;` + | | + | expected `()`, found `F` + | expected `()` because of default return type +... +LL | delegation2!(); + | -------------- in this macro invocation + | + = note: this error originates in the macro `delegation2` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0609]: no field `0` on type `F` + --> $DIR/unused-target-expr-in-glob-or-list.rs:132:53 + | +LL | reuse ::static_value { self.0 } + | ^ unknown field +... +LL | delegation2!(); + | -------------- in this macro invocation + | + = note: this error originates in the macro `delegation2` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0609]: no field `0` on type `&mut F` + --> $DIR/unused-target-expr-in-glob-or-list.rs:134:55 + | +LL | reuse ::static_mut_ref { self.0 } + | ^ unknown field +... +LL | delegation2!(); + | -------------- in this macro invocation + | + = note: this error originates in the macro `delegation2` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0609]: no field `0` on type `&F` + --> $DIR/unused-target-expr-in-glob-or-list.rs:136:51 + | +LL | reuse ::static_ref { self.0 } + | ^ unknown field +... +LL | delegation2!(); + | -------------- in this macro invocation + | + = note: this error originates in the macro `delegation2` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0061]: this function takes 0 arguments but 1 argument was supplied + --> $DIR/unused-target-expr-in-glob-or-list.rs:154:22 + | +LL | reuse to_reuse::{value, mut_ref, r#ref} { () } + | ^^^^^ ------ unexpected argument of type `()` + | +note: function defined here + --> $DIR/unused-target-expr-in-glob-or-list.rs:149:16 + | +LL | pub fn value() -> i32 { 1 } + | ^^^^^ +help: remove the extra argument + | +LL - reuse to_reuse::{value, mut_ref, r#ref} { () } +LL + reuse to_reuse::{valu{ () } + | + +error[E0308]: mismatched types + --> $DIR/unused-target-expr-in-glob-or-list.rs:154:22 + | +LL | reuse to_reuse::{value, mut_ref, r#ref} { () } + | ^^^^^ expected `()`, found `i32` + | +help: consider using a semicolon here + | +LL | reuse to_reuse::{value;, mut_ref, r#ref} { () } + | + +help: try adding a return type + | +LL - reuse to_reuse::{value, mut_ref, r#ref} { () } +LL + reuse to_reuse::{ -> i32, mut_ref, r#ref} { () } + | + +error[E0061]: this function takes 0 arguments but 1 argument was supplied + --> $DIR/unused-target-expr-in-glob-or-list.rs:154:29 + | +LL | reuse to_reuse::{value, mut_ref, r#ref} { () } + | ^^^^^^^ ------ unexpected argument of type `()` + | +note: function defined here + --> $DIR/unused-target-expr-in-glob-or-list.rs:150:16 + | +LL | pub fn mut_ref() -> i32 { 2 } + | ^^^^^^^ +help: remove the extra argument + | +LL - reuse to_reuse::{value, mut_ref, r#ref} { () } +LL + reuse to_reuse::{value, mut_re{ () } + | + +error[E0308]: mismatched types + --> $DIR/unused-target-expr-in-glob-or-list.rs:154:29 + | +LL | reuse to_reuse::{value, mut_ref, r#ref} { () } + | ^^^^^^^ expected `()`, found `i32` + | +help: consider using a semicolon here + | +LL | reuse to_reuse::{value, mut_ref;, r#ref} { () } + | + +help: try adding a return type + | +LL - reuse to_reuse::{value, mut_ref, r#ref} { () } +LL + reuse to_reuse::{value, -> i32, r#ref} { () } + | + +error[E0061]: this function takes 0 arguments but 1 argument was supplied + --> $DIR/unused-target-expr-in-glob-or-list.rs:154:38 + | +LL | reuse to_reuse::{value, mut_ref, r#ref} { () } + | ^^^^^ ------ unexpected argument of type `()` + | +note: function defined here + --> $DIR/unused-target-expr-in-glob-or-list.rs:151:16 + | +LL | pub fn r#ref() -> i32 { 3 } + | ^^^^^ +help: remove the extra argument + | +LL - reuse to_reuse::{value, mut_ref, r#ref} { () } +LL + reuse to_reuse::{value, mut_ref, r#re{ () } + | + +error[E0308]: mismatched types + --> $DIR/unused-target-expr-in-glob-or-list.rs:154:38 + | +LL | reuse to_reuse::{value, mut_ref, r#ref} { () } + | ^^^^^ expected `()`, found `i32` + | +help: consider using a semicolon here + | +LL | reuse to_reuse::{value, mut_ref, r#ref;} { () } + | + +help: try adding a return type + | +LL - reuse to_reuse::{value, mut_ref, r#ref} { () } +LL + reuse to_reuse::{value, mut_ref, -> i32} { () } + | + +error[E0061]: this function takes 0 arguments but 1 argument was supplied + --> $DIR/unused-target-expr-in-glob-or-list.rs:165:22 + | +LL | reuse to_reuse::{value as value2} { } + | ^^^^^ --- unexpected argument of type `()` + | +note: function defined here + --> $DIR/unused-target-expr-in-glob-or-list.rs:149:16 + | +LL | pub fn value() -> i32 { 1 } + | ^^^^^ +help: remove the extra argument + | +LL - reuse to_reuse::{value as value2} { } +LL + reuse to_reuse::{valu{ } + | + +error[E0308]: mismatched types + --> $DIR/unused-target-expr-in-glob-or-list.rs:165:22 + | +LL | reuse to_reuse::{value as value2} { } + | ^^^^^ expected `()`, found `i32` + | +help: consider using a semicolon here + | +LL | reuse to_reuse::{value; as value2} { } + | + +help: try adding a return type + | +LL - reuse to_reuse::{value as value2} { } +LL + reuse to_reuse::{ -> i32 as value2} { } + | + +error[E0061]: this function takes 0 arguments but 1 argument was supplied + --> $DIR/unused-target-expr-in-glob-or-list.rs:195:26 + | +LL | reuse to_reuse::{value, mut_ref, r#ref} { 1 + 1 } + | ^^^^^ --------- unexpected argument of type `{integer}` + | +note: function defined here + --> $DIR/unused-target-expr-in-glob-or-list.rs:179:16 + | +LL | pub fn value() -> i32 { 1 } + | ^^^^^ +help: remove the extra argument + | +LL - reuse to_reuse::{value, mut_ref, r#ref} { 1 + 1 } +LL + reuse to_reuse::{valu{ 1 + 1 } + | + +error[E0308]: mismatched types + --> $DIR/unused-target-expr-in-glob-or-list.rs:195:26 + | +LL | reuse to_reuse::{value, mut_ref, r#ref} { 1 + 1 } + | ^^^^^ expected `()`, found `i32` + | +help: consider using a semicolon here + | +LL | reuse to_reuse::{value;, mut_ref, r#ref} { 1 + 1 } + | + +help: try adding a return type + | +LL - reuse to_reuse::{value, mut_ref, r#ref} { 1 + 1 } +LL + reuse to_reuse::{ -> i32, mut_ref, r#ref} { 1 + 1 } + | + +error[E0061]: this function takes 0 arguments but 1 argument was supplied + --> $DIR/unused-target-expr-in-glob-or-list.rs:195:33 + | +LL | reuse to_reuse::{value, mut_ref, r#ref} { 1 + 1 } + | ^^^^^^^ --------- unexpected argument of type `{integer}` + | +note: function defined here + --> $DIR/unused-target-expr-in-glob-or-list.rs:180:16 + | +LL | pub fn mut_ref() -> i32 { 2 } + | ^^^^^^^ +help: remove the extra argument + | +LL - reuse to_reuse::{value, mut_ref, r#ref} { 1 + 1 } +LL + reuse to_reuse::{value, mut_re{ 1 + 1 } + | + +error[E0308]: mismatched types + --> $DIR/unused-target-expr-in-glob-or-list.rs:195:33 + | +LL | reuse to_reuse::{value, mut_ref, r#ref} { 1 + 1 } + | ^^^^^^^ expected `()`, found `i32` + | +help: consider using a semicolon here + | +LL | reuse to_reuse::{value, mut_ref;, r#ref} { 1 + 1 } + | + +help: try adding a return type + | +LL - reuse to_reuse::{value, mut_ref, r#ref} { 1 + 1 } +LL + reuse to_reuse::{value, -> i32, r#ref} { 1 + 1 } + | + +error[E0061]: this function takes 0 arguments but 1 argument was supplied + --> $DIR/unused-target-expr-in-glob-or-list.rs:195:42 + | +LL | reuse to_reuse::{value, mut_ref, r#ref} { 1 + 1 } + | ^^^^^ --------- unexpected argument of type `{integer}` + | +note: function defined here + --> $DIR/unused-target-expr-in-glob-or-list.rs:181:16 + | +LL | pub fn r#ref() -> i32 { 3 } + | ^^^^^ +help: remove the extra argument + | +LL - reuse to_reuse::{value, mut_ref, r#ref} { 1 + 1 } +LL + reuse to_reuse::{value, mut_ref, r#re{ 1 + 1 } + | + +error[E0308]: mismatched types + --> $DIR/unused-target-expr-in-glob-or-list.rs:195:42 + | +LL | reuse to_reuse::{value, mut_ref, r#ref} { 1 + 1 } + | ^^^^^ expected `()`, found `i32` + | +help: consider using a semicolon here + | +LL | reuse to_reuse::{value, mut_ref, r#ref;} { 1 + 1 } + | + +help: try adding a return type + | +LL - reuse to_reuse::{value, mut_ref, r#ref} { 1 + 1 } +LL + reuse to_reuse::{value, mut_ref, -> i32} { 1 + 1 } + | + +error: aborting due to 50 previous errors + +Some errors have detailed explanations: E0053, E0061, E0308, E0433, E0609. +For more information about an error, try `rustc --explain E0053`. diff --git a/tests/ui/dep-graph/dep-graph-assoc-type-codegen.rs b/tests/ui/dep-graph/dep-graph-assoc-type-codegen.rs index 8b87499966de5..3c228d81e0e56 100644 --- a/tests/ui/dep-graph/dep-graph-assoc-type-codegen.rs +++ b/tests/ui/dep-graph/dep-graph-assoc-type-codegen.rs @@ -1,6 +1,6 @@ // Test that when a trait impl changes, fns whose body uses that trait // must also be recompiled. -//@ ignore-parallel-frontend dep graph + //@ incremental //@ compile-flags: -Z query-dep-graph diff --git a/tests/ui/dep-graph/dep-graph-caller-callee.rs b/tests/ui/dep-graph/dep-graph-caller-callee.rs index 43d10cd57cdbb..c4bba8bb2d0b5 100644 --- a/tests/ui/dep-graph/dep-graph-caller-callee.rs +++ b/tests/ui/dep-graph/dep-graph-caller-callee.rs @@ -3,7 +3,7 @@ //@ incremental //@ compile-flags: -Z query-dep-graph -//@ ignore-parallel-frontend dep graph + #![feature(rustc_attrs)] #![allow(dead_code)] diff --git a/tests/ui/dep-graph/dep-graph-struct-signature.rs b/tests/ui/dep-graph/dep-graph-struct-signature.rs index abef7d2e98845..f00a22cf67cf0 100644 --- a/tests/ui/dep-graph/dep-graph-struct-signature.rs +++ b/tests/ui/dep-graph/dep-graph-struct-signature.rs @@ -1,6 +1,6 @@ // Test cases where a changing struct appears in the signature of fns // and methods. -//@ ignore-parallel-frontend dep graph + //@ incremental //@ compile-flags: -Z query-dep-graph diff --git a/tests/ui/dep-graph/dep-graph-trait-impl-two-traits-same-method.rs b/tests/ui/dep-graph/dep-graph-trait-impl-two-traits-same-method.rs index ccdd2ff570f61..cdb74b9c97119 100644 --- a/tests/ui/dep-graph/dep-graph-trait-impl-two-traits-same-method.rs +++ b/tests/ui/dep-graph/dep-graph-trait-impl-two-traits-same-method.rs @@ -1,6 +1,6 @@ // Test that adding an impl to a trait `Foo` DOES affect functions // that only use `Bar` if they have methods in common. -//@ ignore-parallel-frontend dep graph + //@ incremental //@ compile-flags: -Z query-dep-graph diff --git a/tests/ui/dep-graph/dep-graph-trait-impl.rs b/tests/ui/dep-graph/dep-graph-trait-impl.rs index 952ccf61c7d5e..a0aefba6e4658 100644 --- a/tests/ui/dep-graph/dep-graph-trait-impl.rs +++ b/tests/ui/dep-graph/dep-graph-trait-impl.rs @@ -1,6 +1,6 @@ // Test that when a trait impl changes, fns whose body uses that trait // must also be recompiled. -//@ ignore-parallel-frontend dep graph + //@ incremental //@ compile-flags: -Z query-dep-graph diff --git a/tests/ui/dep-graph/dep-graph-type-alias.rs b/tests/ui/dep-graph/dep-graph-type-alias.rs index 8d0407a74ca86..a083f905b8ff9 100644 --- a/tests/ui/dep-graph/dep-graph-type-alias.rs +++ b/tests/ui/dep-graph/dep-graph-type-alias.rs @@ -1,5 +1,5 @@ // Test that changing what a `type` points to does not go unnoticed. -//@ ignore-parallel-frontend dep graph + //@ incremental //@ compile-flags: -Z query-dep-graph diff --git a/tests/ui/dep-graph/dep-graph-variance-alias.rs b/tests/ui/dep-graph/dep-graph-variance-alias.rs index 5e86e77b24a27..8a67fe6d7271d 100644 --- a/tests/ui/dep-graph/dep-graph-variance-alias.rs +++ b/tests/ui/dep-graph/dep-graph-variance-alias.rs @@ -1,6 +1,6 @@ // Test that changing what a `type` points to does not go unnoticed // by the variance analysis. -//@ ignore-parallel-frontend dep graph + //@ incremental //@ compile-flags: -Z query-dep-graph diff --git a/tests/ui/inline-const/required-const.rs b/tests/ui/inline-const/required-const.rs index 437652532ec54..8f640e933d019 100644 --- a/tests/ui/inline-const/required-const.rs +++ b/tests/ui/inline-const/required-const.rs @@ -1,6 +1,6 @@ //@ build-fail //@ compile-flags: -Zmir-opt-level=3 -//@ ignore-parallel-frontend post-monomorphization errors + fn foo() { if false { const { panic!() } //~ ERROR E0080 diff --git a/tests/ui/lint/large_assignments/copy_into_box_rc_arc.rs b/tests/ui/lint/large_assignments/copy_into_box_rc_arc.rs index a8e23c0246eeb..dfa0b8015d037 100644 --- a/tests/ui/lint/large_assignments/copy_into_box_rc_arc.rs +++ b/tests/ui/lint/large_assignments/copy_into_box_rc_arc.rs @@ -3,7 +3,7 @@ #![move_size_limit = "1000"] //@ build-fail //@ only-64bit -//@ ignore-parallel-frontend post-monomorphization errors + //@ edition:2018 //@ compile-flags: -Zmir-opt-level=1 diff --git a/tests/ui/lint/large_assignments/copy_into_fn.rs b/tests/ui/lint/large_assignments/copy_into_fn.rs index 8f8e7f0822bbc..5222e833bcc8f 100644 --- a/tests/ui/lint/large_assignments/copy_into_fn.rs +++ b/tests/ui/lint/large_assignments/copy_into_fn.rs @@ -1,5 +1,5 @@ //@ build-fail -//@ ignore-parallel-frontend post-monomorphization errors + #![feature(large_assignments)] #![move_size_limit = "1000"] #![deny(large_assignments)] diff --git a/tests/ui/lint/large_assignments/inline_mir.rs b/tests/ui/lint/large_assignments/inline_mir.rs index 68c5de4902f34..d16aae6ab145b 100644 --- a/tests/ui/lint/large_assignments/inline_mir.rs +++ b/tests/ui/lint/large_assignments/inline_mir.rs @@ -13,7 +13,7 @@ //! ``` //! //! We want the diagnostics to point to the relevant user code. -//@ ignore-parallel-frontend post-monomorphization errors + //@ build-fail //@ compile-flags: -Zmir-opt-level=1 -Zinline-mir diff --git a/tests/ui/lint/large_assignments/large_future.rs b/tests/ui/lint/large_assignments/large_future.rs index 1be66f16313bb..28c358bdbf086 100644 --- a/tests/ui/lint/large_assignments/large_future.rs +++ b/tests/ui/lint/large_assignments/large_future.rs @@ -5,7 +5,7 @@ //@ only-64bit //@ revisions: attribute option //@ [option]compile-flags: -Zmove-size-limit=1000 -//@ ignore-parallel-frontend post-monomorphization errors + //@ edition:2018 //@ compile-flags: -Zmir-opt-level=0 diff --git a/tests/ui/lint/large_assignments/move_into_fn.rs b/tests/ui/lint/large_assignments/move_into_fn.rs index 1e793a082e3ea..b3b2160ca36e1 100644 --- a/tests/ui/lint/large_assignments/move_into_fn.rs +++ b/tests/ui/lint/large_assignments/move_into_fn.rs @@ -1,5 +1,5 @@ //@ build-fail -//@ ignore-parallel-frontend post-monomorphization errors + #![feature(large_assignments)] #![move_size_limit = "1000"] #![deny(large_assignments)] diff --git a/tests/ui/parser/dyn-2015-identifier.fail.stderr b/tests/ui/parser/dyn-2015-identifier.fail.stderr new file mode 100644 index 0000000000000..da82a9f2d067f --- /dev/null +++ b/tests/ui/parser/dyn-2015-identifier.fail.stderr @@ -0,0 +1,80 @@ +error[E0425]: cannot find type `dyn` in this scope + --> $DIR/dyn-2015-identifier.rs:7:11 + | +LL | type A0 = dyn; + | ^^^ not found in this scope + +error[E0425]: cannot find type `dyn` in this scope + --> $DIR/dyn-2015-identifier.rs:13:11 + | +LL | type A2 = dyn; + | ^^^ not found in this scope + +error[E0425]: cannot find type `dyn` in this scope + --> $DIR/dyn-2015-identifier.rs:13:15 + | +LL | type A2 = dyn; + | ^^^ not found in this scope + +error[E0425]: cannot find type `dyn` in this scope + --> $DIR/dyn-2015-identifier.rs:13:20 + | +LL | type A2 = dyn; + | ^^^ not found in this scope + +error[E0425]: cannot find type `dyn` in this scope + --> $DIR/dyn-2015-identifier.rs:18:11 + | +LL | type A3 = dyn<::dyn>; + | ^^^ not found in this scope + +error[E0405]: cannot find trait `dyn` in this scope + --> $DIR/dyn-2015-identifier.rs:18:23 + | +LL | type A3 = dyn<::dyn>; + | ^^^ not found in this scope + +error[E0425]: cannot find type `dyn` in this scope + --> $DIR/dyn-2015-identifier.rs:18:16 + | +LL | type A3 = dyn<::dyn>; + | ^^^ not found in this scope + +error[E0405]: cannot find trait `dyn` in this scope + --> $DIR/dyn-2015-identifier.rs:24:11 + | +LL | type A4 = dyn + dyn; + | ^^^ not found in this scope + +error[E0405]: cannot find trait `dyn` in this scope + --> $DIR/dyn-2015-identifier.rs:24:17 + | +LL | type A4 = dyn + dyn; + | ^^^ not found in this scope + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/dyn-2015-identifier.rs:24:11 + | +LL | type A4 = dyn + dyn; + | ^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + = note: `#[warn(bare_trait_objects)]` (part of `#[warn(rust_2021_compatibility)]`) on by default +help: if this is a dyn-compatible trait, use `dyn` + | +LL | type A4 = dyn dyn + dyn; + | +++ + +error[E0433]: cannot find module or crate `dyn` in this scope + --> $DIR/dyn-2015-identifier.rs:10:11 + | +LL | type A1 = dyn::dyn; + | ^^^ use of unresolved module or unlinked crate `dyn` + | + = help: you might be missing a crate named `dyn` + +error: aborting due to 10 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0405, E0425, E0433. +For more information about an error, try `rustc --explain E0405`. diff --git a/tests/ui/parser/dyn-2015-identifier.rs b/tests/ui/parser/dyn-2015-identifier.rs new file mode 100644 index 0000000000000..3bac8d2b631dc --- /dev/null +++ b/tests/ui/parser/dyn-2015-identifier.rs @@ -0,0 +1,28 @@ +//@ edition: 2015 +//@ compile-flags: --crate-type=lib +//@ revisions: pass fail +//@[pass] check-pass +#![cfg(fail)] + +type A0 = dyn; +//[fail]~^ ERROR cannot find type `dyn` in this scope + +type A1 = dyn::dyn; +//[fail]~^ ERROR cannot find module or crate `dyn` in this scope + +type A2 = dyn; +//[fail]~^ ERROR cannot find type `dyn` in this scope +//[fail]~| ERROR cannot find type `dyn` in this scope +//[fail]~| ERROR cannot find type `dyn` in this scope + +type A3 = dyn<::dyn>; +//[fail]~^ ERROR cannot find type `dyn` in this scope +//[fail]~| ERROR cannot find type `dyn` in this scope +//[fail]~| ERROR cannot find trait `dyn` in this scope + +// issue: +type A4 = dyn + dyn; +//[fail]~^ ERROR cannot find trait `dyn` in this scope +//[fail]~| ERROR cannot find trait `dyn` in this scope +//[fail]~| WARN trait objects without an explicit `dyn` are deprecated +//[fail]~| WARN this is accepted in the current edition diff --git a/tests/ui/parser/dyn-trait-compatibility.rs b/tests/ui/parser/dyn-trait-compatibility.rs deleted file mode 100644 index dd01b6e19d05a..0000000000000 --- a/tests/ui/parser/dyn-trait-compatibility.rs +++ /dev/null @@ -1,16 +0,0 @@ -//@ edition: 2015 - -type A0 = dyn; -//~^ ERROR cannot find type `dyn` in this scope -type A1 = dyn::dyn; -//~^ ERROR cannot find module or crate `dyn` in this scope -type A2 = dyn; -//~^ ERROR cannot find type `dyn` in this scope -//~| ERROR cannot find type `dyn` in this scope -//~| ERROR cannot find type `dyn` in this scope -type A3 = dyn<::dyn>; -//~^ ERROR cannot find type `dyn` in this scope -//~| ERROR cannot find type `dyn` in this scope -//~| ERROR cannot find trait `dyn` in this scope - -fn main() {} diff --git a/tests/ui/parser/dyn-trait-compatibility.stderr b/tests/ui/parser/dyn-trait-compatibility.stderr deleted file mode 100644 index 233b22123d31c..0000000000000 --- a/tests/ui/parser/dyn-trait-compatibility.stderr +++ /dev/null @@ -1,54 +0,0 @@ -error[E0425]: cannot find type `dyn` in this scope - --> $DIR/dyn-trait-compatibility.rs:3:11 - | -LL | type A0 = dyn; - | ^^^ not found in this scope - -error[E0425]: cannot find type `dyn` in this scope - --> $DIR/dyn-trait-compatibility.rs:7:11 - | -LL | type A2 = dyn; - | ^^^ not found in this scope - -error[E0425]: cannot find type `dyn` in this scope - --> $DIR/dyn-trait-compatibility.rs:7:15 - | -LL | type A2 = dyn; - | ^^^ not found in this scope - -error[E0425]: cannot find type `dyn` in this scope - --> $DIR/dyn-trait-compatibility.rs:7:20 - | -LL | type A2 = dyn; - | ^^^ not found in this scope - -error[E0425]: cannot find type `dyn` in this scope - --> $DIR/dyn-trait-compatibility.rs:11:11 - | -LL | type A3 = dyn<::dyn>; - | ^^^ not found in this scope - -error[E0405]: cannot find trait `dyn` in this scope - --> $DIR/dyn-trait-compatibility.rs:11:23 - | -LL | type A3 = dyn<::dyn>; - | ^^^ not found in this scope - -error[E0425]: cannot find type `dyn` in this scope - --> $DIR/dyn-trait-compatibility.rs:11:16 - | -LL | type A3 = dyn<::dyn>; - | ^^^ not found in this scope - -error[E0433]: cannot find module or crate `dyn` in this scope - --> $DIR/dyn-trait-compatibility.rs:5:11 - | -LL | type A1 = dyn::dyn; - | ^^^ use of unresolved module or unlinked crate `dyn` - | - = help: you might be missing a crate named `dyn` - -error: aborting due to 8 previous errors - -Some errors have detailed explanations: E0405, E0425, E0433. -For more information about an error, try `rustc --explain E0405`. diff --git a/tests/ui/reflection/reflection_methods_in_runtime_code.rs b/tests/ui/reflection/reflection_methods_in_runtime_code.rs new file mode 100644 index 0000000000000..4204fb3ad16f4 --- /dev/null +++ b/tests/ui/reflection/reflection_methods_in_runtime_code.rs @@ -0,0 +1,9 @@ +#![feature(type_info)] + +trait Trait {} + +fn main() { + // Test the (lack of) usability of comptime fns in runtime code. + std::any::TypeId::of::<[u8; usize::MAX]>().trait_info_of::(); + //~^ ERROR: comptime fns can only be called at compile time +} diff --git a/tests/ui/reflection/reflection_methods_in_runtime_code.stderr b/tests/ui/reflection/reflection_methods_in_runtime_code.stderr new file mode 100644 index 0000000000000..ff83c50754254 --- /dev/null +++ b/tests/ui/reflection/reflection_methods_in_runtime_code.stderr @@ -0,0 +1,8 @@ +error: comptime fns can only be called at compile time + --> $DIR/reflection_methods_in_runtime_code.rs:7:5 + | +LL | std::any::TypeId::of::<[u8; usize::MAX]>().trait_info_of::(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/simd/const-err-trumps-simd-err.rs b/tests/ui/simd/const-err-trumps-simd-err.rs index 282d5dabf72fa..33f0abb06f3ea 100644 --- a/tests/ui/simd/const-err-trumps-simd-err.rs +++ b/tests/ui/simd/const-err-trumps-simd-err.rs @@ -1,6 +1,6 @@ //@build-fail //@ dont-require-annotations: NOTE -//@ ignore-parallel-frontend post-monomorphization errors + //! Make sure that monomorphization-time const errors from `static_assert` take priority over the //! error from simd_extract. Basically this checks that if a const fails to evaluate in some //! function, we don't bother codegen'ing the function. diff --git a/tests/ui/structs/default-field-values/post-mono.rs b/tests/ui/structs/default-field-values/post-mono.rs index 57092083ca102..68dfa391bb485 100644 --- a/tests/ui/structs/default-field-values/post-mono.rs +++ b/tests/ui/structs/default-field-values/post-mono.rs @@ -1,6 +1,6 @@ //@ build-fail //@ revisions: direct indirect -//@ ignore-parallel-frontend post-monomorphization errors + #![feature(default_field_values)] struct Z { diff --git a/tests/ui/wf/let-pat-inferred-non-wf.rs b/tests/ui/wf/let-pat-inferred-non-wf.rs new file mode 100644 index 0000000000000..ab032161ebb51 --- /dev/null +++ b/tests/ui/wf/let-pat-inferred-non-wf.rs @@ -0,0 +1,58 @@ +// Regression test for https://github.com/rust-lang/rust/issues/150040 +// When a `let PAT;` has no explicit type, later assignments can infer a non-well-formed +// pattern type such as `[str; 2]` or `(str, i32)`. We must reject those array and tuple +// patterns instead of accepting the invalid type or causing ICE. + +#![allow(unused)] + +struct S(T); + +fn should_fail_1() { + let ref y @ [ref x, _]; //~ ERROR E0277 + x = ""; +} + +fn should_fail_2() { + let [ref x]; //~ ERROR E0277 + x = ""; +} + +fn should_fail_3() { + let [[ref x], [_, y @ ..]]; //~ ERROR E0277 + x = ""; + y = []; +} + +fn should_fail_4() { + let [(ref a, b), x]; //~ ERROR E0277 + a = ""; + b = 5; +} + +fn should_fail_5() { + let (ref a, b); //~ ERROR E0277 + a = ""; + b = 5; +} + +fn should_fail_6() { + let [S(ref x)]; //~ ERROR E0277 + x = ""; +} + +fn should_pass_1() { + let ref x; + x = ""; +} + +fn should_pass_2() { + let ref y @ (ref x,); + x = ""; +} + +fn should_pass_3() { + let S(ref x); + x = ""; +} + +fn main() {} diff --git a/tests/ui/wf/let-pat-inferred-non-wf.stderr b/tests/ui/wf/let-pat-inferred-non-wf.stderr new file mode 100644 index 0000000000000..1c524a22b432b --- /dev/null +++ b/tests/ui/wf/let-pat-inferred-non-wf.stderr @@ -0,0 +1,62 @@ +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/let-pat-inferred-non-wf.rs:11:9 + | +LL | let ref y @ [ref x, _]; + | ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: slice and array elements must have `Sized` type + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/let-pat-inferred-non-wf.rs:16:9 + | +LL | let [ref x]; + | ^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: slice and array elements must have `Sized` type + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/let-pat-inferred-non-wf.rs:21:9 + | +LL | let [[ref x], [_, y @ ..]]; + | ^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: slice and array elements must have `Sized` type + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/let-pat-inferred-non-wf.rs:27:9 + | +LL | let [(ref a, b), x]; + | ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: only the last element of a tuple may have a dynamically sized type + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/let-pat-inferred-non-wf.rs:33:9 + | +LL | let (ref a, b); + | ^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: only the last element of a tuple may have a dynamically sized type + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/let-pat-inferred-non-wf.rs:39:9 + | +LL | let [S(ref x)]; + | ^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: within `S`, the trait `Sized` is not implemented for `str` +note: required because it appears within the type `S` + --> $DIR/let-pat-inferred-non-wf.rs:8:8 + | +LL | struct S(T); + | ^ + = note: slice and array elements must have `Sized` type + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-dyn-in-hrtb-bound-const-mismatch.rs b/tests/ui/wf/wf-dyn-in-hrtb-bound-const-mismatch.rs new file mode 100644 index 0000000000000..a0808f820aa38 --- /dev/null +++ b/tests/ui/wf/wf-dyn-in-hrtb-bound-const-mismatch.rs @@ -0,0 +1,19 @@ +// Companion to #157122 / `wf-dyn-in-hrtb-bound-issue-157122.rs`. +// +// That test covers an ICE in `WfPredicates::visit_ty` where a `dyn Trait` nested +// inside a `for<'a>` binder reached `ExistentialTraitRef::with_self_ty` with an +// escaping self type. The fix removes the offending `debug_assert!` rather than +// skipping the block. Skipping would have been a silent regression: the block +// emits the `ConstArgHasType` obligation that type-checks a `dyn`'s const +// argument, so dropping it makes an ill-typed const argument compile. +// +// Here `B` has type `bool` but `HasConst` expects `const N: usize`, and the +// `dyn HasConst<'a, B>` carries the escaping late-bound `'a`. This must still be +// rejected, exactly as it is without the surrounding `for<'a>` binder. + +trait HasConst<'a, const N: usize> {} + +fn nested(_f: &dyn for<'a> Fn(&'a (), &'a dyn HasConst<'a, B>)) {} +//~^ ERROR the constant `B` is not of type `usize` + +fn main() {} diff --git a/tests/ui/wf/wf-dyn-in-hrtb-bound-const-mismatch.stderr b/tests/ui/wf/wf-dyn-in-hrtb-bound-const-mismatch.stderr new file mode 100644 index 0000000000000..317fbb5dcafe1 --- /dev/null +++ b/tests/ui/wf/wf-dyn-in-hrtb-bound-const-mismatch.stderr @@ -0,0 +1,14 @@ +error: the constant `B` is not of type `usize` + --> $DIR/wf-dyn-in-hrtb-bound-const-mismatch.rs:16:30 + | +LL | fn nested(_f: &dyn for<'a> Fn(&'a (), &'a dyn HasConst<'a, B>)) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `bool` + | +note: required by a const generic parameter in `HasConst` + --> $DIR/wf-dyn-in-hrtb-bound-const-mismatch.rs:14:20 + | +LL | trait HasConst<'a, const N: usize> {} + | ^^^^^^^^^^^^^^ required by this const generic parameter in `HasConst` + +error: aborting due to 1 previous error + diff --git a/tests/ui/wf/wf-dyn-in-hrtb-bound-issue-157122.rs b/tests/ui/wf/wf-dyn-in-hrtb-bound-issue-157122.rs new file mode 100644 index 0000000000000..6254a2cb1100b --- /dev/null +++ b/tests/ui/wf/wf-dyn-in-hrtb-bound-issue-157122.rs @@ -0,0 +1,28 @@ +//@ check-pass + +// Regression test for #157122. +// +// When WF-checking a type, the visitor recurses through higher-ranked binders +// without instantiating them, so a `dyn Trait` nested inside a `for<'a>` binder +// reaches the `ty::Dynamic` arm of `WfPredicates::visit_ty` while still carrying +// escaping bound vars. Building the principal trait ref there via +// `ExistentialTraitRef::with_self_ty` passed that escaping self type to a +// `debug_assert!(!self_ty.has_escaping_bound_vars())`, which ICEs once the +// assertion is enabled. Creating a trait ref with an escaping self type is fine +// -- escaping bound vars are caught where they are actually used -- so the +// assertion was removed rather than worked around. The `ConstArgHasType` check +// this arm reads off still runs; see `wf-dyn-in-hrtb-bound-const-mismatch.rs`. +// Distilled from `itertools`'s `FormatWith` `Display` impl. + +use std::fmt; + +fn call(mut f: F) +where + F: FnMut(&mut dyn FnMut(&dyn fmt::Display) -> fmt::Result) -> fmt::Result, +{ + let _ = f(&mut |_disp: &dyn fmt::Display| Ok(())); +} + +fn main() { + call(|cb| cb(&0i32)); +}